Passed
Push — 2.6 ( 48bfef...6e56bc )
by Luís
12:52 queued 04:45
created

DefaultEntityHydrator::buildCacheEntry()   C

Complexity

Conditions 15
Paths 36

Size

Total Lines 79
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 15.0713

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 43
c 1
b 0
f 0
nop 3
dl 0
loc 79
ccs 41
cts 44
cp 0.9318
crap 15.0713
rs 5.9166
nc 36

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the MIT license. For more information, see
18
 * <http://www.doctrine-project.org>.
19
 */
20
21
namespace Doctrine\ORM\Cache;
22
23
use Doctrine\Common\Util\ClassUtils;
24
25
use Doctrine\ORM\Query;
26
use Doctrine\ORM\Mapping\ClassMetadata;
27
use Doctrine\ORM\EntityManagerInterface;
28
use Doctrine\ORM\Utility\IdentifierFlattener;
29
30
/**
31
 * Default hydrator cache for entities
32
 *
33
 * @since   2.5
34
 * @author  Fabio B. Silva <[email protected]>
35
 */
36
class DefaultEntityHydrator implements EntityHydrator
37
{
38
    /**
39
     * @var \Doctrine\ORM\EntityManagerInterface
40
     */
41
    private $em;
42
43
    /**
44
     * @var \Doctrine\ORM\UnitOfWork
45
     */
46
    private $uow;
47
48
    /**
49
     * The IdentifierFlattener used for manipulating identifiers
50
     *
51
     * @var \Doctrine\ORM\Utility\IdentifierFlattener
52
     */
53
    private $identifierFlattener;
54
55
    /**
56
     * @var array
57
     */
58
    private static $hints = [Query::HINT_CACHE_ENABLED => true];
59
60
    /**
61
     * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager.
62
     */
63 217
    public function __construct(EntityManagerInterface $em)
64
    {
65 217
        $this->em   = $em;
66 217
        $this->uow  = $em->getUnitOfWork();
67 217
        $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory());
68 217
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73 119
    public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity)
74
    {
75 119
        $data = $this->uow->getOriginalEntityData($entity);
76 119
        $data = array_merge($data, $metadata->getIdentifierValues($entity)); // why update has no identifier values ?
77
78 119
        if ($metadata->isVersioned) {
79 1
            $data[$metadata->versionField] = $metadata->getFieldValue($entity, $metadata->versionField);
80
        }
81
82 119
        foreach ($metadata->associationMappings as $name => $assoc) {
83 72
            if ( ! isset($data[$name])) {
84 26
                continue;
85
            }
86
87 71
            if ( ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
88 59
                unset($data[$name]);
89
90 59
                continue;
91
            }
92
93 70
            if ( ! isset($assoc['cache'])) {
94 5
                $targetClassMetadata = $this->em->getClassMetadata($assoc['targetEntity']);
95 5
                $owningAssociation   = ( ! $assoc['isOwningSide'])
96 1
                    ? $targetClassMetadata->associationMappings[$assoc['mappedBy']]
0 ignored issues
show
Bug introduced by
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
97 5
                    : $assoc;
98 5
                $associationIds      = $this->identifierFlattener->flattenIdentifier(
99 5
                    $targetClassMetadata,
100 5
                    $targetClassMetadata->getIdentifierValues($data[$name])
101
                );
102
103 5
                unset($data[$name]);
104
105 5
                foreach ($associationIds as $fieldName => $fieldValue) {
106 5
                    if (isset($targetClassMetadata->fieldMappings[$fieldName])) {
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
107 5
                        $fieldMapping = $targetClassMetadata->fieldMappings[$fieldName];
108
109 5
                        $data[$owningAssociation['targetToSourceKeyColumns'][$fieldMapping['columnName']]] = $fieldValue;
110
111 5
                        continue;
112
                    }
113
114 1
                    $targetAssoc = $targetClassMetadata->associationMappings[$fieldName];
115
116 1
                    foreach($assoc['targetToSourceKeyColumns'] as $referencedColumn => $localColumn) {
117 1
                        if (isset($targetAssoc['sourceToTargetKeyColumns'][$referencedColumn])) {
118 1
                            $data[$localColumn] = $fieldValue;
119
                        }
120
                    }
121
                }
122
123 5
                continue;
124
            }
125
126 66
            if ( ! isset($assoc['id'])) {
127 65
                $targetClass = ClassUtils::getClass($data[$name]);
128 65
                $targetId    = $this->uow->getEntityIdentifier($data[$name]);
129 65
                $data[$name] = new AssociationCacheEntry($targetClass, $targetId);
130
131 65
                continue;
132
            }
133
134
            // handle association identifier
135 5
            $targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name])
