class CachedStorage
Same name in other branches
- 8.9.x core/lib/Drupal/Core/Config/CachedStorage.php \Drupal\Core\Config\CachedStorage
- 10 core/lib/Drupal/Core/Config/CachedStorage.php \Drupal\Core\Config\CachedStorage
- 11.x core/lib/Drupal/Core/Config/CachedStorage.php \Drupal\Core\Config\CachedStorage
Defines the cached storage.
The class gets another storage and a cache backend injected. It reads from the cache and delegates the read to the storage on a cache miss. It also handles cache invalidation.
Hierarchy
- class \Drupal\Core\Config\CachedStorage implements \Drupal\Core\Config\StorageInterface, \Drupal\Core\Config\StorageCacheInterface uses \Drupal\Core\DependencyInjection\DependencySerializationTrait
Expanded class hierarchy of CachedStorage
2 files declare their use of CachedStorage
- CachedStorageTest.php in core/
tests/ Drupal/ KernelTests/ Core/ Config/ Storage/ CachedStorageTest.php - CachedStorageTest.php in core/
tests/ Drupal/ Tests/ Core/ Config/ CachedStorageTest.php
1 string reference to 'CachedStorage'
- core.services.yml in core/
core.services.yml - core/core.services.yml
1 service uses CachedStorage
File
-
core/
lib/ Drupal/ Core/ Config/ CachedStorage.php, line 15
Namespace
Drupal\Core\ConfigView source
class CachedStorage implements StorageInterface, StorageCacheInterface {
use DependencySerializationTrait;
/**
* The configuration storage to be cached.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $storage;
/**
* The instantiated Cache backend.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cache;
/**
* List of listAll() prefixes with their results.
*
* @var array
*/
protected $findByPrefixCache = [];
/**
* Constructs a new CachedStorage.
*
* @param \Drupal\Core\Config\StorageInterface $storage
* A configuration storage to be cached.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* A cache backend used to store configuration.
*/
public function __construct(StorageInterface $storage, CacheBackendInterface $cache) {
$this->storage = $storage;
$this->cache = $cache;
}
/**
* {@inheritdoc}
*/
public function exists($name) {
// The cache would read in the entire data (instead of only checking whether
// any data exists), and on a potential cache miss, an additional storage
// lookup would have to happen, so check the storage directly.
return $this->storage
->exists($name);
}
/**
* {@inheritdoc}
*/
public function read($name) {
$cache_key = $this->getCacheKey($name);
if ($cache = $this->cache
->get($cache_key)) {
// The cache contains either the cached configuration data or FALSE
// if the configuration file does not exist.
return $cache->data;
}
// Read from the storage on a cache miss and cache the data. Also cache
// information about missing configuration objects.
$data = $this->storage
->read($name);
$this->cache
->set($cache_key, $data);
return $data;
}
/**
* {@inheritdoc}
*/
public function readMultiple(array $names) {
$data_to_return = [];
$cache_keys_map = $this->getCacheKeys($names);
$cache_keys = array_values($cache_keys_map);
$cached_list = $this->cache
->getMultiple($cache_keys);
if (!empty($cache_keys)) {
// $cache_keys_map contains the full $name => $cache_key map, while
// $cache_keys contains just the $cache_key values that weren't found in
// the cache.
// @see \Drupal\Core\Cache\CacheBackendInterface::getMultiple()
$names_to_get = array_keys(array_intersect($cache_keys_map, $cache_keys));
$list = $this->storage
->readMultiple($names_to_get);
// Cache configuration objects that were loaded from the storage, cache
// missing configuration objects as an explicit FALSE.
$items = [];
foreach ($names_to_get as $name) {
$data = $list[$name] ?? FALSE;
$data_to_return[$name] = $data;
$items[$cache_keys_map[$name]] = [
'data' => $data,
];
}
$this->cache
->setMultiple($items);
}
// Add the configuration objects from the cache to the list.
$cache_keys_inverse_map = array_flip($cache_keys_map);
foreach ($cached_list as $cache_key => $cache) {
$name = $cache_keys_inverse_map[$cache_key];
$data_to_return[$name] = $cache->data;
}
// Ensure that only existing configuration objects are returned, filter out
// cached information about missing objects.
return array_filter($data_to_return);
}
/**
* {@inheritdoc}
*/
public function write($name, array $data) {
if ($this->storage
->write($name, $data)) {
// While not all written data is read back, setting the cache instead of
// just deleting it avoids cache rebuild stampedes.
$this->cache
->set($this->getCacheKey($name), $data);
$this->findByPrefixCache = [];
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function delete($name) {
// If the cache was the first to be deleted, another process might start
// rebuilding the cache before the storage is gone.
if ($this->storage
->delete($name)) {
$this->cache
->delete($this->getCacheKey($name));
$this->findByPrefixCache = [];
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function rename($name, $new_name) {
// If the cache was the first to be deleted, another process might start
// rebuilding the cache before the storage is renamed.
if ($this->storage
->rename($name, $new_name)) {
$this->cache
->delete($this->getCacheKey($name));
$this->cache
->delete($this->getCacheKey($new_name));
$this->findByPrefixCache = [];
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function encode($data) {
return $this->storage
->encode($data);
}
/**
* {@inheritdoc}
*/
public function decode($raw) {
return $this->storage
->decode($raw);
}
/**
* {@inheritdoc}
*/
public function listAll($prefix = '') {
// Do not cache when a prefix is not provided.
if ($prefix) {
return $this->findByPrefix($prefix);
}
return $this->storage
->listAll();
}
/**
* Finds configuration object names starting with a given prefix.
*
* Given the following configuration objects:
* - node.type.article
* - node.type.page
*
* Passing the prefix 'node.type.' will return an array containing the above
* names.
*
* @param string $prefix
* The prefix to search for
*
* @return array
* An array containing matching configuration object names.
*/
protected function findByPrefix($prefix) {
$cache_key = $this->getCacheKey($prefix);
if (!isset($this->findByPrefixCache[$cache_key])) {
$this->findByPrefixCache[$cache_key] = $this->storage
->listAll($prefix);
}
return $this->findByPrefixCache[$cache_key];
}
/**
* {@inheritdoc}
*/
public function deleteAll($prefix = '') {
// If the cache was the first to be deleted, another process might start
// rebuilding the cache before the storage is renamed.
$names = $this->storage
->listAll($prefix);
if ($this->storage
->deleteAll($prefix)) {
$this->cache
->deleteMultiple($this->getCacheKeys($names));
return TRUE;
}
return FALSE;
}
/**
* Clears the static list cache.
*/
public function resetListCache() {
$this->findByPrefixCache = [];
}
/**
* {@inheritdoc}
*/
public function createCollection($collection) {
return new static($this->storage
->createCollection($collection), $this->cache);
}
/**
* {@inheritdoc}
*/
public function getAllCollectionNames() {
return $this->storage
->getAllCollectionNames();
}
/**
* {@inheritdoc}
*/
public function getCollectionName() {
return $this->storage
->getCollectionName();
}
/**
* Returns a cache key for a configuration name using the collection.
*
* @param string $name
* The configuration name.
*
* @return string
* The cache key for the configuration name.
*/
protected function getCacheKey($name) {
return $this->getCollectionPrefix() . $name;
}
/**
* Returns a cache key map for an array of configuration names.
*
* @param array $names
* The configuration names.
*
* @return array
* An array of cache keys keyed by configuration names.
*/
protected function getCacheKeys(array $names) {
$prefix = $this->getCollectionPrefix();
$cache_keys = array_map(function ($name) use ($prefix) {
return $prefix . $name;
}, $names);
return array_combine($names, $cache_keys);
}
/**
* Returns a cache ID prefix to use for the collection.
*
* @return string
* The cache ID prefix.
*/
protected function getCollectionPrefix() {
$collection = $this->storage
->getCollectionName();
if ($collection == StorageInterface::DEFAULT_COLLECTION) {
return '';
}
return $collection . ':';
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|
CachedStorage::$cache | protected | property | The instantiated Cache backend. | ||
CachedStorage::$findByPrefixCache | protected | property | List of listAll() prefixes with their results. | ||
CachedStorage::$storage | protected | property | The configuration storage to be cached. | ||
CachedStorage::createCollection | public | function | Creates a collection on the storage. | Overrides StorageInterface::createCollection | |
CachedStorage::decode | public | function | Decodes configuration data from the storage-specific format. | Overrides StorageInterface::decode | |
CachedStorage::delete | public | function | Deletes a configuration object from the storage. | Overrides StorageInterface::delete | |
CachedStorage::deleteAll | public | function | Deletes configuration objects whose names start with a given prefix. | Overrides StorageInterface::deleteAll | |
CachedStorage::encode | public | function | Encodes configuration data into the storage-specific format. | Overrides StorageInterface::encode | |
CachedStorage::exists | public | function | Returns whether a configuration object exists. | Overrides StorageInterface::exists | |
CachedStorage::findByPrefix | protected | function | Finds configuration object names starting with a given prefix. | ||
CachedStorage::getAllCollectionNames | public | function | Gets the existing collections. | Overrides StorageInterface::getAllCollectionNames | |
CachedStorage::getCacheKey | protected | function | Returns a cache key for a configuration name using the collection. | ||
CachedStorage::getCacheKeys | protected | function | Returns a cache key map for an array of configuration names. | ||
CachedStorage::getCollectionName | public | function | Gets the name of the current collection the storage is using. | Overrides StorageInterface::getCollectionName | |
CachedStorage::getCollectionPrefix | protected | function | Returns a cache ID prefix to use for the collection. | ||
CachedStorage::listAll | public | function | Gets configuration object names starting with a given prefix. | Overrides StorageInterface::listAll | |
CachedStorage::read | public | function | Reads configuration data from the storage. | Overrides StorageInterface::read | |
CachedStorage::readMultiple | public | function | Reads configuration data from the storage. | Overrides StorageInterface::readMultiple | |
CachedStorage::rename | public | function | Renames a configuration object in the storage. | Overrides StorageInterface::rename | |
CachedStorage::resetListCache | public | function | Clears the static list cache. | Overrides StorageCacheInterface::resetListCache | |
CachedStorage::write | public | function | Writes configuration data to the storage. | Overrides StorageInterface::write | |
CachedStorage::__construct | public | function | Constructs a new CachedStorage. | ||
DependencySerializationTrait::$_entityStorages | protected | property | |||
DependencySerializationTrait::$_serviceIds | protected | property | |||
DependencySerializationTrait::__sleep | public | function | 1 | ||
DependencySerializationTrait::__wakeup | public | function | 2 | ||
StorageInterface::DEFAULT_COLLECTION | constant | The default collection name. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.