LICENSE000064400000002064144760115210005554 0ustar00The MIT License (MIT) Copyright (c) 2015 My C-Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. README.md000064400000007563144760115210006037 0ustar00# PHP Enum implementation inspired from SplEnum [![Build Status](https://travis-ci.org/myclabs/php-enum.png?branch=master)](https://travis-ci.org/myclabs/php-enum) [![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) [![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) [![psalm](https://shepherd.dev/github/myclabs/php-enum/coverage.svg)](https://shepherd.dev/github/myclabs/php-enum) Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). ## Why? First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately. Using an enum instead of class constants provides the following advantages: - You can type-hint: `function setAction(Action $action) {` - You can enrich the enum with methods (e.g. `format`, `parse`, …) - You can extend the enum to add new values (make your enum `final` to prevent it) - You can get a list of all the possible values (see below) This Enum class is not intended to replace class constants, but only to be used when it makes sense. ## Installation ``` composer require myclabs/php-enum ``` ## Declaration ```php use MyCLabs\Enum\Enum; /** * Action enum */ class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; } ``` ## Usage ```php $action = Action::VIEW(); // or with a dynamic key: $action = Action::$key(); // or with a dynamic value: $action = new Action($value); ``` As you can see, static methods are automatically implemented to provide quick access to an enum value. One advantage over using class constants is to be able to type-hint enum values: ```php function setAction(Action $action) { // ... } ``` ## Documentation - `__construct()` The constructor checks that the value exist in the enum - `__toString()` You can `echo $myValue`, it will display the enum value (value of the constant) - `getValue()` Returns the current value of the enum - `getKey()` Returns the key of the current value on Enum - `equals()` Tests whether enum instances are equal (returns `true` if enum values are equal, `false` otherwise) Static methods: - `toArray()` method Returns all possible values as an array (constant name in key, constant value in value) - `keys()` Returns the names (keys) of all constants in the Enum class - `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value) - `isValid()` Check if tested value is valid on enum set - `isValidKey()` Check if tested key is valid on enum set - `search()` Return key for searched value ### Static methods ```php class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; } // Static method: $action = Action::VIEW(); $action = Action::EDIT(); ``` Static method helpers are implemented using [`__callStatic()`](http://www.php.net/manual/en/language.oop5.overloading.php#object.callstatic). If you care about IDE autocompletion, you can either implement the static methods yourself: ```php class Action extends Enum { private const VIEW = 'view'; /** * @return Action */ public static function VIEW() { return new Action(self::VIEW); } } ``` or you can use phpdoc (this is supported in PhpStorm for example): ```php /** * @method static Action VIEW() * @method static Action EDIT() */ class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; } ``` ## Related projects - [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) - [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) - [PHPStan integration](https://github.com/timeweb/phpstan-enum) SECURITY.md000064400000000427144760115210006341 0ustar00# Security Policy ## Supported Versions Only the latest stable release is supported. ## Reporting a Vulnerability To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. composer.json000064400000001415144760115210007270 0ustar00{ "name": "myclabs/php-enum", "type": "library", "description": "PHP Enum implementation", "keywords": ["enum"], "homepage": "http://github.com/myclabs/php-enum", "license": "MIT", "authors": [ { "name": "PHP Enum contributors", "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" } ], "autoload": { "psr-4": { "MyCLabs\\Enum\\": "src/" } }, "autoload-dev": { "psr-4": { "MyCLabs\\Tests\\Enum\\": "tests/" } }, "require": { "php": ">=7.1", "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^7", "squizlabs/php_codesniffer": "1.*", "vimeo/psalm": "^3.8" } } psalm.xml000064400000001106144760115210006401 0ustar00 src/Enum.php000064400000013210144760115210006746 0ustar00 * @author Daniel Costa * @author Mirosław Filip * * @psalm-template T * @psalm-immutable */ abstract class Enum implements \JsonSerializable { /** * Enum value * * @var mixed * @psalm-var T */ protected $value; /** * Store existing constants in a static cache per object. * * * @var array * @psalm-var array> */ protected static $cache = []; /** * Creates a new value of some type * * @psalm-pure * @param mixed $value * * @psalm-param static|T $value * @throws \UnexpectedValueException if incompatible type is given. */ public function __construct($value) { if ($value instanceof static) { /** @psalm-var T */ $value = $value->getValue(); } if (!$this->isValid($value)) { /** @psalm-suppress InvalidCast */ throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); } /** @psalm-var T */ $this->value = $value; } /** * @psalm-pure * @return mixed * @psalm-return T */ public function getValue() { return $this->value; } /** * Returns the enum key (i.e. the constant name). * * @psalm-pure * @return mixed */ public function getKey() { return static::search($this->value); } /** * @psalm-pure * @psalm-suppress InvalidCast * @return string */ public function __toString() { return (string)$this->value; } /** * Determines if Enum should be considered equal with the variable passed as a parameter. * Returns false if an argument is an object of different class or not an object. * * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 * * @psalm-pure * @psalm-param mixed $variable * @return bool */ final public function equals($variable = null): bool { return $variable instanceof self && $this->getValue() === $variable->getValue() && static::class === \get_class($variable); } /** * Returns the names (keys) of all constants in the Enum class * * @psalm-pure * @psalm-return list * @return array */ public static function keys() { return \array_keys(static::toArray()); } /** * Returns instances of the Enum class of all Enum constants * * @psalm-pure * @psalm-return array * @return static[] Constant name in key, Enum instance in value */ public static function values() { $values = array(); /** @psalm-var T $value */ foreach (static::toArray() as $key => $value) { $values[$key] = new static($value); } return $values; } /** * Returns all possible values as an array * * @psalm-pure * @psalm-suppress ImpureStaticProperty * * @psalm-return array * @return array Constant name in key, constant value in value */ public static function toArray() { $class = static::class; if (!isset(static::$cache[$class])) { $reflection = new \ReflectionClass($class); static::$cache[$class] = $reflection->getConstants(); } return static::$cache[$class]; } /** * Check if is valid enum value * * @param $value * @psalm-param mixed $value * @psalm-pure * @return bool */ public static function isValid($value) { return \in_array($value, static::toArray(), true); } /** * Check if is valid enum key * * @param $key * @psalm-param string $key * @psalm-pure * @return bool */ public static function isValidKey($key) { $array = static::toArray(); return isset($array[$key]) || \array_key_exists($key, $array); } /** * Return key for value * * @param $value * * @psalm-param mixed $value * @psalm-pure * @return mixed */ public static function search($value) { return \array_search($value, static::toArray(), true); } /** * Returns a value when called statically like so: MyEnum::SOME_VALUE() given SOME_VALUE is a class constant * * @param string $name * @param array $arguments * * @return static * @psalm-pure * @throws \BadMethodCallException */ public static function __callStatic($name, $arguments) { $array = static::toArray(); if (isset($array[$name]) || \array_key_exists($name, $array)) { return new static($array[$name]); } throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); } /** * Specify data which should be serialized to JSON. This method returns data that can be serialized by json_encode() * natively. * * @return mixed * @link http://php.net/manual/en/jsonserializable.jsonserialize.php * @psalm-pure */ public function jsonSerialize() { return $this->getValue(); } } src/PHPUnit/Comparator.php000064400000002532144760115210011445 0ustar00register(new \MyCLabs\Enum\PHPUnit\Comparator()); */ final class Comparator extends \SebastianBergmann\Comparator\Comparator { public function accepts($expected, $actual) { return $expected instanceof Enum && ( $actual instanceof Enum || $actual === null ); } /** * @param Enum $expected * @param Enum|null $actual * * @return void */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) { if ($expected->equals($actual)) { return; } throw new ComparisonFailure( $expected, $actual, $this->formatEnum($expected), $this->formatEnum($actual), false, 'Failed asserting that two Enums are equal.' ); } private function formatEnum(Enum $enum = null) { if ($enum === null) { return "null"; } return get_class($enum)."::{$enum->getKey()}()"; } }