Failed Conditions
Push — master ( 8be1e3...e3936d )
by Marco
14s
created

DefaultCacheFactory::buildCachedEntityPersister()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 3
dl 0
loc 21
ccs 11
cts 11
cp 1
crap 4
rs 9.0534
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Cache;
6
7
use Doctrine\Common\Cache\Cache as CacheAdapter;
8
use Doctrine\Common\Cache\CacheProvider;
9
use Doctrine\Common\Cache\MultiGetCache;
10
use Doctrine\ORM\Cache;
11
use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister;
12
use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister;
13
use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister;
14
use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister;
15
use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister;
16
use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister;
17
use Doctrine\ORM\Cache\Region\DefaultMultiGetRegion;
18
use Doctrine\ORM\Cache\Region\DefaultRegion;
19
use Doctrine\ORM\Cache\Region\FileLockRegion;
20
use Doctrine\ORM\Cache\Region\UpdateTimestampCache;
21
use Doctrine\ORM\EntityManagerInterface;
22
use Doctrine\ORM\Mapping\AssociationMetadata;
23
use Doctrine\ORM\Mapping\CacheMetadata;
24
use Doctrine\ORM\Mapping\CacheUsage;
25
use Doctrine\ORM\Mapping\ClassMetadata;
26
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
27
use Doctrine\ORM\Persisters\Entity\EntityPersister;
28
29
class DefaultCacheFactory implements CacheFactory
30
{
31
    /**
32
     * @var CacheAdapter
33
     */
34
    private $cache;
35
36
    /**
37
     * @var \Doctrine\ORM\Cache\RegionsConfiguration
38
     */
39
    private $regionsConfig;
40
41
    /**
42
     * @var \Doctrine\ORM\Cache\TimestampRegion|null
43
     */
44
    private $timestampRegion;
45
46
    /**
47
     * @var \Doctrine\ORM\Cache\Region[]
48
     */
49
    private $regions = [];
50
51
    /**
52
     * @var string|null
53
     */
54
    private $fileLockRegionDirectory;
55
56 279
    public function __construct(RegionsConfiguration $cacheConfig, CacheAdapter $cache)
57
    {
58 279
        $this->regionsConfig = $cacheConfig;
59 279
        $this->cache         = $cache;
60 279
    }
61
62
    /**
63
     * @param string $fileLockRegionDirectory
64
     */
65 1
    public function setFileLockRegionDirectory($fileLockRegionDirectory)
66
    {
67 1
        $this->fileLockRegionDirectory = (string) $fileLockRegionDirectory;
68 1
    }
69
70
    /**
71
     * @return string
72
     */
73
    public function getFileLockRegionDirectory()
74
    {
75
        return $this->fileLockRegionDirectory;
76
    }
77
78
    public function setRegion(Region $region)
79
    {
80
        $this->regions[$region->getName()] = $region;
81
    }
82
83
    public function setTimestampRegion(TimestampRegion $region)
84
    {
85
        $this->timestampRegion = $region;
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 136
    public function buildCachedEntityPersister(
92
        EntityManagerInterface $em,
93
        EntityPersister $persister,
94
        ClassMetadata $metadata
95
    ) {
96 136
        $cache  = $metadata->getCache();
97 136
        $region = $this->getRegion($cache);
98 136
        $usage  = $cache->getUsage();
99
100
        switch ($usage) {
101 136
            case CacheUsage::READ_ONLY:
102 126
                return new ReadOnlyCachedEntityPersister($persister, $region, $em, $metadata);
103
104 93
            case CacheUsage::READ_WRITE:
105 1
                return new ReadWriteCachedEntityPersister($persister, $region, $em, $metadata);
106
107 92
            case CacheUsage::NONSTRICT_READ_WRITE:
108 91
                return new NonStrictReadWriteCachedEntityPersister($persister, $region, $em, $metadata);
109
110
            default:
111 1
                throw new \InvalidArgumentException(sprintf('Unrecognized access strategy type [%s]', $usage));
112
        }
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 81
    public function buildCachedCollectionPersister(
119
        EntityManagerInterface $em,
120
        CollectionPersister $persister,
121
        AssociationMetadata $association
122
    ) {
123 81
        $cache  = $association->getCache();
124 81
        $region = $this->getRegion($cache);
125 81
        $usage  = $cache->getUsage();
126
127
        switch ($usage) {
128 81
            case CacheUsage::READ_ONLY:
129 59
                return new ReadOnlyCachedCollectionPersister($persister, $region, $em, $association);
130
131 80
            case CacheUsage::READ_WRITE:
132 1
                return new ReadWriteCachedCollectionPersister($persister, $region, $em, $association);
133
134 79
            case CacheUsage::NONSTRICT_READ_WRITE:
135 78
                return new NonStrictReadWriteCachedCollectionPersister($persister, $region, $em, $association);
136
137
            default:
138 1
                throw new \InvalidArgumentException(
139 1
                    sprintf('Unrecognized access strategy type [%s]', $usage)
140
                );
141
        }
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 64
    public function buildQueryCache(EntityManagerInterface $em, $regionName = null)
148
    {
149 64
        $cacheMetadata = new CacheMetadata(
150 64
            CacheUsage::NONSTRICT_READ_WRITE,
151 64
            $regionName ?: Cache::DEFAULT_QUERY_REGION_NAME
152
        );
153
154 64
        return new DefaultQueryCache($em, $this->getRegion($cacheMetadata));
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160 117
    public function buildCollectionHydrator(EntityManagerInterface $em, AssociationMetadata $association)
161
    {
162 117
        return new DefaultCollectionHydrator($em);
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168 202
    public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata)
169
    {
170 202
        return new DefaultEntityHydrator($em);
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 139
    public function getRegion(CacheMetadata $cache)
177
    {
178 139
        $regionName = $cache->getRegion();
179
180 139
        if (isset($this->regions[$regionName])) {
181 88
            return $this->regions[$regionName];
182
        }
183
184 139
        $cacheAdapter = $this->createRegionCache($regionName);
185 139
        $lifetime     = $this->regionsConfig->getLifetime($regionName);
186 139
        $region       = ($cacheAdapter instanceof MultiGetCache)
187 138
            ? new DefaultMultiGetRegion($regionName, $cacheAdapter, $lifetime)
188 139
            : new DefaultRegion($regionName, $cacheAdapter, $lifetime)
189
        ;
190
191 139
        if ($cache->getUsage() === CacheUsage::READ_WRITE) {
192 2
            if (! $this->fileLockRegionDirectory) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->fileLockRegionDirectory of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
193 2
                throw new \LogicException(
194
                    'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' .
195 2
                    'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you want to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). '
196
                );
197
            }
198
199
            $directory = $this->fileLockRegionDirectory . DIRECTORY_SEPARATOR . $regionName;
200
            $region    = new FileLockRegion($region, $directory, $this->regionsConfig->getLockLifetime($regionName));
201
        }
202
203 137
        return $this->regions[$regionName] = $region;
204
    }
205
206
    /**
207
     * @param string $name
208
     *
209
     * @return CacheAdapter
210
     */
211 139
    private function createRegionCache($name)
212
    {
213 139
        $cacheAdapter = clone $this->cache;
214
215 139
        if (! $cacheAdapter instanceof CacheProvider) {
216 1
            return $cacheAdapter;
217
        }
218
219 138
        $namespace = $cacheAdapter->getNamespace();
220
221 138
        if ($namespace !== '') {
222 1
            $namespace .= ':';
223
        }
224
225 138
        $cacheAdapter->setNamespace($namespace . $name);
226
227 138
        return $cacheAdapter;
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233 216
    public function getTimestampRegion()
234
    {
235 216
        if ($this->timestampRegion === null) {
236 216
            $name     = Cache::DEFAULT_TIMESTAMP_REGION_NAME;
237 216
            $lifetime = $this->regionsConfig->getLifetime($name);
238
239 216
            $this->timestampRegion = new UpdateTimestampCache($name, clone $this->cache, $lifetime);
240
        }
241
242 216
        return $this->timestampRegion;
243
    }
244
245
    /**
246
     * {@inheritdoc}
247
     */
248 279
    public function createCache(EntityManagerInterface $em)
249
    {
250 279
        return new DefaultCache($em);
251
    }
252
}
253