diff --git a/includes/theme.inc b/includes/theme.inc index c211248..c42999b 100644 --- a/includes/theme.inc +++ b/includes/theme.inc @@ -279,28 +279,7 @@ function _theme_registry_callback($callback = NULL, array $arguments = array()) * The name of the theme engine. */ function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL) { - // Check the theme registry cache; if it exists, use it. - $cache = cache_get("theme_registry:$theme->name", 'cache'); - if (isset($cache->data)) { - $registry = $cache->data; - } - else { - // If not, build one and cache it. - $registry = _theme_build_registry($theme, $base_theme, $theme_engine); - // Only persist this registry if all modules are loaded. This assures a - // complete set of theme hooks. - if (module_load_all(NULL)) { - _theme_save_registry($theme, $registry); - } - } - return $registry; -} - -/** - * Write the theme_registry cache into the database. - */ -function _theme_save_registry($theme, $registry) { - cache_set("theme_registry:$theme->name", $registry); + return new ThemeRegistry($theme, $base_theme, $theme_engine); } /** @@ -563,6 +542,113 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) { } /** + * Builds the run-time theme registry. + * + * This class extends the ArrayObject class 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 loade and used to update the run-time cache. + */ +class ThemeRegistry Extends ArrayObject { + private $theme; + private $base_theme; + private $theme_engine; + private $cid; + private $bin; + + function __construct($theme, $base_theme = NULL, $theme_engine = NULL) { + // Make the arguments available to the rest of the class. + $this->theme = $theme; + $this->base_theme = $base_theme; + $this->theme_engine = $theme_engine; + $this->cid = 'theme_registry:' . $theme->name; + $this->bin = 'cache'; + + // Load the run-time theme registry from cache if available. + if ($cached = cache_get($this->cid, $this->bin)) { + parent::__construct($cached->data); + } + else { + parent::__construct(array()); + } + } + + public function offsetExists($offset) { + // The values of the theme registry are always arrays, so ensure that the + // value is non-empty. + if (!empty($this->$offset)) { + return TRUE; + } + // If the value is isset but empty, this is a cached miss for a theme key. + else { + if (isset($this->$offset)) { + return FALSE; + } + else { + // If the key is not available, load it from the complete theme + // registry, then re-run this method. + $this->resolveCacheMiss($offset); + if (!empty($this->$offset)) { + return TRUE; + } + else if (isset($this->$offset)) { + return FALSE; + } + } + } + } + + public function offsetGet($offset) { + if (!empty($this->$offset)) { + return $this->$offset; + } + else { + if (isset($this->$offset)) { + return NULL; + } + else { + $this->resolveCacheMiss($offset); + return $this->$offset; + } + } + } + + /** + * Resolve cache misses from the run-time registry. + * + * @param $offset + * The array key requested. + */ + public function resolveCacheMiss($offset) { + $this->cacheMiss = TRUE; + // Load the full theme registry. + if ($cached = cache_get('theme_registry:complete:' . $this->theme->name)) { + $complete_registry = $cached->data; + } + else { + $complete_registry = _theme_build_registry($this->theme, $this->base_theme, $this->theme_engine); + // Only persist this registry if all modules are loaded. This assures a + // complete set of theme hooks. + if (module_load_all(NULL)) { + cache_set('theme_registry:complete:' . $this->theme->name, $complete_registry); + } + } + if (isset($complete_registry[$offset])) { + $this->$offset = $complete_registry[$offset]; + } + else { + $this->$offset = FALSE; + } + } + + public function __destruct() { + if (!empty($this->cacheMiss) && module_load_all(NULL)) { + cache_set($this->cid, $this->getarrayCopy(), $this->bin); + } + } +} + +/** * Return a list of all currently available themes. * * Retrieved from the database, if available and the site is not in maintenance