136 5
                ? $this->uow->getEntityIdentifier($data[$name])
137 5
                : $data[$name];
138
139
            // @TODO - fix it !
140
            // handle UnitOfWork#createEntity hash generation
141 5
            if ( ! is_array($targetId)) {
142
                $data[reset($assoc['joinColumnFieldNames'])] = $targetId;
143
144
                $targetEntity = $this->em->getClassMetadata($assoc['targetEntity']);
145
                $targetId     = [$targetEntity->identifier[0] => $targetId];
0 ignored issues
show
Bug introduced by
Accessing identifier on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
146
            }
147
148 5
            $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId);
149
        }
150
151 119
        return new EntityCacheEntry($metadata->name, $data);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 43
    public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null)
158
    {
159 43
        $data  = $entry->data;
160 43
        $hints = self::$hints;
161
162 43
        if ($entity !== null) {
163 7
            $hints[Query::HINT_REFRESH]         = true;
164 7
            $hints[Query::HINT_REFRESH_ENTITY]  = $entity;
165
        }
166
167 43
        foreach ($metadata->associationMappings as $name => $assoc) {
168 35
            if ( ! isset($assoc['cache']) ||  ! isset($data[$name])) {
169 27
                continue;
170
            }
171
172 29
            $assocClass     = $data[$name]->class;
173 29
            $assocId        = $data[$name]->identifier;
174 29
            $isEagerLoad    = ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ($assoc['type'] === ClassMetadata::ONE_TO_ONE && ! $assoc['isOwningSide']));
175
176 29
            if ( ! $isEagerLoad) {
177 27
                $data[$name] = $this->em->getReference($assocClass, $assocId);
178
179 27
                continue;
180
            }
181
182 4
            $assocMetadata  = $this->em->getClassMetadata($assoc['targetEntity']);
183 4
            $assocKey       = new EntityCacheKey($assocMetadata->rootEntityName, $assocId);
0 ignored issues
show
Bug introduced by
Accessing rootEntityName on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
184 4
            $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
185 4
            $assocRegion    = $assocPersister->getCacheRegion();
0 ignored issues
show
Bug introduced by
The method getCacheRegion() does not exist on Doctrine\ORM\Persisters\Entity\EntityPersister. It seems like you code against a sub-type of Doctrine\ORM\Persisters\Entity\EntityPersister such as Doctrine\ORM\Cache\Persi...y\CachedEntityPersister. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

185
            /** @scrutinizer ignore-call */ 
186
            $assocRegion    = $assocPersister->getCacheRegion();
Loading history...
186 4
            $assocEntry     = $assocRegion->get($assocKey);
187
188 4
            if ($assocEntry === null) {
189 1
                return null;
190
            }
191
192 3
            $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), $hints);
193
        }
194
195 43
        if ($entity !== null) {
196 6
            $this->uow->registerManaged($entity, $key->identifier, $data);
197
        }
198
199 43
        $result = $this->uow->createEntity($entry->class, $data, $hints);
200
201 43
        $this->uow->hydrationComplete();
202
203 43
        return $result;
204
    }
205
}
206