Failed Conditions
Push — 2.8.x ( 0ee171...60c486 )
by Benjamin
22:42 queued 16:29
created

storeCollectionCache()   B

Complexity

Conditions 9
Paths 16

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 9

Importance

Changes 0
Metric Value
cc 9
eloc 20
nc 16
nop 2
dl 0
loc 38
ccs 21
cts 21
cp 1
crap 9
rs 8.0555
c 0
b 0
f 0
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\Persister\Collection;
22
23
use Doctrine\Common\Collections\Criteria;
24
use Doctrine\ORM\Cache\EntityCacheKey;
25
use Doctrine\ORM\Cache\CollectionCacheKey;
26
use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister;
27
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
28
use Doctrine\ORM\PersistentCollection;
29
use Doctrine\ORM\EntityManagerInterface;
30
use Doctrine\ORM\Cache\Region;
31
use Doctrine\Common\Util\ClassUtils;
32
33
/**
34
 * @author Fabio B. Silva <[email protected]>
35
 * @author Guilherme Blanco <[email protected]>
36
 * @since 2.5
37
 */
38
abstract class AbstractCollectionPersister implements CachedCollectionPersister
39
{
40
     /**
41
     * @var \Doctrine\ORM\UnitOfWork
42
     */
43
    protected $uow;
44
45
    /**
46
     * @var \Doctrine\ORM\Mapping\ClassMetadataFactory
47
     */
48
    protected $metadataFactory;
49
50
    /**
51
     * @var \Doctrine\ORM\Persisters\Collection\CollectionPersister
52
     */
53
    protected $persister;
54
55
    /**
56
     * @var \Doctrine\ORM\Mapping\ClassMetadata
57
     */
58
    protected $sourceEntity;
59
60
    /**
61
     * @var \Doctrine\ORM\Mapping\ClassMetadata
62
     */
63
    protected $targetEntity;
64
65
    /**
66
     * @var array
67
     */
68
    protected $association;
69
70
     /**
71
     * @var array
72
     */
73
    protected $queuedCache = [];
74
75
    /**
76
     * @var \Doctrine\ORM\Cache\Region
77
     */
78
    protected $region;
79
80
    /**
81
     * @var string
82
     */
83
    protected $regionName;
84
85
    /**
86
     * @var \Doctrine\ORM\Cache\CollectionHydrator
87
     */
88
    protected $hydrator;
89
90
    /**
91
     * @var \Doctrine\ORM\Cache\Logging\CacheLogger
92
     */
93
    protected $cacheLogger;
94
95
    /**
96
     * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister   The collection persister that will be cached.
97
     * @param \Doctrine\ORM\Cache\Region                              $region      The collection region.
98
     * @param \Doctrine\ORM\EntityManagerInterface                    $em          The entity manager.
99
     * @param array                                                   $association The association mapping.
100
     */
101 114
    public function __construct(CollectionPersister $persister, Region $region, EntityManagerInterface $em, array $association)
102
    {
103 114
        $configuration  = $em->getConfiguration();
104 114
        $cacheConfig    = $configuration->getSecondLevelCacheConfiguration();
105 114
        $cacheFactory   = $cacheConfig->getCacheFactory();
106
107 114
        $this->region           = $region;
108 114
        $this->persister        = $persister;
109 114
        $this->association      = $association;
110 114
        $this->regionName       = $region->getName();
111 114
        $this->uow              = $em->getUnitOfWork();
112 114
        $this->metadataFactory  = $em->getMetadataFactory();
113 114
        $this->cacheLogger      = $cacheConfig->getCacheLogger();
114 114
        $this->hydrator         = $cacheFactory->buildCollectionHydrator($em, $association);
115 114
        $this->sourceEntity     = $em->getClassMetadata($association['sourceEntity']);
116 114
        $this->targetEntity     = $em->getClassMetadata($association['targetEntity']);
117 114
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122 63
    public function getCacheRegion()
123
    {
124 63
        return $this->region;
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function getSourceEntityMetadata()
131
    {
132
        return $this->sourceEntity;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138
    public function getTargetEntityMetadata()
139
    {
140
        return $this->targetEntity;
141
    }
142
143
    /**
144
     * @param \Doctrine\ORM\PersistentCollection     $collection
145
     * @param \Doctrine\ORM\Cache\CollectionCacheKey $key
146
     *
147
     * @return \Doctrine\ORM\PersistentCollection|null
148
     */
149 18
    public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key)
150
    {
151 18
        if (($cache = $this->region->get($key)) === null) {
152 14
            return null;
153
        }
154
155 15
        if (($cache = $this->hydrator->loadCacheEntry($this->sourceEntity, $key, $cache, $collection)) === null) {
0 ignored issues
show
introduced by
The condition $cache = $this->hydrator..., $collection) === null is always false.
Loading history...
156 1
            return null;
157
        }
158
159 15
        return $cache;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $cache returns the type array which is incompatible with the documented return type Doctrine\ORM\PersistentCollection|null.
Loading history...
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165 45
    public function storeCollectionCache(CollectionCacheKey $key, $elements)
166
    {
167
        /* @var $targetPersister CachedEntityPersister */
168 45
        $associationMapping = $this->sourceEntity->associationMappings[$key->association];
169 45
        $targetPersister    = $this->uow->getEntityPersister($this->targetEntity->rootEntityName);
170 45
        $targetRegion       = $targetPersister->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

170
        /** @scrutinizer ignore-call */ 
171
        $targetRegion       = $targetPersister->getCacheRegion();
Loading history...
171 45
        $targetHydrator     = $targetPersister->getEntityHydrator();
0 ignored issues
show
Bug introduced by
The method getEntityHydrator() 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

171
        /** @scrutinizer ignore-call */ 
172
        $targetHydrator     = $targetPersister->getEntityHydrator();
Loading history...
172
173
        // Only preserve ordering if association configured it
174 45
        if ( ! (isset($associationMapping['indexBy']) && $associationMapping['indexBy'])) {
175
            // Elements may be an array or a Collection
176 45
            $elements = array_values(is_array($elements) ? $elements : $elements->getValues());
177
        }
178
179 45
        $entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements);
180
181 45
        foreach ($entry->identifiers as $index => $entityKey) {
182 45
            if ($targetRegion->contains($entityKey)) {
183 45
                continue;
184
            }
185
186 11
            $class      = $this->targetEntity;
187 11
            $className  = ClassUtils::getClass($elements[$index]);
188
189 11
            if ($className !== $this->targetEntity->name) {
190 2
                $class = $this->metadataFactory->getMetadataFor($className);
191
            }
192
193 11
            $entity       = $elements[$index];
194 11
            $entityEntry  = $targetHydrator->buildCacheEntry($class, $entityKey, $entity);
195
196 11
            $targetRegion->put($entityKey, $entityEntry);
197
        }
198
199 45
        $cached = $this->region->put($key, $entry);
200
201 45
        if ($this->cacheLogger && $cached) {
202 45
            $this->cacheLogger->collectionCachePut($this->regionName, $key);
203
        }
204 45
    }
205
206
    /**
207
     * {@inheritdoc}
208
     */
209 3
    public function contains(PersistentCollection $collection, $element)
210
    {
211 3
        return $this->persister->contains($collection, $element);
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217 3
    public function containsKey(PersistentCollection $collection, $key)
218
    {
219 3
        return $this->persister->containsKey($collection, $key);
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225 4
    public function count(PersistentCollection $collection)
226
    {
227 4
        $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
228 4
        $key     = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId);
229 4
        $entry   = $this->region->get($key);
230
231 4
        if ($entry !== null) {
232 1
            return count($entry->identifiers);
0 ignored issues
show
Bug introduced by
Accessing identifiers on the interface Doctrine\ORM\Cache\CacheEntry suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
233
        }
234
235 4
        return $this->persister->count($collection);
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241 3
    public function get(PersistentCollection $collection, $index)
242
    {
243 3
        return $this->persister->get($collection, $index);
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249 3
    public function slice(PersistentCollection $collection, $offset, $length = null)
250
    {
251 3
        return $this->persister->slice($collection, $offset, $length);
252
    }
253
254
    /**
255
     * {@inheritDoc}
256
     */
257
    public function loadCriteria(PersistentCollection $collection, Criteria $criteria)
258
    {
259
        return $this->persister->loadCriteria($collection, $criteria);
260
    }
261
262
    /**
263
     * Clears cache entries related to the current collection
264
     *
265
     * @param PersistentCollection $collection
266
     */
267
    protected function evictCollectionCache(PersistentCollection $collection)
268
    {
269
        $key = new CollectionCacheKey(
270
            $this->sourceEntity->rootEntityName,
271
            $this->association['fieldName'],
272
            $this->uow->getEntityIdentifier($collection->getOwner())
273
        );
274
275
        $this->region->evict($key);
276
277
        if ($this->cacheLogger) {
278
            $this->cacheLogger->collectionCachePut($this->regionName, $key);
279
        }
280
    }
281
282
    /**
283
     * @param string $targetEntity
284
     * @param object $element
285
     */
286
    protected function evictElementCache($targetEntity, $element)
287
    {
288
        /* @var $targetPersister CachedEntityPersister */
289
        $targetPersister = $this->uow->getEntityPersister($targetEntity);
290
        $targetRegion    = $targetPersister->getCacheRegion();
291
        $key             = new EntityCacheKey($targetEntity, $this->uow->getEntityIdentifier($element));
292
293
        $targetRegion->evict($key);
294
295
        if ($this->cacheLogger) {
296
            $this->cacheLogger->entityCachePut($targetRegion->getName(), $key);
297
        }
298
    }
299
}
300