21
21
class Options implements \ArrayAccess, \Iterator, \Countable
22
22
{
23
23
/**
24
- * A list of option values and LazyOption instances .
24
+ * A list of option values.
25
25
* @var array
26
26
*/
27
27
private $ options = array ();
@@ -33,19 +33,13 @@ class Options implements \ArrayAccess, \Iterator, \Countable
33
33
private $ normalizers = array ();
34
34
35
35
/**
36
- * A list storing the names of all options that need to be normalized.
37
- * @var array
38
- */
39
- private $ normalization = array ();
40
-
41
- /**
42
- * A list storing the names of all LazyOption instances as keys.
36
+ * A list of closures for evaluating lazy options.
43
37
* @var array
44
38
*/
45
39
private $ lazy = array ();
46
40
47
41
/**
48
- * A list of Boolean locks for each LazyOption .
42
+ * A list containing the currently locked options .
49
43
* @var array
50
44
*/
51
45
private $ lock = array ();
@@ -95,6 +89,7 @@ public function set($option, $value)
95
89
// Setting is equivalent to overloading while discarding the previous
96
90
// option value
97
91
unset($ this ->options [$ option ]);
92
+ unset($ this ->lazy [$ option ]);
98
93
99
94
$ this ->overload ($ option , $ value );
100
95
}
@@ -126,9 +121,6 @@ public function setNormalizer($option, \Closure $normalizer)
126
121
}
127
122
128
123
$ this ->normalizers [$ option ] = $ normalizer ;
129
-
130
- // Each option for which a normalizer exists needs to be normalized
131
- $ this ->normalization [$ option ] = true ;
132
124
}
133
125
134
126
/**
@@ -150,6 +142,7 @@ public function replace(array $options)
150
142
}
151
143
152
144
$ this ->options = array ();
145
+ $ this ->lazy = array ();
153
146
154
147
foreach ($ options as $ option => $ value ) {
155
148
$ this ->overload ($ option , $ value );
@@ -184,25 +177,30 @@ public function overload($option, $value)
184
177
}
185
178
186
179
// If an option is a closure that should be evaluated lazily, store it
187
- // inside a LazyOption instance .
180
+ // in the "lazy" property .
188
181
if ($ value instanceof \Closure) {
189
182
$ reflClosure = new \ReflectionFunction ($ value );
190
183
$ params = $ reflClosure ->getParameters ();
191
184
192
185
if (isset ($ params [0 ]) && null !== ($ class = $ params [0 ]->getClass ()) && __CLASS__ === $ class ->name ) {
193
- $ currentValue = isset ($ params [1 ]) && isset ($ this ->options [$ option ]) ? $ this ->options [$ option ] : null ;
194
- $ value = new LazyOption ($ value , $ currentValue );
186
+ // Initialize the option if no previous value exists
187
+ if (!isset ($ this ->options [$ option ])) {
188
+ $ this ->options [$ option ] = null ;
189
+ }
195
190
196
- // Store which options are lazy for more efficient resolving
197
- $ this ->lazy [$ option ] = true ;
191
+ // Ignore previous lazy options if the closure has no second parameter
192
+ if (!isset ($ this ->lazy [$ option ]) || !isset ($ params [1 ])) {
193
+ $ this ->lazy [$ option ] = array ();
194
+ }
198
195
199
- $ this ->options [$ option ] = $ value ;
196
+ // Store closure for later evaluation
197
+ $ this ->lazy [$ option ][] = $ value ;
200
198
201
199
return ;
202
200
}
203
201
}
204
202
205
- // Reset lazy flag and locks by default
203
+ // Remove lazy options by default
206
204
unset($ this ->lazy [$ option ]);
207
205
208
206
$ this ->options [$ option ] = $ value ;
@@ -233,7 +231,7 @@ public function get($option)
233
231
$ this ->resolve ($ option );
234
232
}
235
233
236
- if (isset ($ this ->normalization [$ option ])) {
234
+ if (isset ($ this ->normalizers [$ option ])) {
237
235
$ this ->normalize ($ option );
238
236
}
239
237
@@ -269,6 +267,7 @@ public function remove($option)
269
267
270
268
unset($ this ->options [$ option ]);
271
269
unset($ this ->lazy [$ option ]);
270
+ unset($ this ->normalizers [$ option ]);
272
271
}
273
272
274
273
/**
@@ -286,6 +285,7 @@ public function clear()
286
285
287
286
$ this ->options = array ();
288
287
$ this ->lazy = array ();
288
+ $ this ->normalizers = array ();
289
289
}
290
290
291
291
/**
@@ -301,14 +301,16 @@ public function all()
301
301
302
302
// Performance-wise this is slightly better than
303
303
// while (null !== $option = key($this->lazy))
304
- foreach ($ this ->lazy as $ option => $ isLazy ) {
304
+ foreach ($ this ->lazy as $ option => $ closures ) {
305
+ // Double check, in case the option has already been resolved
306
+ // by cascade in the previous cycles
305
307
if (isset ($ this ->lazy [$ option ])) {
306
308
$ this ->resolve ($ option );
307
309
}
308
310
}
309
311
310
- foreach ($ this ->normalization as $ option => $ normalize ) {
311
- if (isset ($ this ->normalization [$ option ])) {
312
+ foreach ($ this ->normalizers as $ option => $ normalizer ) {
313
+ if (isset ($ this ->normalizers [$ option ])) {
312
314
$ this ->normalize ($ option );
313
315
}
314
316
}
@@ -443,6 +445,10 @@ public function count()
443
445
*/
444
446
private function resolve ($ option )
445
447
{
448
+ // The code duplication with normalize() exists for performance
449
+ // reasons, in order to save a method call.
450
+ // Remember that this method is potentially called a couple of thousand
451
+ // times and needs to be as efficient as possible.
446
452
if (isset ($ this ->lock [$ option ])) {
447
453
$ conflicts = array ();
448
454
@@ -456,7 +462,9 @@ private function resolve($option)
456
462
}
457
463
458
464
$ this ->lock [$ option ] = true ;
459
- $ this ->options [$ option ] = $ this ->options [$ option ]->evaluate ($ this );
465
+ foreach ($ this ->lazy [$ option ] as $ closure ) {
466
+ $ this ->options [$ option ] = $ closure ($ this , $ this ->options [$ option ]);
467
+ }
460
468
unset($ this ->lock [$ option ]);
461
469
462
470
// The option now isn't lazy anymore
@@ -475,6 +483,10 @@ private function resolve($option)
475
483
*/
476
484
private function normalize ($ option )
477
485
{
486
+ // The code duplication with resolve() exists for performance
487
+ // reasons, in order to save a method call.
488
+ // Remember that this method is potentially called a couple of thousand
489
+ // times and needs to be as efficient as possible.
478
490
if (isset ($ this ->lock [$ option ])) {
479
491
$ conflicts = array ();
480
492
@@ -495,6 +507,6 @@ private function normalize($option)
495
507
unset($ this ->lock [$ option ]);
496
508
497
509
// The option is now normalized
498
- unset($ this ->normalization [$ option ]);
510
+ unset($ this ->normalizers [$ option ]);
499
511
}
500
512
}
0 commit comments