Passed
Push — master ( fda770...94640a )
by Marco
23:51 queued 14:09
created

DefaultCacheFactory::setTimestampRegion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 0
cts 3
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
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\Cache\Cache as CacheAdapter;
24
use Doctrine\Common\Cache\CacheProvider;
25
use Doctrine\Common\Cache\MultiGetCache;
26
use Doctrine\ORM\Cache;
27
use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister;
28
use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister;
29
use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister;
30
use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister;
31
use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister;
32
use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister;
33
use Doctrine\ORM\Cache\Region\DefaultMultiGetRegion;
34
use Doctrine\ORM\Cache\Region\DefaultRegion;
35
use Doctrine\ORM\Cache\Region\FileLockRegion;
36
use Doctrine\ORM\Cache\Region\UpdateTimestampCache;
37
use Doctrine\ORM\EntityManagerInterface;
38
use Doctrine\ORM\Mapping\ClassMetadata;
39
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
40
use Doctrine\ORM\Persisters\Entity\EntityPersister;
41
42
/**
43
 * @since   2.5
44
 * @author  Fabio B. Silva <[email protected]>
45
 */
46
class DefaultCacheFactory implements CacheFactory
47
{
48
    /**
49
     * @var CacheAdapter
50
     */
51
    private $cache;
52
53
    /**
54
     * @var \Doctrine\ORM\Cache\RegionsConfiguration
55
     */
56
    private $regionsConfig;
57
58
    /**
59
     * @var \Doctrine\ORM\Cache\TimestampRegion|null
60
     */
61
    private $timestampRegion;
62
63
    /**
64
     * @var \Doctrine\ORM\Cache\Region[]
65
     */
66
    private $regions = [];
67
68
    /**
69
     * @var string|null
70
     */
71
    private $fileLockRegionDirectory;
72
73
    /**
74
     * @param RegionsConfiguration $cacheConfig
75
     * @param CacheAdapter         $cache
76
     */
77 284
    public function __construct(RegionsConfiguration $cacheConfig, CacheAdapter $cache)
78
    {
79 284
        $this->cache         = $cache;
80 284
        $this->regionsConfig = $cacheConfig;
81 284
    }
82
83
    /**
84
     * @param string $fileLockRegionDirectory
85
     */
86 1
    public function setFileLockRegionDirectory($fileLockRegionDirectory)
87
    {
88 1
        $this->fileLockRegionDirectory = (string) $fileLockRegionDirectory;
89 1
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function getFileLockRegionDirectory()
95
    {
96
        return $this->fileLockRegionDirectory;
97
    }
98
99
    /**
100
     * @param \Doctrine\ORM\Cache\Region $region
101
     */
102
    public function setRegion(Region $region)
103
    {
104
        $this->regions[$region->getName()] = $region;
105
    }
106
107
    /**
108
     * @param \Doctrine\ORM\Cache\TimestampRegion $region
109
     */
110
    public function setTimestampRegion(TimestampRegion $region)
111
    {
112
        $this->timestampRegion = $region;
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 130
    public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata)
119
    {
120 130
        $region     = $this->getRegion($metadata->cache);
121 130
        $usage      = $metadata->cache['usage'];
122
123 130
        if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) {
124 120
            return new ReadOnlyCachedEntityPersister($persister, $region, $em, $metadata);
125
        }
126
127 93
        if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) {
128 91
            return new NonStrictReadWriteCachedEntityPersister($persister, $region, $em, $metadata);
129
        }
130
131 2
        if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) {
132 1
            return new ReadWriteCachedEntityPersister($persister, $region, $em, $metadata);
0 ignored issues
show
Compatibility introduced by
$region of type object<Doctrine\ORM\Cache\Region> is not a sub-type of object<Doctrine\ORM\Cache\ConcurrentRegion>. It seems like you assume a child interface of the interface Doctrine\ORM\Cache\Region to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
133
        }
134
135 1
        throw new \InvalidArgumentException(sprintf("Unrecognized access strategy type [%s]", $usage));
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 81
    public function buildCachedCollectionPersister(EntityManagerInterface $em, CollectionPersister $persister, array $mapping)
