diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php index 8547ac4..de8a2c7 100644 --- a/core/lib/Drupal/Core/Cache/CacheFactory.php +++ b/core/lib/Drupal/Core/Cache/CacheFactory.php @@ -67,12 +67,12 @@ public function get($bin) { if (isset($cache_settings['bins'][$bin])) { $service_name = $cache_settings['bins'][$bin]; } - elseif (isset($cache_settings['default'])) { - $service_name = $cache_settings['default']; - } elseif (isset($this->defaultBinBackends[$bin])) { $service_name = $this->defaultBinBackends[$bin]; } + elseif (isset($cache_settings['default'])) { + $service_name = $cache_settings['default']; + } else { $service_name = 'cache.backend.database'; } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 3834dae..53fcb01 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -2,6 +2,7 @@ namespace Drupal\Core\Config\Entity; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigImporterException; @@ -104,9 +105,12 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora * The UUID service. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. + * @param \Drupal\Core\Cache\CacheBackendInterface $static_cache_backend + * The static cache backend. */ - public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager) { - parent::__construct($entity_type); + public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $static_cache_backend = NULL) { + $static_cache_backend = isset($static_cache_backend) ? $static_cache_backend : \Drupal::service('cache.static'); + parent::__construct($entity_type, $static_cache_backend); $this->configFactory = $config_factory; $this->uuidService = $uuid_service; @@ -317,43 +321,10 @@ protected function has($id, EntityInterface $entity) { } /** - * Gets entities from the static cache. - * - * @param array $ids - * If not empty, return entities that match these IDs. - * - * @return \Drupal\Core\Entity\EntityInterface[] - * Array of entities from the entity cache. - */ - protected function getFromStaticCache(array $ids) { - $entities = array(); - // Load any available entities from the internal cache. - if ($this->entityType->isStaticallyCacheable() && !empty($this->entities)) { - $config_overrides_key = $this->overrideFree ? '' : implode(':', $this->configFactory->getCacheKeys()); - foreach ($ids as $id) { - if (!empty($this->entities[$id])) { - if (isset($this->entities[$id][$config_overrides_key])) { - $entities[$id] = $this->entities[$id][$config_overrides_key]; - } - } - } - } - return $entities; - } - - /** - * Stores entities in the static entity cache. - * - * @param \Drupal\Core\Entity\EntityInterface[] $entities - * Entities to store in the cache. - */ - protected function setStaticCache(array $entities) { - if ($this->entityType->isStaticallyCacheable()) { - $config_overrides_key = $this->overrideFree ? '' : implode(':', $this->configFactory->getCacheKeys()); - foreach ($entities as $id => $entity) { - $this->entities[$id][$config_overrides_key] = $entity; - } - } + * {@inheritdoc} + */ + protected function getCacheId($id) { + return parent::getCacheId($id) . ':' . $config_overrides_key = $this->overrideFree ? '' : implode(':', $this->configFactory->getCacheKeys()); } /** diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php index dea8865..7efdaa6 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php @@ -622,17 +622,17 @@ protected function setPersistentCache($entities) { */ public function resetCache(array $ids = NULL) { if ($ids) { - $cids = array(); - foreach ($ids as $id) { - unset($this->entities[$id]); - $cids[] = $this->buildCacheId($id); - } + parent::resetCache($ids); if ($this->entityType->isPersistentlyCacheable()) { + $cids = array(); + foreach ($ids as $id) { + $cids[] = $this->buildCacheId($id); + } $this->cacheBackend->deleteMultiple($cids); } } else { - $this->entities = array(); + parent::resetCache(); if ($this->entityType->isPersistentlyCacheable()) { Cache::invalidateTags(array($this->entityTypeId . '_values')); } diff --git a/core/lib/Drupal/Core/Entity/EntityStorageBase.php b/core/lib/Drupal/Core/Entity/EntityStorageBase.php index f583121..3b78371 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php @@ -3,6 +3,8 @@ namespace Drupal\Core\Entity; use Drupal\Core\Entity\Query\QueryInterface; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Cache\Cache; /** * A base entity storage class. @@ -73,18 +75,28 @@ protected $entityClass; /** + * The static cache backend. + * + * @var \Drupal\Core\Cache\CacheBackendInterface + */ + protected $staticCacheBackend; + + /** * Constructs an EntityStorageBase instance. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type definition. + * @param \Drupal\Core\Cache\CacheBackendInterface + * The static cache backend. */ - public function __construct(EntityTypeInterface $entity_type) { + public function __construct(EntityTypeInterface $entity_type, CacheBackendInterface $static_cache_backend = NULL) { $this->entityTypeId = $entity_type->id(); $this->entityType = $entity_type; $this->idKey = $this->entityType->getKey('id'); $this->uuidKey = $this->entityType->getKey('uuid'); $this->langcodeKey = $this->entityType->getKey('langcode'); $this->entityClass = $this->entityType->getClass(); + $this->staticCacheBackend = isset($static_cache_backend) ? $static_cache_backend : \Drupal::service('cache.static'); } /** @@ -102,6 +114,13 @@ public function getEntityType() { } /** + * Build a cache ID for an entity. + */ + protected function getCacheId($id) { + return 'entity_storage_cache:' . $this->entityTypeId . ':' . $id; + } + + /** * {@inheritdoc} */ public function loadUnchanged($id) { @@ -115,11 +134,12 @@ public function loadUnchanged($id) { public function resetCache(array $ids = NULL) { if ($this->entityType->isStaticallyCacheable() && isset($ids)) { foreach ($ids as $id) { - unset($this->entities[$id]); + $this->staticCacheBackend->delete($this->getCacheId($id)); } } else { - $this->entities = array(); + // Call the backend method directly. + $this->staticCacheBackend->invalidateTags(['entity_static_cache']); } } @@ -135,8 +155,12 @@ public function resetCache(array $ids = NULL) { protected function getFromStaticCache(array $ids) { $entities = array(); // Load any available entities from the internal cache. - if ($this->entityType->isStaticallyCacheable() && !empty($this->entities)) { - $entities += array_intersect_key($this->entities, array_flip($ids)); + if ($this->entityType->isStaticallyCacheable()) { + foreach ($ids as $id) { + if ($cached = $this->staticCacheBackend->get($this->getCacheId($id))) { + $entities[$id] = $cached->data; + } + } } return $entities; } @@ -149,7 +173,9 @@ protected function getFromStaticCache(array $ids) { */ protected function setStaticCache(array $entities) { if ($this->entityType->isStaticallyCacheable()) { - $this->entities += $entities; + foreach ($entities as $id => $entity) { + $this->staticCacheBackend->set($this->getCacheId($entity->id()), $entity, CacheBackendInterface::CACHE_PERMANENT, ['entity_static_cache']); + } } } @@ -530,4 +556,8 @@ public function getAggregateQuery($conjunction = 'AND') { */ abstract protected function getQueryServiceName(); + public function __destruct() { + $this->staticCacheBackend->invalidateTags(['entity_static_cache']); + } + } diff --git a/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php index 478bca7..1f9abde 100644 --- a/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php @@ -3,6 +3,7 @@ namespace Drupal\Core\Entity\KeyValueStore; use Drupal\Component\Uuid\UuidInterface; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Entity\EntityInterface; @@ -50,6 +51,13 @@ class KeyValueEntityStorage extends EntityStorageBase { protected $languageManager; /** + * The memory cache backend. + * + * @var \Drupal\Core\Cache\CacheBackendInterface + */ + protected $staticCacheBackend; + + /** * Constructs a new KeyValueEntityStorage. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type @@ -60,9 +68,12 @@ class KeyValueEntityStorage extends EntityStorageBase { * The UUID service. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. + * @param \Drupal\Core\Cache\CacheBackendInterface $static_cache_backend + * The static cache backend. */ - public function __construct(EntityTypeInterface $entity_type, KeyValueStoreInterface $key_value_store, UuidInterface $uuid_service, LanguageManagerInterface $language_manager) { - parent::__construct($entity_type); + public function __construct(EntityTypeInterface $entity_type, KeyValueStoreInterface $key_value_store, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $static_cache_backend = NULL) { + $static_cache_backend = isset($static_cache_backend) ? $static_cache_backend : \Drupal::service('cache.static'); + parent::__construct($entity_type, $static_cache_backend); $this->keyValueStore = $key_value_store; $this->uuidService = $uuid_service; $this->languageManager = $language_manager; diff --git a/core/modules/migrate/src/MigrationStorage.php b/core/modules/migrate/src/MigrationStorage.php index 282b0c9..ae3ae88 100644 --- a/core/modules/migrate/src/MigrationStorage.php +++ b/core/modules/migrate/src/MigrationStorage.php @@ -4,6 +4,7 @@ use Drupal\Component\Graph\Graph; use Drupal\Component\Uuid\UuidInterface; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Entity\ConfigEntityStorage; use Drupal\Core\Entity\EntityTypeInterface; @@ -36,9 +37,12 @@ class MigrationStorage extends ConfigEntityStorage implements MigrateBuildDepend * The language manager. * @param \Drupal\Core\Entity\Query\QueryFactoryInterface $query_factory * The entity query factory service. + * @param \Drupal\Core\Cache\CacheBackendInterface + * The static cache backend. */ - public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, QueryFactoryInterface $query_factory) { - parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager); + public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, QueryFactoryInterface $query_factory, CacheBackendInterface $static_cache_backend = NULL) { + $static_cache_backend = isset($static_cache_backend) ? $static_cache_backend : \Drupal::service('cache.static'); + parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $static_cache_backend); $this->queryFactory = $query_factory; } diff --git a/core/modules/migrate/tests/src/Unit/MigrationStorageTest.php b/core/modules/migrate/tests/src/Unit/MigrationStorageTest.php index 3ff44fa..8ce528f 100644 --- a/core/modules/migrate/tests/src/Unit/MigrationStorageTest.php +++ b/core/modules/migrate/tests/src/Unit/MigrationStorageTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\migrate\Unit; use Drupal\Component\Uuid\UuidInterface; +use Drupal\Core\Cache\MemoryBackend; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Query\QueryFactoryInterface; @@ -53,7 +54,8 @@ protected function setUp() { $this->getMock(ConfigFactoryInterface::class), $this->getMock(UuidInterface::class), $this->getMock(LanguageManagerInterface::class), - $query_factory + $query_factory, + new MemoryBackend('static') ); } diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php index 2c4a01b..d505b54 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\Core\Config\Entity { use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\MemoryBackend; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Language\Language; @@ -150,7 +151,7 @@ protected function setUp() { $this->entityQuery = $this->getMock('Drupal\Core\Entity\Query\QueryInterface'); $this->entityStorage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage') - ->setConstructorArgs(array($this->entityType, $this->configFactory, $this->uuidService, $this->languageManager)) + ->setConstructorArgs(array($this->entityType, $this->configFactory, $this->uuidService, $this->languageManager, new MemoryBackend('static'))) ->setMethods(array('getQuery')) ->getMock(); $this->entityStorage->expects($this->any()) diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php index 3c337bb..5a07d7f 100644 --- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\Core\Entity\KeyValueStore { +use Drupal\Core\Cache\MemoryBackend; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Entity\EntityInterface; @@ -120,7 +121,7 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') { ->method('getCurrentLanguage') ->will($this->returnValue($language)); - $this->entityStorage = new KeyValueEntityStorage($this->entityType, $this->keyValueStore, $this->uuidService, $this->languageManager); + $this->entityStorage = new KeyValueEntityStorage($this->entityType, $this->keyValueStore, $this->uuidService, $this->languageManager, new MemoryBackend('static')); $this->entityStorage->setModuleHandler($this->moduleHandler); $container = new ContainerBuilder();