Fix cyclic dependency with Horde_Db_Base_Adapter binder
authorMichael M Slusarz <slusarz@curecanti.org>
Wed, 19 May 2010 03:35:46 +0000 (21:35 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Wed, 19 May 2010 03:38:06 +0000 (21:38 -0600)
Horde_Db (optionally) uses both cache and/or logger objects. However,
these objects can themselves use Horde_Db. Thus, to init these objects,
the Horde_Db object must have already been instantiated. These objects
cannot be passed to Horde_Db at construct time - they must be added in
afterwards.

framework/Core/lib/Horde/Core/Binder/Db.php
framework/Db/lib/Horde/Db/Adapter/Base.php
framework/Db/package.xml

index 6e166ac..2a5aba4 100644 (file)
@@ -38,19 +38,21 @@ class Horde_Core_Binder_Db implements Horde_Injector_Binder
             $config['host'] = $config['hostspec'];
         }
 
-        if (!isset($config['logger'])) {
-            $config['logger'] = $injector->getInstance('Horde_Log_Logger');
-        }
-
-        if (!isset($config['cache'])) {
-            $config['cache'] = $injector->getInstance('Horde_Cache');
-        }
-
         $adapter = str_replace(' ', '_' , ucwords(str_replace('_', ' ', basename($config['adapter']))));
         $class = 'Horde_Db_Adapter_' . $adapter;
 
         if (class_exists($class)) {
-            return new $class($config);
+            $ob = new $class($config);
+
+            if (!isset($config['cache'])) {
+                $ob->setCache($injector->getInstance('Horde_Cache'));
+            }
+
+            if (!isset($config['logger'])) {
+                $ob->setLogger($injector->getInstance('Horde_Log_Logger'));
+            }
+
+            return $ob;
         }
 
         throw new Horde_Exception('Adapter class "' . $class . '" not found');
index 682eb14..faad463 100644 (file)
@@ -48,7 +48,7 @@ abstract class Horde_Db_Adapter_Base
     /**
      * @var int
      */
-    protected $_runtime = null;
+    protected $_runtime;
 
     /**
      * @var boolean
@@ -56,14 +56,14 @@ abstract class Horde_Db_Adapter_Base
     protected $_active = null;
 
     /**
-     * @var Cache object
+     * @var Horde_Cache_Base
      */
-    protected $_cache = null;
+    protected $_cache;
 
     /**
-     * @var Logger
+     * @var Horde_Log_Logger
      */
-    protected $_logger = null;
+    protected $_logger;
 
     /**
      * @var Horde_Db_Adapter_Base_Schema
@@ -97,32 +97,18 @@ abstract class Horde_Db_Adapter_Base
      *
      * @param array $config  Configuration options and optional objects:
      * <pre>
-     * 'cache' - (Horde_Cache) Cache object.
      * 'charset' - (string) TODO
-     * 'logger' - (Horde_Log_Logger) Logging object.
      * 'write_db' - (Horde_Db_Adapter_Base) Use this DB for write operations.
      * </pre>
      */
     public function __construct($config)
     {
-        // Create a stub if we don't have a useable cache.
-        if (isset($config['cache'])
-            && is_callable(array($config['cache'], 'get'))
-            && is_callable(array($config['cache'], 'set'))) {
-            $this->_cache = $config['cache'];
-            unset($config['cache']);
-        } else {
-            $this->_cache = new Horde_Support_Stub;
-        }
-
-        // Create a stub if we don't have a useable logger.
-        if (isset($config['logger'])
-            && is_callable(array($config['logger'], 'log'))) {
-            $this->_logger = $config['logger'];
-            unset($config['logger']);
-        } else {
-            $this->_logger = new Horde_Support_Stub;
-        }
+        /* Can't set cache/logger in constructor - these objects may use DB
+         * for storage. Add stubs for now - they have to be manually set
+         * later with setCache() and setLogger(). */
+        $stub = new Horde_Support_Stub();
+        $this->_cache = $stub;
+        $this->_logger = $stub;
 
         // Default to UTF-8
         if (!isset($config['charset'])) {
@@ -132,16 +118,9 @@ abstract class Horde_Db_Adapter_Base
         $this->_config  = $config;
         $this->_runtime = 0;
 
-        // Create the database-specific (but not adapter specific) schema
-        // object.
         if (!$this->_schemaClass) {
             $this->_schemaClass = __CLASS__ . '_Schema';
         }
-        $this->_schema = new $this->_schemaClass($this, array(
-            'cache' => $this->_cache,
-            'logger' => $this->_logger
-        ));
-        $this->_schemaMethods = array_flip(get_class_methods($this->_schema));
 
         $this->connect();
     }
@@ -156,6 +135,31 @@ abstract class Horde_Db_Adapter_Base
 
 
     /*##########################################################################
+    # Object helpers
+    ##########################################################################*/
+
+    /**
+     * Set a cache object.
+     *
+     * @var Horde_Cache_Base $logger  The cache object.
+     */
+    public function setCache(Horde_Cache_Base $cache)
+    {
+        $this->_cache = $cache;
+    }
+
+    /**
+     * Set a logger object.
+     *
+     * @var Horde_Log_Logger $logger  The logger object.
+     */
+    public function setLogger(Horde_Log_Logger $logger)
+    {
+        $this->_logger = $logger;
+    }
+
+
+    /*##########################################################################
     # Object factory
     ##########################################################################*/
 
@@ -191,6 +195,16 @@ abstract class Horde_Db_Adapter_Base
      */
     public function __call($method, $args)
     {
+        if (!$this->_schema) {
+            // Create the database-specific (but not adapter specific) schema
+            // object.
+            $this->_schema = new $this->_schemaClass($this, array(
+                'cache' => $this->_cache,
+                'logger' => $this->_logger
+            ));
+            $this->_schemaMethods = array_flip(get_class_methods($this->_schema));
+        }
+
         if (isset($this->_schemaMethods[$method])) {
             return call_user_func_array(array($this->_schema, $method), $args);
         }
index 0272a87..37faba3 100644 (file)
@@ -104,6 +104,16 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <channel>pear.horde.org</channel>
    </package>
   </required>
+  <optional>
+   <package>
+    <name>Cache</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <package>
+    <name>Log</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </optional>
  </dependencies>
  <phprelease>
   <filelist>