142
    {
143 81
        $usage      = $mapping['cache']['usage'];
144 81
        $region     = $this->getRegion($mapping['cache']);
145
146 81
        if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) {
147 59
            return new ReadOnlyCachedCollectionPersister($persister, $region, $em, $mapping);
148
        }
149
150 80
        if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) {
151 78
            return new NonStrictReadWriteCachedCollectionPersister($persister, $region, $em, $mapping);
152
        }
153
154 2
        if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) {
155 1
            return new ReadWriteCachedCollectionPersister($persister, $region, $em, $mapping);
0 ignored issues
show
Compatibility introduced by
$region of type object<Doctrine\ORM\Cache\Region> is not a sub-type of object<Doctrine\ORM\Cache\ConcurrentRegion>. It seems like you assume a child interface of the interface Doctrine\ORM\Cache\Region to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
156
        }
157
158 1
        throw new \InvalidArgumentException(sprintf("Unrecognized access strategy type [%s]", $usage));
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164 63
    public function buildQueryCache(EntityManagerInterface $em, $regionName = null)
165
    {
166 63
        return new DefaultQueryCache(
167 63
            $em,
168 63
            $this->getRegion(
169
                [
170 63
                    'region' => $regionName ?: Cache::DEFAULT_QUERY_REGION_NAME,
171 63
                    'usage'  => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE
172
                ]
173
            )
174
        );
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 117
    public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping)
181
    {
182 117
        return new DefaultCollectionHydrator($em);
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188 207
    public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata)
189
    {
190 207
        return new DefaultEntityHydrator($em);
191
    }
192
193
    /**
194
     * {@inheritdoc}
195
     */
196 133
    public function getRegion(array $cache)
197
    {
198 133
        if (isset($this->regions[$cache['region']])) {
199 25
            return $this->regions[$cache['region']];
200
        }
201
202 133
        $name         = $cache['region'];
203 133
        $cacheAdapter = $this->createRegionCache($name);
204 133
        $lifetime     = $this->regionsConfig->getLifetime($cache['region']);
205
206 133
        $region = ($cacheAdapter instanceof MultiGetCache)
207 132
            ? new DefaultMultiGetRegion($name, $cacheAdapter, $lifetime)
208 133
            : new DefaultRegion($name, $cacheAdapter, $lifetime);
209
210 133
        if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
211
212
            if (
213 2
                '' === $this->fileLockRegionDirectory ||
214 2
                null === $this->fileLockRegionDirectory
215
            ) {
216 2
                throw new \LogicException(
217
                    'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' .
218 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(). '
219
                );
220
            }
221
222
            $directory = $this->fileLockRegionDirectory . DIRECTORY_SEPARATOR . $cache['region'];
223
            $region    = new FileLockRegion($region, $directory, $this->regionsConfig->getLockLifetime($cache['region']));
224
        }
225
226 131
        return $this->regions[$cache['region']] = $region;
227
    }
228
229
    /**
230
     * @param string $name
231
     *
232
     * @return CacheAdapter
233
     */
234 133
    private function createRegionCache($name)
235
    {
236 133
        $cacheAdapter = clone $this->cache;
237
238 133
        if (!$cacheAdapter instanceof CacheProvider) {
239 1
            return $cacheAdapter;
240
        }
241
242 132
        $namespace = $cacheAdapter->getNamespace();
243
244 132
        if ('' !== $namespace) {
245 1
            $namespace .= ':';
246
        }
247
248 132
        $cacheAdapter->setNamespace($namespace . $name);
249
250 132
        return $cacheAdapter;
251
    }
252
253
    /**
254
     * {@inheritdoc}
255
     */
256 221
    public function getTimestampRegion()
257
    {
258 221
        if ($this->timestampRegion === null) {
259 221
            $name     = Cache::DEFAULT_TIMESTAMP_REGION_NAME;
260 221
            $lifetime = $this->regionsConfig->getLifetime($name);
261
262 221
            $this->timestampRegion = new UpdateTimestampCache($name, clone $this->cache, $lifetime);
263
        }
264
265 221
        return $this->timestampRegion;
266
    }
267
268
    /**
269
     * {@inheritdoc}
270
     */
271 284
    public function createCache(EntityManagerInterface $em)
272
    {
273 284
        return new DefaultCache($em);
274
    }
275
}
276