8000 Rebase, fix tests, review & update CHANGELOG · symfony/symfony@98e5554 · GitHub
[go: up one dir, main page]

Skip to content

Commit 98e5554

Browse files
committed
Rebase, fix tests, review & update CHANGELOG
1 parent fc25086 commit 98e5554

12 files changed

+150
-158
lines changed

src/Symfony/Component/PropertyAccess/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* Linking to PropertyInfo extractor to remove a lot of duplicate code
8+
49
4.4.0
510
-----
611

src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,14 @@ class PropertyAccessor implements PropertyAccessorInterface
7676
* Should not be used by application code. Use
7777
* {@link PropertyAccess::createPropertyAccessor()} instead.
7878
*/
79-
public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null, bool $throwExceptionOnInvalidPropertyPath = true)
79+
public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null, bool $throwExceptionOnInvalidPropertyPath = true, PropertyReadInfoExtractorInterface $readInfoExtractor = null, PropertyWriteInfoExtractorInterface $writeInfoExtractor = null)
8080
{
8181
$this->magicCall = $magicCall;
8282
$this->ignoreInvalidIndices = !$throwExceptionOnInvalidIndex;
8383
$this->cacheItemPool = $cacheItemPool instanceof NullAdapter ? null : $cacheItemPool; // Replace the NullAdapter by the null value
8484
$this->ignoreInvalidProperty = !$throwExceptionOnInvalidPropertyPath;
85-
$this->readInfoExtractor = $this->writeInfoExtractor = new ReflectionExtractor(
86-
['set'],
87-
['get', 'is', 'has', 'can'],
88-
['add', 'remove'],
89-
false,
90-
ReflectionExtractor::ALLOW_PUBLIC
91-
);
85+
$this->readInfoExtractor = $readInfoExtractor ?? new ReflectionExtractor(['set'], null, null, false);
86+
$this->writeInfoExtractor = $writeInfoExtractor ?? new ReflectionExtractor(['set'], null, null, false);
9287
}
9388

