Failed Conditions
Push — master ( 2ade86...13f838 )
by Jonathan
18s
created

lib/Doctrine/ORM/Cache/DefaultCacheFactory.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 285
    public function __construct(RegionsConfiguration $cacheConfig, CacheAdapter $cache)
78
    {
79 285
        $this->cache         = $cache;
80 285
        $this->regionsConfig = $cacheConfig;
81 285
    }
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 131
    public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata)
119
    {
120 131
        $region     = $this->getRegion($metadata->cache);
121 131
        $usage      = $metadata->cache['usage'];
122
123 131
        if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) {
124 120
            return new ReadOnlyCachedEntityPersister($persister, $region, $em, $metadata);
125
        }
126
127 94
        if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) {
128 92
            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
$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
$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 64
    public function buildQueryCache(EntityManagerInterface $em, $regionName = null)
165
    {
166 64
        return new DefaultQueryCache(
167 64
            $em,
168 64
            $this->getRegion(
169
                [
170 64
                    'region' => $regionName ?: Cache::DEFAULT_QUERY_REGION_NAME,
171 64
                    '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 208
    public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata)
189
    {
190 208
        return new DefaultEntityHydrator($em);
191
    }
192
193
    /**
194
     * {@inheritdoc}
195
     */
196 134
    public function getRegion(array $cache)
197
    {
198 134
        if (isset($this->regions[$cache['region']])) {
199 26
            return $this->regions[$cache['region']];
200
        }
201
202 134
        $name         = $cache['region'];
203 134
        $cacheAdapter = $this->createRegionCache($name);
204 134
        $lifetime     = $this->regionsConfig->getLifetime($cache['region']);
205
206 134
        $region = ($cacheAdapter instanceof MultiGetCache)
207 133
            ? new DefaultMultiGetRegion($name, $cacheAdapter, $lifetime)
208 134
            : new DefaultRegion($name, $cacheAdapter, $lifetime);
209
210 134
        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 132
        return $this->regions[$cache['region']] = $region;
227
    }
228
229
    /**
230
     * @param string $name
231
     *
232
     * @return CacheAdapter
233
     */
234 134
    private function createRegionCache($name)
235
    {
236 134
        $cacheAdapter = clone $this->cache;
237
238 134
        if (!$cacheAdapter instanceof CacheProvider) {
239 1
            return $cacheAdapter;
240
        }
241
242 133
        $namespace = $cacheAdapter->getNamespace();
243
244 133
        if ('' !== $namespace) {
245 1
            $namespace .= ':';
246
        }
247
248 133
        $cacheAdapter->setNamespace($namespace . $name);
249
250 133
        return $cacheAdapter;
251
    }
252
253
    /**
254
     * {@inheritdoc}
255
     */
256 222
    public function getTimestampRegion()
257
    {
258 222
        if ($this->timestampRegion === null) {
259 222
            $name     = Cache::DEFAULT_TIMESTAMP_REGION_NAME;
260 222
            $lifetime = $this->regionsConfig->getLifetime($name);
261
262 222
            $this->timestampRegion = new UpdateTimestampCache($name, clone $this->cache, $lifetime);
263
        }
264
265 222
        return $this->timestampRegion;
266
    }
267
268
    /**
269
     * {@inheritdoc}
270
     */
271 285
    public function createCache(EntityManagerInterface $em)
272
    {
273 285
        return new DefaultCache($em);
274
    }
275
}
276