Make Horde_Memcache injectable
authorMichael M Slusarz <slusarz@curecanti.org>
Sun, 31 Jan 2010 00:14:36 +0000 (17:14 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Sun, 31 Jan 2010 04:15:13 +0000 (21:15 -0700)
framework/Cache/lib/Horde/Cache.php
framework/Cache/lib/Horde/Cache/Memcache.php
framework/Core/lib/Horde/Core/Binder/Cache.php
framework/Core/lib/Horde/Core/Binder/Memcache.php [new file with mode: 0644]
framework/Core/lib/Horde/Registry.php
framework/Core/package.xml
framework/Memcache/lib/Horde/Memcache.php
framework/Memcache/scripts/Horde/Memcache/stats.php
framework/SessionHandler/lib/Horde/SessionHandler.php
framework/SessionHandler/lib/Horde/SessionHandler/Memcache.php
kronolith/fb.php

index f828e8f..2aeb301 100644 (file)
@@ -48,8 +48,11 @@ class Horde_Cache
             return new Horde_Cache_Null($params);
         }
 
-        $class = (empty($app) ? 'Horde' : $app) . '_Cache_' . ucfirst($driver);
+        if ($driver == 'memcache') {
+            $params['memcache'] = $GLOBALS['injector']->getInstance('Horde_Memcache');
+        }
 
+        $class = (empty($app) ? 'Horde' : $app) . '_Cache_' . ucfirst($driver);
         if (class_exists($class)) {
             return new $class($params);
         }
index 96002ec..2bf20ae 100644 (file)
@@ -3,6 +3,12 @@
  * The Horde_Cache_Memcache:: class provides a memcached implementation of the
  * Horde caching system.
  *
