class ThemeRegistry
Same name in other branches
- 7.x includes/theme.inc \ThemeRegistry
- 9 core/lib/Drupal/Core/Utility/ThemeRegistry.php \Drupal\Core\Utility\ThemeRegistry
- 8.9.x core/lib/Drupal/Core/Utility/ThemeRegistry.php \Drupal\Core\Utility\ThemeRegistry
- 11.x core/lib/Drupal/Core/Utility/ThemeRegistry.php \Drupal\Core\Utility\ThemeRegistry
Builds the run-time theme registry.
A cache collector to allow the theme registry to be accessed as a complete registry, while internally caching only the parts of the registry that are actually in use on the site. On cache misses the complete theme registry is loaded and used to update the run-time cache.
Hierarchy
- class \Drupal\Core\Cache\CacheCollector implements \Drupal\Core\Cache\CacheCollectorInterface, \Drupal\Core\DestructableInterface
- class \Drupal\Core\Utility\ThemeRegistry extends \Drupal\Core\Cache\CacheCollector implements \Drupal\Core\DestructableInterface
Expanded class hierarchy of ThemeRegistry
2 files declare their use of ThemeRegistry
- Registry.php in core/
lib/ Drupal/ Core/ Theme/ Registry.php - RegistryTest.php in core/
tests/ Drupal/ KernelTests/ Core/ Theme/ RegistryTest.php
File
-
core/
lib/ Drupal/ Core/ Utility/ ThemeRegistry.php, line 19
Namespace
Drupal\Core\UtilityView source
class ThemeRegistry extends CacheCollector implements DestructableInterface {
/**
* Whether the partial registry can be persisted to the cache.
*
* This is only allowed if all modules and the request method is GET. _theme()
* should be very rarely called on POST requests and this avoids polluting
* the runtime cache.
*
* @var bool
*/
protected $persistable;
/**
* The complete theme registry array.
*/
protected $completeRegistry;
/**
* Constructs a ThemeRegistry object.
*
* @param string $cid
* The cid for the array being cached.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend.
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* The lock backend.
* @param array $tags
* (optional) The tags to specify for the cache item.
* @param bool $modules_loaded
* Whether all modules have already been loaded.
*/
public function __construct($cid, CacheBackendInterface $cache, LockBackendInterface $lock, $tags = [], $modules_loaded = FALSE) {
$this->cid = $cid;
$this->cache = $cache;
$this->lock = $lock;
$this->tags = $tags;
$this->persistable = $modules_loaded && \Drupal::hasRequest() && \Drupal::request()->isMethod('GET');
// @todo Implement lazy-loading.
$this->cacheLoaded = TRUE;
if ($this->persistable && ($cached = $this->cache
->get($this->cid))) {
$this->storage = $cached->data;
}
else {
// If there is no runtime cache stored, fetch the full theme registry,
// but then initialize each value to NULL. This allows offsetExists()
// to function correctly on non-registered theme hooks without triggering
// a call to resolveCacheMiss().
$this->storage = $this->initializeRegistry();
foreach (array_keys($this->storage) as $key) {
$this->persist($key);
}
// RegistryTest::testRaceCondition() ensures that the cache entry is
// written on the initial construction of the theme registry.
$this->updateCache();
}
}
/**
* Initializes the full theme registry.
*
* @return array
* An array with the keys of the full theme registry, but the values
* initialized to NULL.
*/
public function initializeRegistry() {
// @todo DIC this.
$this->completeRegistry = \Drupal::service('theme.registry')->get();
return array_fill_keys(array_keys($this->completeRegistry), NULL);
}
/**
* {@inheritdoc}
*/
public function has($key) {
// Since the theme registry allows for theme hooks to be requested that
// are not registered, just check the existence of the key in the registry.
// Use array_key_exists() here since a NULL value indicates that the theme
// hook exists but has not yet been requested.
return \array_key_exists($key, $this->storage);
}
/**
* {@inheritdoc}
*/
public function get($key) {
// If the offset is set but empty, it is a registered theme hook that has
// not yet been requested. Offsets that do not exist at all were not
// registered in hook_theme().
if (isset($this->storage[$key])) {
return $this->storage[$key];
}
elseif (array_key_exists($key, $this->storage)) {
return $this->resolveCacheMiss($key);
}
}
/**
* {@inheritdoc}
*/
public function resolveCacheMiss($key) {
if (!isset($this->completeRegistry)) {
$this->completeRegistry = \Drupal::service('theme.registry')->get();
}
$this->storage[$key] = $this->completeRegistry[$key];
if ($this->persistable) {
$this->persist($key);
}
return $this->storage[$key];
}
/**
* {@inheritdoc}
*/
protected function updateCache($lock = TRUE) {
if (!$this->persistable) {
return;
}
// @todo Is the custom implementation necessary?
$data = [];
foreach ($this->keysToPersist as $offset => $persist) {
if ($persist) {
$data[$offset] = $this->storage[$offset];
}
}
if (empty($data)) {
return;
}
$lock_name = $this->cid . ':' . __CLASS__;
if (!$lock || $this->lock
->acquire($lock_name)) {
if ($cached = $this->cache
->get($this->cid)) {
// Use array merge instead of union so that filled in values in $data
// overwrite empty values in the current cache.
$data = array_merge($cached->data, $data);
}
else {
$registry = $this->initializeRegistry();
$data = array_merge($registry, $data);
}
$this->cache
->set($this->cid, $data, Cache::PERMANENT, $this->tags);
if ($lock) {
$this->lock
->release($lock_name);
}
}
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|
CacheCollector::$cache | protected | property | The cache backend that should be used. | 1 | |
CacheCollector::$cacheCreated | protected | property | Stores the cache creation time. | ||
CacheCollector::$cacheInvalidated | protected | property | Flag that indicates of the cache has been invalidated. | ||
CacheCollector::$cacheLoaded | protected | property | Indicates if the collected cache was already loaded. | ||
CacheCollector::$cid | protected | property | The cache id that is used for the cache entry. | ||
CacheCollector::$keysToPersist | protected | property | An array of keys to add to the cache on service termination. | ||
CacheCollector::$keysToRemove | protected | property | An array of keys to remove from the cache on service termination. | ||
CacheCollector::$lock | protected | property | The lock backend that should be used. | 1 | |
CacheCollector::$storage | protected | property | Storage for the data itself. | ||
CacheCollector::$tags | protected | property | A list of tags that are used for the cache entry. | ||
CacheCollector::clear | public | function | Clears the collected cache entry. | Overrides CacheCollectorInterface::clear | 1 |
CacheCollector::delete | public | function | Deletes the element. | Overrides CacheCollectorInterface::delete | 1 |
CacheCollector::destruct | public | function | Performs destruct operations. | Overrides DestructableInterface::destruct | |
CacheCollector::getCid | protected | function | Gets the cache ID. | 3 | |
CacheCollector::invalidateCache | protected | function | Invalidate the cache. | 1 | |
CacheCollector::lazyLoadCache | protected | function | Loads the cache if not already done. | 1 | |
CacheCollector::normalizeLockName | protected | function | Normalizes a cache ID in order to comply with database limitations. | 1 | |
CacheCollector::persist | protected | function | Flags an offset value to be written to the persistent cache. | ||
CacheCollector::reset | public | function | Resets the local cache. | Overrides CacheCollectorInterface::reset | 1 |
CacheCollector::set | public | function | Implements \Drupal\Core\Cache\CacheCollectorInterface::set(). | Overrides CacheCollectorInterface::set | 2 |
ThemeRegistry::$completeRegistry | protected | property | The complete theme registry array. | ||
ThemeRegistry::$persistable | protected | property | Whether the partial registry can be persisted to the cache. | ||
ThemeRegistry::get | public | function | Gets value from the cache. | Overrides CacheCollector::get | |
ThemeRegistry::has | public | function | Returns whether data exists for this key. | Overrides CacheCollector::has | |
ThemeRegistry::initializeRegistry | public | function | Initializes the full theme registry. | ||
ThemeRegistry::resolveCacheMiss | public | function | Resolves a cache miss. | Overrides CacheCollector::resolveCacheMiss | |
ThemeRegistry::updateCache | protected | function | Writes a value to the persistent cache immediately. | Overrides CacheCollector::updateCache | |
ThemeRegistry::__construct | public | function | Constructs a ThemeRegistry object. | Overrides CacheCollector::__construct |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.