Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6c191b7

Browse files
committed
Trigger deprecation only if the option is used
1 parent 23279c7 commit 6c191b7

File tree

3 files changed

+112
-30
lines changed

3 files changed

+112
-30
lines changed

src/Symfony/Component/OptionsResolver/Options.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*
1717
* @author Bernhard Schussek <[email protected]>
1818
* @author Tobias Schultze <http://tobion.de>
19+
*
20+
* @method mixed offsetGet(string $option, bool $triggerDeprecation = true)
1921
*/
2022
interface Options extends \ArrayAccess, \Countable
2123
{

src/Symfony/Component/OptionsResolver/OptionsResolver.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -766,13 +766,6 @@ public function resolve(array $options = array())
766766
// Lock the container
767767
$clone->locked = true;
768768

769-
if ($clone->defaults && $clone->deprecated) {
770-
// Deprecated options must be evaluated last
771-
uksort($clone->defaults, function ($option) use ($clone): int {
772-
return (int) isset($clone->deprecated[$option]);
773-
});
774-
}
775-
776769
// Now process the individual options. Use offsetGet(), which resolves
777770
// the option itself and any options that the option depends on
778771
foreach ($clone->defaults as $option => $_) {
@@ -797,14 +790,20 @@ public function resolve(array $options = array())
797790
* @throws OptionDefinitionException If there is a cyclic dependency between
798791
* lazy options and/or normalizers
799792
*/
800-
public function offsetGet($option)
793+
public function offsetGet($option/*, bool $triggerDeprecation = true*/)
801794
{
802795
if (!$this->locked) {
803796
throw new AccessException('Array access is only supported within closures of lazy options and normalizers.');
804797
}
805798

799+
$triggerDeprecation = 1 === \func_num_args() || \func_get_arg(1);
800+
806801
// Shortcut for resolved options
807802
if (array_key_exists($option, $this->resolved)) {
803+
if ($triggerDeprecation && isset($this->deprecated[$option]) && \is_string($this->deprecated[$option])) {
804+
@trigger_error(strtr($this->deprecated[$option], array('%name%' => $option)), E_USER_DEPRECATED);
805+
}
806+
808807
return $this->resolved[$option];
809808
}
810809

@@ -934,7 +933,7 @@ public function offsetGet($option)
934933

935934
// Check whether the option is deprecated
936935
// and it is provided by the user or is being called from a lazy evaluation
937-
if (isset($this->deprecated[$option]) && (isset($this->given[$option]) || $this->calling)) {
936+
if ($triggerDeprecation && isset($this->deprecated[$option]) && (isset($this->given[$option]) || $this->calling)) {
938937
$deprecationMessage = $this->deprecated[$option];
939938

940939
if ($deprecationMessage instanceof \Closure) {

src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php

Lines changed: 102 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ public function testLazyDeprecationFailsIfInvalidDeprecationMessageType()
501501

502502
/**
503503
* @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
504-
* @expectedExceptionMessage The options "bar", "foo" have a cyclic dependency.
504+
* @expectedExceptionMessage The options "foo", "bar" have a cyclic dependency.
505505
*/
506506
public function testFailsIfCyclicDependencyBetweenDeprecation()
507507
{
@@ -538,10 +538,15 @@ public function testIsNotDeprecatedIfEmptyString()
538538
/**
539539
* @dataProvider provideDeprecationData
540540
*/
541-
public function testDeprecationMessages(\Closure $configureOptions, array $options, ?array $expectedError)
541+
public function testDeprecationMessages(\Closure $configureOptions, array $options, ?array $expectedError, int $expectedCount)
542542
{
543+
$count = 0;
543544
error_clear_last();
544-
set_error_handler(function () { return false; });
545+
set_error_handler(function () use (&$count) {
546+
++$count;
547+
548+
return false;
549+
});
545550
$e = error_reporting(0);
546551

547552
$configureOptions($this->resolver);
@@ -554,6 +559,7 @@ public function testDeprecationMessages(\Closure $configureOptions, array $optio
554559
unset($lastError['file'], $lastError['line']);
555560

556561
$this->assertSame($expectedError, $lastError);
562+
$this->assertSame($expectedCount, $count);
557563
}
558564

559565
public function provideDeprecationData()
@@ -570,6 +576,7 @@ function (OptionsResolver $resolver) {
570576
'type' => E_USER_DEPRECATED,
571577
'message' => 'The option "foo" is deprecated.',
572578
),
579+
1,
573580
);
574581

575582
yield 'It deprecates an option with custom message' => array(
@@ -587,17 +594,7 @@ function (OptionsResolver $resolver) {
587594
'type' => E_USER_DEPRECATED,
588595
'message' => 'The option "foo" is deprecated, use "bar" option instead.',
589596
),
590-
);
591-
592-
yield 'It does not deprecates a missing option with default value' => array(
593-
function (OptionsResolver $resolver) {
594-
$resolver
595-
->setDefault('foo', null)
596-
->setDeprecated('foo')
597-
;
598-
},
599-
array(),
600-
null,
597+
2,
601598
);
602599

603600
yield 'It deprecates an option evaluated in another definition' => array(
@@ -609,14 +606,15 @@ function (OptionsResolver $resolver) {
609606
;
610607
// defined by subclass
611608
$resolver->setDefault('bar', function (Options $options) {
612-
return $options['foo'];
609+
return $options['foo']; // It triggers a deprecation
613610
});
614611
},
615612
array(),
616613
array(
617614
'type' => E_USER_DEPRECATED,
618615
'message' => 'The option "foo" is deprecated.',
619616
),
617+
1,
620618
);
621619

622620
yield 'It deprecates allowed type and value' => array(
@@ -638,20 +636,46 @@ function (OptionsResolver $resolver) {
638636
'type' => E_USER_DEPRECATED,
639637
'message' => 'Passing an instance of "stdClass" to option "foo" is deprecated, pass its FQCN instead.',
640638
),
639+
1,
641640
);
642641

643-
yield 'It ignores deprecation for missing option without default value' => array(
642+
yield 'It triggers a deprecation based on the value only if option is provided by the user' => array(
644643
function (OptionsResolver $resolver) {
645644
$resolver
646-
->setDefined(array('foo', 'bar'))
647-
->setDeprecated('foo')
645+
->setDefined('foo')
646+
->setAllowedTypes('foo', array('null', 'bool'))
647+
->setDeprecated('foo', function (Options $options, $value) {
648+
if (!\is_bool($value)) {
649+
return 'Passing a value different than true or false is deprecated.';
650+
}
651+
652+
return '';
653+
})
654+
->setDefault('baz', null)
655+
->setAllowedTypes('baz', array('null', 'int'))
656+
->setDeprecated('baz', function (Options $options, $value) {
657+
if (!\is_int($value)) {
658+
return 'Not passing an integer is deprecated.';
659+
}
660+
661+
return '';
662+
})
663+
->setDefault('bar', function (Options $options) {
664+
$options['baz']; // It does not triggers a deprecation
665+
666+
return $options['foo']; // It does not triggers a deprecation
667+
})
648668
;
649669
},
650-
array('bar' => 'baz'),
651-
null,
670+
array('foo' => null), // It triggers a deprecation
671+
array(
672+
'type' => E_USER_DEPRECATED,
673+
'message' => 'Passing a value different than true or false is deprecated.',
674+
),
675+
1,
652676
);
653677

654-
yield 'It ignores deprecation if closure returns an empty string' => array(
678+
yield 'It ignores a deprecation if closure returns an empty string' => array(
655679
function (OptionsResolver $resolver) {
656680
$resolver
657681
->setDefault('foo', null)
@@ -662,6 +686,7 @@ function (OptionsResolver $resolver) {
662686
},
663687
array('foo' => Bar::class),
664688
null,
689+
0,
665690
);
666691

667692
yield 'It deprecates value depending on other option value' => array(
@@ -683,6 +708,62 @@ function (OptionsResolver $resolver) {
683708
'type' => E_USER_DEPRECATED,
684709
'message' => 'Using the "date_format" option when the "widget" option is set to "single_text" is deprecated.',
685710
),
711+
1,
712+
);
713+
714+
yield 'It triggers a deprecation for each evaluation' => array(
715+
function (OptionsResolver $resolver) {
716+
$resolver
717+
// defined by superclass
718+
->setDefined('foo')
719+
->setDeprecated('foo')
720+
// defined by subclass
721+
->setDefault('bar', function (Options $options) {
722+
return $options['foo']; // It triggers a deprecation
723+
})
724+
->setNormalizer('bar', function (Options $options, $value) {
725+
$options['foo']; // It triggers a deprecation
726+
$options['foo']; // It triggers a deprecation
727+
728+
return $value;
729+
})
730+
;
731+
},
732+
array('foo' => 'baz'), // It triggers a deprecation
733+
array(
734+
'type' => E_USER_DEPRECATED,
735+
'message' => 'The option "foo" is deprecated.',
736+
),
737+
4,
738+
);
739+
740+
yield 'It ignores a deprecation if no option is provided by the user' => array(
741+
function (OptionsResolver $resolver) {
742+
$resolver
743+
->setDefined('foo')
744+
->setDefault('bar', null)
745+
->setDeprecated('foo')
746+
->setDeprecated('bar')
747+
;
748+
},
749+
array(),
750+
null,
751+
0,
752+
);
753+
754+
yield 'It explicitly ignores a depreciation' => array(
755+
function (OptionsResolver $resolver) {
756+
$resolver
757+
->setDefault('foo', null)
758+
->setDeprecated('foo')
759+
->setDefault('bar', function (Options $options) {
760+
return $options->offsetGet('foo', false);
761+
})
762+
;
763+
},
764+
array(),
765+
null,
766+
0,
686767
);
687768
}
688769

0 commit comments

Comments
 (0)