Import Horde_Cache from CVS HEAD.
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 5 Mar 2009 03:53:00 +0000 (20:53 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 5 Mar 2009 03:59:29 +0000 (20:59 -0700)
12 files changed:
framework/Cache/data/cache.sql [new file with mode: 0644]
framework/Cache/lib/Horde/Cache.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Apc.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Base.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Eaccelerator.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/File.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Memcache.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Null.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Sql.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Xcache.php [new file with mode: 0644]
framework/Cache/lib/Horde/Cache/Zps4.php [new file with mode: 0644]
framework/Cache/package.xml [new file with mode: 0644]

diff --git a/framework/Cache/data/cache.sql b/framework/Cache/data/cache.sql
new file mode 100644 (file)
index 0000000..fcc8ec1
--- /dev/null
@@ -0,0 +1,9 @@
+CREATE TABLE horde_cache (
+    cache_id          VARCHAR(32) NOT NULL,
+    cache_timestamp   BIGINT NOT NULL,
+    cache_data        LONGBLOB,
+-- Or, on some DBMS systems:
+--  cache_data        IMAGE,
+
+    PRIMARY KEY  (cache_id)
+);
diff --git a/framework/Cache/lib/Horde/Cache.php b/framework/Cache/lib/Horde/Cache.php
new file mode 100644 (file)
index 0000000..4d9b3c3
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * The Horde_Cache:: class provides a common abstracted interface into
+ * the various caching backends.  It also provides functions for
+ * checking in, retrieving, and flushing a cache.
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Anil Madhavapeddy <anil@recoil.org>
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Cache
+ */
+class Horde_Cache
+{
+    /**
+     * Singleton instances.
+     *
+     * @var array
+     */
+    static protected $_instances = array();
+
+    /**
+     * Attempts to return a concrete Horde_Cache instance based on $driver.
+     *
+     * @param mixed $driver  The type of concrete Horde_Cache subclass to
+     *                       return. If $driver is an array, then we will look
+     *                       in $driver[0]/lib/Cache/ for the subclass
+     *                       implementation named $driver[1].php.
+     * @param array $params  A hash containing any additional configuration
+     *                       or connection parameters a subclass might need.
+     *
+     * @return Horde_Cache  The newly created concrete Horde_Cache instance.
+     * @throws Horde_Exception
+     */
+    static public function factory($driver, $params = array())
+    {
+        if (is_array($driver)) {
+            list($app, $driv_name) = $driver;
+            $driver = basename($driv_name);
+        } else {
+            $driver = basename($driver);
+        }
+
+        if (empty($driver) || $driver == 'none') {
+            return new Horde_Cache_Null($params);
+        }
+
+        $class = (empty($app) ? 'Horde' : $app) . '_Cache_' . ucfirst($driver);
+
+        if (class_exists($class)) {
+            return new $class($params);
+        }
+
+        throw new Horde_Exception('Class definition of ' . $class . ' not found.');
+    }
+
+    /**
+     * Attempts to return a reference to a concrete Horde_Cache instance
+     * based on $driver. It will only create a new instance if no
+     * Horde_Cache instance with the same parameters currently exists.
+     *
+     * This should be used if multiple cache backends (and, thus,
+     * multiple Horde_Cache instances) are required.
+     *
+     * This method must be invoked as:
+     *   $var = &Horde_Cache::singleton()
+     *
+     * @param mixed $driver  The type of concrete Horde_Cache subclass to
+     *                       return. If $driver is an array, then we will look
+     *                       in $driver[0]/lib/Cache/ for the subclass
+     *                       implementation named $driver[1].php.
+     * @param array $params  A hash containing any additional configuration or
+     *                       connection parameters a subclass might need.
+     *
+     * @return Horde_Cache  The concrete Horde_Cache reference.
+     * @throws Horde_Exception
+     */
+    static public function singleton($driver, $params = array())
+    {
+        ksort($params);
+        $signature = hash('md5', serialize(array($driver, $params)));
+
+        if (!isset(self::$_instances[$signature])) {
+            self::$_instances[$signature] = Horde_Cache::factory($driver, $params);
+        }
+
+        return self::$_instances[$signature];
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Apc.php b/framework/Cache/lib/Horde/Cache/Apc.php
new file mode 100644 (file)
index 0000000..c73a2d2
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * The Horde_Cache_Apc:: class provides an Alternative PHP Cache
+ * implementation of the Horde caching system.
+ *
+ * Copyright 2006-2007 Duck <duck@obala.net>
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Duck <duck@obala.net>
+ * @package Horde_Cache
+ */
+class Horde_Cache_Apc extends Horde_Cache_Base
+{
+    /**
+     * Attempts to retrieve a piece of cached data and return it to
+     * the caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        $this->_setExpire($key, $lifetime);
+        return apc_fetch($key);
+    }
+
+    /**
+     * Attempts to store an object to the cache.
+     *
+     * @param string $key        Cache key (identifier).
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Data lifetime.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        $lifetime = $this->_getLifetime($lifetime);
+        apc_store($key . '_expire', time(), $lifetime);
+        return apc_store($key, $data, $lifetime);
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        $this->_setExpire($key, $lifetime);
+        return (apc_fetch($key) === false) ? false : true;
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        apc_delete($key . '_expire');
+        return apc_delete($key);
+    }
+
+    /**
+     * Set expire time on each call since APC sets it on cache creation.
+     *
+     * @param string $key        Cache key to expire.
+     * @param integer $lifetime  Lifetime of the data in seconds.
+     */
+    protected function _setExpire($key, $lifetime)
+    {
+        if ($lifetime == 0) {
+            // Don't expire.
+            return;
+        }
+
+        $expire = apc_fetch($key . '_expire');
+
+        // Set prune period.
+        if ($expire + $lifetime < time()) {
+            // Expired
+            apc_delete($key);
+            apc_delete($key . '_expire');
+        }
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Base.php b/framework/Cache/lib/Horde/Cache/Base.php
new file mode 100644 (file)
index 0000000..b0dc48d
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * The Horde_Cache_Base:: class provides the abstract class definition for
+ * Horde_Cache drivers.
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Anil Madhavapeddy <anil@recoil.org>
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Cache
+ */
+abstract class Horde_Cache_Base
+{
+    /**
+     * Cache parameters.
+     *
+     * @var array
+     */
+    protected $_params = array();
+
+    /**
+     * Construct a new Horde_Cache object.
+     *
+     * @param array $params  Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        if (!isset($params['lifetime'])) {
+            $params['lifetime'] = isset($GLOBALS['conf']['cache']['default_lifetime'])
+                ? $GLOBALS['conf']['cache']['default_lifetime']
+                : 86400;
+        }
+
+        $this->_params = $params;
+    }
+
+    /**
+     * Attempts to retrieve a cached object and return it to the
+     * caller.
+     *
+     * @param string $key        Object ID to query.
+     * @param integer $lifetime  Lifetime of the object in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    abstract public function get($key, $lifetime = 1);
+
+    /**
+     * Attempts to store an object in the cache.
+     *
+     * @param string $key        Object ID used as the caching key.
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Object lifetime - i.e. the time before the
+     *                           data becomes available for garbage
+     *                           collection.  If null use the default Horde GC
+     *                           time.  If 0 will not be GC'd.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    abstract public function set($key, $data, $lifetime = null);
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    abstract public function exists($key, $lifetime = 1);
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    abstract public function expire($key);
+
+    /**
+     * Attempts to directly output a cached object.
+     *
+     * @param string $key        Object ID to query.
+     * @param integer $lifetime  Lifetime of the object in seconds.
+     *
+     * @return boolean  True if output or false if no object was found.
+     */
+    public function output($key, $lifetime = 1)
+    {
+        $data = $this->get($key, $lifetime);
+        if ($data === false) {
+            return false;
+        }
+
+        echo $data;
+        return true;
+    }
+
+    /**
+     * Determine the default lifetime for data.
+     *
+     * @param mixed $lifetime  The lifetime to use or null for default.
+     *
+     * @return integer  The lifetime, in seconds.
+     */
+    protected function _getLifetime($lifetime)
+    {
+        return is_null($lifetime) ? $this->_params['lifetime'] : $lifetime;
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Eaccelerator.php b/framework/Cache/lib/Horde/Cache/Eaccelerator.php
new file mode 100644 (file)
index 0000000..83e25b8
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * The Horde_Cache_Eaccelerator:: class provides a eAccelerator content cache
+ * (version 0.9.5+) implementation of the Horde caching system.
+ *
+ * Copyright 2006-2007 Duck <duck@obala.net>
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Duck <duck@obala.net>
+ * @package Horde_Cache
+ */
+class Horde_Cache_Eaccelerator extends Horde_Cache_Base
+{
+    /**
+     * Attempts to retrieve a piece of cached data and return it to the caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        $this->_setExpire($key, $lifetime);
+        return eaccelerator_get($key);
+    }
+
+    /**
+     * Attempts to store an object to the cache.
+     *
+     * @param string $key        Cache key (identifier).
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Data lifetime.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        $lifetime = $this->_getLifetime($lifetime);
+        eaccelerator_put($key . '_expire', time(), $lifetime);
+        return eaccelerator_put($key, $data, $lifetime);
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        $this->_setExpire($key, $lifetime);
+        return (eaccelerator_get($key) === false) ? false : true;
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        eaccelerator_rm($key . '_expire');
+        return eaccelerator_rm($key);
+    }
+
+    /**
+     * Set expire time on each call since eAccelerator sets it on
+     * cache creation.
+     *
+     * @param string $key        Cache key to expire.
+     * @param integer $lifetime  Lifetime of the data in seconds.
+     */
+    protected function _setExpire($key, $lifetime)
+    {
+        if ($lifetime == 0) {
+            // Don't expire.
+            return;
+        }
+
+        $expire = eaccelerator_get($key . '_expire');
+
+        // Set prune period.
+        if ($expire + $lifetime < time()) {
+            // Expired
+            eaccelerator_rm($key);
+            eaccelerator_rm($key . '_expire');
+        }
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/File.php b/framework/Cache/lib/Horde/Cache/File.php
new file mode 100644 (file)
index 0000000..5968a22
--- /dev/null
@@ -0,0 +1,313 @@
+<?php
+/**
+ * The Horde_Cache_File:: class provides a filesystem implementation of the
+ * Horde caching system.
+ *
+ * Optional parameters:<pre>
+ *   'dir'     The base directory to store the cache files in.
+ *   'prefix'  The filename prefix to use for the cache files.
+ *   'sub'     An integer. If non-zero, the number of subdirectories to
+ *             create to store the file (i.e. PHP's session.save_path).</pre>
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Anil Madhavapeddy <anil@recoil.org>
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Cache
+ */
+class Horde_Cache_File extends Horde_Cache_Base
+{
+    /**
+     * The location of the temp directory.
+     *
+     * @var string
+     */
+    protected $_dir;
+
+    /**
+     * The filename prefix for cache files.
+     *
+     * @var string
+     */
+    protected $_prefix = 'cache_';
+
+    /**
+     * The subdirectory level the cache files should live at.
+     *
+     * @var integer
+     */
+    protected $_sub = 0;
+
+    /**
+     * List of key to filename mappings.
+     *
+     * @var array
+     */
+    protected $_file = array();
+
+    /**
+     * Construct a new Horde_Cache_File object.
+     *
+     * @param array $params  Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        if (!empty($params['dir']) && @is_dir($params['dir'])) {
+            $this->_dir = $params['dir'];
+        } else {
+            require_once 'Horde/Util.php';
+            $this->_dir = Util::getTempDir();
+        }
+
+        foreach (array('prefix', 'sub') as $val) {
+            if (isset($params[$val])) {
+                $name = '_' . $val;
+                $this->$name = $params[$val];
+            }
+        }
+
+        parent::__construct($params);
+    }
+
+    /**
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        /* Only do garbage collection 0.1% of the time we create an object. */
+        if (rand(0, 999) != 0) {
+            return;
+        }
+
+        $filename = $this->_dir . '/horde_cache_gc';
+        $excepts = array();
+
+        if (file_exists($filename)) {
+            $flags = defined('FILE_IGNORE_NEW_LINES')
+                ? FILE_IGNORE_NEW_LINES
+                : 0;
+
+            $gc_file = file($filename, $flags);
+            array_pop($gc_file);
+            reset($gc_file);
+            while (list(,$data) = each($gc_file)) {
+                if (!$flags) {
+                    $data = rtrim($data);
+                }
+                $parts = explode("\t", $data, 2);
+                $excepts[$parts[0]] = $parts[1];
+            }
+        }
+
+        try {
+            $this->_gcDir($this->_dir, $excepts);
+        } catch (Horde_Exception $e) {}
+
+        $out = '';
+        foreach ($excepts as $key => $val) {
+            $out .= $key . "\t" . $val . "\n";
+        }
+
+        file_put_contents($filename, $out);
+    }
+
+    /**
+     * Attempts to retrieve cached data from the filesystem and return it to
+     * the caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the data in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        if (!$this->exists($key, $lifetime)) {
+            /* Nothing cached, return failure. */
+            return false;
+        }
+
+        $filename = $this->_keyToFile($key);
+        $size = filesize($filename);
+        if (!$size) {
+            return '';
+        }
+        $old_error = error_reporting(0);
+        $data = file_get_contents($filename);
+        error_reporting($old_error);
+
+        return $data;
+    }
+
+    /**
+     * Attempts to store data to the filesystem.
+     *
+     * @param string $key        Cache key.
+     * @param mixed $data        Data to store in the cache. (MUST BE A STRING)
+     * @param integer $lifetime  Data lifetime.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        require_once 'Horde/Util.php';
+        $filename = $this->_keyToFile($key, true);
+        $tmp_file = Util::getTempFile('HordeCache', true, $this->_dir);
+        if (isset($this->_params['umask'])) {
+            chmod($tmp_file, 0666 & ~$this->_params['umask']);
+        }
+
+        if (file_put_contents($tmp_file, $data) === false) {
+            return false;
+        }
+
+        @rename($tmp_file, $filename);
+
+        $lifetime = $this->_getLifetime($lifetime);
+        if ($lifetime != $this->_params['lifetime']) {
+            // This may result in duplicate entries in horde_cache_gc, but we
+            // will take care of these whenever we do GC and this is quicker
+            // than having to check every time we access the file.
+            $fp = fopen($this->_dir . '/horde_cache_gc', 'a');
+            fwrite($fp, $filename . "\t" . (empty($lifetime) ? 0 : time() + $lifetime) . "\n");
+            fclose($fp);
+        }
+
+        return true;
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime. If it exists but is expired, delete the file.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        $filename = $this->_keyToFile($key);
+
+        /* Key exists in the cache */
+        if (file_exists($filename)) {
+            /* 0 means no expire. */
+            if ($lifetime == 0) {
+                return true;
+            }
+
+            /* If the file was been created after the supplied value,
+             * the data is valid (fresh). */
+            if (time() - $lifetime <= filemtime($filename)) {
+                return true;
+            } else {
+                @unlink($filename);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        $filename = $this->_keyToFile($key);
+        return @unlink($filename);
+    }
+
+    /**
+     * Attempts to directly output a cached object.
+     *
+     * @param string $key        Object ID to query.
+     * @param integer $lifetime  Lifetime of the object in seconds.
+     *
+     * @return boolean  True if output or false if no object was found.
+     */
+    public function output($key, $lifetime = 1)
+    {
+        if (!$this->exists($key, $lifetime)) {
+            return false;
+        }
+
+        $filename = $this->_keyToFile($key);
+        return @readfile($filename);
+    }
+
+    /**
+     * Map a cache key to a unique filename.
+     *
+     * @param string $key     Cache key.
+     * @param string $create  Create path if it doesn't exist?
+     *
+     * @return string  Fully qualified filename.
+     */
+    protected function _keyToFile($key, $create = false)
+    {
+        if ($create || !isset($this->_file[$key])) {
+            $dir = $this->_dir . '/';
+            $sub = '';
+            $md5 = md5($key);
+            if (!empty($this->_sub)) {
+                $max = min($this->_sub, strlen($md5));
+                for ($i = 0; $i < $max; $i++) {
+                    $sub .= $md5[$i];
+                    if ($create && !is_dir($dir . $sub)) {
+                        if (!mkdir($dir . $sub)) {
+                            $sub = '';
+                            break;
+                        }
+                    }
+                    $sub .= '/';
+                }
+            }
+            $this->_file[$key] = $dir . $sub . $this->_prefix . $md5;
+        }
+
+        return $this->_file[$key];
+    }
+
+    /**
+     * TODO
+     *
+     * @throws Horde_Exception
+     */
+    protected function _gcDir($dir, &$excepts)
+    {
+        $d = @dir($dir);
+        if (!$d) {
+            throw new Horde_Exception('Permission denied to ' . $dir);
+        }
+
+        $c_time = time();
+
+        while (($entry = $d->read()) !== false) {
+            $path = $dir . '/' . $entry;
+            if (($entry == '.') || ($entry == '..')) {
+                continue;
+            }
+
+            if (strpos($entry, $this->_prefix) === 0) {
+                $d_time = isset($excepts[$path]) ? $excepts[$path] : $this->_params['lifetime'];
+                if (!empty($d_time) &&
+                    (($c_time - $d_time) > filemtime($path))) {
+                    @unlink($path);
+                    unset($excepts[$path]);
+                }
+            } elseif (!empty($this->_sub) && is_dir($path)) {
+                $this->_gcDir($path, $excepts);
+            }
+        }
+        $d->close();
+    }
+
+}
+
diff --git a/framework/Cache/lib/Horde/Cache/Memcache.php b/framework/Cache/lib/Horde/Cache/Memcache.php
new file mode 100644 (file)
index 0000000..1cecf81
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * The Horde_Cache_Memcache:: class provides a memcached implementation of the
+ * Horde caching system.
+ *
+ * Copyright 2006-2007 Duck <duck@obala.net>
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Duck <duck@obala.net>
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package  Horde_Cache
+ */
+class Horde_Cache_Memcache extends Horde_Cache_Base
+{
+    /**
+     * Horde_memcache object.
+     *
+     * @var Horde_Memcache
+     */
+    protected $_memcache;
+
+    /**
+     * Cache results of expire() calls (since we will get the entire object
+     * on an expire() call anyway).
+     */
+    protected $_expirecache = array();
+
+    /**
+     * Construct a new Horde_Cache_Memcache object.
+     *
+     * @param array $params  Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        $this->_memcache = &Horde_Memcache::singleton();
+
+        parent::__construct($params);
+    }
+
+    /**
+     * Attempts to retrieve cached data from the memcache and return it to
+     * the caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the data in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        if (isset($this->_expirecache[$key])) {
+            return $this->_expirecache[$key];
+        }
+
+        $key_list = array($key);
+        if (!empty($lifetime)) {
+            $key_list[] = $key . '_e';
+        }
+
+        $res = $this->_memcache->get($key_list);
+
+        if ($res === false) {
+            unset($this->_expirecache[$key]);
+        } else {
+            // If we can't find the expire time, assume we have exceeded it.
+            if (empty($lifetime) ||
+                (($res[$key . '_e'] !== false) && ($res[$key . '_e'] + $lifetime > time()))) {
+                $this->_expirecache[$key] = $res[$key];
+            } else {
+                $res[$key] = false;
+                $this->expire($key);
+            }
+        }
+
+        return $res[$key];
+    }
+
+    /**
+     * Attempts to store data to the memcache.
+     *
+     * @param string $key        Cache key.
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Data lifetime.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        $lifetime = $this->_getLifetime($lifetime);
+        return ($this->_memcache->set($key . '_e', time(), $lifetime) === false)
+            ? false
+            : $this->_memcache->set($key, $data, $lifetime);
+    }
+
+    /**
+     * Checks if a given key exists in the cache.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        return ($this->_get($key, $lifetime) !== false);
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        unset($this->_expirecache[$key]);
+        $this->_memcache->delete($key . '_e');
+        return $this->_memcache->delete($key);
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Null.php b/framework/Cache/lib/Horde/Cache/Null.php
new file mode 100644 (file)
index 0000000..da9c085
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * The Horde_Cache_Null:: class provides a null implementation of the Horde
+ * caching system.
+ *
+ * Copyright 2006-2007 Duck <duck@obala.net>
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Duck <duck@obala.net>
+ * @package Horde_Cache
+ */
+class Horde_Cache_Apc extends Horde_Cache_Base
+{
+    /**
+     * Attempts to retrieve a piece of cached data and return it to
+     * the caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        return false;
+    }
+
+    /**
+     * Attempts to store an object to the cache.
+     *
+     * @param string $key        Cache key (identifier).
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Data lifetime.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        return false;
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        return false;
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        return false;
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Sql.php b/framework/Cache/lib/Horde/Cache/Sql.php
new file mode 100644 (file)
index 0000000..9b28c78
--- /dev/null
@@ -0,0 +1,406 @@
+<?php
+/**
+ * The Horde_Cache_Sql:: class provides a SQL implementation of the Horde
+ * Caching system.
+ *
+ * Required parameters:<pre>
+ *   'phptype'      The database type (ie. 'pgsql', 'mysql', etc.).</pre>
+ *
+ * Required by some database implementations:<pre>
+ *   'database'     The name of the database.
+ *   'hostspec'     The hostname of the database server.
+ *   'username'     The username with which to connect to the database.
+ *   'password'     The password associated with 'username'.
+ *   'options'      Additional options to pass to the database.
+ *   'tty'          The TTY on which to connect to the database.
+ *   'port'         The port on which to connect to the database.</pre>
+ *
+ * Optional parameters:<pre>
+ *   'table'               The name of the cache table in 'database'.
+ *                         Defaults to 'horde_cache'.
+ *   'use_memorycache'     Use a Horde_Cache:: memory caching driver to cache
+ *                         the data (to avoid DB accesses).  Either empty or
+ *                         'none' if not needed, or else the name of a valid
+ *                         Horde_Cache:: driver.</pre>
+ *
+ * Optional values when using separate reading and writing servers, for example
+ * in replication settings:<pre>
+ *   'splitread'   Boolean, whether to implement the separation or not.
+ *   'read'        Array containing the parameters which are different for
+ *                 the read database connection, currently supported
+ *                 only 'hostspec' and 'port' parameters.</pre>
+ *
+ * The table structure for the cache is as follows:
+ * <pre>
+ * CREATE TABLE horde_cache (
+ *     cache_id          VARCHAR(32) NOT NULL,
+ *     cache_timestamp   BIGINT NOT NULL,
+ *     cache_data        LONGBLOB,
+ *     (Or on PostgreSQL:)
+ *     cache_data        TEXT,
+ *     (Or on some other DBMS systems:)
+ *     cache_data        IMAGE,
+ *
+ *     PRIMARY KEY (cache_id)
+ * );
+ * </pre>
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@curecanti.org>
+ * @author  Ben Klang <ben@alkaloid.net>
+ * @package Horde_Cache
+ */
+class Horde_Cache_Sql extends Horde_Cache_Base
+{
+    /**
+     * Handle for the current database connection.
+     *
+     * @var DB
+     */
+    protected $_db;
+
+    /**
+     * Handle for the current database connection, used for writing. Defaults
+     * to the same handle as $_db if a separate write database isn't required.
+     *
+     * @var DB
+     */
+    protected $_write_db;
+
+    /**
+     * Boolean indicating whether or not we're connected to the SQL server.
+     *
+     * @var boolean
+     */
+    protected $_connected = false;
+
+    /**
+     * The memory cache object to use, if configured.
+     *
+     * @var Horde_Cache
+     */
+    protected $_mc = null;
+
+    /**
+     * Constructs a new Horde_Cache_Sql object.
+     *
+     * @param array $params  A hash containing configuration parameters.
+     */
+    public function __construct($params = array())
+    {
+        $options = array(
+            'database' => '',
+            'username' => '',
+            'password' => '',
+            'hostspec' => '',
+            'table' => '',
+        );
+        $this->_params = array_merge($options, $params);
+        if (empty($this->_params['table'])) {
+            $this->_params['table'] = 'horde_cache';
+        }
+
+        /* Create the memory cache object, if configured. */
+        if (!empty($this->_params['use_memorycache'])) {
+            $this->_mc = &Horde_Cache::singleton($params['use_memorycache'], !empty($conf['cache'][$params['use_memorycache']]) ? $conf['cache'][$params['use_memorycache']] : array());
+        }
+
+        parent::__construct($this->_params);
+    }
+
+    /**
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        /* Only do garbage collection 0.1% of the time we create an object. */
+        if (rand(0, 999) != 0) {
+            return;
+        }
+
+        try {
+            $this->_connect();
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return;
+        }
+
+        $query = 'DELETE FROM ' . $this->_params['table'] .
+                 ' WHERE cache_expiration < ? AND cache_expiration <> 0';
+        $values = array(time());
+
+        $result = $this->_write_db->query($query, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+        }
+    }
+
+    /**
+     * Attempts to retrieve cached data.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Maximum age of the data in seconds or
+     *                           0 for any object.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        $okey = $key;
+        $key = hash('md5', $key);
+
+        if ($this->_mc) {
+            $data = $this->_mc->get($key, $lifetime);
+            if ($data !== false) {
+                return $data;
+            }
+        }
+
+        try {
+            $this->_connect();
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        $timestamp = time();
+        $maxage = $timestamp - $lifetime;
+
+        /* Build SQL query. */
+        $query = 'SELECT cache_data FROM ' . $this->_params['table'] .
+                 ' WHERE cache_id = ?';
+        $values = array($key);
+
+        // 0 lifetime checks for objects which have no expiration
+        if ($lifetime != 0) {
+            $query .= ' AND cache_timestamp >= ?';
+            $values[] = $maxage;
+        }
+
+        $result = $this->_db->getOne($query, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        } elseif (is_null($result)) {
+            /* No rows were found - cache miss */
+            Horde::logMessage(sprintf('Cache miss: %s (Id %s newer than %d)', $okey, $key, $maxage), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+            return false;
+        }
+
+        if ($this->_mc) {
+            $this->_mc->set($key, $result);
+        }
+        Horde::logMessage(sprintf('Cache hit: %s (Id %s newer than %d)', $okey, $key, $maxage), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+        return $result;
+    }
+
+    /**
+     * Attempts to store data.
+     *
+     * @param string $key        Cache key.
+     * @param mixed $data        Data to store in the cache. (MUST BE A STRING)
+     * @param integer $lifetime  Maximum data life span or 0 for a
+     *                           non-expiring object.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        $okey = $key;
+        $key = hash('md5', $key);
+
+        if ($this->_mc) {
+            $this->_mc->set($key, $data);
+        }
+
+        try {
+            $this->_connect();
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        $timestamp = time();
+
+        // 0 lifetime indicates the object should not be GC'd.
+        $expiration = ($lifetime === 0)
+            ? 0
+            : $this->_getLifetime($lifetime) + $timestamp;
+
+        Horde::logMessage(sprintf('Cache set: %s (Id %s set at %d expires at %d)', $okey, $key, $timestamp, $expiration), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+        // Remove any old cache data and prevent duplicate keys
+        $query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE cache_id=?';
+        $values = array($key);
+        $this->_write_db->query($query, $values);
+
+        /* Build SQL query. */
+        $query = 'INSERT INTO ' . $this->_params['table'] .
+                 ' (cache_id, cache_timestamp, cache_expiration, cache_data)' .
+                 ' VALUES (?, ?, ?, ?)';
+        $values = array($key, $timestamp, $expiration, $data);
+
+        $result = $this->_write_db->query($query, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Maximum age of the key in seconds or 0 for
+     *                           any object.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        $okey = $key;
+        $key = hash('md5', $key);
+
+        if ($this->_mc && $this->_mc->exists($key, $lifetime)) {
+            return true;
+        }
+
+        try {
+            $this->_connect();
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        /* Build SQL query. */
+        $query = 'SELECT 1 FROM ' . $this->_params['table'] .
+                 ' WHERE cache_id = ?';
+        $values = array($key);
+
+        // 0 lifetime checks for objects which have no expiration
+        if ($lifetime != 0) {
+            $query .= ' AND cache_timestamp >= ?';
+            $values[] = time() - $lifetime;
+        }
+
+        $result = $this->_db->getRow($query, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        $timestamp = time();
+        if (empty($result)) {
+            Horde::logMessage(sprintf('Cache exists() miss: %s (Id %s newer than %d)', $okey, $key, $timestamp), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+            return false;
+        }
+        Horde::logMessage(sprintf('Cache exists() hit: %s (Id %s newer than %d)', $okey, $key, $timestamp), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+        return true;
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        $key = hash('md5', $key);
+
+        if ($this->_mc) {
+            $this->_mc->expire($key);
+        }
+
+        try {
+            $this->_connect();
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        $query = 'DELETE FROM ' . $this->_params['table'] .
+                 ' WHERE cache_id = ?';
+        $values = array($key);
+
+        $result = $this->_write_db->query($query, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Opens a connection to the SQL server.
+     *
+     * @throws Horde_Exception
+     */
+    protected function _connect()
+    {
+        if ($this->_connected) {
+            return true;
+        }
+
+        $result = Util::assertDriverConfig($this->_params, array('phptype'),
+                                           'cache SQL', array('driver' => 'cache'));
+        if (is_a($result, 'PEAR_Error')) {
+            throw new Horde_Exception($result->getMessage());
+        }
+
+        require_once 'DB.php';
+        $this->_write_db = &DB::connect(
+            $this->_params,
+            array('persistent' => !empty($this->_params['persistent']),
+                  'ssl' => !empty($this->_params['ssl']))
+        );
+        if (is_a($this->_write_db, 'PEAR_Error')) {
+            throw new Horde_Exception($this->_write_db->getMessage());
+        }
+
+        // Set DB portability options.
+        $portability = DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS;
+        if ($this->_write_db->phptype) {
+            $portability |= DB_PORTABILITY_RTRIM;
+        }
+        $this->_write_db->setOption('portability', $portability);
+
+        /* Check if we need to set up the read DB connection
+         * seperately. */
+        if (!empty($this->_params['splitread'])) {
+            $params = array_merge($this->_params, $this->_params['read']);
+            $this->_db = &DB::connect(
+                $params,
+                array('persistent' => !empty($params['persistent']),
+                      'ssl' => !empty($params['ssl']))
+            );
+            if (is_a($this->_db, 'PEAR_Error')) {
+                throw new Horde_Exception($this->_db->getMessage());
+            }
+
+            // Set DB portability options.
+            $portability = DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS;
+            if ($this->_db->phptype) {
+                $portability |= DB_PORTABILITY_RTRIM;
+            }
+            $this->_db->setOption('portability', $portability);
+        } else {
+            /* Default to the same DB handle for read. */
+            $this->_db = $this->_write_db;
+        }
+
+        $this->_connected = true;
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Xcache.php b/framework/Cache/lib/Horde/Cache/Xcache.php
new file mode 100644 (file)
index 0000000..861ec11
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/**
+ * The Horde_Cache_Xcache:: class provides an XCache implementation of
+ * the Horde caching system.
+ *
+ * Copyright 2006-2007 Duck <duck@obala.net>
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Duck <duck@obala.net>
+ * @package Horde_Cache
+ */
+class Horde_Cache_Xcache extends Horde_Cache_Base
+{
+    /**
+     * Construct a new Horde_Cache_Xcache object.
+     *
+     * @param array $params  Parameter array.
+     */
+    public function __construct($params = array())
+    {
+        parent::__construct($params);
+
+        if (empty($this->_params['prefix'])) {
+            $this->_params['prefix'] = $_SERVER['SERVER_NAME']
+                ? $_SERVER['SERVER_NAME']
+                : $_SERVER['HOSTNAME'];
+        }
+    }
+
+    /**
+     * Attempts to retrieve a piece of cached data and return it to the caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        $key = $this->_params['prefix'] . $key;
+        $this->_setExpire($key, $lifetime);
+        $result = xcache_get($key);
+
+        return empty($result)
+            ? false
+            : $result;
+    }
+
+    /**
+     * Attempts to store an object to the cache.
+     *
+     * @param string $key        Cache key (identifier).
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Data lifetime.
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        $key = $this->_params['prefix'] . $key;
+        $lifetime = $this->_getLifetime($lifetime);
+        xcache_set($key . '_expire', time(), $lifetime);
+        return xcache_set($key, $data, $lifetime);
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key        Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        $key = $this->_params['prefix'] . $key;
+        $this->_setExpire($key, $lifetime);
+        return xcache_isset($key);
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        $key = $this->_params['prefix'] . $key;
+        xcache_unset($key . '_expire');
+        return xcache_unset($key);
+    }
+
+    /**
+     * Set expire time on each call since memcache sets it on cache creation.
+     *
+     * @param string $key        Cache key to expire.
+     * @param integer $lifetime  Lifetime of the data in seconds.
+     */
+    protected function _setExpire($key, $lifetime)
+    {
+        if ($lifetime == 0) {
+            // don't expire
+            return;
+        }
+
+        $expire = xcache_get($key . '_expire');
+
+        // set prune period
+        if ($expire + $lifetime < time()) {
+            // Expired
+            xcache_unset($key . '_expire');
+            xcache_unset($key);
+        }
+    }
+
+}
diff --git a/framework/Cache/lib/Horde/Cache/Zps4.php b/framework/Cache/lib/Horde/Cache/Zps4.php
new file mode 100644 (file)
index 0000000..701f189
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/**
+ * The Horde_Cache_Zps4:: class provides a Zend Performance Suite
+ * (version 4.0+) implementation of the Horde caching system.
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Cache
+ */
+class Horde_Cache_Zps4 extends Horde_Cache_Base
+{
+    /**
+     * Attempts to retrieve a piece of cached data and return it to the
+     * caller.
+     *
+     * @param string $key        Cache key to fetch.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return mixed  Cached data, or false if none was found.
+     */
+    public function get($key, $lifetime = 1)
+    {
+        return output_cache_get($key, $lifetime);
+    }
+
+    /**
+     * Attempts to store an object to the cache.
+     *
+     * @param string $key        Cache key (identifier).
+     * @param mixed $data        Data to store in the cache.
+     * @param integer $lifetime  Data lifetime. [Not used]
+     *
+     * @return boolean  True on success, false on failure.
+     */
+    public function set($key, $data, $lifetime = null)
+    {
+        output_cache_put($key, $data);
+        return true;
+    }
+
+    /**
+     * Checks if a given key exists in the cache, valid for the given
+     * lifetime.
+     *
+     * @param string $key       Cache key to check.
+     * @param integer $lifetime  Lifetime of the key in seconds.
+     *
+     * @return boolean  Existence.
+     */
+    public function exists($key, $lifetime = 1)
+    {
+        $exists = output_cache_exists($key, $lifetime);
+        output_cache_stop();
+        return $exists;
+    }
+
+    /**
+     * Expire any existing data for the given key.
+     *
+     * @param string $key  Cache key to expire.
+     *
+     * @return boolean  Success or failure.
+     */
+    public function expire($key)
+    {
+        return output_cache_remove_key($key);
+    }
+
+}
diff --git a/framework/Cache/package.xml b/framework/Cache/package.xml
new file mode 100644 (file)
index 0000000..4ac63a6
--- /dev/null
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Cache</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde Caching API</summary>
+ <description>This package provides a simple, functional caching API,
+with the option to store the cached data on the filesystem, in one of
+the PHP opcode cache systems (APC, eAcclerator, XCache, or Zend
+Performance Suite&apos;s content cache), memcached, or an SQL table.
+ </description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Michael Slusarz</name>
+  <user>slusarz</user>
+  <email>slusarz@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2008-03-04</date>
+ <version>
+  <release>0.2.0</release>
+  <api>0.2.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Initial Horde 4 package.</notes>
+ <contents>
+  <dir name="/">
+   <dir name="data">
+    <file name="cache.sql" role="data" />
+   </dir> <!-- /data -->
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Cache">
+      <file name="Apc.php" role="php" />
+      <file name="Base.php" role="php" />
+      <file name="Eaccelerator.php" role="php" />
+      <file name="File.php" role="php" />
+      <file name="Memcache.php" role="php" />
+      <file name="Null.php" role="php" />
+      <file name="Sql.php" role="php" />
+      <file name="Xcache.php" role="php" />
+      <file name="Zps4.php" role="php" />
+     </dir> <!-- /lib/Horde/Cache -->
+     <file name="Cache.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.0</min>
+   </pearinstaller>
+   <package>
+    <name>Util</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </required>
+  <optional>
+   <extension>
+    <name>apc</name>
+   </extension>
+   <extension>
+    <name>eaccelerator</name>
+   </extension>
+   <extension>
+    <name>memcache</name>
+   </extension>
+  </optional>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Cache/Apc.php" as="Horde/Cache/Apc.php" />
+   <install name="lib/Horde/Cache/Base.php" as="Horde/Cache/Base.php" />
+   <install name="lib/Horde/Cache/Eaccelerator.php" as="Horde/Cache/Eaccelerator.php" />
+   <install name="lib/Horde/Cache/File.php" as="Horde/Cache/File.php" />
+   <install name="lib/Horde/Cache/Memcache.php" as="Horde/Cache/Memcache.php" />
+   <install name="lib/Horde/Cache/Null.php" as="Horde/Cache/Null.php" />
+   <install name="lib/Horde/Cache/Sql.php" as="Horde/Cache/Sql.php" />
+   <install name="lib/Horde/Cache/Xcache.php" as="Horde/Cache/Xcache.php" />
+   <install name="lib/Horde/Cache/Zps4.php" as="Horde/Cache/Zps4.php" />
+   <install name="lib/Horde/Cache.php" as="Horde/Cache.php" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <date>2006-05-08</date>
+   <version>
+    <release>0.1.0</release>
+    <api>0.1.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>* Add SQL backend.
+* Converted to package.xml 2.0 for pear.horde.org.
+* Add APC, eAccelerator, and XCache backends (duck@obala.net).
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2004-01-01</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial packaging.
+   </notes>
+  </release>
+ </changelog>
+</package>