10
10
* After using this Trait, the class can define public static "factory" methods to define its instances.
11
11
*
12
12
* For example, here is a very simple implementation:
13
- * ```
13
+ * ```php
14
14
* class FooBarEnum implements EnumInterface
15
15
* {
16
16
* use EnumTrait;
@@ -72,7 +72,7 @@ trait EnumTrait /* implements EnumInterface */
72
72
{
73
73
private static $ instancesById ;
74
74
75
- /** @var array */
75
+ /** @var int[] */
76
76
private static $ allInstancesInitialized = [];
77
77
78
78
/**
@@ -99,14 +99,30 @@ final protected static function define(string $id, ...$constructorArguments)
99
99
return self ::$ instancesById [static ::class][$ id ];
100
100
}
101
101
102
+ /**
103
+ * This method is called the first time it's needed.
104
+ * It should call `define` for each instance to be created.
105
+ *
106
+ * The default behavior is to call every public factory method in the class, with
107
+ * the expectation that those methods will call `define`. Override this method to provide
108
+ * different behavior, for instance loading instances parametrically from an array or file.
109
+ *
110
+ * If you override this method, the class must be final, because child classes won't be able
111
+ * to add instances.
112
+ */
113
+ protected static function defineInstances (): void
114
+ {
115
+ call_all_public_nullary_factory_methods (static ::class);
116
+ }
117
+
102
118
/**
103
119
* @param string $id
104
120
* @param bool $throwIfNotFound
105
121
* @return null|$this
106
122
*/
107
123
final public static function instance (string $ id , bool $ throwIfNotFound = false )
108
124
{
109
- static ::_ensureAllInstancesInitialized (static ::class );
125
+ static ::_ensureAllInstancesInitialized ();
110
126
111
127
if (isset (self ::$ instancesById [static ::class][$ id ])) {
112
128
return self ::$ instancesById [static ::class][$ id ];
@@ -124,42 +140,39 @@ final public static function instance(string $id, bool $throwIfNotFound = false)
124
140
*/
125
141
final public static function instances (): array
126
142
{
127
- static ::_ensureAllInstancesInitialized (static ::class );
143
+ static ::_ensureAllInstancesInitialized ();
128
144
129
145
return array_values (self ::$ instancesById [static ::class]);
130
146
}
131
147
132
148
final public function getId (): string
133
149
{
134
- static ::_ensureAllInstancesInitialized (static ::class );
150
+ static ::_ensureAllInstancesInitialized ();
135
151
136
- foreach (self ::$ instancesById [static ::class] as $ id => $ instance ) {
137
- if ($ instance === $ this ) {
138
- return $ id ;
139
- }
140
- }
141
-
142
- return null ;
152
+ return array_search ($ this , self ::$ instancesById [static ::class], true );
143
153
}
144
154
145
- private static function _ensureAllInstancesInitialized (string $ class ): void
155
+ private static function _ensureAllInstancesInitialized (): void
146
156
{
147
- if (!isset (self ::$ allInstancesInitialized [$ class ])) {
148
- initialize_all_enum_instances ($ class );
149
- self ::$ allInstancesInitialized [$ class ] = true ;
157
+ static $ _isInitializing ;
158
+ if (!$ _isInitializing && !isset (self ::$ allInstancesInitialized [static ::class])) {
159
+ $ _isInitializing = true ;
160
+ static ::defineInstances ();
161
+ $ _isInitializing = false ;
162
+ self ::$ allInstancesInitialized [static ::class] = true ;
150
163
}
151
164
}
152
165
}
153
166
154
- function initialize_all_enum_instances (string $ enumClass ): void
167
+ function call_all_public_nullary_factory_methods (string $ enumClass ): void
155
168
{
156
169
try {
157
170
$ reflectionClass = new \ReflectionClass ($ enumClass );
158
171
159
172
/** @var \ReflectionMethod[] $factoryMethods */
160
173
$ factoryMethods = array_filter (
161
174
$ reflectionClass ->getMethods (),
162
- 'SolidPhp\ValueObjects\Enum\is_enum_factory_method '
175
+ 'SolidPhp\ValueObjects\Enum\is_public_nullary_factory_method '
163
176
);
164
177
foreach ($ factoryMethods as $ method ) {
165
178
$ method ->invoke (null );
@@ -169,7 +182,7 @@ function initialize_all_enum_instances(string $enumClass): void
169
182
}
170
183
}
171
184
172
- function is_enum_factory_method (\ReflectionMethod $ method ): bool
185
+ function is_public_nullary_factory_method (\ReflectionMethod $ method ): bool
173
186
{
174
187
return $ method ->isPublic ()
175
188
&& $ method ->isStatic ()
0 commit comments