Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\Serializer\Normalizer;
|
Chris@0
|
13
|
Chris@0
|
14 use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
|
Chris@0
|
15 use Symfony\Component\PropertyAccess\PropertyAccess;
|
Chris@0
|
16 use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
Chris@0
|
17 use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
Chris@14
|
18 use Symfony\Component\Serializer\Exception\RuntimeException;
|
Chris@0
|
19 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
Chris@0
|
20 use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
Chris@0
|
21
|
Chris@0
|
22 /**
|
Chris@0
|
23 * Converts between objects and arrays using the PropertyAccess component.
|
Chris@0
|
24 *
|
Chris@0
|
25 * @author Kévin Dunglas <dunglas@gmail.com>
|
Chris@0
|
26 */
|
Chris@0
|
27 class ObjectNormalizer extends AbstractObjectNormalizer
|
Chris@0
|
28 {
|
Chris@0
|
29 protected $propertyAccessor;
|
Chris@0
|
30
|
Chris@0
|
31 public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null)
|
Chris@0
|
32 {
|
Chris@14
|
33 if (!\class_exists(PropertyAccess::class)) {
|
Chris@14
|
34 throw new RuntimeException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.');
|
Chris@14
|
35 }
|
Chris@14
|
36
|
Chris@0
|
37 parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor);
|
Chris@0
|
38
|
Chris@0
|
39 $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
Chris@0
|
40 }
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * {@inheritdoc}
|
Chris@0
|
44 */
|
Chris@17
|
45 protected function extractAttributes($object, $format = null, array $context = [])
|
Chris@0
|
46 {
|
Chris@0
|
47 // If not using groups, detect manually
|
Chris@17
|
48 $attributes = [];
|
Chris@0
|
49
|
Chris@0
|
50 // methods
|
Chris@0
|
51 $reflClass = new \ReflectionClass($object);
|
Chris@0
|
52 foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
|
Chris@0
|
53 if (
|
Chris@14
|
54 0 !== $reflMethod->getNumberOfRequiredParameters() ||
|
Chris@0
|
55 $reflMethod->isStatic() ||
|
Chris@0
|
56 $reflMethod->isConstructor() ||
|
Chris@0
|
57 $reflMethod->isDestructor()
|
Chris@0
|
58 ) {
|
Chris@0
|
59 continue;
|
Chris@0
|
60 }
|
Chris@0
|
61
|
Chris@0
|
62 $name = $reflMethod->name;
|
Chris@0
|
63 $attributeName = null;
|
Chris@0
|
64
|
Chris@0
|
65 if (0 === strpos($name, 'get') || 0 === strpos($name, 'has')) {
|
Chris@0
|
66 // getters and hassers
|
Chris@0
|
67 $attributeName = substr($name, 3);
|
Chris@0
|
68
|
Chris@0
|
69 if (!$reflClass->hasProperty($attributeName)) {
|
Chris@0
|
70 $attributeName = lcfirst($attributeName);
|
Chris@0
|
71 }
|
Chris@14
|
72 } elseif (0 === strpos($name, 'is')) {
|
Chris@0
|
73 // issers
|
Chris@0
|
74 $attributeName = substr($name, 2);
|
Chris@0
|
75
|
Chris@0
|
76 if (!$reflClass->hasProperty($attributeName)) {
|
Chris@0
|
77 $attributeName = lcfirst($attributeName);
|
Chris@0
|
78 }
|
Chris@0
|
79 }
|
Chris@0
|
80
|
Chris@0
|
81 if (null !== $attributeName && $this->isAllowedAttribute($object, $attributeName, $format, $context)) {
|
Chris@0
|
82 $attributes[$attributeName] = true;
|
Chris@0
|
83 }
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@0
|
86 // properties
|
Chris@0
|
87 foreach ($reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflProperty) {
|
Chris@0
|
88 if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
|
Chris@0
|
89 continue;
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 $attributes[$reflProperty->name] = true;
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 return array_keys($attributes);
|
Chris@0
|
96 }
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * {@inheritdoc}
|
Chris@0
|
100 */
|
Chris@17
|
101 protected function getAttributeValue($object, $attribute, $format = null, array $context = [])
|
Chris@0
|
102 {
|
Chris@0
|
103 return $this->propertyAccessor->getValue($object, $attribute);
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 /**
|
Chris@0
|
107 * {@inheritdoc}
|
Chris@0
|
108 */
|
Chris@17
|
109 protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
|
Chris@0
|
110 {
|
Chris@0
|
111 try {
|
Chris@0
|
112 $this->propertyAccessor->setValue($object, $attribute, $value);
|
Chris@0
|
113 } catch (NoSuchPropertyException $exception) {
|
Chris@0
|
114 // Properties not found are ignored
|
Chris@0
|
115 }
|
Chris@0
|
116 }
|
Chris@0
|
117 }
|