/lib/php-enum/src/Enum.php

https://github.com/markn86/moodle · PHP · 250 lines · 87 code · 24 blank · 139 comment · 9 complexity · 6ea23b036aef4b28fda749363aabca27 MD5 · raw file

  1. <?php
  2. /**
  3. * @link http://github.com/myclabs/php-enum
  4. * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
  5. */
  6. namespace MyCLabs\Enum;
  7. /**
  8. * Base Enum class
  9. *
  10. * Create an enum by implementing this class and adding class constants.
  11. *
  12. * @author Matthieu Napoli <matthieu@mnapoli.fr>
  13. * @author Daniel Costa <danielcosta@gmail.com>
  14. * @author Mirosław Filip <mirfilip@gmail.com>
  15. *
  16. * @psalm-template T
  17. * @psalm-immutable
  18. */
  19. abstract class Enum implements \JsonSerializable
  20. {
  21. /**
  22. * Enum value
  23. *
  24. * @var mixed
  25. * @psalm-var T
  26. */
  27. protected $value;
  28. /**
  29. * Store existing constants in a static cache per object.
  30. *
  31. *
  32. * @var array
  33. * @psalm-var array<class-string, array<string, mixed>>
  34. */
  35. protected static $cache = [];
  36. /**
  37. * Cache of instances of the Enum class
  38. *
  39. * @var array
  40. * @psalm-var array<class-string, array<string, static>>
  41. */
  42. protected static $instances = [];
  43. /**
  44. * Creates a new value of some type
  45. *
  46. * @psalm-pure
  47. * @param mixed $value
  48. *
  49. * @psalm-param static<T>|T $value
  50. * @throws \UnexpectedValueException if incompatible type is given.
  51. */
  52. public function __construct($value)
  53. {
  54. if ($value instanceof static) {
  55. /** @psalm-var T */
  56. $value = $value->getValue();
  57. }
  58. if (!$this->isValid($value)) {
  59. /** @psalm-suppress InvalidCast */
  60. throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class);
  61. }
  62. /** @psalm-var T */
  63. $this->value = $value;
  64. }
  65. /**
  66. * @psalm-pure
  67. * @return mixed
  68. * @psalm-return T
  69. */
  70. public function getValue()
  71. {
  72. return $this->value;
  73. }
  74. /**
  75. * Returns the enum key (i.e. the constant name).
  76. *
  77. * @psalm-pure
  78. * @return mixed
  79. */
  80. public function getKey()
  81. {
  82. return static::search($this->value);
  83. }
  84. /**
  85. * @psalm-pure
  86. * @psalm-suppress InvalidCast
  87. * @return string
  88. */
  89. public function __toString()
  90. {
  91. return (string)$this->value;
  92. }
  93. /**
  94. * Determines if Enum should be considered equal with the variable passed as a parameter.
  95. * Returns false if an argument is an object of different class or not an object.
  96. *
  97. * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4
  98. *
  99. * @psalm-pure
  100. * @psalm-param mixed $variable
  101. * @return bool
  102. */
  103. final public function equals($variable = null): bool
  104. {
  105. return $variable instanceof self
  106. && $this->getValue() === $variable->getValue()
  107. && static::class === \get_class($variable);
  108. }
  109. /**
  110. * Returns the names (keys) of all constants in the Enum class
  111. *
  112. * @psalm-pure
  113. * @psalm-return list<string>
  114. * @return array
  115. */
  116. public static function keys()
  117. {
  118. return \array_keys(static::toArray());
  119. }
  120. /**
  121. * Returns instances of the Enum class of all Enum constants
  122. *
  123. * @psalm-pure
  124. * @psalm-return array<string, static>
  125. * @return static[] Constant name in key, Enum instance in value
  126. */
  127. public static function values()
  128. {
  129. $values = array();
  130. /** @psalm-var T $value */
  131. foreach (static::toArray() as $key => $value) {
  132. $values[$key] = new static($value);
  133. }
  134. return $values;
  135. }
  136. /**
  137. * Returns all possible values as an array
  138. *
  139. * @psalm-pure
  140. * @psalm-suppress ImpureStaticProperty
  141. *
  142. * @psalm-return array<string, mixed>
  143. * @return array Constant name in key, constant value in value
  144. */
  145. public static function toArray()
  146. {
  147. $class = static::class;
  148. if (!isset(static::$cache[$class])) {
  149. $reflection = new \ReflectionClass($class);
  150. static::$cache[$class] = $reflection->getConstants();
  151. }
  152. return static::$cache[$class];
  153. }
  154. /**
  155. * Check if is valid enum value
  156. *
  157. * @param $value
  158. * @psalm-param mixed $value
  159. * @psalm-pure
  160. * @return bool
  161. */
  162. public static function isValid($value)
  163. {
  164. return \in_array($value, static::toArray(), true);
  165. }
  166. /**
  167. * Check if is valid enum key
  168. *
  169. * @param $key
  170. * @psalm-param string $key
  171. * @psalm-pure
  172. * @return bool
  173. */
  174. public static function isValidKey($key)
  175. {
  176. $array = static::toArray();
  177. return isset($array[$key]) || \array_key_exists($key, $array);
  178. }
  179. /**
  180. * Return key for value
  181. *
  182. * @param $value
  183. *
  184. * @psalm-param mixed $value
  185. * @psalm-pure
  186. * @return mixed
  187. */
  188. public static function search($value)
  189. {
  190. return \array_search($value, static::toArray(), true);
  191. }
  192. /**
  193. * Returns a value when called statically like so: MyEnum::SOME_VALUE() given SOME_VALUE is a class constant
  194. *
  195. * @param string $name
  196. * @param array $arguments
  197. *
  198. * @return static
  199. * @throws \BadMethodCallException
  200. */
  201. public static function __callStatic($name, $arguments)
  202. {
  203. $class = static::class;
  204. if (!isset(self::$instances[$class][$name])) {
  205. $array = static::toArray();
  206. if (!isset($array[$name]) && !\array_key_exists($name, $array)) {
  207. $message = "No static method or enum constant '$name' in class " . static::class;
  208. throw new \BadMethodCallException($message);
  209. }
  210. return self::$instances[$class][$name] = new static($array[$name]);
  211. }
  212. return clone self::$instances[$class][$name];
  213. }
  214. /**
  215. * Specify data which should be serialized to JSON. This method returns data that can be serialized by json_encode()
  216. * natively.
  217. *
  218. * @return mixed
  219. * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
  220. * @psalm-pure
  221. */
  222. public function jsonSerialize()
  223. {
  224. return $this->getValue();
  225. }
  226. }