Overview

Namespaces

  • GAubry
    • Enum

Classes

  • EnumAbstract
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: namespace GAubry\Enum;
  4: 
  5: /**
  6:  * A simple-to-use PHP class that provides the ability to emulate and create type-safe enumerations.
  7:  *
  8:  * Definition:
  9:  * <code>
 10:  *     class ColorEnum extends EnumAbstract {
 11:  *         public static $RED;
 12:  *         public static $GREEN;
 13:  *         public static $BLUE;
 14:  *     }
 15:  * </code>
 16:  *
 17:  * Usage:
 18:  * <code>
 19:  *     // One call per enumeration is necessary and sufficient,
 20:  *     // typically at the top of the program, during instantiation phase:
 21:  *     ColorEnum::buildInstances();
 22:  *
 23:  *     $color = ColorEnum::$RED;
 24:  *     var_dump((string)$color); // string(3) "RED"
 25:  *     var_dump(ColorEnum::$RED === ColorEnum::RED()); // true
 26:  *
 27:  *     function f (ColorEnum $color) {
 28:  *         switch($color) {
 29:  *             case ColorEnum::$RED:
 30:  *             …
 31:  *         }
 32:  *         …
 33:  *     }
 34:  *     f(ColorEnum::$RED);
 35:  * </code>
 36:  *
 37:  *
 38:  *
 39:  * Copyright (c) 2013 Geoffroy Aubry <geoffroy.aubry@free.fr>
 40:  * Licensed under the GNU Lesser General Public License v3 (LGPL version 3).
 41:  *
 42:  * @copyright 2013 Geoffroy Aubry <geoffroy.aubry@free.fr>
 43:  * @license http://www.gnu.org/licenses/lgpl.html
 44:  */
 45: abstract class EnumAbstract
 46: {
 47:     /**
 48:      * Global static counter to ensure that each EnumAbstract instance is unique.
 49:      * @var int
 50:      */
 51:     private static $iCounter = 0;
 52: 
 53:     /**
 54:      * A cache of all enum values to increase performance.
 55:      * Structure: <code>array(
 56:      *     'class' => array(
 57:      *         'key' => EnumAbstract instance,
 58:      *         …
 59:      *     ),
 60:      *     …
 61:      * )</code>
 62:      *
 63:      * @var array
 64:      */
 65:     private static $aCache = array();
 66: 
 67:     /**
 68:      * A unique value to ensure that each EnumAbstract instance is unique.
 69:      * @var int
 70:      * @see self::$iCounter
 71:      */
 72:     private $iValue;
 73: 
 74:     /**
 75:      * Name of enum instance, used by __toString().
 76:      * @var string
 77:      * @see __toString()
 78:      */
 79:     private $sName;
 80: 
 81:     /**
 82:      * Constructor.
 83:      *
 84:      * @param string $sName Name of instance, used by __toString().
 85:      */
 86:     protected function __construct ($sName)
 87:     {
 88:         $this->iValue = self::$iCounter++;
 89:         $this->sName = $sName;
 90:     }
 91: 
 92:     /**
 93:      * Converts all static properties into EnumAbstract instances.
 94:      *
 95:      * @throws \BadMethodCallException if called directly on EnumAbstract instead of derived class
 96:      * @return string
 97:      */
 98:     public static function buildInstances ()
 99:     {
100:         $sClass = get_called_class();
101:         if (empty(self::$aCache[$sClass])) {
102:             if ($sClass == get_class()) {
103:                 $sMsg = 'Method for only purpose of inherited classes!';
104:                 throw new \BadMethodCallException($sMsg, 1);
105:             } else {
106:                 $oReflected = new \ReflectionClass($sClass);
107:                 foreach ($oReflected->getStaticProperties() as $sKey => $mValue) {
108:                     $sName = (empty($mValue) ? $sKey : (string)$mValue);
109:                     $oReflected->setStaticPropertyValue($sKey, new static($sName));
110:                 }
111:                 self::$aCache[$sClass] = $oReflected->getStaticProperties();
112:             }
113:         }
114:         return $sClass;
115:     }
116: 
117:     /**
118:      * Returns an associative array containing all constants in the enum.
119:      *
120:      * @throws \BadMethodCallException if called directly on EnumAbstract instead of derived class
121:      * @return array Associative array (name => instance, …)
122:      */
123:     public static function values()
124:     {
125:         $sClass = self::buildInstances();
126:         return self::$aCache[$sClass];
127:     }
128: 
129:     /**
130:      * Returns the names (or keys) of all of constants in the enum.
131:      *
132:      * @throws \BadMethodCallException if called directly on EnumAbstract instead of derived class
133:      * @return array Array of string
134:      */
135:     public static function keys()
136:     {
137:         return array_keys(self::values());
138:     }
139: 
140:     /**
141:      * Get enum instances with lazy instanciation.
142:      * Triggered when invoking inaccessible methods in a static context.
143:      *
144:      * @SuppressWarnings(UnusedFormalParameter)
145:      * @param string $sName name of the static property
146:      * @param array  $aArgs not used…
147:      * @throws \DomainException if not called on one of the static properties
148:      * @throws \BadMethodCallException if called directly on EnumAbstract instead of derived class
149:      * @return EnumAbstract enum instance with the specified name
150:      */
151:     public static function __callStatic ($sName, $aArgs)
152:     {
153:         $sClass = self::buildInstances();
154:         if (! isset(self::$aCache[$sClass][$sName])) {
155:             $sMsg = "Unknown type '$sName'! Type must be in: "
156:                   . implode(', ', array_keys(self::$aCache[$sClass])) . '.';
157:             throw new \DomainException($sMsg, 1);
158:         }
159:         return self::$aCache[$sClass][$sName];
160:     }
161: 
162:     /**
163:      * Returns the name of the instance.
164:      *
165:      * This magic method is used for setting a string value for the object.
166:      * It will be used if the object is used as a string.
167:      *
168:      * @return string representing the object
169:      */
170:     public function __toString ()
171:     {
172:         return $this->sName;
173:     }
174: 
175:     /**
176:      * Prevent cloning.
177:      *
178:      * @throws \RuntimeException Cloning of this object isn't authorized!
179:      */
180:     final public function __clone()
181:     {
182:         throw new \RuntimeException('Cloning of this object isn\'t authorized!');
183:     }
184: }
185: 
Type-safe PHP Enum API documentation generated by ApiGen 2.8.0