<?php
/**
* AbstractError.php
*
* @package WordPress\Error
*/
namespace WordPress\Error;
use InvalidArgumentException;
use RuntimeException;
/**
* WordPress Errors extend {@link RuntimeException} with relevant data.
*
* Extend this class with domain-specific codes and messages and call this
* constructor to include the instance in the list of recorded errors.
*
* Use {@link is_wp_error()} to check if this class is returned. Many core
* WordPress functions pass this class in the event of an error and if not
* handled properly will result in code errors.
*
* @package WordPress\Error
* @since 2.1.0
*/
abstract class AbstractError extends RuntimeException
{
/**
* Internal map of code messages
*
* @var array code (int) => message (string)
*/
protected static $codeMessages = [];
/**
* Internal list of AbstractError instances
*
* @var self[]
*/
private static $instances = [];
/**
* Optional error data
*
* @var mixed
*/
private $data;
/**
* Initialize the error
*
* @param int $code an error code
* @param mixed $data optional error data
* @param self $previous optional previous error
*
* @throws InvalidArgumentException when the code is not recognized
*/
public function __construct($code, $data = null, self $previous = null)
{
if (!isset(static::$codeMessages[$code])) {
throw new InvalidArgumentException("Invalid error code [$code]");
}
parent::__construct(static::$codeMessages[$code], $code, $previous);
$this->data = $data;
self::$instances[] = $this;
}
/**
* Remove all instances having the specified code
*
* @param int $code an error code to remove
*/
final public static function remove($code)
{
foreach (self::$instances as $index => $error) {
if ($code === $error->getCode()) {
unset(self::$instances[$index]);
}
}
}
/**
* Retrieve all instances having the specified code
*
* @param int $code an error code
*
* @yield self each error instance with matching code
*/
final public static function get($code)
{
foreach (self::$instances as $error) {
if ($code === $error->getCode()) {
yield $error;
}
}
}
/**
* Retrieve all error instances
*
* @yield self each error instance
*/
final public static function getAll()
{
foreach (self::$instances as $error) {
yield $error;
}
}
/**
* Retrieve the error data
*
* @return mixed error data, if available
*/
public function getData()
{
return $this->data;
}
/**
* Replace the error data
*
* @param mixed $data optional error data
*
* @return self an instance with the new data
*/
public function setData($data = null)
{
return new static($this->getCode(), $data, $this);
}
/**
* Triggers a PHP error
*
* @param int $type optional PHP error type
*/
public function trigger($type = E_USER_NOTICE)
{
trigger_error((string) $this, (int) $type);
}
/**
* Converts the object to a string
*
* @return string a formatted error string
*/
public function __toString()
{
return "Error " . $this->getCode() . ": " . $this->getMessage();
}
}
class E extends AbstractError
{
protected static $codeMessages = [
5001 => 'foo',
6001 => 'bar'
];
public static function foo($data = null)
{
return new static(5001, $data);
}
public static function bar($data = null)
{
return new static(6001, $data);
}
}
$e = E::foo();
$s = $e->setData('snowflake');
foreach (AbstractError::getAll() as $error) {
echo $error->getMessage() . PHP_EOL;
}
var_dump($e, $s);