1fd7fb1f7bbd967f50cb31e9f65c204af9584943
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Type / Enumeration.php
1 <?php
2 namespace TYPO3\CMS\Core\Type;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Thomas Maroschik <tmaroschik@dfau.de>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 /**
31 * Abstract class for Enumeration.
32 * Inspired by SplEnum.
33 *
34 * The prefix "Abstract" has been left out by intention because
35 * a "type" is abstract by definition.
36 */
37 abstract class Enumeration {
38
39 /**
40 * @var string
41 */
42 protected $value;
43
44 /**
45 * @var array
46 */
47 protected static $enumConstants;
48
49 /**
50 * @param mixed $value
51 * @throws \DomainException
52 * @throws \UnexpectedValueException
53 */
54 public function __construct($value = NULL) {
55 if (!defined('static::__default')) {
56 throw new \DomainException(sprintf("Required constant __default for Enum %s is not defined", __CLASS__), 1381512753);
57 }
58 if ($value === NULL) {
59 $value = static::__default;
60 }
61 $this->loadValues();
62 if (!$this->isValid($value)) {
63 throw new \UnexpectedValueException(sprintf("Invalid enumeration %s for Enum %s", $value, __CLASS__), 1381512761);
64 }
65 $this->setValue($value);
66 }
67
68 /**
69 * @throws \Exception
70 * @internal param string $class
71 */
72 protected function loadValues() {
73 $class = get_called_class();
74
75 if (isset(static::$enumConstants[$class])) {
76 return;
77 }
78
79 $reflection = new \ReflectionClass($class);
80 $constants = $reflection->getConstants();
81 if (isset($constants['__default'])) {
82 unset($constants['__default']);
83 }
84 if (empty($constants)) {
85 throw new \Exception(
86 sprintf(
87 'No enumeration constants defined for "%s"', $class
88 ),
89 1381512807
90 );
91 }
92 foreach ($constants as $constant => $value) {
93 if (!is_int($value) && !is_string($value)) {
94 throw new \Exception(
95 sprintf(
96 'Constant value must be of type integer or string; constant=%s; type=%s',
97 $constant,
98 is_object($value) ? get_class($value) : gettype($value)
99 ),
100 1381512797
101 );
102 }
103 }
104 $constantValueCounts = array_count_values($constants);
105 arsort($constantValueCounts, SORT_NUMERIC);
106 $constantValueCount = current($constantValueCounts);
107 $constant = key($constantValueCounts);
108 if ($constantValueCount > 1) {
109 throw new \Exception(
110 sprintf(
111 'Constant value is not unique; constant=%s; value=%s; enum=%s',
112 $constant, $constantValueCount, $class
113 ),
114 1381512859
115 );
116 }
117 static::$enumConstants[$class] = $constants;
118 }
119
120 /**
121 * @param mixed $value
122 */
123 protected function setValue($value) {
124 $this->value = $value;
125 }
126
127 /**
128 * Check if the value on this enum is a valid value for the enum
129 *
130 * @param mixed $value
131 * @return boolean
132 */
133 protected function isValid($value) {
134 return in_array($value, static::$enumConstants[get_called_class()]);
135 }
136
137 /**
138 * Get the valid values for this enum
139 * Defaults to constants you define in your subclass
140 * override to provide custom functionality
141 *
142 * @param boolean $include_default
143 * @return array
144 */
145 public function getConstants($include_default = FALSE) {
146 $enumConstants = static::$enumConstants[get_called_class()];
147 if (!$include_default) {
148 unset($enumConstants['__default']);
149 }
150 return $enumConstants;
151 }
152
153 /**
154 * Compare if the value of the current object value equals the given value
155 *
156 * @param mixed $value default
157 * @return boolean
158 */
159 public function equals($value) {
160 $currentClass = get_class($this);
161 if (!is_object($value) || get_class($value) !== $currentClass) {
162 $value = new $currentClass($value);
163 }
164 return $this === $value;
165 }
166
167 /**
168 * @return string
169 */
170 public function __toString() {
171 return (string)$this->value;
172 }
173 }