[TASK] Removes extra empty lines
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Type / Enumeration.php
1 <?php
2 namespace TYPO3\CMS\Core\Type;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Abstract class for Enumeration.
19 * Inspired by SplEnum.
20 *
21 * The prefix "Abstract" has been left out by intention because
22 * a "type" is abstract by definition.
23 */
24 abstract class Enumeration implements TypeInterface
25 {
26 /**
27 * @var mixed
28 */
29 protected $value;
30
31 /**
32 * @var array
33 */
34 protected static $enumConstants;
35
36 /**
37 * @param mixed $value
38 * @throws Exception\InvalidEnumerationValueException
39 */
40 public function __construct($value = null)
41 {
42 if ($value === null && !defined('static::__default')) {
43 throw new Exception\InvalidEnumerationValueException(
44 sprintf('A value for %s is required if no __default is defined.', get_class($this)),
45 1381512753
46 );
47 }
48 if ($value === null) {
49 $value = static::__default;
50 }
51 static::loadValues();
52 if (!$this->isValid($value)) {
53 throw new Exception\InvalidEnumerationValueException(
54 sprintf('Invalid value %s for %s', $value, get_class($this)),
55 1381512761
56 );
57 }
58 $this->setValue($value);
59 }
60
61 /**
62 * @throws Exception\InvalidEnumerationValueException
63 * @throws Exception\InvalidEnumerationDefinitionException
64 * @internal param string $class
65 */
66 protected static function loadValues()
67 {
68 $class = get_called_class();
69
70 if (isset(static::$enumConstants[$class])) {
71 return;
72 }
73
74 $reflection = new \ReflectionClass($class);
75 $constants = $reflection->getConstants();
76 $defaultValue = null;
77 if (isset($constants['__default'])) {
78 $defaultValue = $constants['__default'];
79 unset($constants['__default']);
80 }
81 if (empty($constants)) {
82 throw new Exception\InvalidEnumerationValueException(
83 sprintf(
84 'No enumeration constants defined for "%s"', $class
85 ),
86 1381512807
87 );
88 }
89 foreach ($constants as $constant => $value) {
90 if (!is_int($value) && !is_string($value)) {
91 throw new Exception\InvalidEnumerationDefinitionException(
92 sprintf(
93 'Constant value must be of type integer or string; constant=%s; type=%s',
94 $constant,
95 is_object($value) ? get_class($value) : gettype($value)
96 ),
97 1381512797
98 );
99 }
100 }
101 $constantValueCounts = array_count_values($constants);
102 arsort($constantValueCounts, SORT_NUMERIC);
103 $constantValueCount = current($constantValueCounts);
104 $constant = key($constantValueCounts);
105 if ($constantValueCount > 1) {
106 throw new Exception\InvalidEnumerationDefinitionException(
107 sprintf(
108 'Constant value is not unique; constant=%s; value=%s; enum=%s',
109 $constant, $constantValueCount, $class
110 ),
111 1381512859
112 );
113 }
114 if ($defaultValue !== null) {
115 $constants['__default'] = $defaultValue;
116 }
117 static::$enumConstants[$class] = $constants;
118 }
119
120 /**
121 * Set the Enumeration value to the associated enumeration value by a loose comparison.
122 * The value, that is used as the enumeration value, will be of the same type like defined in the enumeration
123 *
124 * @param mixed $value
125 * @throws Exception\InvalidEnumerationValueException
126 */
127 protected function setValue($value)
128 {
129 $enumKey = array_search($value, static::$enumConstants[get_class($this)]);
130 if ($enumKey === false) {
131 throw new Exception\InvalidEnumerationValueException(
132 sprintf('Invalid value %s for %s', $value, __CLASS__),
133 1381615295
134 );
135 }
136 $this->value = static::$enumConstants[get_class($this)][$enumKey];
137 }
138
139 /**
140 * Check if the value on this enum is a valid value for the enum
141 *
142 * @param mixed $value
143 * @return bool
144 */
145 protected function isValid($value)
146 {
147 $value = (string)$value;
148 foreach (static::$enumConstants[get_class($this)] as $constantValue) {
149 if ($value === (string)$constantValue) {
150 return true;
151 }
152 }
153 return false;
154 }
155
156 /**
157 * Get the valid values for this enum
158 * Defaults to constants you define in your subclass
159 * override to provide custom functionality
160 *
161 * @param bool $include_default
162 * @return array
163 */
164 public static function getConstants($include_default = false)
165 {
166 static::loadValues();
167 $enumConstants = static::$enumConstants[get_called_class()];
168 if (!$include_default) {
169 unset($enumConstants['__default']);
170 }
171 return $enumConstants;
172 }
173
174 /**
175 * Cast value to enumeration type
176 *
177 * @param mixed $value Value that has to be casted
178 * @return Enumeration
179 */
180 public static function cast($value)
181 {
182 $currentClass = get_called_class();
183 if (!is_object($value) || get_class($value) !== $currentClass) {
184 $value = new $currentClass($value);
185 }
186 return $value;
187 }
188
189 /**
190 * Compare if the value of the current object value equals the given value
191 *
192 * @param mixed $value default
193 * @return bool
194 */
195 public function equals($value)
196 {
197 $value = static::cast($value);
198 return $this == $value;
199 }
200
201 /**
202 * @return string
203 */
204 public function __toString()
205 {
206 return (string)$this->value;
207 }
208 }