From: Michael M Slusarz Date: Mon, 20 Dec 2010 04:31:59 +0000 (-0700) Subject: Revert "Revert "Cleanup registry caching." This caused registry methods not to be... X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=597ba3fb5d9b9df6b16f83c1ad863721bc6e9eae;p=horde.git Revert "Revert "Cleanup registry caching." This caused registry methods not to be visible to external applications for me, plus other problems for Jan." This reverts commit 3be8781b0fc7bc17f52b2a65adedd0198a780e5a. --- diff --git a/framework/Core/lib/Horde/Registry.php b/framework/Core/lib/Horde/Registry.php index b119f5c7f..7acfd0763 100644 --- a/framework/Core/lib/Horde/Registry.php +++ b/framework/Core/lib/Horde/Registry.php @@ -57,18 +57,18 @@ class Horde_Registry protected $_appStack = array(); /** - * The list of APIs. + * The list of external services. * - * @param array + * @var array */ - protected $_apis = array(); + protected $_apis; /** - * Cached information. + * The list of APIs. * * @var array */ - protected $_cache = array(); + protected $_apiList = array(); /** * Cached configuration information. @@ -77,6 +77,19 @@ class Horde_Registry */ protected $_confCache = array(); + /** + * Interfaces list. + * + * @var array + */ + protected $_interfaces = array(); + + /** + * Object (Application/Api) cache. + * + * @var array + */ + protected $_obCache = array(); /** * The last modified time of the newest modified registry file. @@ -86,11 +99,11 @@ class Horde_Registry protected $_regmtime; /** - * The list of cache entries to save on shutdown. + * The current vhost configuration file. * - * @var array + * @var string */ - protected $_savecache = array(); + protected $_vhost = null; /** * Application bootstrap initialization. @@ -319,7 +332,7 @@ class Horde_Registry } $GLOBALS['registry'] = $this; - $injector->setInstance('Horde_Registry', $this); + $injector->setInstance(__CLASS__, $this); /* Setup autoloader instance and callbacks. * $__autoloader is defined in horde/lib/core.php */ @@ -358,13 +371,12 @@ class Horde_Registry $this->_regmtime = max(filemtime(HORDE_BASE . '/config/registry.php'), filemtime(HORDE_BASE . '/config/registry.d')); - $vhost = null; if (!empty($conf['vhosts'])) { - $vhost = HORDE_BASE . '/config/registry-' . $conf['server']['name'] . '.php'; - if (file_exists($vhost)) { - $this->_regmtime = max($this->_regmtime, filemtime($vhost)); + $this->_vhost = HORDE_BASE . '/config/registry-' . $conf['server']['name'] . '.php'; + if (file_exists($this->_vhost)) { + $this->_regmtime = max($this->_regmtime, filemtime($this->_vhost)); } else { - $vhost = null; + $this->_vhost = null; } } @@ -388,7 +400,7 @@ class Horde_Registry $injector->setInstance('Horde_Session', $session); /* Always need to load applications information. */ - $this->_loadApplicationsCache($vhost); + $this->_loadApplications(); /* Load the language configuration. */ $this->nlsconfig = Horde::loadConfiguration('nls.php', 'horde_nls_config', 'horde'); @@ -421,27 +433,6 @@ class Horde_Registry */ public function shutdown() { - /* Store cache entries to persistent storage. */ - if (!empty($this->_savecache)) { - $ob = $GLOBALS['injector']->getInstance('Horde_Cache'); - - foreach ($this->_savecache as $key => $val) { - if ($val) { - // Entry has been updated. - $data = serialize($this->_cache[$key]); - $md5sum = hash('md5', $data); - $GLOBALS['session']->set('horde', 'registry/' . $key, $md5sum); - $id = $this->_getCacheId($key, false) . '|' . $md5sum; - if ($ob->set($id, $data, 86400)) { - Horde::logMessage('Horde_Registry: stored ' . $key . ' with cache ID ' . $id, 'DEBUG'); - } - } elseif ($id = $this->_getCacheId($key)) { - // Entry has been deleted. - $ob->expire($id); - } - } - } - /* Register access key logger for translators. */ if (!empty($GLOBALS['conf']['log_accesskeys'])) { Horde::getAccessKey(null, null, true); @@ -470,7 +461,7 @@ class Horde_Registry */ public function __clone() { - throw new Horde_Exception('Horde_Registry objects should never be cloned.'); + throw new Horde_Exception('Registry objects should never be cloned.'); } /** @@ -480,36 +471,40 @@ class Horde_Registry */ public function __sleep() { - throw new Horde_Exception('Horde_Registry objects should never be serialized.'); + throw new Horde_Exception('Registry objects should never be serialized.'); } /** - * Clear the registry cache. + * Rebuild the registry configuration. */ - public function clearCache() + public function rebuild() { + $app = $this->getApp(); + + $this->applications = $this->_apiList = $this->_apis = $this->_confCache = $this->_interfaces = array(); + $GLOBALS['session']->remove('horde', 'registry/'); - $this->_cache = array(); - $this->_savecache['api'] = false; - $this->_savecache['appcache'] = false; + $this->_saveCache('apis'); + $this->_saveCache('app'); + + $this->_loadApplications(); + + $this->importConfig('horde'); + $this->importConfig($app); } /** - * Fills the registry's application cache with application information. - * - * @param string $vhost TODO + * Load application configuration information. */ - protected function _loadApplicationsCache($vhost) + protected function _loadApplications() { /* First, try to load from cache. */ - if ($this->_loadCache('appcache')) { - $this->applications = $this->_cache['appcache'][0]; - $this->_cache['interfaces'] = $this->_cache['appcache'][1]; + if ($ret = $this->_loadCache('app')) { + $this->applications = $ret[0]; + $this->_interfaces = $ret[1]; return; } - $this->_cache['interfaces'] = array(); - /* Read the registry configuration files. */ if (!file_exists(HORDE_BASE . '/config/registry.php')) { throw new Horde_Exception('Missing registry.php configuration file'); @@ -520,8 +515,8 @@ class Horde_Registry include $r; } - if ($vhost) { - include $vhost; + if ($this->_vhost) { + include $this->_vhost; } /* Scan for all APIs provided by each app, and set other common @@ -551,10 +546,10 @@ class Horde_Registry (($app['status'] != 'admin') || $this->isAdmin())) { if (is_array($app['provides'])) { foreach ($app['provides'] as $interface) { - $this->_cache['interfaces'][$interface] = $appName; + $this->_interfaces[$interface] = $appName; } } else { - $this->_cache['interfaces'][$app['provides']] = $appName; + $this->_interfaces[$app['provides']] = $appName; } } @@ -575,24 +570,21 @@ class Horde_Registry } } - $this->_cache['appcache'] = array( - // Index 0 + $this->_saveCache('app', array( $this->applications, - // Index 1 - $this->_cache['interfaces'] - ); - $this->_savecache['appcache'] = true; + $this->_interfaces + )); } /** - * Fills the registry's API cache with the available external services. + * Load the list of available external services. * * @throws Horde_Exception */ - protected function _loadApiCache() + protected function _loadApis() { - /* First, try to load from cache. */ - if ($this->_loadCache('api')) { + if (isset($this->_apis) || + ($this->_apis = $this->_loadCache('apis'))) { return; } @@ -602,13 +594,13 @@ class Horde_Registry $status[] = 'admin'; } - $this->_cache['api'] = array(); + $this->_apis = array(); foreach (array_keys($this->applications) as $app) { if (in_array($this->applications[$app]['status'], $status)) { try { $api = $this->getApiInstance($app, 'api'); - $this->_cache['api'][$app] = array( + $this->_apis[$app] = array( 'api' => array_diff(get_class_methods($api), array('__construct'), $api->disabled), 'links' => $api->links, 'noperms' => $api->noPerms @@ -619,7 +611,7 @@ class Horde_Registry } } - $this->_savecache['api'] = true; + $this->_saveCache('apis', $this->_api); } /** @@ -633,8 +625,8 @@ class Horde_Registry */ public function getApiInstance($app, $type) { - if (isset($this->_cache['ob'][$app][$type])) { - return $this->_cache['ob'][$app][$type]; + if (isset($this->_obCache[$app][$type])) { + return $this->_obCache[$app][$type]; } $cname = Horde_String::ucfirst($type); @@ -646,15 +638,16 @@ class Horde_Registry if (file_exists($path)) { include_once $path; } else { - $classname = 'Horde_Registry_' . $cname; + $classname = __CLASS__ . '_' . $cname; } if (!class_exists($classname, false)) { throw new Horde_Exception("$app does not have an API"); } - $this->_cache['ob'][$app][$type] = new $classname(); - return $this->_cache['ob'][$app][$type]; + $this->_obCache[$app][$type] = new $classname(); + + return $this->_obCache[$app][$type]; } /** @@ -712,16 +705,18 @@ class Horde_Registry */ public function listAPIs() { - if (empty($this->_apis)) { - if (!empty($this->_cache['interfaces'])) { - foreach (array_keys($this->_cache['interfaces']) as $interface) { - list($api,) = explode('/', $interface, 2); - $this->_apis[$api] = true; - } + if (empty($this->_apiList) && !empty($this->_interfaces)) { + $apis = array(); + + foreach (array_keys($this->_interfaces) as $interface) { + list($api,) = explode('/', $interface, 2); + $apis[$api] = true; } + + $this->_apiList = array_keys($apis); } - return array_keys($this->_apis); + return $this->_apiList; } /** @@ -737,7 +732,7 @@ class Horde_Registry { $methods = array(); - $this->_loadApiCache(); + $this->_loadApis(); foreach (array_keys($this->applications) as $app) { if (isset($this->applications[$app]['provides'])) { @@ -745,17 +740,17 @@ class Horde_Registry if (!is_array($provides)) { $provides = array($provides); } + foreach ($provides as $method) { if (strpos($method, '/') !== false) { if (is_null($api) || (substr($method, 0, strlen($api)) == $api)) { $methods[$method] = true; } - } elseif (is_null($api) || ($method == $api)) { - if (isset($this->_cache['api'][$app])) { - foreach ($this->_cache['api'][$app]['api'] as $service) { - $methods[$method . '/' . $service] = true; - } + } elseif (isset($this->_apis[$app]) && + (is_null($api) || ($method == $api))) { + foreach ($this->_apis[$app]['api'] as $service) { + $methods[$method . '/' . $service] = true; } } } @@ -775,8 +770,8 @@ class Horde_Registry */ public function hasInterface($interface) { - return !empty($this->_cache['interfaces'][$interface]) ? - $this->_cache['interfaces'][$interface] : + return !empty($this->interfaces[$interface]) ? + $this->interfaces[$interface] : false; } @@ -793,10 +788,10 @@ class Horde_Registry { if (is_null($app)) { list($interface, $call) = explode('/', $method, 2); - if (!empty($this->_cache['interfaces'][$method])) { - $app = $this->_cache['interfaces'][$method]; - } elseif (!empty($this->_cache['interfaces'][$interface])) { - $app = $this->_cache['interfaces'][$interface]; + if (!empty($this->interfaces[$method])) { + $app = $this->interfaces[$method]; + } elseif (!empty($this->interfaces[$interface])) { + $app = $this->interfaces[$interface]; } else { return false; } @@ -804,9 +799,9 @@ class Horde_Registry $call = $method; } - $this->_loadApiCache(); + $this->_loadApis(); - return (isset($this->_cache['api'][$app]) && in_array($call, $this->_cache['api'][$app]['api'])) + return (isset($this->_apis[$app]) && in_array($call, $this->_apis[$app]['api'])) ? $app : false; } @@ -826,7 +821,9 @@ class Horde_Registry } catch (Horde_Exception $e) { return false; } - return (method_exists($appob, $method) && !in_array($method, $appob->disabled)); + + return (method_exists($appob, $method) && + !in_array($method, $appob->disabled)); } /** @@ -845,10 +842,10 @@ class Horde_Registry { list($interface, $call) = explode('/', $method, 2); - if (!empty($this->_cache['interfaces'][$method])) { - $app = $this->_cache['interfaces'][$method]; - } elseif (!empty($this->_cache['interfaces'][$interface])) { - $app = $this->_cache['interfaces'][$interface]; + if (!empty($this->interfaces[$method])) { + $app = $this->interfaces[$method]; + } elseif (!empty($this->interfaces[$interface])) { + $app = $this->interfaces[$interface]; } else { throw new Horde_Exception('The method "' . $method . '" is not defined in the Horde Registry.'); } @@ -891,7 +888,7 @@ class Horde_Registry /* Switch application contexts now, if necessary, before * including any files which might do it for us. Return an * error immediately if pushApp() fails. */ - $pushed = $this->pushApp($app, array('check_perms' => !in_array($call, $this->_cache['api'][$app]['noperms']) && empty($options['noperms']))); + $pushed = $this->pushApp($app, array('check_perms' => !in_array($call, $this->_apis[$app]['noperms']) && empty($options['noperms']))); try { $result = call_user_func_array(array($api, $call), $args); @@ -977,10 +974,10 @@ class Horde_Registry { list($interface, $call) = explode('/', $method, 2); - if (!empty($this->_cache['interfaces'][$method])) { - $app = $this->_cache['interfaces'][$method]; - } elseif (!empty($this->_cache['interfaces'][$interface])) { - $app = $this->_cache['interfaces'][$interface]; + if (!empty($this->interfaces[$method])) { + $app = $this->interfaces[$method]; + } elseif (!empty($this->interfaces[$interface])) { + $app = $this->interfaces[$interface]; } else { throw new Horde_Exception('The method "' . $method . '" is not defined in the Horde Registry.'); } @@ -1002,13 +999,13 @@ class Horde_Registry public function linkByPackage($app, $call, $args = array(), $extra = '') { /* Make sure the link is defined. */ - $this->_loadApiCache(); - if (empty($this->_cache['api'][$app]['links'][$call])) { + $this->_loadApis(); + if (empty($this->_apis[$app]['links'][$call])) { throw new Horde_Exception('The link ' . $call . ' is not defined in ' . $app . '\'s API.'); } /* Initial link value. */ - $link = $this->_cache['api'][$app]['links'][$call]; + $link = $this->_apis[$app]['links'][$call]; /* Fill in html-encoded arguments. */ foreach ($args as $key => $val) { @@ -1525,20 +1522,15 @@ class Horde_Registry * * @param string $name Cache variable name. * - * @return boolean True if value loaded from cache. + * @return mixed The cached data or false if no data retrieved. */ protected function _loadCache($name) { - if (isset($this->_cache[$name])) { - return true; - } - if ($id = $this->_getCacheId($name)) { $result = $GLOBALS['injector']->getInstance('Horde_Cache')->get($id, 86400); if ($result !== false) { - $this->_cache[$name] = unserialize($result); - Horde::logMessage('Horde_Registry: retrieved ' . $name . ' with cache ID ' . $id, 'DEBUG'); - return true; + Horde::logMessage(__CLASS__ . ': retrieved ' . $name . ' with cache ID ' . $id, 'DEBUG'); + return unserialize($result); } } @@ -1549,25 +1541,51 @@ class Horde_Registry * Get the cache storage ID for a particular cache name. * * @param string $name Cache variable name. - * @param string $md5 Append MD5 value? + * @param string $md5 Use this MD5 value instead of session MD5 value. * * @return mixed The cache ID or false if cache entry doesn't exist in * the session. */ - protected function _getCacheId($name, $md5 = true) + protected function _getCacheId($name, $md5 = null) { - $id = 'horde_registry_' . $name . '|' . $this->_regmtime; + $id = 'horde_registry|' . $name . '|' . $this->_regmtime; - if (!$md5) { - return $id; - } elseif ($hash = $GLOBALS['session']->get('horde', 'registry/' . $name)) { - return $id . '|' . $hash; + if (!is_null($md5) || + ($md5 = $GLOBALS['session']->get('horde', 'registry/' . $name))) { + return $id . '|' . $md5; } return false; } /** + * Save a registry cache entry. + * + * @param string $key The cache key. + * @param mixed $data The cache data. If null, deletes the item. + */ + protected function _saveCache($key, $data = null) + { + $ob = $GLOBALS['injector']->getInstance('Horde_Cache'); + + if (is_null($data)) { + if ($id = $this->_getCacheId($key)) { + // Entry has been deleted. + $ob->expire($id); + } + } else { + // Entry has been updated. + $data = serialize($data); + $md5sum = hash('md5', $data); + $GLOBALS['session']->set('horde', 'registry/' . $key, $md5sum); + $id = $this->_getCacheId($key, $md5sum); + if ($ob->set($id, $data, 86400)) { + Horde::logMessage(__CLASS__ . ': stored ' . $key . ' with cache ID ' . $id, 'DEBUG'); + } + } + } + + /** * Destroys any existing session on login and make sure to use a new * session ID, to avoid session fixation issues. Should be called before * checking a login. @@ -2179,10 +2197,7 @@ class Horde_Registry if ($GLOBALS['language'] == $lang) { return; } - $this->clearCache(); - $this->_confCache = array(); - $this->importConfig('horde'); - $this->importConfig($this->getApp()); + $changed = true; } $GLOBALS['language'] = $lang; @@ -2191,6 +2206,10 @@ class Horde_Registry @putenv('LC_ALL=' . $lang_charset); @putenv('LANG=' . $lang_charset); @putenv('LANGUAGE=' . $lang_charset); + + if ($changed) { + $this->rebuild(); + } } /** diff --git a/horde/admin/config/config.php b/horde/admin/config/config.php index e217d8b43..e4c748c67 100644 --- a/horde/admin/config/config.php +++ b/horde/admin/config/config.php @@ -61,7 +61,7 @@ if (Horde_Util::getFormData('submitbutton') == _("Revert Configuration")) { fwrite($fp, $php); fclose($fp); $notification->push(sprintf(_("Successfully wrote %s"), Horde_Util::realPath($configFile)), 'horde.success'); - $registry->clearCache(); + $registry->rebuild(); Horde::url('admin/config/index.php', true)->redirect(); } else { /* Cannot write. */ diff --git a/horde/admin/config/index.php b/horde/admin/config/index.php index f764cbf8a..7abec0650 100644 --- a/horde/admin/config/index.php +++ b/horde/admin/config/index.php @@ -51,7 +51,9 @@ function _uploadFTP($params) $notification->push(sprintf(_("Could not write configuration for \"%s\": %s"), $app, $e->getMessage()), 'horde.error'); } } - $registry->clearCache(); + + $registry->rebuild(); + return $no_errors; } diff --git a/horde/admin/config/scripts.php b/horde/admin/config/scripts.php index 89ff4d3e7..b78b8b78e 100644 --- a/horde/admin/config/scripts.php +++ b/horde/admin/config/scripts.php @@ -34,7 +34,7 @@ if ($clean == 'tmp') { } else { $notification->push(sprintf(_("Could not delete configuration upgrade script \"%s\"."), Horde_Util::realPath($path)), 'horde.error'); } - $registry->clearCache(); + $registry->rebuild(); Horde::url('admin/config/index.php', true)->redirect(); }