Completed
Push — master ( 1250b5...ac33b4 )
by Pavel
04:37
created

DoctrineObjectNormalizer   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 56.92%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 23
c 2
b 1
f 0
lcom 1
cbo 7
dl 0
loc 139
ccs 37
cts 65
cp 0.5692
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setRegistry() 0 4 1
A supportsNormalization() 0 4 2
B getAttributeValue() 0 26 5
B setAttributeValue() 0 29 5
A getObjectByValue() 0 8 2
A getAssociationValue() 0 10 3
A getObjectMetadata() 0 16 3
A getAssocMetadata() 0 16 2
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 ($metadata->isSingleValuedAssociation($attribute)) {
72
            $value = $this->getObjectByValue($manager, $assocMetadata, $rawValue);
0 ignored issues
show
Bug introduced by
It seems like $manager defined by $this->registry->getMana...socMetadata->getName()) on line 70 can be null; however, ScayTrase\Api\Cruds\Adap...zer::getObjectByValue() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
73
74
            return parent::setAttributeValue($object, $attribute, $value, $format, $context);
75
        }
76
77
        $objects = [];
78
        foreach ($rawValue as $item) {
79
            $objects[] = $this->getObjectByValue($manager, $assocMetadata, $item);
0 ignored issues
show
Bug introduced by
It seems like $manager defined by $this->registry->getMana...socMetadata->getName()) on line 70 can be null; however, ScayTrase\Api\Cruds\Adap...zer::getObjectByValue() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
80
        }
81
82
        return parent::setAttributeValue($object, $attribute, new ArrayCollection($objects), $format, $context);
83
    }
84
85
    /**
86
     * @param ObjectManager          $manager
87
     * @param ClassMetadataInterface $assocMetadata
88
     * @param                        $rawValue
89
     *
90
     * @return object
91
     */
92
    protected function getObjectByValue(ObjectManager $manager, ClassMetadataInterface $assocMetadata, $rawValue)
93
    {
94
        if ($manager instanceof EntityManagerInterface) {
95
            return $manager->getReference($assocMetadata->getName(), $rawValue);
96
        }
97
98
        return $manager->find($assocMetadata->getName(), $rawValue);
99
    }
100
101
    /**
102
     * @param $assocMetadata
103
     * @param $rawValue
104
     *
105
     * @return mixed
106
     */
107 4
    private function getAssociationValue(ClassMetadataInterface $assocMetadata, $rawValue)
108
    {
109 4
        $identifier = $assocMetadata->getIdentifierValues($rawValue);
110
111 4
        if (!$assocMetadata instanceof ClassMetadata || $assocMetadata->isIdentifierComposite) {
112
            return $identifier;
113
        }
114
115 4
        return array_shift($identifier);
116
    }
117
118 5
    private function getObjectMetadata($object, $attribute)
119
    {
120 5
        $class = get_class($object);
121
122 5
        $manager = $this->registry->getManagerForClass($class);
123 5
        if (null === $manager) {
124
            return null;
125
        }
126
127 5
        $metadata = $manager->getClassMetadata($class);
128 5
        if (!$metadata->hasAssociation($attribute)) {
129 5
            return null;
130
        }
131
132 5
        return $metadata;
133
    }
134
135 5
    private function getAssocMetadata(ClassMetadataInterface $metadata, $attribute)
136
    {
137 5
        $assoc        = $metadata->getAssociationTargetClass($attribute);
138 5
        $assocManager = $this->registry->getManagerForClass($assoc);
139
140 5
        if (null === $assocManager) {
141
            throw new \LogicException(
142
                $metadata->getName().
143
                '::$'.
144
                $attribute.
145
                ' references non-existent managed entity'
146
            );
147
        }
148
149 5
        return $assocManager->getClassMetadata($assoc);
150
    }
151
}
152