+ * Addtional parameters:
+ * ---------------------
+ * <pre>
+ * 'memcache' - (Horde_Memcache) A Horde_Memcache object.
+ * </pre>
+ *
  * Copyright 2006-2007 Duck <duck@obala.net>
  * Copyright 2007-2010 The Horde Project (http://www.horde.org/)
  *
@@ -17,7 +23,7 @@
 class Horde_Cache_Memcache extends Horde_Cache_Base
 {
     /**
-     * Horde_memcache object.
+     * Memcache object.
      *
      * @var Horde_Memcache
      */
@@ -33,10 +39,16 @@ class Horde_Cache_Memcache extends Horde_Cache_Base
      * Construct a new Horde_Cache_Memcache object.
      *
      * @param array $params  Parameter array.
+     *
+     * @throws InvalidArgumentException
      */
     public function __construct($params = array())
     {
-        $this->_memcache = Horde_Memcache::singleton();
+        if (!isset($params['memcache'])) {
+            throw new InvalidArgumentException('Missing memcache object');
+        }
+
+        $this->_memcache = $params['memcache'];
 
         parent::__construct($params);
     }
index bd56c6c..2370355 100644 (file)
@@ -13,10 +13,14 @@ class Horde_Core_Binder_Cache implements Horde_Injector_Binder
             $driver = basename($driver);
         }
 
-        if (empty($driver) || $driver == 'none') {
+        if (empty($driver) || ($driver == 'none')) {
             return new Horde_Cache_Null($params);
         }
 
+        if ($driver == 'memcache') {
+            $params['memcache'] = $injector->getInstance('Horde_Memcache');
+        }
+
         $class = (empty($app) ? 'Horde' : $app) . '_Cache_' . ucfirst($driver);
         if (class_exists($class)) {
             return new $class($params);
diff --git a/framework/Core/lib/Horde/Core/Binder/Memcache.php b/framework/Core/lib/Horde/Core/Binder/Memcache.php
new file mode 100644 (file)
index 0000000..d10b95b
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+class Horde_Core_Binder_Memcache implements Horde_Injector_Binder
+{
+    public function create(Horde_Injector $injector)
+    {
+        return empty($GLOBALS['conf']['memcache']['enabled'])
+            ? null
+            : new Horde_Memcache($GLOBALS['conf']['memcache']);
+    }
+
+    public function equals(Horde_Injector_Binder $binder)
+    {
+        return false;
+    }
+}
index 242bfa6..e8b5da4 100644 (file)
@@ -42,13 +42,6 @@ class Horde_Registry
     protected $_cache = array();
 
     /**
-     * The Horde_Cache object.
-     *
-     * @var Horde_Cache
-     */
-    protected $_cacheob;
-
-    /**
      * The last modified time of the newest modified registry file.
      *
      * @var integer
@@ -261,6 +254,11 @@ class Horde_Registry
             umask($conf['umask']);
         }
 
+        /* Setup injector. Need to init Horde_Memcache here because it may
+         * be called in setupSessionHandler(). */
+        $GLOBALS['injector'] = new Horde_Injector(new Horde_Injector_TopLevel());
+        $GLOBALS['injector']->addBinder('Horde_Memcache', new Horde_Core_Binder_Memcache());
+
         /* Start a session. */
         if ($session_flags & self::SESSION_NONE ||
             (PHP_SAPI == 'cli') ||
@@ -286,17 +284,8 @@ class Horde_Registry
         Horde_Nls::setTextdomain('horde', HORDE_BASE . '/locale', Horde_Nls::getCharset());
         Horde_String::setDefaultCharset(Horde_Nls::getCharset());
 
-        /* Check for caching availability. Using cache while not authenticated
-         * isn't possible because, although storage is possible, retrieval
-         * isn't since there is no MD5 sum in the session to use to build
-         * the cache IDs. */
-        if (Horde_Auth::getAuth()) {
-            try {
-                $this->_cacheob = Horde_Cache::singleton($conf['cache']['driver'], Horde::getDriverConfig('cache', $conf['cache']['driver']));
-            } catch (Horde_Exception $e) {
-                // @TODO Log error
-            }
-        }
+        /* Initialize caching. */
+        $GLOBALS['injector']->addBinder('Horde_Cache', new Horde_Core_Binder_Cache());
 
         $this->_regmtime = max(filemtime(HORDE_BASE . '/config/registry.php'),
                                filemtime(HORDE_BASE . '/config/registry.d'));
@@ -319,9 +308,7 @@ class Horde_Registry
             throw new Horde_Exception(_("This system is currently deactivated."));
         }
 
-        /* Set default bindings. */
-        $GLOBALS['injector'] = new Horde_Injector(new Horde_Injector_TopLevel());
-        $GLOBALS['injector']->addBinder('Horde_Cache', new Horde_Core_Binder_Cache());
+        /* Set the rest of the default bindings. */
         $GLOBALS['injector']->addBinder('Horde_Db_Adapter_Base', new Horde_Core_Binder_Db('reader'));
         $GLOBALS['injector']->addBinder('Horde_Log_Logger', new Horde_Core_Binder_Logger());
 
@@ -1376,18 +1363,25 @@ class Horde_Registry
      */
     protected function _saveCacheVar($name, $expire = false)
     {
-        if ($this->_cacheob) {
-            if ($expire) {
-                if ($id = $this->_getCacheId($name)) {
-                    $this->_cacheob->expire($id);
-                }
-            } else {
-                $data = serialize($this->_cache[$name]);
-                $_SESSION['_registry']['md5'][$name] = $md5sum = hash('md5', $data);
-                $id = $this->_getCacheId($name, false) . '|' . $md5sum;
-                if ($this->_cacheob->set($id, $data, 86400)) {
-                    Horde::logMessage('Horde_Registry: stored ' . $name . ' with cache ID ' . $id, __FILE__, __LINE__, PEAR_LOG_DEBUG);
-                }
+        /* Using cache while not authenticated isn't possible because,
+         * although storage is possible, retrieval isn't since there is no
+         * MD5 sum in the session to use to build the cache IDs. */
+        if (!Horde_Auth::getAuth()) {
+            return;
+        }
+
+        $ob = $GLOBALS['injector']->getInstance('Horde_Cache');
+
+        if ($expire) {
+            if ($id = $this->_getCacheId($name)) {
+                $ob->expire($id);
+            }
+        } else {
+            $data = serialize($this->_cache[$name]);
+            $_SESSION['_registry']['md5'][$name] = $md5sum = hash('md5', $data);
+            $id = $this->_getCacheId($name, false) . '|' . $md5sum;
+            if ($ob->set($id, $data, 86400)) {
+                Horde::logMessage('Horde_Registry: stored ' . $name . ' with cache ID ' . $id, __FILE__, __LINE__, PEAR_LOG_DEBUG);
             }
         }
     }
@@ -1405,9 +1399,12 @@ class Horde_Registry
             return true;
         }
 
-        if ($this->_cacheob &&
+        /* Using cache while not authenticated isn't possible because,
+         * although storage is possible, retrieval isn't since there is no
+         * MD5 sum in the session to use to build the cache IDs. */
+        if (Horde_Auth::getAuth() &&
             ($id = $this->_getCacheId($name))) {
-            $result = $this->_cacheob->get($id, 86400);
+            $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, __FILE__, __LINE__, PEAR_LOG_DEBUG);
@@ -1482,15 +1479,11 @@ class Horde_Registry
                                      $calls['destroy'],
                                      $calls['gc']);
         } elseif ($type != 'none') {
-            $sh = Horde_SessionHandler::singleton($conf['sessionhandler']['type'], array_merge(Horde::getDriverConfig('sessionhandler', $conf['sessionhandler']['type']), array('memcache' => !empty($conf['sessionhandler']['memcache']))));
-            ini_set('session.save_handler', 'user');
-            session_set_save_handler(array($sh, 'open'),
-                                     array($sh, 'close'),
-                                     array($sh, 'read'),
-                                     array($sh, 'write'),
-                                     array($sh, 'destroy'),
-                                     array($sh, 'gc'));
-            $this->sessionHandler = $sh;
+            $sh_config = Horde::getDriverConfig('sessionhandler', $conf['sessionhandler']['type']);
+            if (!empty($conf['sessionhandler']['memcache'])) {
+                $sh_config['memcache'] = $GLOBALS['injector']->getInstance('Horde_Memcache');
+            }
+            $this->sessionHandler = Horde_SessionHandler::factory($conf['sessionhandler']['type'], $sh_config);
         }
     }
 
index 3f47c8a..ad0ff50 100644 (file)
@@ -54,6 +54,7 @@ Application Framework.
        <file name="Cache.php" role="php" />
        <file name="Db.php" role="php" />
        <file name="Logger.php" role="php" />
+       <file name="Memcache.php" role="php" />
       </dir> <!-- /lib/Horde/Core/Binder -->
      </dir> <!-- /lib/Horde/Core -->
      <file name="ErrorHandler.php" role="php" />
@@ -133,6 +134,7 @@ Application Framework.
    <install name="lib/Horde/Core/Binder/Cache.php" as="Horde/Core/Binder/Cache.php" />
    <install name="lib/Horde/Core/Binder/Db.php" as="Horde/Core/Binder/Db.php" />
    <install name="lib/Horde/Core/Binder/Logger.php" as="Horde/Core/Binder/Logger.php" />
+   <install name="lib/Horde/Core/Binder/Memcache.php" as="Horde/Core/Binder/Memcache.php" />
    <install name="lib/Horde/ErrorHandler.php" as="Horde/ErrorHandler.php" />
    <install name="lib/Horde/Exception/HookNotSet.php" as="Horde/Exception/HookNotSet.php" />
    <install name="lib/Horde/Help.php" as="Horde/Help.php" />
index 5b2daa5..9c589d2 100644 (file)
@@ -53,13 +53,6 @@ class Horde_Memcache
     const MAX_SIZE = 1000000;
 
     /**
-     * The singleton instance.
-     *
-     * @var Horde_Memcache
-     */
-    static protected $_instance = null;
-
-    /**
      * Memcache object.
      *
      * @var Memcache
@@ -94,25 +87,15 @@ class Horde_Memcache
     protected $_noexist = array();
 
     /**
-     * Singleton.
-     */
-    public static function singleton()
-    {
-        if (!self::$_instance) {
-            self::$_instance = new self();
-        }
-
-        return self::$_instance;
-    }
-
-    /**
      * Constructor.
      *
+     * @param array $params  TODO
+     *
      * @throws Horde_Exception
      */
-    protected function __construct()
+    public function __construct($params = array())
     {
-        $this->_params = array_merge($this->_params, $GLOBALS['conf']['memcache']);
+        $this->_params = array_merge($this->_params, $params);
         $this->_params['prefix'] = (empty($this->_params['prefix'])) ? 'horde' : $this->_params['prefix'];
         $this->_large = !empty($this->_params['large_items']);
 
index f408bd3..f1cc527 100755 (executable)
@@ -36,7 +36,7 @@ if (PEAR::isError($options)) {
 }
 
 $all = $raw = $summary = false;
-$memcache = &Horde_Memcache::singleton();
+$memcache = $injector->getInstance('Horde_Memcache');
 
 foreach ($options[0] as $val) {
     switch ($val[0]) {
index f37ebb4..2400fd3 100644 (file)
@@ -4,7 +4,8 @@
  * handlers.
  *
  * Optional parameters:<pre>
- *   'memcache' - (boolean) Use memcache to cache session data?
+ * 'memcache' - (Horde_Memcache) If set, uses memcache to cache session
+ *              data.
  * </pre>
  *
  * Copyright 2002-2010 The Horde Project (http://www.horde.org/)
 class Horde_SessionHandler
 {
     /**
-     * Singleton instances.
-     *
-     * @var array
-     */
-    static protected $_instances = array();
-
-    /**
      * Hash containing connection parameters.
      *
      * @var array
@@ -74,10 +68,15 @@ class Horde_SessionHandler
             // Trap for old driver name.
             $driver = 'memcache';
         } elseif (($driver != 'memcache') && !empty($params['memcache'])) {
-            unset($params['memcache']);
-            $persistent_params = array('persistent_driver' => $driver, 'persistent_params' => $params);
+            $p_params = $params;
+            unset($p_params['memcache']);
+
+            $persistent_params = array(
+                'persistent_driver' => $driver,
+                'persistent_params' => $p_params
+            );
+
             $driver = 'memcache';
-            $params = array();
         }
 
         $class = __CLASS__ . '_' . ucfirst($driver);
@@ -93,32 +92,6 @@ class Horde_SessionHandler
     }
 
     /**
-     * Attempts to return a reference to a concrete Horde_SessionHandler
-     * instance based on $driver. It will only create a new instance
-     * if no Horde_SessionHandler instance with the same parameters
-     * currently exists.
-     *
-     * This method must be invoked as:
-     *   $var = Horde_SessionHandler::singleton()
-     *
-     * @param string $driver  See Horde_SessionHandler::factory().
-     * @param array $params   See Horde_SessionHandler::factory().
-     *
-     * @return Horde_SessionHandler  The singleton instance.
-     * @throws Horde_Exception
-     */
-    static public function singleton($driver, $params = array())
-    {
-        ksort($params);
-        $signature = hash('md5', serialize(array($driver, $params)));
-        if (empty(self::$_instances[$signature])) {
-            self::$_instances[$signature] = self::factory($driver, $params);
-        }
-
-        return self::$_instances[$signature];
-    }
-
-    /**
      * Constructor.
      *
      * @param array $params  A hash containing connection parameters.
@@ -128,7 +101,18 @@ class Horde_SessionHandler
     protected function __construct($params = array())
     {
         $this->_params = $params;
+
         register_shutdown_function(array($this, 'shutdown'));
+
+        ini_set('session.save_handler', 'user');
+        session_set_save_handler(
+            array($this, 'open'),
+            array($this, 'close'),
+            array($this, 'read'),
+            array($this, 'write'),
+            array($this, 'destroy'),
+            array($this, 'gc')
+        );
     }
 
     /**
index c133150..5d98880 100644 (file)
@@ -1,19 +1,19 @@
 <?php
 /**
- * Horde_SessionHandler:: implementation for memcache.
+ * Horde_SessionHandler implementation for memcache.
  *
- * NOTE FOR WINDOWS USERS w/PHP 4: Due to limitations in PHP 4, you should not
- * use the memcache driver.  Either upgrade to PHP 5 or use a different
- * session handler.
+ * Required parameters:<pre>
+ * 'memcache' - (Horde_Memcache) A memcache object.
+ * </pre>
  *
  * Optional parameters:<pre>
- *   'persistent_driver' - (string) If set, uses this backend to store session
- *                         data persistently.
- *   'persistent_params' - (array) If using a persistent backend, the params
- *                         to use for the persistent backend.
- *   'track' - (boolean) Track active sessions?
- *   'track_lifetime' - (integer) The number of seconds after which tracked
- *                      sessions will be treated as expired.
+ * 'persistent_driver' - (string) If set, uses this backend to store session
+ *                       data persistently.
+ * 'persistent_params' - (array) If using a persistent backend, the params
+ *                       to use for the persistent backend.
+ * 'track' - (boolean) Track active sessions?
+ * 'track_lifetime' - (integer) The number of seconds after which tracked
+ *                    sessions will be treated as expired.
  * </pre>
  *
  * Copyright 2005-2010 The Horde Project (http://www.horde.org/)
@@ -28,7 +28,7 @@
 class Horde_SessionHandler_Memcache extends Horde_SessionHandler
 {
     /**
-     * Horde_Memcache object.
+     * Memcache object.
      *
      * @var Horde_Memcache
      */
@@ -68,9 +68,16 @@ class Horde_SessionHandler_Memcache extends Horde_SessionHandler
      * @param array $params  A hash containing connection parameters.
      *
      * @throws Horde_Exception
+     * @throws InvalidArgumentException
      */
     protected function __construct($params = array())
     {
+        if (empty($params['memcache'])) {
+            throw InvalidArgumentException('Missing memcache object.');
+        }
+
+        $this->_memcache = $params['memcache'];
+
         if (!empty($params['persistent_driver'])) {
             try {
                 $this->_persistent = self::singleton($params['persistent_driver'], empty($params['persistent_params']) ? null : $params['persistent_params']);
@@ -105,8 +112,6 @@ class Horde_SessionHandler_Memcache extends Horde_SessionHandler
      */
     protected function _open($save_path = null, $session_name = null)
     {
-        $this->_memcache = Horde_Memcache::singleton();
-
         if (isset($this->_persistent)) {
             if (!$this->_persistent->open($save_path, $session_name)) {
                 throw new Horde_Exception('Could not open persistent backend.');
index 2a4ff2d..fd26bf8 100644 (file)
@@ -26,7 +26,7 @@ if (!empty($cal)) {
     $user = basename($pathInfo);
 }
 
-$cache = Horde_Cache::factory($conf['cache']['driver'], Horde::getDriverConfig('cache', $conf['cache']['driver']));
+$cache = $injector->getInstance('Horde_Cache');
 $key = 'kronolith.fb.' . ($user ? 'u.' . $user : 'c.' . $cal);
 $fb = $cache->get($key, 360);
 if (!$fb) {