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

Skip to content

Commit 184a256

Browse files
committed
[Serializer] Use PropertyAccessor to access / mutate values in AbstractObjectNormalizer
1 parent 0a92dab commit 184a256

File tree

6 files changed

+56
-137
lines changed

6 files changed

+56
-137
lines changed

src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ class PropertyAccessor implements PropertyAccessorInterface
4848
* @var bool
4949
*/
5050
private $magicCall;
51+
/**
52+
* @var bool
53+
*/
54+
private $staticCall;
5155
private $ignoreInvalidIndices;
5256
private $ignoreInvalidProperty;
5357

@@ -76,9 +80,10 @@ class PropertyAccessor implements PropertyAccessorInterface
7680
* Should not be used by application code. Use
7781
* {@link PropertyAccess::createPropertyAccessor()} instead.
7882
*/
79-
public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null, bool $throwExceptionOnInvalidPropertyPath = true, PropertyReadInfoExtractorInterface $readInfoExtractor = null, PropertyWriteInfoExtractorInterface $writeInfoExtractor = null)
83+
public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null, bool $throwExceptionOnInvalidPropertyPath = true, PropertyReadInfoExtractorInterface $readInfoExtractor = null, PropertyWriteInfoExtractorInterface $writeInfoExtractor = null, bool $staticCall = true)
8084
{
8185
$this->magicCall = $magicCall;
86+
$this->staticCall = $staticCall;
8287
$this->ignoreInvalidIndices = !$throwExceptionOnInvalidIndex;
8388
$this->cacheItemPool = $cacheItemPool instanceof NullAdapter ? null : $cacheItemPool; // Replace the NullAdapter by the null value
8489
$this->ignoreInvalidProperty = !$throwExceptionOnInvalidPropertyPath;
@@ -385,7 +390,7 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
385390
$class = \get_class($object);
386391
$access = $this->getReadInfo($class, $property);
387392

388-
if (null !== $access) {
393+
if (null !== $access && (!$access->isStatic() || $this->staticCall)) {
389394
$name = $access->getName();
390395
$type = $access->getType();
391396

@@ -480,7 +485,7 @@ private function writeProperty(array $zval, string $property, $value)
480485
$class = \get_class($object);
481486
$mutator = $this->getWriteInfo($class, $property, $value);
482487

483-
if (PropertyWriteInfo::TYPE_NONE !== $mutator->getType()) {
488+
if (PropertyWriteInfo::TYPE_NONE !== $mutator->getType() && (!$mutator->isStatic() || $this->staticCall)) {
484489
$type = $mutator->getType();
485490

486491
if (PropertyWriteInfo::TYPE_METHOD === $type) {

src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
class PropertyAccessorBuilder
2222
{
2323
private $magicCall = false;
24+
private $staticCall = true;
2425
private $throwExceptionOnInvalidIndex = false;
2526
private $throwExceptionOnInvalidPropertyPath = true;
2627

@@ -61,6 +62,20 @@ public function isMagicCallEnabled()
6162
return $this->magicCall;
6263
}
6364

65+
public function enableStaticCall(): self
66+
{
67+
$this->staticCall = true;
68+
69+
return $this;
70+
}
71+
72+
public function disableStaticCall(): self
73+
{
74+
$this->staticCall = false;
75+
76+
return $this;
77+
}
78+
6479
/**
6580
* Enables exceptions when reading a non-existing index.
6681
*
@@ -164,6 +179,6 @@ public function getCacheItemPool()
164179
*/
165180
public function getPropertyAccessor()
166181
{
167-
return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cacheItemPool, $this->throwExceptionOnInvalidPropertyPath);
182+
return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cacheItemPool, $this->throwExceptionOnInvalidPropertyPath, null, null, $this->staticCall);
168183
}
169184
}

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
1515
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
16+
use Symfony\Component\PropertyAccess\PropertyAccess;
17+
use Symfony\Component\PropertyAccess\PropertyAccessor;
18+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
1619
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
1720
use Symfony\Component\PropertyInfo\Type;
1821
use Symfony\Component\Serializer\Encoder\JsonEncoder;
@@ -93,15 +96,18 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
9396
private $propertyTypeExtractor;
9497
private $typesCache = [];
9598
private $attributesCache = [];
99+
private $discriminatorCache = [];
96100

97101
private $objectClassResolver;
102+
private $propertyAccessor;
98103

99104
/**
100105
* @var ClassDiscriminatorResolverInterface|null
101106
*/
102107
protected $classDiscriminatorResolver;
103108

104-
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = [])
109+
110+
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = [], PropertyAccessorInterface $propertyAccessor = null)
105111
{
106112
parent::__construct($classMetadataFactory, $nameConverter, $defaultContext);
107113

@@ -118,6 +124,11 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory
118124
}
119125
$this->classDiscriminatorResolver = $classDiscriminatorResolver;
120126
$this->objectClassResolver = $objectClassResolver;
127+
128+
$this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessorBuilder()
129+
->disableExceptionOnInvalidPropertyPath()
130+
->disableStaticCall()
131+
->getPropertyAccessor();
121132
}
122133

