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@0
|
18 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
Chris@0
|
19 use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
Chris@0
|
20
|
Chris@0
|
21 /**
|
Chris@0
|
22 * Converts between objects and arrays using the PropertyAccess component.
|
Chris@0
|
23 *
|
Chris@0
|
24 * @author Kévin Dunglas <dunglas@gmail.com>
|
Chris@0
|
25 */
|
Chris@0
|
26 class ObjectNormalizer extends AbstractObjectNormalizer
|
Chris@0
|
27 {
|
Chris@0
|
28 /**
|
Chris@0
|
29 * @var PropertyAccessorInterface
|
Chris@0
|
30 */
|
Chris@0
|
31 protected $propertyAccessor;
|
Chris@0
|
32
|
Chris@0
|
33 public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null)
|
Chris@0
|
34 {
|
Chris@0
|
35 parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor);
|
Chris@0
|
36
|
Chris@0
|
37 $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
Chris@0
|
38 }
|
Chris@0
|
39
|
Chris@0
|
40 /**
|
Chris@0
|
41 * {@inheritdoc}
|
Chris@0
|
42 */
|
Chris@0
|
43 protected function extractAttributes($object, $format = null, array $context = array())
|
Chris@0
|
44 {
|
Chris@0
|
45 // If not using groups, detect manually
|
Chris@0
|
46 $attributes = array();
|
Chris@0
|
47
|
Chris@0
|
48 // methods
|
Chris@0
|
49 $reflClass = new \ReflectionClass($object);
|
Chris@0
|
50 foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
|
Chris@0
|
51 if (
|
Chris@0
|
52 $reflMethod->getNumberOfRequiredParameters() !== 0 ||
|
Chris@0
|
53 $reflMethod->isStatic() ||
|
Chris@0
|
54 $reflMethod->isConstructor() ||
|
Chris@0
|
55 $reflMethod->isDestructor()
|
Chris@0
|
56 ) {
|
Chris@0
|
57 continue;
|
Chris@0
|
58 }
|
Chris@0
|
59
|
Chris@0
|
60 $name = $reflMethod->name;
|
Chris@0
|
61 $attributeName = null;
|
Chris@0
|
62
|
Chris@0
|
63 if (0 === strpos($name, 'get') || 0 === strpos($name, 'has')) {
|
Chris@0
|
64 // getters and hassers
|
Chris@0
|
65 $attributeName = substr($name, 3);
|
Chris@0
|
66
|
Chris@0
|
67 if (!$reflClass->hasProperty($attributeName)) {
|
Chris@0
|
68 $attributeName = lcfirst($attributeName);
|
Chris@0
|
69 }
|
Chris@0
|
70 } elseif (strpos($name, 'is') === 0) {
|
Chris@0
|
71 // issers
|
Chris@0
|
72 $attributeName = substr($name, 2);
|
Chris@0
|
73
|
Chris@0
|
74 if (!$reflClass->hasProperty($attributeName)) {
|
Chris@0
|
75 $attributeName = lcfirst($attributeName);
|
Chris@0
|
76 }
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 if (null !== $attributeName && $this->isAllowedAttribute($object, $attributeName, $format, $context)) {
|
Chris@0
|
80 $attributes[$attributeName] = true;
|
Chris@0
|
81 }
|
Chris@0
|
82 }
|
Chris@0
|
83
|
Chris@0
|
84 // properties
|
Chris@0
|
85 foreach ($reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflProperty) {
|
Chris@0
|
86 if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
|
Chris@0
|
87 continue;
|
Chris@0
|
88 }
|
Chris@0
|
89
|
Chris@0
|
90 $attributes[$reflProperty->name] = true;
|
Chris@0
|
91 }
|
Chris@0
|
92
|
Chris@0
|
93 return array_keys($attributes);
|
Chris@0
|
94 }
|
Chris@0
|
95
|
Chris@0
|
96 /**
|
Chris@0
|
97 * {@inheritdoc}
|
Chris@0
|
98 */
|
Chris@0
|
99 protected function getAttributeValue($object, $attribute, $format = null, array $context = array())
|
Chris@0
|
100 {
|
Chris@0
|
101 return $this->propertyAccessor->getValue($object, $attribute);
|
Chris@0
|
102 }
|
Chris@0
|
103
|
Chris@0
|
104 /**
|
Chris@0
|
105 * {@inheritdoc}
|
Chris@0
|
106 */
|
Chris@0
|
107 protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = array())
|
Chris@0
|
108 {
|
Chris@0
|
109 try {
|
Chris@0
|
110 $this->propertyAccessor->setValue($object, $attribute, $value);
|
Chris@0
|
111 } catch (NoSuchPropertyException $exception) {
|
Chris@0
|
112 // Properties not found are ignored
|
Chris@0
|
113 }
|
Chris@0
|
114 }
|
Chris@0
|
115 }
|