Skip to content

Commit f64bf61

Browse files
committed
[OptionsResolver] fix calling resolve from within closure
1 parent 3d0a0c4 commit f64bf61

File tree

2 files changed

+57
-41
lines changed

2 files changed

+57
-41
lines changed

OptionsResolver.php

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,17 @@ class OptionsResolver implements Options, OptionsResolverInterface
145145
* @param string $option The name of the option
146146
* @param mixed $value The default value of the option
147147
*
148-
* @return Options This instance
148+
* @return OptionsResolver This instance
149149
*
150-
* @throws AccessException If the options are resolved already
150+
* @throws AccessException If called from a lazy option or normalizer
151151
*/
152152
public function setDefault($option, $value)
153153
{
154154
// Setting is not possible once resolving starts, because then lazy
155155
// options could manipulate the state of the object, leading to
156156
// inconsistent results.
157157
if ($this->locked) {
158-
throw new AccessException('Default values cannot be set anymore once resolving has begun.');
158+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
159159
}
160160

161161
// If an option is a closure that should be evaluated lazily, store it
@@ -208,9 +208,9 @@ public function setDefault($option, $value)
208208
*
209209
* @param array $defaults The default values to set
210210
*
211-
* @return Options This instance
211+
* @return OptionsResolver This instance
212212
*
213-
* @throws AccessException If the options are resolved already
213+
* @throws AccessException If called from a lazy option or normalizer
214214
*/
215215
public function setDefaults(array $defaults)
216216
{
@@ -241,14 +241,14 @@ public function hasDefault($option)
241241
*
242242
* @param string|string[] $optionNames One or more option names
243243
*
244-
* @return Options This instance
244+
* @return OptionsResolver This instance
245245
*
246-
* @throws AccessException If the options are resolved already
246+
* @throws AccessException If called from a lazy option or normalizer
247247
*/
248248
public function setRequired($optionNames)
249249
{
250250
if ($this->locked) {
251-
throw new AccessException('Options cannot be made required anymore once resolving has begun.');
251+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
252252
}
253253

254254
foreach ((array) $optionNames as $key => $option) {
@@ -322,14 +322,14 @@ public function getMissingOptions()
322322
*
323323
* @param string|string[] $optionNames One or more option names
324324
*
325-
* @return Options This instance
325+
* @return OptionsResolver This instance
326326
*
327-
* @throws AccessException If the options are resolved already
327+
* @throws AccessException If called from a lazy option or normalizer
328328
*/
329329
public function setDefined($optionNames)
330330
{
331331
if ($this->locked) {
332-
throw new AccessException('Options cannot be defined anymore once resolving has begun.');
332+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
333333
}
334334

335335
foreach ((array) $optionNames as $key => $option) {
@@ -389,15 +389,15 @@ public function getDefinedOptions()
389389
* @param string $option The option name
390390
* @param \Closure $normalizer The normalizer
391391
*
392-
* @return Options This instance
392+
* @return OptionsResolver This instance
393393
*
394-
* @throws AccessException If the options are resolved already
395394
* @throws UndefinedOptionsException If the option is undefined
395+
* @throws AccessException If called from a lazy option or normalizer
396396
*/
397397
public function setNormalizer($option, \Closure $normalizer)
398398
{
399399
if ($this->locked) {
400-
throw new AccessException('Normalizers cannot be added anymore once resolving has begun.');
400+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
401401
}
402402

403403
if (!isset($this->defined[$option])) {
@@ -444,16 +444,15 @@ public function setNormalizers(array $normalizers)
444444
* @param string $option The option name
445445
* @param mixed $allowedValues One or more acceptable values/closures
446446
*
447+
* @return OptionsResolver This instance
447448
*
448-
* @return Options This instance
449-
*
450-
* @throws AccessException If the options are resolved already
451-
* @throws UndefinedOptionsException If an option is undefined
449+
* @throws UndefinedOptionsException If the option is undefined
450+
* @throws AccessException If called from a lazy option or normalizer
452451
*/
453452
public function setAllowedValues($option, $allowedValues = null)
454453
{
455454
if ($this->locked) {
456-
throw new AccessException('Allowed values cannot be set anymore once resolving has begun.');
455+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
457456
}
458457

459458
// BC
@@ -499,15 +498,15 @@ public function setAllowedValues($option, $allowedValues = null)
499498
* @param string $option The option name
500499
* @param mixed $allowedValues One or more acceptable values/closures
501500
*
502-
* @return Options This instance
501+
* @return OptionsResolver This instance
503502
*
504-
* @throws AccessException If the options are resolved already
505-
* @throws UndefinedOptionsException If an option is undefined
503+
* @throws UndefinedOptionsException If the option is undefined
504+
* @throws AccessException If called from a lazy option or normalizer
506505
*/
507506
public function addAllowedValues($option, $allowedValues = null)
508507
{
509508
if ($this->locked) {
510-
throw new AccessException('Allowed values cannot be added anymore once resolving has begun.');
509+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
511510
}
512511

513512
// BC
@@ -551,15 +550,15 @@ public function addAllowedValues($option, $allowedValues = null)
551550
* @param string $option The option name
552551
* @param string|string[] $allowedTypes One or more accepted types
553552
*
554-
* @return Options This instance
553+
* @return OptionsResolver This instance
555554
*
556-
* @throws AccessException If the options are resolved already
557-
* @throws UndefinedOptionsException If an option is undefined
555+
* @throws UndefinedOptionsException If the option is undefined
556+
* @throws AccessException If called from a lazy option or normalizer
558557
*/
559558
public function setAllowedTypes($option, $allowedTypes = null)
560559
{
561560
if ($this->locked) {
562-
throw new AccessException('Allowed types cannot be set anymore once resolving has begun.');
561+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
563562
}
564563

565564
// BC
@@ -599,15 +598,15 @@ public function setAllowedTypes($option, $allowedTypes = null)
599598
* @param string $option The option name
600599
* @param string|string[] $allowedTypes One or more accepted types
601600
*
602-
* @return Options This instance
601+
* @return OptionsResolver This instance
603602
*
604-
* @throws AccessException If the options are resolved already
605-
* @throws UndefinedOptionsException If an option is undefined
603+
* @throws UndefinedOptionsException If the option is undefined
604+
* @throws AccessException If called from a lazy option or normalizer
606605
*/
607606
public function addAllowedTypes($option, $allowedTypes = null)
608607
{
609608
if ($this->locked) {
610-
throw new AccessException('Allowed types cannot be added anymore once resolving has begun.');
609+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
611610
}
612611

613612
// BC
@@ -646,14 +645,14 @@ public function addAllowedTypes($option, $allowedTypes = null)
646645
*
647646
* @param string|string[] $optionNames One or more option names
648647
*
649-
* @return Options This instance
648+
* @return OptionsResolver This instance
650649
*
651-
* @throws AccessException If the options are resolved already
650+
* @throws AccessException If called from a lazy option or normalizer
652651
*/
653652
public function remove($optionNames)
654653
{
655654
if ($this->locked) {
656-
throw new AccessException('Options cannot be removed anymore once resolving has begun.');
655+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
657656
}
658657

659658
foreach ((array) $optionNames as $option) {
@@ -673,14 +672,14 @@ public function remove($optionNames)
673672
/**
674673
* Removes all options.
675674
*
676-
* @return Options This instance
675+
* @return OptionsResolver This instance
677676
*
678-
* @throws AccessException If the options are resolved already
677+
* @throws AccessException If called from a lazy option or normalizer
679678
*/
680679
public function clear()
681680
{
682681
if ($this->locked) {
683-
throw new AccessException('Options cannot be cleared anymore once resolving has begun.');
682+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
684683
}
685684

686685
$this->defined = array();
@@ -714,11 +713,16 @@ public function clear()
714713
* @throws InvalidOptionsException If an option doesn't fulfill the
715714
* specified validation rules
716715
* @throws MissingOptionsException If a required option is missing
717-
* @throws OptionDefinitionException If a cyclic dependency is depended
718-
* between lazy options and/or normalizers
716+
* @throws OptionDefinitionException If there is a cyclic dependency between
717+
* lazy options and/or normalizers
718+
* @throws AccessException If called from a lazy option or normalizer
719719
*/
720720
public function resolve(array $options = array())
721721
{
722+
if ($this->locked) {
723+
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
724+
}
725+
722726
// Allow this method to be called multiple times
723727
$clone = clone $this;
724728

@@ -778,8 +782,8 @@ public function resolve(array $options = array())
778782
* @throws \OutOfBoundsException If the option is not set
779783
* @throws InvalidOptionsException If an option doesn't fulfill the
780784
* specified validation rules
781-
* @throws OptionDefinitionException If a cyclic dependency is detected
782-
* between two lazily evaluated options
785+
* @throws OptionDefinitionException If there is a cyclic dependency between
786+
* lazy options and/or normalizers
783787
*/
784788
public function offsetGet($option)
785789
{

Tests/OptionsResolver2Dot6Test.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,18 @@ public function testResolveFailsIfNonExistingOption()
4141
$resolver->resolve(array('foo' => 'bar'));
4242
}
4343

44+
/**
45+
* @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
46+
*/
47+
public function testResolveFailsFromLazyOption()
48+
{
49+
$this->resolver->setDefault('foo', function (Options $options) {
50+
$options->resolve(array());
51+
});
52+
53+
$this->resolver->resolve();
54+
}
55+
4456
////////////////////////////////////////////////////////////////////////////
4557
// setDefault()/hasDefault()
4658
////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)