Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
15.00% |
3 / 20 |
CRAP | |
17.81% |
13 / 73 |
| CachedStorage | |
0.00% |
0 / 1 |
|
15.00% |
3 / 20 |
600.57 | |
17.81% |
13 / 73 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| exists | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| read | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| readMultiple | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 18 |
|||
| write | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| delete | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| rename | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| encode | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| decode | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| listAll | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
| findByPrefix | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
| deleteAll | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| resetListCache | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| createCollection | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| getAllCollectionNames | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getCollectionName | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getCacheKey | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getCacheKeys | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| anonymous function | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getCollectionPrefix | |
0.00% |
0 / 1 |
2.06 | |
75.00% |
3 / 4 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\Core\Config\CachedStorage. | |
| */ | |
| namespace Drupal\Core\Config; | |
| use Drupal\Core\Cache\CacheBackendInterface; | |
| use Drupal\Core\DependencyInjection\DependencySerializationTrait; | |
| /** | |
| * 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. | |
| */ | |
| 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 = array(); | |
| /** | |
| * 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 = array(); | |
| $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 = array(); | |
| foreach ($names_to_get as $name) { | |
| $data = isset($list[$name]) ? $list[$name] : FALSE; | |
| $data_to_return[$name] = $data; | |
| $items[$cache_keys_map[$name]] = array('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 = array(); | |
| 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 = array(); | |
| 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 = array(); | |
| 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 = array(); | |
| } | |
| /** | |
| * {@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 . ':'; | |
| } | |
| } |