123134
/**
@@ -208,6 +219,25 @@ public function normalize($object, string $format = null, array $context = [])
208219
return $data;
209220
}
210221

222+
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
223+
{
224+
$cacheKey = \get_class($object);
225+
if (!\array_key_exists($cacheKey, $this->discriminatorCache)) {
226+
$this->discriminatorCache[$cacheKey] = null;
227+
if (null !== $this->classDiscriminatorResolver) {
228+
$mapping = $this->classDiscriminatorResolver->getMappingForMappedObject($object);
229+
$this->discriminatorCache[$cacheKey] = null === $mapping ? null : $mapping->getTypeProperty();
230+
}
231+
}
232+
233+
return $attribute === $this->discriminatorCache[$cacheKey] ? $this->classDiscriminatorResolver->getTypeForMappedObject($object) : $this->propertyAccessor->getValue($object, $attribute);
234+
}
235+
236+
protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = [])
237+
{
238+
$this->propertyAccessor->setValue($object, $attribute, $value);
239+
}
240+
211241
/**
212242
* {@inheritdoc}
213243
*/
@@ -276,13 +306,6 @@ protected function getAttributes($object, string $format = null, array $context)
276306
*/
277307
abstract protected function extractAttributes(object $object, string $format = null, array $context = []);
278308

279-
/**
280-
* Gets the attribute value.
281-
*
282-
* @return mixed
283-
*/
284-
abstract protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []);
285-
286309
/**
287310
* {@inheritdoc}
288311
*/
@@ -343,11 +366,6 @@ public function denormalize($data, string $type, string $format = null, array $c
343366
return $object;
344367
}
345368

346-
/**
347-
* Sets attribute value.
348-
*/
349-
abstract protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = []);
350-
351369
/**
352370
* Validates the submitted data and denormalizes it.
353371
*

src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -117,46 +117,4 @@ protected function extractAttributes(object $object, string $format = null, arra
117117

118118
return $attributes;
119119
}
120-
121-
/**
122-
* {@inheritdoc}
123-
*/
124-
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
125-
{
126-
$ucfirsted = ucfirst($attribute);
127-
128-
$getter = 'get'.$ucfirsted;
129-
if (\is_callable([$object, $getter])) {
130-
return $object->$getter();
131-
}
132-
133-
$isser = 'is'.$ucfirsted;
134-
if (\is_callable([$object, $isser])) {
135-
return $object->$isser();
136-
}
137-
138-
$haser = 'has'.$ucfirsted;
139-
if (\is_callable([$object, $haser])) {
140-
return $object->$haser();
141-
}
142-
143-
return null;
144-
}
145-
146-
/**
147-
* {@inheritdoc}
148-
*/
149-
protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = [])
150-
{
151-
$setter = 'set'.ucfirst($attribute);
152-
$key = \get_class($object).':'.$setter;
153-
154-
if (!isset(self::$setterAccessibleCache[$key])) {
155-
self::$setterAccessibleCache[$key] = \is_callable([$object, $setter]) && !(new \ReflectionMethod($object, $setter))->isStatic();
156-
}
157-
158-
if (self::$setterAccessibleCache[$key]) {
159-
$object->$setter($value);
160-
}
161-
}
162120
}

