Completed
Push — master ( af9049...dfa6c4 )
by Pierre
05:13 queued 01:50
created

RecursiveObjectNormalizer::hasProperty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
3
namespace Guzzle\ConfigOperationsBundle\Normalizer;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Guzzle\ConfigOperationsBundle\Normalizer\Annotation\Type;
7
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
8
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
9
10
/**
11
 * @author Pierre Rolland <[email protected]>
12
 */
13
class RecursiveObjectNormalizer extends ObjectNormalizer
14
{
15
    /**
16
     * @var AnnotationReader
17
     */
18
    private $annotationReader;
19
20
    /**
21
     * @var \ReflectionClass[]
22
     */
23
    private $reflectionClasses;
24
25
    /**
26
     * {@inheritdoc}
27
     */
28
    protected function instantiateObject(
29
        array &$data,
30
        $class,
31
        array &$context,
32
        \ReflectionClass $reflectionClass,
33
        $allowedAttributes
34
    ) {
35
        $this->reflectionClasses[$class] = $reflectionClass;
36
        return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes);
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
43
    {
44
        try {
45
            if ($this->hasProperty($object, $attribute) && ($type = $this->getTypeAnnotation($object, $attribute))) {
46
                $value = $this->getDenormalizedValue($type, $value, $format, $context);
47
            }
48
            $this->propertyAccessor->setValue($object, $attribute, $value);
49
        } catch (NoSuchPropertyException $exception) {
50
            // Properties not found are ignored
51
        }
52
    }
53
54
    /**
55
     * @param Type $type
56
     * @param mixed $value
57
     * @param string $format
58
     * @param array $context
59
     *
60
     * @return array|object
61
     */
62
    protected function getDenormalizedValue(Type $type, $value, $format, $context)
63
    {
64
        if (substr($type->name, -2) === '[]' && is_array($value)) {
65
            $denormalized = [];
66
            $class = substr($type->name, 0, -2);
67
            foreach ($value as $item) {
68
                $denormalized[] = $this->denormalize($item, $class, $format, $context);
69
            }
70
71
            return $denormalized;
72
        }
73
74
        return $this->denormalize($value, $type->name, $format, $context);
75
    }
76
77
    /**
78
     * @param object $object
79
     * @param string $attribute
80
     *
81
     * @return null|Type
82
     */
83
    protected function getTypeAnnotation($object, $attribute)
84
    {
85
        return $this->getAnnotationReader()->getPropertyAnnotation(
86
            $this->reflectionClasses[get_class($object)]->getProperty($attribute),
87
            Type::class
88
        );
89
    }
90
91
    /**
92
     * @param object $object
93
     * @param string $attribute
94
     *
95
     * @return bool
96
     */
97
    protected function hasProperty($object, $attribute)
98
    {
99
        return $this->reflectionClasses[get_class($object)]->hasProperty($attribute);
100
    }
101
102
    /**
103
     * @return AnnotationReader
104
     */
105
    public function getAnnotationReader()
106
    {
107
        if (null === $this->annotationReader) {
108
            $this->annotationReader = new AnnotationReader();
109
        }
110
111
        return $this->annotationReader;
112
    }
113
114
    /**
115
     * @param AnnotationReader $annotationReader
116
     */
117
    public function setAnnotationReader(AnnotationReader $annotationReader)
118
    {
119
        $this->annotationReader = $annotationReader;
120
    }
121
}
122