Completed
Push — master ( ac33b4...891d18 )
by Pavel
04:55
created

DoctrineObjectNormalizer::getObjectByValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 3
crap 6
1
<?php
2
3
namespace ScayTrase\Api\Cruds\Adaptors\DoctrineOrm;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Persistence\ManagerRegistry;
7
use Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface;
8
use Doctrine\Common\Persistence\ObjectManager;
9
use Doctrine\ORM\EntityManagerInterface;
10
use Doctrine\ORM\Mapping\ClassMetadata;
11
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
12
13
class DoctrineObjectNormalizer extends ObjectNormalizer
14
{
15
    /** @var ManagerRegistry */
16
    private $registry;
17
18 6
    public function setRegistry(ManagerRegistry $registry)
19
    {
20 6
        $this->registry = $registry;
21 6
    }
22
23 6
    public function supportsNormalization($data, $format = null)
24
    {
25 6
        return is_object($data) && null !== $this->registry->getManagerForClass(get_class($data));
26
    }
27
28 5
    protected function getAttributeValue($object, $attribute, $format = null, array $context = [])
29
    {
30 5
        $rawValue = parent::getAttributeValue($object, $attribute, $format, $context);
31
32 5
        if (null === $rawValue) {
33 3
            return null;
34
        }
35
36 5
        $metadata = $this->getObjectMetadata($object, $attribute);
37 5
        if (null === $metadata) {
38 5
            return $rawValue;
39
        }
40
41 5
        $assocMetadata = $this->getAssocMetadata($metadata, $attribute);
42
43 5
        if ($metadata->isSingleValuedAssociation($attribute)) {
44 4
            return $this->getAssociationValue($assocMetadata, $rawValue);
45
        }
46
47 5
        $result = [];
48 5
        foreach ($rawValue as $item) {
49 1
            $result[] = $this->getAssociationValue($assocMetadata, $item);
50 5
        }
51
52 5
        return $result;
53
    }
54
55
    protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
56
    {
57
        if (null === $value) {
58
            return parent::setAttributeValue($object, $attribute, $value, $format, $context);
59
        }
60
61
        $rawValue = $value;
62
63
        $metadata = $this->getObjectMetadata($object, $attribute);
64
        if (null === $metadata) {
65
            return $rawValue;
66
        }
67
68
        $assocMetadata = $this->getAssocMetadata($metadata, $attribute);
69
70
        $manager = $this->registry->getManagerForClass($assocMetadata->getName());
71
        if (null === $manager) {
72
            throw new \LogicException('Unsupported class '.$assocMetadata->getName());
73
        }
74
75
        if ($metadata->isSingleValuedAssociation($attribute)) {
76
            $value = $this->getObjectByValue($manager, $assocMetadata, $rawValue);
77
78
            return parent::setAttributeValue($object, $attribute, $value, $format, $context);
79
        }
80
81
        $objects = [];
82
        foreach ($rawValue as $item) {
83
            $objects[] = $this->getObjectByValue($manager, $assocMetadata, $item);
84
        }
85
86
        return parent::setAttributeValue($object, $attribute, new ArrayCollection($objects), $format, $context);
87
    }
88
89
    /**
90
     * @param ObjectManager          $manager
91
     * @param ClassMetadataInterface $assocMetadata
92
     * @param                        $rawValue
93
     *
94
     * @return object
95
     */
96
    protected function getObjectByValue(ObjectManager $manager, ClassMetadataInterface $assocMetadata, $rawValue)
97
    {
98
        if ($manager instanceof EntityManagerInterface) {
99
            return $manager->getReference($assocMetadata->getName(), $rawValue);
100
        }
101
102
        return $manager->find($assocMetadata->getName(), $rawValue);
103
    }
104
105
    /**
106
     * @param $assocMetadata
107
     * @param $rawValue
108
     *
109
     * @return mixed
110
     */
111 4
    private function getAssociationValue(ClassMetadataInterface $assocMetadata, $rawValue)
112
    {
113 4
        $identifier = $assocMetadata->getIdentifierValues($rawValue);
114
115 4
        if (!$assocMetadata instanceof ClassMetadata || $assocMetadata->isIdentifierComposite) {
116
            return $identifier;
117
        }
118
119 4
        return array_shift($identifier);
120
    }
121
122 5
    private function getObjectMetadata($object, $attribute)
123
    {
124 5
        $class = get_class($object);
125
126 5
        $manager = $this->registry->getManagerForClass($class);
127 5
        if (null === $manager) {
128
            return null;
129
        }
130
131 5
        $metadata = $manager->getClassMetadata($class);
132 5
        if (!$metadata->hasAssociation($attribute)) {
133 5
            return null;
134
        }
135
136 5
        return $metadata;
137
    }
138
139 5
    private function getAssocMetadata(ClassMetadataInterface $metadata, $attribute)
140
    {
141 5
        $assoc        = $metadata->getAssociationTargetClass($attribute);
142 5
        $assocManager = $this->registry->getManagerForClass($assoc);
143
144 5
        if (null === $assocManager) {
145
            throw new \LogicException(
146
                $metadata->getName().
147
                '::$'.
148
                $attribute.
149
                ' references non-existent managed entity'
150
            );
151
        }
152
153 5
        return $assocManager->getClassMetadata($assoc);
154
    }
155
}
156