diff --git a/core/includes/theme.inc b/core/includes/theme.inc index ea1dd1e753b5..34e1ee516ca3 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1,5 +1,5 @@ deletePrefix('theme_registry'); } -/** - * Builds the run-time theme registry. - * - * Extends DrupalCacheArray 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. - */ -class ThemeRegistry Extends CacheArray { - - /** - * 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. - */ - protected $persistable; - - /** - * The complete theme registry array. - */ - protected $completeRegistry; - - function __construct($cid, $bin) { - $this->cid = $cid; - $this->bin = $bin; - $this->persistable = module_load_all(NULL) && $_SERVER['REQUEST_METHOD'] == 'GET'; - - $data = array(); - if ($this->persistable && $cached = cache($this->bin)->get($this->cid)) { - $data = $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(). - $data = $this->initializeRegistry(); - if ($this->persistable) { - $this->set($data); - } - } - $this->storage = $data; - } - - /** - * Initializes the full theme registry. - * - * @return - * An array with the keys of the full theme registry, but the values - * initialized to NULL. - */ - function initializeRegistry() { - $this->completeRegistry = theme_get_registry(); - - return array_fill_keys(array_keys($this->completeRegistry), NULL); - } - - public function offsetExists($offset) { - // 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($offset, $this->storage); - } - - public function offsetGet($offset) { - // 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[$offset])) { - return $this->storage[$offset]; - } - elseif (array_key_exists($offset, $this->storage)) { - return $this->resolveCacheMiss($offset); - } - } - - public function resolveCacheMiss($offset) { - if (!isset($this->completeRegistry)) { - $this->completeRegistry = theme_get_registry(); - } - $this->storage[$offset] = $this->completeRegistry[$offset]; - if ($this->persistable) { - $this->persist($offset); - } - return $this->storage[$offset]; - } - - public function set($data, $lock = TRUE) { - $lock_name = $this->cid . ':' . $this->bin; - if (!$lock || lock_acquire($lock_name)) { - if ($cached = cache($this->bin)->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); - } - cache($this->bin)->set($this->cid, $data); - if ($lock) { - lock_release($lock_name); - } - } - } -} - /** * Process a single implementation of hook_theme(). * diff --git a/core/lib/Drupal/Core/Utility/ThemeRegistry.php b/core/lib/Drupal/Core/Utility/ThemeRegistry.php new file mode 100644 index 000000000000..e9512e9de8dd --- /dev/null +++ b/core/lib/Drupal/Core/Utility/ThemeRegistry.php @@ -0,0 +1,118 @@ +cid = $cid; + $this->bin = $bin; + $this->persistable = module_load_all(NULL) && $_SERVER['REQUEST_METHOD'] == 'GET'; + + $data = array(); + if ($this->persistable && $cached = cache($this->bin)->get($this->cid)) { + $data = $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(). + $data = $this->initializeRegistry(); + if ($this->persistable) { + $this->set($data); + } + } + $this->storage = $data; + } + + /** + * Initializes the full theme registry. + * + * @return + * An array with the keys of the full theme registry, but the values + * initialized to NULL. + */ + function initializeRegistry() { + $this->completeRegistry = theme_get_registry(); + + return array_fill_keys(array_keys($this->completeRegistry), NULL); + } + + public function offsetExists($offset) { + // 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($offset, $this->storage); + } + + public function offsetGet($offset) { + // 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[$offset])) { + return $this->storage[$offset]; + } + elseif (array_key_exists($offset, $this->storage)) { + return $this->resolveCacheMiss($offset); + } + } + + public function resolveCacheMiss($offset) { + if (!isset($this->completeRegistry)) { + $this->completeRegistry = theme_get_registry(); + } + $this->storage[$offset] = $this->completeRegistry[$offset]; + if ($this->persistable) { + $this->persist($offset); + } + return $this->storage[$offset]; + } + + public function set($data, $lock = TRUE) { + $lock_name = $this->cid . ':' . $this->bin; + if (!$lock || lock_acquire($lock_name)) { + if ($cached = cache($this->bin)->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); + } + cache($this->bin)->set($this->cid, $data); + if ($lock) { + lock_release($lock_name); + } + } + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/RegistryTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/RegistryTest.php index 41e0a694ef2b..16abc7852904 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Theme/RegistryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Theme/RegistryTest.php @@ -8,7 +8,7 @@ namespace Drupal\system\Tests\Theme; use Drupal\simpletest\WebTestBase; -use ThemeRegistry; +use Drupal\Core\Utility\ThemeRegistry; /** * Tests for the ThemeRegistry class.