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

Skip to content

Commit e3cd4a8

Browse files
committed
#30536 PropertyAccessor->getValue disable exception
1 parent 29f81b0 commit e3cd4a8

File tree

12 files changed

+89
-11
lines changed

12 files changed

+89
-11
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ private function addPropertyAccessSection(ArrayNodeDefinition $rootNode)
849849
->children()
850850
->booleanNode('magic_call')->defaultFalse()->end()
851851
->booleanNode('throw_exception_on_invalid_index')->defaultFalse()->end()
852+
->booleanNode('throw_exception_on_invalid_property_path')->defaultTrue()->end()
852853
->end()
853854
->end()
854855
->end()

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,7 @@ private function registerPropertyAccessConfiguration(array $config, ContainerBui
13041304
->getDefinition('property_accessor')
13051305
->replaceArgument(0, $config['magic_call'])
13061306
->replaceArgument(1, $config['throw_exception_on_invalid_index'])
1307+
->replaceArgument(3, $config['throw_exception_on_invalid_property_path'])
13071308
;
13081309
}
13091310

src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<argument /> <!-- magicCall, set by the extension -->
1212
<argument /> <!-- throwExceptionOnInvalidIndex, set by the extension -->
1313
<argument type="service" id="cache.property_access" on-invalid="ignore" />
14+
<argument /> <!-- throwExceptionOnInvalidPropertyPath, set by the extension -->
1415
</service>
1516
<service id="Symfony\Component\PropertyAccess\PropertyAccessorInterface" alias="property_accessor" />
1617
</services>

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@
224224
<xsd:complexType name="property_access">
225225
<xsd:attribute name="magic-call" type="xsd:boolean" />
226226
<xsd:attribute name="throw-exception-on-invalid-index" type="xsd:boolean" />
227+
<xsd:attribute name="throw-exception-on-invalid-property-path" type="xsd:boolean" />
227228
</xsd:complexType>
228229

229230
<xsd:complexType name="serializer">

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ protected static function getBundleDefaultConfig()
246246
'property_access' => [
247247
'magic_call' => false,
248248
'throw_exception_on_invalid_index' => false,
249+
'throw_exception_on_invalid_property_path' => true,
249250
],
250251
'property_info' => [
251252
'enabled' => !class_exists(FullStack::class),

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
'property_access' => [
55
'magic_call' => true,
66
'throw_exception_on_invalid_index' => true,
7+
'throw_exception_on_invalid_property_path' => false,
78
],
89
]);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
88

99
<framework:config>
10-
<framework:property-access magic-call="true" throw-exception-on-invalid-index="true" />
10+
<framework:property-access magic-call="true" throw-exception-on-invalid-index="true" throw-exception-on-invalid-property-path="false"/>
1111
</framework:config>
1212
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ framework:
22
property_access:
33
magic_call: true
44
throw_exception_on_invalid_index: true
5+
throw_exception_on_invalid_property_path: false

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public function testPropertyAccessWithDefaultValue()
7777
$def = $container->getDefinition('property_accessor');
7878
$this->assertFalse($def->getArgument(0));
7979
$this->assertFalse($def->getArgument(1));
80+
$this->assertTrue($def->getArgument(3));
8081
}
8182

8283
public function testPropertyAccessWithOverriddenValues()
@@ -85,6 +86,7 @@ public function testPropertyAccessWithOverriddenValues()
8586
$def = $container->getDefinition('property_accessor');
8687
$this->assertTrue($def->getArgument(0));
8788
$this->assertTrue($def->getArgument(1));
89+
$this->assertFalse($def->getArgument(3));
8890
}
8991

9092
public function testPropertyAccessCache()

src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class PropertyAccessor implements PropertyAccessorInterface
5656
*/
5757
private $magicCall;
5858
private $ignoreInvalidIndices;
59+
private $ignoreInvalidProperty;
5960

6061
/**
6162
* @var CacheItemPoolInterface
@@ -70,11 +71,12 @@ class PropertyAccessor implements PropertyAccessorInterface
7071
* Should not be used by application code. Use
7172
* {@link PropertyAccess::createPropertyAccessor()} instead.
7273
*/
73-
public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null)
74+
public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null, bool $throwExceptionOnInvalidPropertyPath = true)
7475
{
7576
$this->magicCall = $magicCall;
7677
$this->ignoreInvalidIndices = !$throwExceptionOnInvalidIndex;
7778
$this->cacheItemPool = $cacheItemPool instanceof NullAdapter ? null : $cacheItemPool; // Replace the NullAdapter by the null value
79+
$this->ignoreInvalidProperty = !$throwExceptionOnInvalidPropertyPath;
7880
}
7981