src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
*/
2929
class ObjectNormalizer extends AbstractObjectNormalizer
3030
{
31-
protected $propertyAccessor;
32-
33-
private $discriminatorCache = [];
34-
3531
private $objectClassResolver;
3632

3733
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = [])
@@ -40,9 +36,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory
4036
throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.');
4137
}
4238

43-
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
44-
45-
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
39+
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext, $propertyAccessor);
4640

4741
$this->objectClassResolver = $objectClassResolver ?? function ($class) {
4842
return \is_object($class) ? \get_class($class) : $class;
@@ -121,35 +115,6 @@ protected function extractAttributes(object $object, string $format = null, arra
121115
return array_keys($attributes);
122116
}
123117

124-
/**
125-
* {@inheritdoc}
126-
*/
127-
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
128-
{
129-
$cacheKey = \get_class($object);
130-
if (!\array_key_exists($cacheKey, $this->discriminatorCache)) {
131-
$this->discriminatorCache[$cacheKey] = null;
132-
if (null !== $this->classDiscriminatorResolver) {
133-
$mapping = $this->classDiscriminatorResolver->getMappingForMappedObject($object);
134-
$this->discriminatorCache[$cacheKey] = null === $mapping ? null : $mapping->getTypeProperty();
135-
}
136-
}
137-
138-
return $attribute === $this->discriminatorCache[$cacheKey] ? $this->classDiscriminatorResolver->getTypeForMappedObject($object) : $this->propertyAccessor->getValue($object, $attribute);
139-
}
140-
141-
/**
142-
* {@inheritdoc}
143-
*/
144-
protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = [])
145-
{
146-
try {
147-
$this->propertyAccessor->setValue($object, $attribute, $value);
148-
} catch (NoSuchPropertyException $exception) {
149-
// Properties not found are ignored
150-
}
151-
}
152-
153118
/**
154119
* {@inheritdoc}
155120
*/

src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -126,48 +126,6 @@ protected function extractAttributes(object $object, string $format = null, arra
126126
return $attributes;
127127
}
128128

129-
/**
130-
* {@inheritdoc}
131-
*/
132-
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
133-
{
134-
try {
135-
$reflectionProperty = $this->getReflectionProperty($object, $attribute);
136-
} catch (\ReflectionException $reflectionException) {
137-
return null;
138-
}
139-
140-
// Override visibility
141-
if (!$reflectionProperty->isPublic()) {
142-
$reflectionProperty->setAccessible(true);
143-
}
144-
145-
return $reflectionProperty->getValue($object);
146-
}
147-
148-
/**
149-
* {@inheritdoc}
150-
*/
151-
protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = [])
152-
{
153-
try {
154-
$reflectionProperty = $this->getReflectionProperty($object, $attribute);
155-
} catch (\ReflectionException $reflectionException) {
156-
return;
157-
}
158-
159-
if ($reflectionProperty->isStatic()) {
160-
return;
161-
}
162-
163-
// Override visibility
164-
if (!$reflectionProperty->isPublic()) {
165-
$reflectionProperty->setAccessible(true);
166-
}
167-
168-
$reflectionProperty->setValue($object, $value);
169-
}
170-
171129
/**
172130
* @param string|object $classOrObject
173131
*

0 commit comments

Comments
 (0)