9489
/**
@@ -391,34 +386,25 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
391386
$access = $this->getReadInfo($class, $property);
392387

393388
if (null !== $access) {
394-
if (PropertyReadInfo::TYPE_METHOD === $access->getType()) {
395-
$result[self::VALUE] = $object->{$access->getName()}();
396-
}
389+
$name = $access->getName();
390+
$type = $access->getType();
397391

398-
if (PropertyReadInfo::TYPE_PROPERTY === $access->getType()) {
399-
$result[self::VALUE] = $object->{$access->getName()};
392+
if (PropertyReadInfo::TYPE_METHOD === $type) {
393+
$result[self::VALUE] = $object->$name();
394+
} elseif (PropertyReadInfo::TYPE_PROPERTY === $type) {
395+
$result[self::VALUE] = $object->$name;
400396

401397
if (isset($zval[self::REF]) && $access->canBeReference()) {
402-
$result[self::REF] = &$object->{$access->getName()};
398+
$result[self::REF] = &$object->$name;
403399
}
404400
}
405401
} elseif ($object instanceof \stdClass && property_exists($object, $property)) {
406-
// Needed to support \stdClass instances. We need to explicitly
407-
// exclude $access[self::ACCESS_HAS_PROPERTY], otherwise if
408-
// a *protected* property was found on the class, property_exists()
409-
// returns true, consequently the following line will result in a
410-
// fatal error.
411-
412402
$result[self::VALUE] = $object->$property;
413403
if (isset($zval[self::REF])) {
414404
$result[self::REF] = &$object->$property;
415405
}
416406
} elseif (!$ignoreInvalidProperty) {
417-
throw new NoSuchPropertyException(sprintf(
418-
'Can get a way to read the property "%s" in class "%s".',
419-
$property,
420-
$class
421-
));
407+
throw new NoSuchPropertyException(sprintf('Can get a way to read the property "%s" in class "%s".', $property, $class));
422408
}
423409

424410
// Objects are always passed around by reference
@@ -494,46 +480,39 @@ private function writeProperty(array $zval, string $property, $value)
494480
$class = \get_class($object);
495481
$mutator = $this->getWriteInfo($class, $property, $value);
496482

497-
if (null !== $mutator) {
498-
if (PropertyWriteInfo::TYPE_METHOD === $mutator->getType()) {
499-
$object->{$mutator->getName()}($value);
500-
}
483+
if (PropertyWriteInfo::TYPE_NONE !== $mutator->getType()) {
484+
$type = $mutator->getType();
501485

502-
if (PropertyWriteInfo::TYPE_PROPERTY === $mutator->getType()) {
486+
if (PropertyWriteInfo::TYPE_METHOD === $type) {
487+
$object->{$mutator->getName()}($value);
488+
} elseif (PropertyWriteInfo::TYPE_PROPERTY === $type) {
503489
$object->{$mutator->getName()} = $value;
504-
}
505-
506-
if (PropertyWriteInfo::TYPE_ADDER_AND_REMOVER === $mutator->getType()) {
490+
} elseif (PropertyWriteInfo::TYPE_ADDER_AND_REMOVER === $type) {
507491
$this->writeCollection($zval, $property, $value, $mutator->getAdderInfo(), $mutator->getRemoverInfo());
508492
}
509493
} elseif ($object instanceof \stdClass && property_exists($object, $property)) {
510-
// Needed to support \stdClass instances. We need to explicitly
511-
// exclude $access[self::ACCESS_HAS_PROPERTY], otherwise if
512-
// a *protected* property was found on the class, property_exists()
513-
// returns true, consequently the following line will result in a
514-
// fatal error.
515-
516494
$object->$property = $value;
517495
} else {
496+
if ($mutator->hasErrors()) {
497+
throw new NoSuchPropertyException(implode('. ', $mutator->getErrors()).'.');
498+
}
499+
518500
throw new NoSuchPropertyException(sprintf('Could not determine access type for property "%s" in class "%s".', $property, \get_class($object)));
519501
}
520502
}
521503

522504
/**
523505
* Adjusts a collection-valued property by calling add*() and remove*() methods.
524-
*
525-
* @param array $zval The array containing the object to write to
526-
* @param string $property The property to write
527-
* @param iterable $collection The collection to write
528-
* @param PropertyWriteInfo $addMethod The add*() method
529-
* @param PropertyWriteInfo $removeMethod The remove*() method
530506
*/
531507
private function writeCollection(array $zval, string $property, iterable $collection, PropertyWriteInfo $addMethod, PropertyWriteInfo $removeMethod)
532508
{
533509
// At this point the add and remove methods have been found
534510
$previousValue = $this->readProperty($zval, $property);
535511
$previousValue = $previousValue[self::VALUE];
536512

513+
$removeMethodName = $removeMethod->getName();
514+
$addMethodName = $addMethod->getName();
515+
537516
if ($previousValue instanceof \Traversable) {
538517
$previousValue = iterator_to_array($previousValue);
539518
}
@@ -544,7 +523,7 @@ private function writeCollection(array $zval, string $property, iterable $collec
544523
foreach ($previousValue as $key => $item) {
545524
if (!\in_array($item, $collection, true)) {
546525
unset($previousValue[$key]);
547-
$zval[self::VALUE]->{$removeMethod->getName()}($item);
526+
$zval[self::VALUE]->$removeMethodName($item);
548527
}
549528
}
550529
} else {
@@ -553,12 +532,12 @@ private function writeCollection(array $zval, string $property, iterable $collec
553532

554533
foreach ($collection as $item) {
555534
if (!$previousValue || !\in_array($item, $previousValue, true)) {
556-
$zval[self::VALUE]->{$addMethod->getName()}($item);
535+
$zval[self::VALUE]->$addMethodName($item);
557536
}
558537
}
559538
}
560539

561-
private function getWriteInfo(string $class, string $property, $value): ?PropertyWriteInfo
540+
private function getWriteInfo(string $class, string $property, $value): PropertyWriteInfo
562541
{
563542
$useAdderAndRemover = \is_array($value) || $value instanceof \Traversable;
564543
$key = str_replace('\\', '.', $class).'..'.$property.'..'.(int) $useAdderAndRemover;
@@ -601,13 +580,13 @@ private function isPropertyWritable($object, string $property): bool
601580

602581
$mutatorForArray = $this->getWriteInfo(\get_class($object), $property, []);
603582

604-
if (null !== $mutatorForArray || ($object instanceof \stdClass && property_exists($object, $property))) {
583+
if (PropertyWriteInfo::TYPE_NONE !== $mutatorForArray->getType() || ($object instanceof \stdClass && property_exists($object, $property))) {
605584
return true;
606585
}
607586

608587
$mutator = $this->getWriteInfo(\get_class($object), $property, '');
609588

610-
return null !== $mutator || ($object instanceof \stdClass && property_exists($object, $property));
589+
return PropertyWriteInfo::TYPE_NONE !== $mutator->getType() || ($object instanceof \stdClass && property_exists($object, $property));
611590
}
612591

613592
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ public function testIsWritableReturnsFalseIfNoAdderNorRemoverExists()
188188
public function testSetValueFailsIfAdderAndRemoverExistButValueIsNotTraversable()
189189
{
190190
$this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException');
191-
$this->expectExceptionMessageRegExp('/Could not determine access type for property "axes" in class "Symfony\\\\Component\\\\PropertyAccess\\\\Tests\\\\PropertyAccessorCollectionTest_Car[^"]*": The property "axes" in class "Symfony\\\\Component\\\\PropertyAccess\\\\Tests\\\\PropertyAccessorCollectionTest_Car[^"]*" can be defined with the methods "addAxis\(\)", "removeAxis\(\)" but the new value must be an array or an instance of \\\\Traversable, "string" given./');
191+
$this->expectExceptionMessageRegExp('/The property "axes" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\PropertyAccessorCollectionTest_Car" can be defined with the methods "addAxis\(\)", "removeAxis\(\)" but the new value must be an array or an instance of \\\Traversable\./');
192192
$car = new PropertyAccessorCollectionTest_Car();
193193

194194
$this->propertyAccessor->setValue($car, 'axes', 'Not an array or Traversable');

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ public function testRemoverWithoutAdder()
760760
public function testAdderAndRemoveNeedsTheExactParametersDefined()
761761
{
762762
$this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException');
763-
$this->expectExceptionMessageRegExp('/.*The method "addFoo" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\Fixtures\\\TestAdderRemoverInvalidArgumentLength" requires 0 arguments, but should accept only 1\. The method "removeFoo" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\Fixtures\\\TestAdderRemoverInvalidArgumentLength" requires 2 arguments, but should accept only 1\./');
763+
$this->expectExceptionMessageRegExp('/.*The method "addFoo" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\Fixtures\\\TestAdderRemoverInvalidArgumentLength" requires 0 arguments, but should accept only 1\./');
764764
$object = new TestAdderRemoverInvalidArgumentLength();
765765
$this->propertyAccessor->setValue($object, 'foo', [1, 2]);
766766
}

src/Symfony/Component/PropertyAccess/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": "^7.2.5",
2020
"symfony/inflector": "^4.4|^5.0",
21-
"symfony/property-info": "^4.4|^5.0"
21+
"symfony/property-info": "^5.1"
2222
},
2323
"require-dev": {
2424
"symfony/cache": "^4.4|^5.0"

src/Symfony/Component/PropertyInfo/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* Add support for extracting accessor and mutator via PHP Reflection
8+
49
4.3.0
510
-----
611

0 commit comments

Comments
 (0)
0