commit
4cde35dc18
@ -19,6 +19,7 @@
|
|||||||
"doctrine/dbal": ">=2.5-dev,<2.6-dev",
|
"doctrine/dbal": ">=2.5-dev,<2.6-dev",
|
||||||
"doctrine/instantiator": "~1.0.1",
|
"doctrine/instantiator": "~1.0.1",
|
||||||
"doctrine/common": ">=2.5-dev,<2.6-dev",
|
"doctrine/common": ">=2.5-dev,<2.6-dev",
|
||||||
|
"doctrine/cache": "~1.4",
|
||||||
"symfony/console": "~2.5"
|
"symfony/console": "~2.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
@ -185,7 +185,7 @@ To enable the second-level-cache, you should provide a cache factory
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/* var $config \Doctrine\ORM\Cache\RegionsConfiguration */
|
/* var $config \Doctrine\ORM\Cache\RegionsConfiguration */
|
||||||
/* var $cache \Doctrine\Common\Cache\CacheProvider */
|
/* var $cache \Doctrine\Common\Cache\Cache */
|
||||||
|
|
||||||
$factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($config, $cache);
|
$factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($config, $cache);
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ class CollectionCacheEntry implements CacheEntry
|
|||||||
/**
|
/**
|
||||||
* READ-ONLY: Public only for performance reasons, it should be considered immutable.
|
* READ-ONLY: Public only for performance reasons, it should be considered immutable.
|
||||||
*
|
*
|
||||||
* @var array The list of entity identifiers hold by the collection
|
* @var CacheKey[] The list of entity identifiers hold by the collection
|
||||||
*/
|
*/
|
||||||
public $identifiers;
|
public $identifiers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $identifiers List of entity identifiers hold by the collection
|
* @param CacheKey[] $identifiers List of entity identifiers hold by the collection
|
||||||
*/
|
*/
|
||||||
public function __construct(array $identifiers)
|
public function __construct(array $identifiers)
|
||||||
{
|
{
|
||||||
@ -46,9 +46,11 @@ class CollectionCacheEntry implements CacheEntry
|
|||||||
/**
|
/**
|
||||||
* Creates a new CollectionCacheEntry
|
* Creates a new CollectionCacheEntry
|
||||||
*
|
*
|
||||||
* This method allow Doctrine\Common\Cache\PhpFileCache compatibility
|
* This method allows for Doctrine\Common\Cache\PhpFileCache compatibility
|
||||||
*
|
*
|
||||||
* @param array $values array containing property values
|
* @param array $values array containing property values
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
*/
|
*/
|
||||||
public static function __set_state(array $values)
|
public static function __set_state(array $values)
|
||||||
{
|
{
|
||||||
|
@ -20,23 +20,25 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Cache;
|
namespace Doctrine\ORM\Cache;
|
||||||
|
|
||||||
|
use Doctrine\Common\Cache\Cache as CacheAdapter;
|
||||||
use Doctrine\Common\Cache\CacheProvider;
|
use Doctrine\Common\Cache\CacheProvider;
|
||||||
|
use Doctrine\Common\Cache\MultiGetCache;
|
||||||
use Doctrine\ORM\Cache;
|
use Doctrine\ORM\Cache;
|
||||||
use Doctrine\ORM\Cache\Region;
|
use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use Doctrine\ORM\Cache\Region\DefaultRegion;
|
|
||||||
use Doctrine\ORM\Cache\Region\FileLockRegion;
|
|
||||||
use Doctrine\ORM\Cache\Region\UpdateTimestampCache;
|
|
||||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
|
||||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
|
||||||
use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister;
|
|
||||||
use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister;
|
|
||||||
use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister;
|
use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister;
|
||||||
use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister;
|
use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister;
|
||||||
use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister;
|
use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister;
|
||||||
use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister;
|
use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister;
|
||||||
|
use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister;
|
||||||
|
use Doctrine\ORM\Cache\Region;
|
||||||
|
use Doctrine\ORM\Cache\Region\DefaultMultiGetRegion;
|
||||||
|
use Doctrine\ORM\Cache\Region\DefaultRegion;
|
||||||
|
use Doctrine\ORM\Cache\Region\FileLockRegion;
|
||||||
|
use Doctrine\ORM\Cache\Region\UpdateTimestampCache;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||||
|
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 2.5
|
* @since 2.5
|
||||||
@ -45,7 +47,7 @@ use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPe
|
|||||||
class DefaultCacheFactory implements CacheFactory
|
class DefaultCacheFactory implements CacheFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var \Doctrine\Common\Cache\CacheProvider
|
* @var CacheAdapter
|
||||||
*/
|
*/
|
||||||
private $cache;
|
private $cache;
|
||||||
|
|
||||||
@ -70,10 +72,10 @@ class DefaultCacheFactory implements CacheFactory
|
|||||||
private $fileLockRegionDirectory;
|
private $fileLockRegionDirectory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Doctrine\ORM\Cache\RegionsConfiguration $cacheConfig
|
* @param RegionsConfiguration $cacheConfig
|
||||||
* @param \Doctrine\Common\Cache\CacheProvider $cache
|
* @param CacheAdapter $cache
|
||||||
*/
|
*/
|
||||||
public function __construct(RegionsConfiguration $cacheConfig, CacheProvider $cache)
|
public function __construct(RegionsConfiguration $cacheConfig, CacheAdapter $cache)
|
||||||
{
|
{
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
$this->regionsConfig = $cacheConfig;
|
$this->regionsConfig = $cacheConfig;
|
||||||
@ -178,7 +180,13 @@ class DefaultCacheFactory implements CacheFactory
|
|||||||
*/
|
*/
|
||||||
public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping)
|
public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping)
|
||||||
{
|
{
|
||||||
return new DefaultCollectionHydrator($em);
|
/* @var $targetPersister \Doctrine\ORM\Cache\Persister\CachedPersister */
|
||||||
|
$targetPersister = $em->getUnitOfWork()->getEntityPersister($mapping['targetEntity']);
|
||||||
|
|
||||||
|
return new DefaultCollectionHydrator(
|
||||||
|
$em,
|
||||||
|
$targetPersister->getCacheRegion()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,9 +208,16 @@ class DefaultCacheFactory implements CacheFactory
|
|||||||
|
|
||||||
$cacheAdapter = clone $this->cache;
|
$cacheAdapter = clone $this->cache;
|
||||||
|
|
||||||
|
if ($cacheAdapter instanceof CacheProvider) {
|
||||||
$cacheAdapter->setNamespace($cache['region']);
|
$cacheAdapter->setNamespace($cache['region']);
|
||||||
|
}
|
||||||
|
|
||||||
$region = new DefaultRegion($cache['region'], $cacheAdapter, $this->regionsConfig->getLifetime($cache['region']));
|
$name = $cache['region'];
|
||||||
|
$lifetime = $this->regionsConfig->getLifetime($cache['region']);
|
||||||
|
|
||||||
|
$region = ($cacheAdapter instanceof MultiGetCache)
|
||||||
|
? new DefaultMultiGetRegion($name, $cacheAdapter, $lifetime)
|
||||||
|
: new DefaultRegion($name, $cacheAdapter, $lifetime);
|
||||||
|
|
||||||
if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
|
if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
|
||||||
|
|
||||||
|
@ -65,9 +65,8 @@ class DefaultCollectionHydrator implements CollectionHydrator
|
|||||||
$data = array();
|
$data = array();
|
||||||
|
|
||||||
foreach ($collection as $index => $entity) {
|
foreach ($collection as $index => $entity) {
|
||||||
$data[$index] = $this->uow->getEntityIdentifier($entity);
|
$data[$index] = new EntityCacheKey($metadata->name, $this->uow->getEntityIdentifier($entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CollectionCacheEntry($data);
|
return new CollectionCacheEntry($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,19 +76,20 @@ class DefaultCollectionHydrator implements CollectionHydrator
|
|||||||
public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection)
|
public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection)
|
||||||
{
|
{
|
||||||
$assoc = $metadata->associationMappings[$key->association];
|
$assoc = $metadata->associationMappings[$key->association];
|
||||||
|
/* @var $targetPersister \Doctrine\ORM\Cache\Persister\CachedPersister */
|
||||||
$targetPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
|
$targetPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
|
||||||
$targetRegion = $targetPersister->getCacheRegion();
|
$targetRegion = $targetPersister->getCacheRegion();
|
||||||
$list = array();
|
$list = array();
|
||||||
|
|
||||||
foreach ($entry->identifiers as $index => $identifier) {
|
$entityEntries = $targetRegion->getMultiple($entry);
|
||||||
|
|
||||||
$entityEntry = $targetRegion->get(new EntityCacheKey($assoc['targetEntity'], $identifier));
|
if ($entityEntries === null) {
|
||||||
|
|
||||||
if ($entityEntry === null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$list[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints);
|
/* @var $entityEntries \Doctrine\ORM\Cache\EntityCacheEntry[] */
|
||||||
|
foreach ($entityEntries as $index => $entityEntry) {
|
||||||
|
$list[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->data, self::$hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($list, function($entity, $index) use ($collection) {
|
array_walk($list, function($entity, $index) use ($collection) {
|
||||||
|
42
lib/Doctrine/ORM/Cache/MultiGetRegion.php
Normal file
42
lib/Doctrine/ORM/Cache/MultiGetRegion.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many individuals
|
||||||
|
* and is licensed under the MIT license. For more information, see
|
||||||
|
* <http://www.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a region that supports multi-get reading.
|
||||||
|
*
|
||||||
|
* With one method call we can get multipe items.
|
||||||
|
*
|
||||||
|
* @since 2.5
|
||||||
|
* @author Asmir Mustafic
|
||||||
|
*/
|
||||||
|
interface MultiGetRegion
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get all items from the cache indentifed by $keys.
|
||||||
|
* It returns NULL if some elements can not be found.
|
||||||
|
*
|
||||||
|
* @param CollectionCacheEntry $collection The collection of the items to be retrieved.
|
||||||
|
*
|
||||||
|
* @return CacheEntry[]|null The cached entries or NULL if one or more entries can not be found
|
||||||
|
*/
|
||||||
|
public function getMultiple(CollectionCacheEntry $collection);
|
||||||
|
}
|
@ -167,8 +167,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
|
|||||||
$targetHydrator = $targetPersister->getEntityHydrator();
|
$targetHydrator = $targetPersister->getEntityHydrator();
|
||||||
$entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements);
|
$entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements);
|
||||||
|
|
||||||
foreach ($entry->identifiers as $index => $identifier) {
|
foreach ($entry->identifiers as $index => $entityKey) {
|
||||||
$entityKey = new EntityCacheKey($this->targetEntity->rootEntityName, $identifier);
|
|
||||||
|
|
||||||
if ($targetRegion->contains($entityKey)) {
|
if ($targetRegion->contains($entityKey)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -26,7 +26,7 @@ namespace Doctrine\ORM\Cache;
|
|||||||
* @since 2.5
|
* @since 2.5
|
||||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||||
*/
|
*/
|
||||||
interface Region
|
interface Region extends MultiGetRegion
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Retrieve the name of this region.
|
* Retrieve the name of this region.
|
||||||
|
75
lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php
Normal file
75
lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many individuals
|
||||||
|
* and is licensed under the MIT license. For more information, see
|
||||||
|
* <http://www.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Cache\Region;
|
||||||
|
|
||||||
|
use Doctrine\Common\Cache\MultiGetCache;
|
||||||
|
use Doctrine\ORM\Cache\Region;
|
||||||
|
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cache region that enables the retrieval of multiple elements with one call
|
||||||
|
*
|
||||||
|
* @since 2.5
|
||||||
|
* @author Asmir Mustafic <goetas@gmail.com>
|
||||||
|
*/
|
||||||
|
class DefaultMultiGetRegion extends DefaultRegion
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Note that the multiple type is due to doctrine/cache not integrating the MultiGetCache interface
|
||||||
|
* in its signature due to BC in 1.x
|
||||||
|
*
|
||||||
|
* @var MultiGetCache|\Doctrine\Common\Cache\Cache
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @param MultiGetCache $cache
|
||||||
|
*/
|
||||||
|
public function __construct($name, MultiGetCache $cache, $lifetime = 0)
|
||||||
|
{
|
||||||
|
/* @var $cache \Doctrine\Common\Cache\Cache */
|
||||||
|
parent::__construct($name, $cache, $lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMultiple(CollectionCacheEntry $collection)
|
||||||
|
{
|
||||||
|
$keysToRetrieve = array();
|
||||||
|
foreach ($collection->identifiers as $index => $key) {
|
||||||
|
$keysToRetrieve[$index] = $this->name . '_' . $key->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = $this->cache->fetchMultiple($keysToRetrieve);
|
||||||
|
if (count($items) !== count($keysToRetrieve)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$returnableItems = array();
|
||||||
|
foreach ($keysToRetrieve as $index => $key) {
|
||||||
|
$returnableItems[$index] = $items[$key];
|
||||||
|
}
|
||||||
|
return $returnableItems;
|
||||||
|
}
|
||||||
|
}
|
@ -20,11 +20,13 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Cache\Region;
|
namespace Doctrine\ORM\Cache\Region;
|
||||||
|
|
||||||
|
use Doctrine\Common\Cache\Cache as CacheAdapter;
|
||||||
|
use Doctrine\Common\Cache\ClearableCache;
|
||||||
|
use Doctrine\ORM\Cache\CacheEntry;
|
||||||
|
use Doctrine\ORM\Cache\CacheKey;
|
||||||
|
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||||
use Doctrine\ORM\Cache\Lock;
|
use Doctrine\ORM\Cache\Lock;
|
||||||
use Doctrine\ORM\Cache\Region;
|
use Doctrine\ORM\Cache\Region;
|
||||||
use Doctrine\ORM\Cache\CacheKey;
|
|
||||||
use Doctrine\ORM\Cache\CacheEntry;
|
|
||||||
use Doctrine\Common\Cache\CacheProvider;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The simplest cache region compatible with all doctrine-cache drivers.
|
* The simplest cache region compatible with all doctrine-cache drivers.
|
||||||
@ -35,7 +37,7 @@ use Doctrine\Common\Cache\CacheProvider;
|
|||||||
class DefaultRegion implements Region
|
class DefaultRegion implements Region
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var \Doctrine\Common\Cache\CacheProvider
|
* @var CacheAdapter
|
||||||
*/
|
*/
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
|
||||||
@ -51,10 +53,10 @@ class DefaultRegion implements Region
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param \Doctrine\Common\Cache\CacheProvider $cache
|
* @param CacheAdapter $cache
|
||||||
* @param integer $lifetime
|
* @param integer $lifetime
|
||||||
*/
|
*/
|
||||||
public function __construct($name, CacheProvider $cache, $lifetime = 0)
|
public function __construct($name, CacheAdapter $cache, $lifetime = 0)
|
||||||
{
|
{
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
$this->name = (string) $name;
|
$this->name = (string) $name;
|
||||||
@ -93,6 +95,37 @@ class DefaultRegion implements Region
|
|||||||
return $this->cache->fetch($this->name . '_' . $key->hash) ?: null;
|
return $this->cache->fetch($this->name . '_' . $key->hash) ?: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMultiple(CollectionCacheEntry $collection)
|
||||||
|
{
|
||||||
|
$keysToRetrieve = array();
|
||||||
|
|
||||||
|
foreach ($collection->identifiers as $index => $key) {
|
||||||
|
$keysToRetrieve[$index] = $this->name . '_' . $key->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = array_filter(
|
||||||
|
array_map([$this->cache, 'fetch'], $keysToRetrieve),
|
||||||
|
function ($retrieved) {
|
||||||
|
return false !== $retrieved;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (count($items) !== count($keysToRetrieve)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$returnableItems = array();
|
||||||
|
|
||||||
|
foreach ($keysToRetrieve as $index => $key) {
|
||||||
|
$returnableItems[$index] = $items[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnableItems;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -114,6 +147,13 @@ class DefaultRegion implements Region
|
|||||||
*/
|
*/
|
||||||
public function evictAll()
|
public function evictAll()
|
||||||
{
|
{
|
||||||
|
if (! $this->cache instanceof ClearableCache) {
|
||||||
|
throw new \BadMethodCallException(sprintf(
|
||||||
|
'Clearing all cache entries is not supported by the supplied cache adapter of type %s',
|
||||||
|
get_class($this->cache)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return $this->cache->deleteAll();
|
return $this->cache->deleteAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Cache\Region;
|
namespace Doctrine\ORM\Cache\Region;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||||
use Doctrine\ORM\Cache\Lock;
|
use Doctrine\ORM\Cache\Lock;
|
||||||
use Doctrine\ORM\Cache\Region;
|
use Doctrine\ORM\Cache\Region;
|
||||||
use Doctrine\ORM\Cache\CacheKey;
|
use Doctrine\ORM\Cache\CacheKey;
|
||||||
@ -172,6 +173,18 @@ class FileLockRegion implements ConcurrentRegion
|
|||||||
return $this->region->get($key);
|
return $this->region->get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMultiple(CollectionCacheEntry $collection)
|
||||||
|
{
|
||||||
|
if (array_filter(array_map([$this, 'isLocked'], $collection->identifiers))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->region->getMultiple($collection);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {inheritdoc}
|
* {inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -4,6 +4,7 @@ namespace Doctrine\Tests\Mocks;
|
|||||||
|
|
||||||
use Doctrine\ORM\Cache\CacheEntry;
|
use Doctrine\ORM\Cache\CacheEntry;
|
||||||
use Doctrine\ORM\Cache\CacheKey;
|
use Doctrine\ORM\Cache\CacheKey;
|
||||||
|
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||||
use Doctrine\ORM\Cache\Lock;
|
use Doctrine\ORM\Cache\Lock;
|
||||||
use Doctrine\ORM\Cache\Region;
|
use Doctrine\ORM\Cache\Region;
|
||||||
|
|
||||||
@ -94,6 +95,16 @@ class CacheRegionMock implements Region
|
|||||||
return $this->getReturn(__FUNCTION__, null);
|
return $this->getReturn(__FUNCTION__, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMultiple(CollectionCacheEntry $collection)
|
||||||
|
{
|
||||||
|
$this->calls[__FUNCTION__][] = array('collection' => $collection);
|
||||||
|
|
||||||
|
return $this->getReturn(__FUNCTION__, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace Doctrine\Tests\Mocks;
|
namespace Doctrine\Tests\Mocks;
|
||||||
|
|
||||||
|
|
||||||
|
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||||
use Doctrine\ORM\Cache\ConcurrentRegion;
|
use Doctrine\ORM\Cache\ConcurrentRegion;
|
||||||
use Doctrine\ORM\Cache\LockException;
|
use Doctrine\ORM\Cache\LockException;
|
||||||
use Doctrine\ORM\Cache\CacheEntry;
|
use Doctrine\ORM\Cache\CacheEntry;
|
||||||
@ -131,6 +132,18 @@ class ConcurrentRegionMock implements ConcurrentRegion
|
|||||||
return $this->region->get($key);
|
return $this->region->get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMultiple(CollectionCacheEntry $collection)
|
||||||
|
{
|
||||||
|
$this->calls[__FUNCTION__][] = array('collection' => $collection);
|
||||||
|
|
||||||
|
$this->throwException(__FUNCTION__);
|
||||||
|
|
||||||
|
return $this->region->getMultiple($collection);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -64,7 +64,6 @@ class DefaultCacheFactoryTest extends OrmTestCase
|
|||||||
->with($this->equalTo($metadata->cache))
|
->with($this->equalTo($metadata->cache))
|
||||||
->will($this->returnValue($region));
|
->will($this->returnValue($region));
|
||||||
|
|
||||||
|
|
||||||
$cachedPersister = $this->factory->buildCachedEntityPersister($em, $persister, $metadata);
|
$cachedPersister = $this->factory->buildCachedEntityPersister($em, $persister, $metadata);
|
||||||
|
|
||||||
$this->assertInstanceOf('Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister', $cachedPersister);
|
$this->assertInstanceOf('Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister', $cachedPersister);
|
||||||
@ -281,4 +280,37 @@ class DefaultCacheFactoryTest extends OrmTestCase
|
|||||||
$this->assertSame('foo', $fooRegion->getCache()->getNamespace());
|
$this->assertSame('foo', $fooRegion->getCache()->getNamespace());
|
||||||
$this->assertSame('bar', $barRegion->getCache()->getNamespace());
|
$this->assertSame('bar', $barRegion->getCache()->getNamespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testBuildsDefaultCacheRegionFromGenericCacheRegion()
|
||||||
|
{
|
||||||
|
/* @var $cache \Doctrine\Common\Cache\Cache */
|
||||||
|
$cache = $this->getMock('Doctrine\Common\Cache\Cache');
|
||||||
|
|
||||||
|
$factory = new DefaultCacheFactory($this->regionsConfig, $cache);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(
|
||||||
|
'Doctrine\ORM\Cache\Region\DefaultRegion',
|
||||||
|
$factory->getRegion(array(
|
||||||
|
'region' => 'bar',
|
||||||
|
'usage' => ClassMetadata::CACHE_USAGE_READ_ONLY,
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBuildsMultiGetCacheRegionFromGenericCacheRegion()
|
||||||
|
{
|
||||||
|
/* @var $cache \Doctrine\Common\Cache\CacheProvider */
|
||||||
|
$cache = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider');
|
||||||
|
|
||||||
|
$factory = new DefaultCacheFactory($this->regionsConfig, $cache);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(
|
||||||
|
'Doctrine\ORM\Cache\Region\DefaultMultiGetRegion',
|
||||||
|
$factory->getRegion(array(
|
||||||
|
'region' => 'bar',
|
||||||
|
'usage' => ClassMetadata::CACHE_USAGE_READ_ONLY,
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,8 @@ class DefaultCollectionHydratorTest extends OrmFunctionalTestCase
|
|||||||
$this->enableSecondLevelCache();
|
$this->enableSecondLevelCache();
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->structure = new DefaultCollectionHydrator($this->_em);
|
$targetPersister = $this->_em->getUnitOfWork()->getEntityPersister(City::CLASSNAME);
|
||||||
|
$this->structure = new DefaultCollectionHydrator($this->_em, $targetPersister);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testImplementsCollectionEntryStructure()
|
public function testImplementsCollectionEntryStructure()
|
||||||
@ -41,8 +42,8 @@ class DefaultCollectionHydratorTest extends OrmFunctionalTestCase
|
|||||||
{
|
{
|
||||||
$targetRegion = $this->_em->getCache()->getEntityCacheRegion(City::CLASSNAME);
|
$targetRegion = $this->_em->getCache()->getEntityCacheRegion(City::CLASSNAME);
|
||||||
$entry = new CollectionCacheEntry(array(
|
$entry = new CollectionCacheEntry(array(
|
||||||
array('id'=>31),
|
new EntityCacheKey(City::CLASSNAME, array('id'=>31)),
|
||||||
array('id'=>32),
|
new EntityCacheKey(City::CLASSNAME, array('id'=>32)),
|
||||||
));
|
));
|
||||||
|
|
||||||
$targetRegion->put(new EntityCacheKey(City::CLASSNAME, array('id'=>31)), new EntityCacheEntry(City::CLASSNAME, array('id'=>31, 'name'=>'Foo')));
|
$targetRegion->put(new EntityCacheKey(City::CLASSNAME, array('id'=>31)), new EntityCacheEntry(City::CLASSNAME, array('id'=>31, 'name'=>'Foo')));
|
||||||
|
@ -60,4 +60,16 @@ class DefaultRegionTest extends AbstractRegionTest
|
|||||||
|
|
||||||
$this->assertSame('foo', $cache->getNamespace());
|
$this->assertSame('foo', $cache->getNamespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEvictAllWithGenericCacheThrowsUnsupportedException()
|
||||||
|
{
|
||||||
|
/* @var $cache \Doctrine\Common\Cache\Cache */
|
||||||
|
$cache = $this->getMock('Doctrine\Common\Cache\Cache');
|
||||||
|
|
||||||
|
$region = new DefaultRegion('foo', $cache);
|
||||||
|
|
||||||
|
$this->setExpectedException('BadMethodCallException');
|
||||||
|
|
||||||
|
$region->evictAll();
|
||||||
|
}
|
||||||
}
|
}
|
41
tests/Doctrine/Tests/ORM/Cache/MultiGetRegionTest.php
Normal file
41
tests/Doctrine/Tests/ORM/Cache/MultiGetRegionTest.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Cache;
|
||||||
|
|
||||||
|
use Doctrine\Common\Cache\ArrayCache;
|
||||||
|
use Doctrine\Tests\Mocks\CacheEntryMock;
|
||||||
|
use Doctrine\Tests\Mocks\CacheKeyMock;
|
||||||
|
use Doctrine\ORM\Cache\Region\DefaultMultiGetRegion;
|
||||||
|
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||||
|
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Asmir Mustafic <goetas@gmail.com>
|
||||||
|
*/
|
||||||
|
class MultiGetRegionTest extends AbstractRegionTest
|
||||||
|
{
|
||||||
|
protected function createRegion()
|
||||||
|
{
|
||||||
|
return new DefaultMultiGetRegion('default.region.test', $this->cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMulti()
|
||||||
|
{
|
||||||
|
$key1 = new CacheKeyMock('key.1');
|
||||||
|
$value1 = new CacheEntryMock(array('id'=>1, 'name' => 'bar'));
|
||||||
|
|
||||||
|
$key2 = new CacheKeyMock('key.2');
|
||||||
|
$value2 = new CacheEntryMock(array('id'=>2, 'name' => 'bar'));
|
||||||
|
|
||||||
|
$this->assertFalse($this->region->contains($key1));
|
||||||
|
$this->assertFalse($this->region->contains($key2));
|
||||||
|
|
||||||
|
$this->region->put($key1, $value1);
|
||||||
|
$this->region->put($key2, $value2);
|
||||||
|
|
||||||
|
$actual = $this->region->getMultiple(new CollectionCacheEntry(array($key1, $key2)));
|
||||||
|
|
||||||
|
$this->assertEquals($value1, $actual[0]);
|
||||||
|
$this->assertEquals($value2, $actual[1]);
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,7 @@ abstract class AbstractCollectionPersisterTest extends OrmTestCase
|
|||||||
'getName',
|
'getName',
|
||||||
'contains',
|
'contains',
|
||||||
'get',
|
'get',
|
||||||
|
'getMultiple',
|
||||||
'put',
|
'put',
|
||||||
'evict',
|
'evict',
|
||||||
'evictAll'
|
'evictAll'
|
||||||
@ -56,6 +57,7 @@ abstract class AbstractCollectionPersisterTest extends OrmTestCase
|
|||||||
'removeElement',
|
'removeElement',
|
||||||
'removeKey',
|
'removeKey',
|
||||||
'get',
|
'get',
|
||||||
|
'getMultiple',
|
||||||
'loadCriteria'
|
'loadCriteria'
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ abstract class AbstractCollectionPersisterTest extends OrmTestCase
|
|||||||
* @param \Doctrine\ORM\Cache\Region $region
|
* @param \Doctrine\ORM\Cache\Region $region
|
||||||
* @param array $mapping
|
* @param array $mapping
|
||||||
*
|
*
|
||||||
* @return Doctrine\ORM\Cache\Persister\Collection\AbstractCollectionPersister
|
* @return \Doctrine\ORM\Cache\Persister\Collection\AbstractCollectionPersister
|
||||||
*/
|
*/
|
||||||
abstract protected function createPersister(EntityManager $em, CollectionPersister $persister, Region $region, array $mapping);
|
abstract protected function createPersister(EntityManager $em, CollectionPersister $persister, Region $region, array $mapping);
|
||||||
|
|
||||||
@ -77,7 +79,10 @@ abstract class AbstractCollectionPersisterTest extends OrmTestCase
|
|||||||
|
|
||||||
$this->em = $this->_getTestEntityManager();
|
$this->em = $this->_getTestEntityManager();
|
||||||
$this->region = $this->createRegion();
|
$this->region = $this->createRegion();
|
||||||
$this->collectionPersister = $this->getMock('Doctrine\ORM\Persisters\Collection\CollectionPersister', $this->collectionPersisterMockMethods);
|
$this->collectionPersister = $this->getMock(
|
||||||
|
'Doctrine\ORM\Persisters\Collection\CollectionPersister',
|
||||||
|
$this->collectionPersisterMockMethods
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,7 @@ class ReadWriteCachedCollectionPersisterTest extends AbstractCollectionPersister
|
|||||||
'getName',
|
'getName',
|
||||||
'contains',
|
'contains',
|
||||||
'get',
|
'get',
|
||||||
|
'getMultiple',
|
||||||
'put',
|
'put',
|
||||||
'evict',
|
'evict',
|
||||||
'evictAll',
|
'evictAll',
|
||||||
|
@ -41,6 +41,7 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
|
|||||||
'getName',
|
'getName',
|
||||||
'contains',
|
'contains',
|
||||||
'get',
|
'get',
|
||||||
|
'getMultiple',
|
||||||
'put',
|
'put',
|
||||||
'evict',
|
'evict',
|
||||||
'evictAll'
|
'evictAll'
|
||||||
@ -85,7 +86,7 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
|
|||||||
* @param \Doctrine\ORM\Cache\Region $region
|
* @param \Doctrine\ORM\Cache\Region $region
|
||||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $metadata
|
* @param \Doctrine\ORM\Mapping\ClassMetadata $metadata
|
||||||
*
|
*
|
||||||
* @return Doctrine\ORM\Cache\Persister\Entity\AbstractEntityPersister
|
* @return \Doctrine\ORM\Cache\Persister\Entity\AbstractEntityPersister
|
||||||
*/
|
*/
|
||||||
abstract protected function createPersister(EntityManager $em, EntityPersister $persister, Region $region, ClassMetadata $metadata);
|
abstract protected function createPersister(EntityManager $em, EntityPersister $persister, Region $region, ClassMetadata $metadata);
|
||||||
|
|
||||||
@ -97,7 +98,10 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
|
|||||||
|
|
||||||
$this->em = $this->_getTestEntityManager();
|
$this->em = $this->_getTestEntityManager();
|
||||||
$this->region = $this->createRegion();
|
$this->region = $this->createRegion();
|
||||||
$this->entityPersister = $this->getMock('Doctrine\ORM\Persisters\Entity\EntityPersister', $this->entityPersisterMockMethods);
|
$this->entityPersister = $this->getMock(
|
||||||
|
'Doctrine\ORM\Persisters\Entity\EntityPersister',
|
||||||
|
$this->entityPersisterMockMethods
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,7 +113,7 @@ abstract class AbstractEntityPersisterTest extends OrmTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Doctrine\ORM\Cache\Persister\AbstractEntityPersister
|
* @return \Doctrine\ORM\Cache\Persister\AbstractEntityPersister
|
||||||
*/
|
*/
|
||||||
protected function createPersisterDefault()
|
protected function createPersisterDefault()
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@ class ReadWriteCachedEntityPersisterTest extends AbstractEntityPersisterTest
|
|||||||
'getName',
|
'getName',
|
||||||
'contains',
|
'contains',
|
||||||
'get',
|
'get',
|
||||||
|
'getMultiple',
|
||||||
'put',
|
'put',
|
||||||
'evict',
|
'evict',
|
||||||
'evictAll',
|
'evictAll',
|
||||||
|
@ -39,6 +39,10 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$class->associationMappings['phonenumbers']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
|
$class->associationMappings['phonenumbers']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
|
||||||
$class->associationMappings['phonenumbers']['indexBy'] = 'phonenumber';
|
$class->associationMappings['phonenumbers']['indexBy'] = 'phonenumber';
|
||||||
|
|
||||||
|
unset($class->associationMappings['phonenumbers']['cache']);
|
||||||
|
unset($class->associationMappings['articles']['cache']);
|
||||||
|
unset($class->associationMappings['users']['cache']);
|
||||||
|
|
||||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
|
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||||
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
|
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
|
||||||
$class->associationMappings['users']['indexBy'] = 'username';
|
$class->associationMappings['users']['indexBy'] = 'username';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user