<?php
//use ErrorException;
//use InvalidArgumentException;
/**
* HTTP Status values have a code (int) and reason (string).
*
* @internal Implemented similar to a type-safe enum.
*
* @property-read int $code the status code
* @property-read string $reason the status description
*/
final class Status
{
/** @var array (int) code => (string) reason */
private static $codeReasons = [
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-status',
208 => 'Already Reported',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Switch Proxy',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Large',
415 => 'Unsupported Media Type',
416 => 'Requested range not satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
425 => 'Unordered Collection',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Time-out',
505 => 'HTTP Version not supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
508 => 'Loop Detected',
511 => 'Network Authentication Required',
];
/** @var self[] */
private static $instances = [];
/** @var int */
private $code;
/** @var string */
private $reason;
/**
* Singleton constructor
*
* @param int $aCode an http status code
* @throws InvalidArgumentException on invalid code
*/
private function __construct($aCode)
{
if (!static::validate($aCode)) {
throw new InvalidArgumentExeption("Invalid status code: [$aCode]");
}
$this->code = (int) $aCode;
$this->reason = static::$codeReasons[$this->code];
}
/**
* Factory constructor
*
* Methods must not start with a number, so an underscore prefix is necessary.
*
* @example $status = Status::_404();
*
* @param string $aMethod a status code prefixed with an underscore
* @param array $arguments unused arguments passed to the magic method
* @return self
*/
public static function __callStatic($aMethod, array $arguments = [])
{
$aMethod = trim($aMethod, '_');
if (!isset(static::$instances[$aMethod])) {
static::$instances[$aMethod] = new static($aMethod);
}
return static::$instances[$aMethod];
}
/**
* List all HTTP statuses
*
* @yield self
*/
public static function listAll()
{
foreach (static::$codeReasons as $code => $reason) {
yield $code => $reason;
}
}
/**
* Verify that a code is valid
*
* @param int $aCode the status code to verify
* @return bool
*/
public static function validate($aCode)
{
return ($aCode instanceof self) || isset(static::$codeReasons[(int) $aCode]);
}
/**
* Allow public property access
*
* @param string $aProperty
* @return mixed
* @throws ErrorException on invalid property
*/
public function __get($aProperty)
{
if (property_exists($this, $aProperty)) {
return $this->{$aProperty};
}
$debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$error = sprintf('Undefined property %s::$%s', __CLASS__, $aProperty);
throw new ErrorException($error, 0, E_USER_NOTICE, $debug[1]['file'], $debug[1]['line']);
}
/** @return string */
public function __toString()
{
return $this->code . ' ' . $this->reason;
}
}
var_dump(iterator_to_array(Status::listAll()));
preferences:
46.09 ms | 402 KiB | 5 Q