8082
/**
@@ -87,7 +89,7 @@ public function getValue($objectOrArray, $propertyPath)
8789
];
8890

8991
if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[')) {
90-
return $this->readProperty($zval, $propertyPath)[self::VALUE];
92+
return $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty)[self::VALUE];
9193
}
9294

9395
$propertyPath = $this->getPropertyPath($propertyPath);
@@ -313,7 +315,7 @@ private function readPropertiesUntil($zval, PropertyPathInterface $propertyPath,
313315

314316
$zval = $this->readIndex($zval, $property);
315317
} else {
316-
$zval = $this->readProperty($zval, $property);
318+
$zval = $this->readProperty($zval, $property, $this->ignoreInvalidProperty);
317319
}
318320

319321
// the final value of the path must not be validated
@@ -372,14 +374,13 @@ private function readIndex($zval, $index)
372374
/**
373375
* Reads the a property from an object.
374376
*
375-
* @param array $zval The array containing the object to read from
376-
* @param string $property The property to read
377+
* @param array $zval The array containing the object to read from
378+
* @param string $property The property to read
379+
* @param bool $ignoreInvalidProperty Whether to ignore invalid property or throw an exception
377380
*
378381
* @return array The array containing the value of the property
379-
*
380-
* @throws NoSuchPropertyException if the property does not exist or is not public
381382
*/
382-
private function readProperty($zval, $property)
383+
private function readProperty($zval, $property, bool $ignoreInvalidProperty = false)
383384
{
384385
if (!\is_object($zval[self::VALUE])) {
385386
throw new NoSuchPropertyException(sprintf('Cannot read property "%s" from an array. Maybe you intended to write the property path as "[%1$s]" instead.', $property));
@@ -411,7 +412,7 @@ private function readProperty($zval, $property)
411412
} elseif (self::ACCESS_TYPE_MAGIC === $access[self::ACCESS_TYPE]) {
412413
// we call the getter and hope the __call do the job
413414
$result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}();
414-
} else {
415+
} elseif (!$ignoreInvalidProperty) {
415416
throw new NoSuchPropertyException($access[self::ACCESS_NAME]);
416417
}
417418

src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class PropertyAccessorBuilder
2222
{
2323
private $magicCall = false;
2424
private $throwExceptionOnInvalidIndex = false;
25+
private $throwExceptionOnInvalidPropertyPath = true;
2526

2627
/**
2728
* @var CacheItemPoolInterface|null
@@ -97,6 +98,43 @@ public function isExceptionOnInvalidIndexEnabled()
9798
return $this->throwExceptionOnInvalidIndex;
9899
}
99100

101+
/**
102+
* Enables exceptions when reading a non-existing property.
103+
*
104+
* This has no influence on writing non-existing indices with PropertyAccessorInterface::setValue()
105+
* which are always created on-the-fly.
106+
*
107+
* @return $this
108+
*/
109+
public function enableExceptionOnInvalidPropertyPath()
110+
{
111+
$this->throwExceptionOnInvalidPropertyPath = true;
112+
113+
return $this;
114+
}
115+
116+
/**
117+
* Disables exceptions when reading a non-existing index.
118+
*
119+
* Instead, null is returned when calling PropertyAccessorInterface::getValue() on a non-existing index.
120+
*
121+
* @return $this
122+
*/
123+
public function disableExceptionOnInvalidPropertyPath()
124+
{
125+
$this->throwExceptionOnInvalidPropertyPath = false;
126+
127+
return $this;
128+
}
129+
130+
/**
131+
* @return bool whether an exception is thrown or null is returned when reading a non-existing property
132+
*/
133+
public function isExceptionOnInvalidPropertyPath()
134+
{
135+
return $this->throwExceptionOnInvalidPropertyPath;
136+
}
137+
100138
/**
101139
* Sets a cache system.
102140
*
@@ -128,6 +166,6 @@ public function getCacheItemPool()
128166
*/
129167
public function getPropertyAccessor()
130168
{
131-
return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cacheItemPool);
169+
return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cacheItemPool, $this->throwExceptionOnInvalidPropertyPath);
132170
}
133171
}

src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1616
use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
17+
use Symfony\Component\PropertyAccess\PropertyAccess;
1718
use Symfony\Component\PropertyAccess\PropertyAccessor;
1819
use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped;
1920
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass;
@@ -100,6 +101,16 @@ public function testGetValueThrowsExceptionIfPropertyNotFound($objectOrArray, $p
100101
$this->propertyAccessor->getValue($objectOrArray, $path);
101102
}
102103

104+
/**
105+
* @dataProvider getPathsWithMissingProperty
106+
*/
107+
public function testGetValueReturnsNullIfPropertyNotFoundAndExceptionIsDisabled($objectOrArray, $path)
108+
{
109+
$this->propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()->disableExceptionOnInvalidPropertyPath()->getPropertyAccessor();
110+
111+
$this->assertNull($this->propertyAccessor->getValue($objectOrArray, $path), $path);
112+
}
113+
103114
/**
104115
* @dataProvider getPathsWithMissingIndex
105116
*/
@@ -617,6 +628,25 @@ public function testAnonymousClassRead()
617628
$this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo'));
618629
}
619630

631+
/**
632+
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
633+
*/
634+
public function testAnonymousClassReadThrowExceptionOnInvalidPropertyPath()
635+
{
636+
$obj = $this->generateAnonymousClass('bar');
637+
638+
$this->propertyAccessor->getValue($obj, 'invalid_property');
639+
}
640+
641+
public function testAnonymousClassReadReturnsNullOnInvalidPropertyWithDisabledException()
642+
{
643+
$obj = $this->generateAnonymousClass('bar');
644+
645+
$this->propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()->disableExceptionOnInvalidPropertyPath()->getPropertyAccessor();
646+
647+
$this->assertNull($this->propertyAccessor->getValue($obj, 'invalid_property'));
648+
}
649+
620650
public function testAnonymousClassWrite()
621651
{
622652
$value = 'bar';

0 commit comments

Comments
 (0)