text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Lzf.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_Compress_CompressInterface
 */
require_once 'Zend/Filter/Compress/CompressInterface.php';

/**
 * Compression adapter for Lzf
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_Compress_Lzf implements Zend_Filter_Compress_CompressInterface
{
    /**
     * Class constructor
     */
    public function __construct()
    {
        if (!extension_loaded('lzf')) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception('This filter needs the lzf extension');
        }
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string
     */
    public function compress($content)
    {
        $compressed = lzf_compress($content);
        if (!$compressed) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception('Error during compression');
        }

        return $compressed;
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     */
    public function decompress($content)
    {
        $compressed = lzf_decompress($content);
        if (!$compressed) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception('Error during compression');
        }

        return $compressed;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Lzf';
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: CompressAbstract.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_Compress_CompressInterface
 */
require_once 'Zend/Filter/Compress/CompressInterface.php';

/**
 * Abstract compression adapter
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Filter_Compress_CompressAbstract implements Zend_Filter_Compress_CompressInterface
{
    /**
     * Class constructor
     *
     * @param array|Zend_Config $options (Optional) Options to set
     */
    public function __construct($options = null)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        }

        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Returns one or all set options
     *
     * @param string $option (Optional) Option to return
     * @return mixed
     */
    public function getOptions($option = null)
    {
        if ($option === null) {
            return $this->_options;
        }

        if (!array_key_exists($option, $this->_options)) {
            return null;
        }

        return $this->_options[$option];
    }

    /**
     * Sets all or one option
     *
     * @param  array $options
     * @return Zend_Filter_Compress_Bz2
     */
    public function setOptions(array $options)
    {
        foreach ($options as $key => $option) {
            $method = 'set' . $key;
            if (method_exists($this, $method)) {
                $this->$method($option);
            }
        }

        return $this;
    }
}

repo_name: michael-romer/zf-boilerplate

repo_language: PHP

mime_type: text/html


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Encrypt.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_Encrypt
 */
require_once 'Zend/Filter/Encrypt.php';

/**
 * Encrypts a given file and stores the encrypted file content
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_File_Encrypt extends Zend_Filter_Encrypt
{
    /**
     * New filename to set
     *
     * @var string
     */
    protected $_filename;

    /**
     * Returns the new filename where the content will be stored
     *
     * @return string
     */
    public function getFilename()
    {
        return $this->_filename;
    }

    /**
     * Sets the new filename where the content will be stored
     *
     * @param  string $filename (Optional) New filename to set
     * @return Zend_Filter_File_Encryt
     */
    public function setFilename($filename = null)
    {
        $this->_filename = $filename;
        return $this;
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Encrypts the file $value with the defined settings
     *
     * @param  string $value Full path of file to change
     * @return string The filename which has been set, or false when there were errors
     */
    public function filter($value)
    {
        if (!file_exists($value)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '$value' not found");
        }

        if (!isset($this->_filename)) {
            $this->_filename = $value;
        }

        if (file_exists($this->_filename) and !is_writable($this->_filename)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '{$this->_filename}' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while reading file '$value'");
        }

        $encrypted = parent::filter($content);
        $result    = file_put_contents($this->_filename, $encrypted);

        if (!$result) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while writing file '{$this->_filename}'");
        }

        return $this->_filename;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: LowerCase.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_StringToLower
 */
require_once 'Zend/Filter/StringToLower.php';

/**
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_File_LowerCase extends Zend_Filter_StringToLower
{
    /**
     * Adds options to the filter at initiation
     *
     * @param string $options
     */
    public function __construct($options = null)
    {
        if (!empty($options)) {
            $this->setEncoding($options);
        }
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Does a lowercase on the content of the given file
     *
     * @param  string $value Full path of file to change
     * @return string The given $value
     * @throws Zend_Filter_Exception
     */
    public function filter($value)
    {
        if (!file_exists($value)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '$value' not found");
        }

        if (!is_writable($value)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '$value' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while reading file '$value'");
        }

        $content = parent::filter($content);
        $result  = file_put_contents($value, $content);

        if (!$result) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while writing file '$value'");
        }

        return $value;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: UpperCase.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_StringToUpper
 */
require_once 'Zend/Filter/StringToUpper.php';

/**
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_File_UpperCase extends Zend_Filter_StringToUpper
{
    /**
     * Adds options to the filter at initiation
     *
     * @param string $options
     */
    public function __construct($options = null)
    {
        if (!empty($options)) {
            $this->setEncoding($options);
        }
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Does a lowercase on the content of the given file
     *
     * @param  string $value Full path of file to change
     * @return string The given $value
     * @throws Zend_Filter_Exception
     */
    public function filter($value)
    {
        if (!file_exists($value)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '$value' not found");
        }

        if (!is_writable($value)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '$value' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while reading file '$value'");
        }

        $content = parent::filter($content);
        $result  = file_put_contents($value, $content);

        if (!$result) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while writing file '$value'");
        }

        return $value;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Rename.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_Interface
 */
require_once 'Zend/Filter/Interface.php';

/**
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_File_Rename implements Zend_Filter_Interface
{
    /**
     * Internal array of array(source, target, overwrite)
     */
    protected $_files = array();

    /**
     * Class constructor
     *
     * Options argument may be either a string, a Zend_Config object, or an array.
     * If an array or Zend_Config object, it accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten ?
     *
     * @param  string|array $options Target file or directory to be renamed
     * @param  string $target Source filename or directory (deprecated)
     * @param  bool $overwrite Should existing files be overwritten (deprecated)
     * @return void
     */
    public function __construct($options)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        } elseif (is_string($options)) {
            $options = array('target' => $options);
        } elseif (!is_array($options)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception('Invalid options argument provided to filter');
        }

        if (1 < func_num_args()) {
            $argv = func_get_args();
            array_shift($argv);
            $source    = array_shift($argv);
            $overwrite = false;
            if (!empty($argv)) {
                $overwrite = array_shift($argv);
            }
            $options['source']    = $source;
            $options['overwrite'] = $overwrite;
        }

        $this->setFile($options);
    }

    /**
     * Returns the files to rename and their new name and location
     *
     * @return array
     */
    public function getFile()
    {
        return $this->_files;
    }

    /**
     * Sets a new file or directory as target, deleting existing ones
     *
     * Array accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten ?
     *
     * @param  string|array $options Old file or directory to be rewritten
     * @return Zend_Filter_File_Rename
     */
    public function setFile($options)
    {
        $this->_files = array();
        $this->addFile($options);

        return $this;
    }

    /**
     * Adds a new file or directory as target to the existing ones
     *
     * Array accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten ?
     *
     * @param  string|array $options Old file or directory to be rewritten
     * @return Zend_Filter_File_Rename
     */
    public function addFile($options)
    {
        if (is_string($options)) {
            $options = array('target' => $options);
        } elseif (!is_array($options)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception ('Invalid options to rename filter provided');
        }

        $this->_convertOptions($options);

        return $this;
    }

    /**
     * Returns only the new filename without moving it
     * But existing files will be erased when the overwrite option is true
     *
     * @param  string  $value  Full path of file to change
     * @param  boolean $source Return internal informations
     * @return string The new filename which has been set
     */
    public function getNewName($value, $source = false)
    {
        $file = $this->_getFileName($value);
        if ($file['source'] == $file['target']) {
            return $value;
        }

        if (!file_exists($file['source'])) {
            return $value;
        }

        if (($file['overwrite'] == true) && (file_exists($file['target']))) {
            unlink($file['target']);
        }

        if (file_exists($file['target'])) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. It already exists.", $value));
        }

        if ($source) {
            return $file;
        }

        return $file['target'];
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Renames the file $value to the new name set before
     * Returns the file $value, removing all but digit characters
     *
     * @param  string $value Full path of file to change
     * @throws Zend_Filter_Exception
     * @return string The new filename which has been set, or false when there were errors
     */
    public function filter($value)
    {
        $file   = $this->getNewName($value, true);
        if (is_string($file)) {
            return $file;
        }

        $result = rename($file['source'], $file['target']);

        if ($result === true) {
            return $file['target'];
        }

        require_once 'Zend/Filter/Exception.php';
        throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. An error occured while processing the file.", $value));
    }

    /**
     * Internal method for creating the file array
     * Supports single and nested arrays
     *
     * @param  array $options
     * @return array
     */
    protected function _convertOptions($options) {
        $files = array();
        foreach ($options as $key => $value) {
            if (is_array($value)) {
                $this->_convertOptions($value);
                continue;
            }

            switch ($key) {
                case "source":
                    $files['source'] = (string) $value;
                    break;

                case 'target' :
                    $files['target'] = (string) $value;
                    break;

                case 'overwrite' :
                    $files['overwrite'] = (boolean) $value;
                    break;

                default:
                    break;
            }
        }

        if (empty($files)) {
            return $this;
        }

        if (empty($files['source'])) {
            $files['source'] = '*';
        }

        if (empty($files['target'])) {
            $files['target'] = '*';
        }

        if (empty($files['overwrite'])) {
            $files['overwrite'] = false;
        }

        $found = false;
        foreach ($this->_files as $key => $value) {
            if ($value['source'] == $files['source']) {
                $this->_files[$key] = $files;
                $found              = true;
            }
        }

        if (!$found) {
            $count                = count($this->_files);
            $this->_files[$count] = $files;
        }

        return $this;
    }

    /**
     * Internal method to resolve the requested source
     * and return all other related parameters
     *
     * @param  string $file Filename to get the informations for
     * @return array
     */
    protected function _getFileName($file)
    {
        $rename = array();
        foreach ($this->_files as $value) {
            if ($value['source'] == '*') {
                if (!isset($rename['source'])) {
                    $rename           = $value;
                    $rename['source'] = $file;
                }
            }

            if ($value['source'] == $file) {
                $rename = $value;
            }
        }

        if (!isset($rename['source'])) {
            return $file;
        }

        if (!isset($rename['target']) or ($rename['target'] == '*')) {
            $rename['target'] = $rename['source'];
        }

        if (is_dir($rename['target'])) {
            $name = basename($rename['source']);
            $last = $rename['target'][strlen($rename['target']) - 1];
            if (($last != '/') and ($last != '\\')) {
                $rename['target'] .= DIRECTORY_SEPARATOR;
            }

            $rename['target'] .= $name;
        }

        return $rename;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Decrypt.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Filter_Decrypt
 */
require_once 'Zend/Filter/Decrypt.php';

/**
 * Decrypts a given file and stores the decrypted file content
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_File_Decrypt extends Zend_Filter_Decrypt
{
    /**
     * New filename to set
     *
     * @var string
     */
    protected $_filename;

    /**
     * Returns the new filename where the content will be stored
     *
     * @return string
     */
    public function getFilename()
    {
        return $this->_filename;
    }

    /**
     * Sets the new filename where the content will be stored
     *
     * @param  string $filename (Optional) New filename to set
     * @return Zend_Filter_File_Encryt
     */
    public function setFilename($filename = null)
    {
        $this->_filename = $filename;
        return $this;
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Decrypts the file $value with the defined settings
     *
     * @param  string $value Full path of file to change
     * @return string The filename which has been set, or false when there were errors
     */
    public function filter($value)
    {
        if (!file_exists($value)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '$value' not found");
        }

        if (!isset($this->_filename)) {
            $this->_filename = $value;
        }

        if (file_exists($this->_filename) and !is_writable($this->_filename)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("File '{$this->_filename}' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while reading file '$value'");
        }

        $decrypted = parent::filter($content);
        $result    = file_put_contents($this->_filename, $decrypted);

        if (!$result) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception("Problem while writing file '{$this->_filename}'");
        }

        return $this->_filename;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 * @version   $Id: Adapter.php 23953 2011-05-03 05:47:39Z ralph $
 */

/**
 * Abstract class for Zend_ProgressBar_Adapters
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_ProgressBar_Adapter
{
    /**
     * Option keys to skip when calling setOptions()
     *
     * @var array
     */
    protected $_skipOptions = array(
        'options',
        'config',
    );

    /**
     * Create a new adapter
     *
     * $options may be either be an array or a Zend_Config object which
     * specifies adapter related options.
     *
     * @param null|array|Zend_Config $options
     */
    public function __construct($options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        } elseif ($options instanceof Zend_Config) {
            $this->setConfig($options);
        }
    }

    /**
     * Set options via a Zend_Config instance
     *
     * @param  Zend_Config $config
     * @return Zend_ProgressBar_Adapter
     */
    public function setConfig(Zend_Config $config)
    {
        $this->setOptions($config->toArray());

        return $this;
    }

    /**
     * Set options via an array
     *
     * @param  array $options
     * @return Zend_ProgressBar_Adapter
     */
    public function setOptions(array $options)
    {
        foreach ($options as $key => $value) {
            if (in_array(strtolower($key), $this->_skipOptions)) {
                continue;
            }

            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }

        return $this;
    }

    /**
     * Notify the adapter about an update
     *
     * @param  float   $current       Current progress value
     * @param  float   $max           Max progress value
     * @param  float   $percent       Current percent value
     * @param  integer $timeTaken     Taken time in seconds
     * @param  integer $timeRemaining Remaining time in seconds
     * @param  string  $text          Status text
     * @return void
     */
    abstract public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text);

    /**
     * Called when the progress is explicitly finished
     *
     * @return void
     */
    abstract public function finish();
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 * @version   $Id: Exception.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Exception
 */
require_once 'Zend/Exception.php';

/**
 * Exception class for Zend_ProgressBar
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @uses      Zend_Exception
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_ProgressBar_Exception extends Zend_Exception
{
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 * @version   $Id: Exception.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_ProgressBar_Exception
 */
require_once 'Zend/ProgressBar/Exception.php';

/**
 * Exception class for Zend_ProgressBar_Adapter
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @uses      Zend_ProgressBar_Exception
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_ProgressBar_Adapter_Exception extends Zend_ProgressBar_Exception
{
}


text:
<?php
/**
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Console.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_ProgressBar_Adapter
 */
require_once 'Zend/ProgressBar/Adapter.php';

/**
 * @see Zend_Text_MultiByte
 */
require_once 'Zend/Text/MultiByte.php';

/**
 * Zend_ProgressBar_Adapter_Console offers a text-based progressbar for console
 * applications
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @uses      Zend_ProgressBar_Adapter_Interface
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_ProgressBar_Adapter_Console extends Zend_ProgressBar_Adapter
{
    /**
     * Percentage value of the progress
     */
    const ELEMENT_PERCENT = 'ELEMENT_PERCENT';

    /**
     * Visual value of the progress
     */
    const ELEMENT_BAR = 'ELEMENT_BAR';

    /**
     * ETA of the progress
     */
    const ELEMENT_ETA = 'ELEMENT_ETA';

    /**
     * Text part of the progress
     */
    const ELEMENT_TEXT = 'ELEMENT_TEXT';

    /**
     * Finish action: End of Line
     */
    const FINISH_ACTION_EOL = 'FINISH_ACTION_EOL';

    /**
     * Finish action: Clear Line
     */
    const FINISH_ACTION_CLEAR_LINE = 'FINISH_ACTION_CLEAR_LINE';

    /**
     * Finish action: None
     */
    const FINISH_ACTION_NONE = 'FINISH_ACTION_NONE';

    /**
     * Width of the progressbar
     *
     * @var integer
     */
    protected $_width = null;

    /**
     * Elements to display
     *
     * @var array
     */
    protected $_elements = array(self::ELEMENT_PERCENT,
                                 self::ELEMENT_BAR,
                                 self::ELEMENT_ETA);

    /**
     * Which action to do at finish call
     *
     * @var string
     */
    protected $_finishAction = self::FINISH_ACTION_EOL;

    /**
     * Width of the bar element
     *
     * @var integer
     */
    protected $_barWidth;

    /**
     * Left character(s) within the bar
     *
     * @var string
     */
    protected $_barLeftChar = '#';

    /**
     * Indicator character(s) within the bar
     *
     * @var string
     */
    protected $_barIndicatorChar = '';

    /**
     * Right character(s) within the bar
     *
     * @var string
     */
    protected $_barRightChar = '-';

    /**
     * Output-stream, when STDOUT is not defined (e.g. in CGI) or set manually
     *
     * @var resource
     */
    protected $_outputStream = null;

    /**
     * Width of the text element
     *
     * @var string
     */
    protected $_textWidth = 20;

    /**
     * Wether the output started yet or not
     *
     * @var boolean
     */
    protected $_outputStarted = false;

    /**
     * Charset of text element
     *
     * @var string
     */
    protected $_charset = 'utf-8';

    /**
     * Defined by Zend_ProgressBar_Adapter
     *
     * @param null|array|Zend_Config $options
     */
    public function __construct($options = null)
    {
        // Call parent constructor with options
        parent::__construct($options);

        // Check if a width was set, else use auto width
        if ($this->_width === null) {
            $this->setWidth();
        }
    }

    /**
     * Close local stdout, when open
     */
    public function __destruct()
    {
        if ($this->_outputStream !== null) {
            fclose($this->_outputStream);
        }
    }

    /**
     * Set a different output-stream
     *
     * @param  string $resource
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setOutputStream($resource)
    {
       $stream = @fopen($resource, 'w');

       if ($stream === false) {
            require_once 'Zend/ProgressBar/Adapter/Exception.php';
            throw new Zend_ProgressBar_Adapter_Exception('Unable to open stream');
       }

       if ($this->_outputStream !== null) {
           fclose($this->_outputStream);
       }

       $this->_outputStream = $stream;
    }

    /**
     * Get the current output stream
     *
     * @return resource
     */
    public function getOutputStream()
    {
        if ($this->_outputStream === null) {
            if (!defined('STDOUT')) {
                $this->_outputStream = fopen('php://stdout', 'w');
            } else {
                return STDOUT;
            }
        }

        return $this->_outputStream;
    }

    /**
     * Set the width of the progressbar
     *
     * @param  integer $width
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setWidth($width = null)
    {
        if ($width === null || !is_integer($width)) {
            if (substr(PHP_OS, 0, 3) === 'WIN') {
                // We have to default to 79 on windows, because the windows
                // terminal always has a fixed width of 80 characters and the
                // cursor is counted to the line, else windows would line break
                // after every update.
                $this->_width = 79;
            } else {
                // Set the default width of 80
                $this->_width = 80;

                // Try to determine the width through stty
                if (preg_match('#\d+ (\d+)#', @shell_exec('stty size'), $match) === 1) {
                    $this->_width = (int) $match[1];
                } else if (preg_match('#columns = (\d+);#', @shell_exec('stty'), $match) === 1) {
                    $this->_width = (int) $match[1];
                }
            }
        } else {
            $this->_width = (int) $width;
        }

        $this->_calculateBarWidth();

        return $this;
    }

    /**
     * Set the elements to display with the progressbar
     *
     * @param  array $elements
     * @throws Zend_ProgressBar_Adapter_Exception When an invalid element is foudn in the array
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setElements(array $elements)
    {
        $allowedElements = array(self::ELEMENT_PERCENT,
                                 self::ELEMENT_BAR,
                                 self::ELEMENT_ETA,
                                 self::ELEMENT_TEXT);

        if (count(array_diff($elements, $allowedElements)) > 0) {
            require_once 'Zend/ProgressBar/Adapter/Exception.php';
            throw new Zend_ProgressBar_Adapter_Exception('Invalid element found in $elements array');
        }

        $this->_elements = $elements;

        $this->_calculateBarWidth();

        return $this;
    }

    /**
     * Set the left-hand character for the bar
     *
     * @param  string $char
     * @throws Zend_ProgressBar_Adapter_Exception When character is empty
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setBarLeftChar($char)
    {
        if (empty($char)) {
            require_once 'Zend/ProgressBar/Adapter/Exception.php';
            throw new Zend_ProgressBar_Adapter_Exception('Character may not be empty');
        }

        $this->_barLeftChar = (string) $char;

        return $this;
    }

    /**
     * Set the right-hand character for the bar
     *
     * @param  string $char
     * @throws Zend_ProgressBar_Adapter_Exception When character is empty
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setBarRightChar($char)
    {
        if (empty($char)) {
            require_once 'Zend/ProgressBar/Adapter/Exception.php';
            throw new Zend_ProgressBar_Adapter_Exception('Character may not be empty');
        }

        $this->_barRightChar = (string) $char;

        return $this;
    }

    /**
     * Set the indicator character for the bar
     *
     * @param  string $char
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setBarIndicatorChar($char)
    {
        $this->_barIndicatorChar = (string) $char;

        return $this;
    }

    /**
     * Set the width of the text element
     *
     * @param  integer $width
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setTextWidth($width)
    {
        $this->_textWidth = (int) $width;

        $this->_calculateBarWidth();

        return $this;
    }

    /**
     * Set the charset of the text element
     *
     * @param string $charset
     */
    public function setCharset($charset)
    {
        $this->_charset = $charset;
    }

    /**
     * Set the finish action
     *
     * @param  string $action
     * @throws Zend_ProgressBar_Adapter_Exception When an invalid action is specified
     * @return Zend_ProgressBar_Adapter_Console
     */
    public function setFinishAction($action)
    {
        $allowedActions = array(self::FINISH_ACTION_CLEAR_LINE,
                                self::FINISH_ACTION_EOL,
                                self::FINISH_ACTION_NONE);

        if (!in_array($action, $allowedActions)) {
            require_once 'Zend/ProgressBar/Adapter/Exception.php';
            throw new Zend_ProgressBar_Adapter_Exception('Invalid finish action specified');
        }

        $this->_finishAction = $action;

        return $this;
    }

    /**
     * Defined by Zend_ProgressBar_Adapter_Interface
     *
     * @param  float   $current       Current progress value
     * @param  float   $max           Max progress value
     * @param  float   $percent       Current percent value
     * @param  integer $timeTaken     Taken time in seconds
     * @param  integer $timeRemaining Remaining time in seconds
     * @param  string  $text          Status text
     * @return void
     */
    public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
    {
        // See if we must clear the line
        if ($this->_outputStarted) {
            $data = str_repeat("\x08", $this->_width);
        } else {
            $data = '';
            $this->_outputStarted = true;
        }

        // Build all elements
        $renderedElements = array();

        foreach ($this->_elements as $element) {
            switch ($element) {
                case self::ELEMENT_BAR:
                    $visualWidth = $this->_barWidth - 2;
                    $bar         = '[';

                    $indicatorWidth = strlen($this->_barIndicatorChar);

                    $doneWidth = min($visualWidth - $indicatorWidth, round($visualWidth * $percent));
                    if ($doneWidth > 0) {
                        $bar .= substr(str_repeat($this->_barLeftChar, ceil($doneWidth / strlen($this->_barLeftChar))), 0, $doneWidth);
                    }

                    $bar .= $this->_barIndicatorChar;

                    $leftWidth = $visualWidth - $doneWidth - $indicatorWidth;
                    if ($leftWidth > 0) {
                        $bar .= substr(str_repeat($this->_barRightChar, ceil($leftWidth / strlen($this->_barRightChar))), 0, $leftWidth);
                    }

                    $bar .= ']';

                    $renderedElements[] = $bar;
                    break;

                case self::ELEMENT_PERCENT:
                    $renderedElements[] = str_pad(round($percent * 100), 3, ' ', STR_PAD_LEFT) . '%';
                    break;

                case self::ELEMENT_ETA:
                    // In the first 5 seconds we don't get accurate results,
                    // this skipping technique is found in many progressbar
                    // implementations.
                    if ($timeTaken < 5) {
                        $renderedElements[] = str_repeat(' ', 12);
                        break;
                    }

                    if ($timeRemaining === null || $timeRemaining > 86400) {
                        $etaFormatted = '??:??:??';
                    } else {
                        $hours   = floor($timeRemaining / 3600);
                        $minutes = floor(($timeRemaining % 3600) / 60);
                        $seconds = ($timeRemaining % 3600 % 60);

                        $etaFormatted = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
                    }

                    $renderedElements[] = 'ETA ' . $etaFormatted;
                    break;

                case self::ELEMENT_TEXT:
                    $renderedElements[] = Zend_Text_MultiByte::strPad(substr($text, 0, $this->_textWidth), $this->_textWidth, ' ', STR_PAD_RIGHT, $this->_charset);
                    break;
            }
        }

        $data .= implode(' ', $renderedElements);

        // Output line data
        $this->_outputData($data);
    }

    /**
     * Defined by Zend_ProgressBar_Adapter_Interface
     *
     * @return void
     */
    public function finish()
    {
        switch ($this->_finishAction) {
            case self::FINISH_ACTION_EOL:
                $this->_outputData(PHP_EOL);
                break;

            case self::FINISH_ACTION_CLEAR_LINE:
                if ($this->_outputStarted) {
                    $data = str_repeat("\x08", $this->_width)
                          . str_repeat(' ', $this->_width)
                          . str_repeat("\x08", $this->_width);

                    $this->_outputData($data);
                }
                break;

            case self::FINISH_ACTION_NONE:
                break;
        }
    }

    /**
     * Calculate the bar width when other elements changed
     *
     * @return void
     */
    protected function _calculateBarWidth()
    {
        if (in_array(self::ELEMENT_BAR, $this->_elements)) {
            $barWidth = $this->_width;

            if (in_array(self::ELEMENT_PERCENT, $this->_elements)) {
                $barWidth -= 4;
            }

            if (in_array(self::ELEMENT_ETA, $this->_elements)) {
                $barWidth -= 12;
            }

            if (in_array(self::ELEMENT_TEXT, $this->_elements)) {
                $barWidth -= $this->_textWidth;
            }

            $this->_barWidth = $barWidth - (count($this->_elements) - 1);
        }
    }

    /**
     * Outputs given data to STDOUT.
     *
     * This split-off is required for unit-testing.
     *
     * @param  string $data
     * @return void
     */
    protected function _outputData($data)
    {
        fwrite($this->getOutputStream(), $data);
    }
}


text:
<?php
/**
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: JsPull.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Json
 */
require_once 'Zend/Json.php';

/**
 * @see Zend_ProgressBar_Adapter
 */
require_once 'Zend/ProgressBar/Adapter.php';

/**
 * Zend_ProgressBar_Adapter_JsPull offers a simple method for updating a
 * progressbar in a browser.
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @uses      Zend_ProgressBar_Adapter_Interface
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_ProgressBar_Adapter_JsPull extends Zend_ProgressBar_Adapter
{
    /**
     * Wether to exit after json data send or not
     *
     * @var boolean
     */
    protected $_exitAfterSend = true;

    /**
     * Set wether to exit after json data send or not
     *
     * @param  boolean $exitAfterSend
     * @return Zend_ProgressBar_Adapter_JsPull
     */
    public function setExitAfterSend($exitAfterSend)
    {
        $this->_exitAfterSend = $exitAfterSend;
    }

    /**
     * Defined by Zend_ProgressBar_Adapter_Interface
     *
     * @param  float   $current       Current progress value
     * @param  float   $max           Max progress value
     * @param  float   $percent       Current percent value
     * @param  integer $timeTaken     Taken time in seconds
     * @param  integer $timeRemaining Remaining time in seconds
     * @param  string  $text          Status text
     * @return void
     */
    public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
    {
        $arguments = array(
            'current'       => $current,
            'max'           => $max,
            'percent'       => ($percent * 100),
            'timeTaken'     => $timeTaken,
            'timeRemaining' => $timeRemaining,
            'text'          => $text,
            'finished'      => false
        );

        $data = Zend_Json::encode($arguments);

        // Output the data
        $this->_outputData($data);
    }

    /**
     * Defined by Zend_ProgressBar_Adapter_Interface
     *
     * @return void
     */
    public function finish()
    {
        $data = Zend_Json::encode(array('finished' => true));

        $this->_outputData($data);
    }

    /**
     * Outputs given data the user agent.
     *
     * This split-off is required for unit-testing.
     *
     * @param  string $data
     * @return void
     */
    protected function _outputData($data)
    {
        echo $data;

        if ($this->_exitAfterSend) {
            exit;
        }
    }
}


text:
<?php
/**
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_ProgressBar
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: JsPush.php 23953 2011-05-03 05:47:39Z ralph $
 */

/**
 * @see Zend_Json
 */
require_once 'Zend/Json.php';

/**
 * @see Zend_ProgressBar_Adapter
 */
require_once 'Zend/ProgressBar/Adapter.php';

/**
 * Zend_ProgressBar_Adapter_JsPush offers a simple method for updating a
 * progressbar in a browser.
 *
 * @category  Zend
 * @package   Zend_ProgressBar
 * @uses      Zend_ProgressBar_Adapter_Interface
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_ProgressBar_Adapter_JsPush extends Zend_ProgressBar_Adapter
{
    /**
     * Name of the JavaScript method to call on update
     *
     * @var string
     */
    protected $_updateMethodName = 'Zend_ProgressBar_Update';

    /**
     * Name of the JavaScript method to call on finish
     *
     * @var string
     */
    protected $_finishMethodName;

    /**
     * Set the update method name
     *
     * @param  string $methodName
     * @return Zend_ProgressBar_Adapter_JsPush
     */
    public function setUpdateMethodName($methodName)
    {
        $this->_updateMethodName = $methodName;

        return $this;
    }

    /**
     * Set the finish method name
     *
     * @param  string $methodName
     * @return Zend_ProgressBar_Adapter_JsPush
     */
    public function setFinishMethodName($methodName)
    {
        $this->_finishMethodName = $methodName;

        return $this;
    }

    /**
     * Defined by Zend_ProgressBar_Adapter_Interface
     *
     * @param  float   $current       Current progress value
     * @param  float   $max           Max progress value
     * @param  float   $percent       Current percent value
     * @param  integer $timeTaken     Taken time in seconds
     * @param  integer $timeRemaining Remaining time in seconds
     * @param  string  $text          Status text
     * @return void
     */
    public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
    {
        $arguments = array(
            'current'       => $current,
            'max'           => $max,
            'percent'       => ($percent * 100),
            'timeTaken'     => $timeTaken,
            'timeRemaining' => $timeRemaining,
            'text'          => $text
        );

        $data = '';

        // Output the data
        $this->_outputData($data);
    }

    /**
     * Defined by Zend_ProgressBar_Adapter_Interface
     *
     * @return void
     */
    public function finish()
    {
        if ($this->_finishMethodName === null) {
            return;
        }

        $data = '';

        $this->_outputData($data);
    }

    /**
     * Outputs given data the user agent.
     *
     * This split-off is required for unit-testing.
     *
     * @param  string $data
     * @return void
     */
    protected function _outputData($data)
    {
        // 1024 padding is required for Safari, while 256 padding is required
        // for Internet Explorer. The
 is required so Safari actually
        // executes the


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Cache
 * @subpackage Zend_Cache_Backend
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Backend.php 23800 2011-03-10 20:52:08Z mabe $
 */

/**
 * @package    Zend_Cache
 * @subpackage Zend_Cache_Backend
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Cache_Backend
{
    /**
     * Frontend or Core directives
     *
     * =====> (int) lifetime :
     * - Cache lifetime (in seconds)
     * - If null, the cache is valid forever
     *
     * =====> (int) logging :
     * - if set to true, a logging is activated throw Zend_Log
     *
     * @var array directives
     */
    protected $_directives = array(
        'lifetime' => 3600,
        'logging'  => false,
        'logger'   => null
    );

    /**
     * Available options
     *
     * @var array available options
     */
    protected $_options = array();

    /**
     * Constructor
     *
     * @param  array $options Associative array of options
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function __construct(array $options = array())
    {
        while (list($name, $value) = each($options)) {
            $this->setOption($name, $value);
        }
    }

    /**
     * Set the frontend directives
     *
     * @param  array $directives Assoc of directives
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function setDirectives($directives)
    {
        if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array');
        while (list($name, $value) = each($directives)) {
            if (!is_string($name)) {
                Zend_Cache::throwException("Incorrect option name : $name");
            }
            $name = strtolower($name);
            if (array_key_exists($name, $this->_directives)) {
                $this->_directives[$name] = $value;
            }

        }

        $this->_loggerSanity();
    }

    /**
     * Set an option
     *
     * @param  string $name
     * @param  mixed  $value
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function setOption($name, $value)
    {
        if (!is_string($name)) {
            Zend_Cache::throwException("Incorrect option name : $name");
        }
        $name = strtolower($name);
        if (array_key_exists($name, $this->_options)) {
            $this->_options[$name] = $value;
        }
    }

    /**
     * Get the life time
     *
     * if $specificLifetime is not false, the given specific life time is used
     * else, the global lifetime is used
     *
     * @param  int $specificLifetime
     * @return int Cache life time
     */
    public function getLifetime($specificLifetime)
    {
        if ($specificLifetime === false) {
            return $this->_directives['lifetime'];
        }
        return $specificLifetime;
    }

    /**
     * Return true if the automatic cleaning is available for the backend
     *
     * DEPRECATED : use getCapabilities() instead
     *
     * @deprecated
     * @return boolean
     */
    public function isAutomaticCleaningAvailable()
    {
        return true;
    }

    /**
     * Determine system TMP directory and detect if we have read access
     *
     * inspired from Zend_File_Transfer_Adapter_Abstract
     *
     * @return string
     * @throws Zend_Cache_Exception if unable to determine directory
     */
    public function getTmpDir()
    {
        $tmpdir = array();
        foreach (array($_ENV, $_SERVER) as $tab) {
            foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
                if (isset($tab[$key])) {
                    if (($key == 'windir') or ($key == 'SystemRoot')) {
                        $dir = realpath($tab[$key] . '\\temp');
                    } else {
                        $dir = realpath($tab[$key]);
                    }
                    if ($this->_isGoodTmpDir($dir)) {
                        return $dir;
                    }
                }
            }
        }
        $upload = ini_get('upload_tmp_dir');
        if ($upload) {
            $dir = realpath($upload);
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        if (function_exists('sys_get_temp_dir')) {
            $dir = sys_get_temp_dir();
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        // Attemp to detect by creating a temporary file
        $tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
        if ($tempFile) {
            $dir = realpath(dirname($tempFile));
            unlink($tempFile);
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        if ($this->_isGoodTmpDir('/tmp')) {
            return '/tmp';
        }
        if ($this->_isGoodTmpDir('\\temp')) {
            return '\\temp';
        }
        Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
    }

    /**
     * Verify if the given temporary directory is readable and writable
     *
     * @param string $dir temporary directory
     * @return boolean true if the directory is ok
     */
    protected function _isGoodTmpDir($dir)
    {
        if (is_readable($dir)) {
            if (is_writable($dir)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Make sure if we enable logging that the Zend_Log class
     * is available.
     * Create a default log object if none is set.
     *
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected function _loggerSanity()
    {
        if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {
            return;
        }

        if (isset($this->_directives['logger'])) {
            if ($this->_directives['logger'] instanceof Zend_Log) {
                return;
            }
            Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
        }

        // Create a default logger to the standard output stream
        require_once 'Zend/Log.php';
        require_once 'Zend/Log/Writer/Stream.php';
        require_once 'Zend/Log/Filter/Priority.php';
        $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
        $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
        $this->_directives['logger'] = $logger;
    }

    /**
     * Log a message at the WARN (4) priority.
     *
     * @param  string $message
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected function _log($message, $priority = 4)
    {
        if (!$this->_directives['logging']) {
            return;
        }

        if (!isset($this->_directives['logger'])) {
            Zend_Cache::throwException('Logging is enabled but logger is not set.');
        }
        $logger = $this->_directives['logger'];
        if (!$logger instanceof Zend_Log) {
            Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
        }
        $logger->log($message, $priority);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Cache
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Exception.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Exception
 */
require_once 'Zend/Exception.php';

/**
 * @package    Zend_Cache
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Cache_Exception extends Zend_Exception {}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Cache
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Manager.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** @see Zend_Cache_Exception */
require_once 'Zend/Cache/Exception.php';

/** @see Zend_Cache */
require_once 'Zend/Cache.php';

/**
 * @category   Zend
 * @package    Zend_Cache
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Cache_Manager
{
    /**
     * Constant holding reserved name for default Page Cache
     */
    const PAGECACHE = 'page';

    /**
     * Constant holding reserved name for default Page Tag Cache
     */
    const PAGETAGCACHE = 'pagetag';

    /**
     * Array of caches stored by the Cache Manager instance
     *
     * @var array
     */
    protected $_caches = array();

    /**
     * Array of ready made configuration templates for lazy
     * loading caches.
     *
     * @var array
     */
    protected $_optionTemplates = array(
        // Simple Common Default
        'default' => array(
            'frontend' => array(
                'name'    => 'Core',
                'options' => array(
                    'automatic_serialization' => true,
                ),
            ),
            'backend' => array(
                'name'    => 'File',
                'options' => array(
                    // use system temp dir by default of file backend
                    // 'cache_dir' => '../cache',
                ),
            ),
        ),

        // Static Page HTML Cache
        'page' => array(
            'frontend' => array(
                'name'    => 'Capture',
                'options' => array(
                    'ignore_user_abort' => true,
                ),
            ),
            'backend' => array(
                'name'    => 'Static',
                'options' => array(
                    'public_dir' => '../public',
                ),
            ),
        ),

        // Tag Cache
        'pagetag' => array(
            'frontend' => array(
                'name'    => 'Core',
                'options' => array(
                    'automatic_serialization' => true,
                    'lifetime' => null
                ),
            ),
            'backend' => array(
                'name'    => 'File',
                'options' => array(
                    // use system temp dir by default of file backend
                    // 'cache_dir' => '../cache',
                    // use default umask of file backend
                    // 'cache_file_umask' => 0644
                ),
            ),
        ),
    );

    /**
     * Set a new cache for the Cache Manager to contain
     *
     * @param  string $name
     * @param  Zend_Cache_Core $cache
     * @return Zend_Cache_Manager
     */
    public function setCache($name, Zend_Cache_Core $cache)
    {
        $this->_caches[$name] = $cache;
        return $this;
    }

    /**
     * Check if the Cache Manager contains the named cache object, or a named
     * configuration template to lazy load the cache object
     *
     * @param string $name
     * @return bool
     */
    public function hasCache($name)
    {
        if (isset($this->_caches[$name])
            || $this->hasCacheTemplate($name)
        ) {
            return true;
        }
        return false;
    }

    /**
     * Fetch the named cache object, or instantiate and return a cache object
     * using a named configuration template
     *
     * @param  string $name
     * @return Zend_Cache_Core
     */
    public function getCache($name)
    {
        if (isset($this->_caches[$name])) {
            return $this->_caches[$name];
        }
        if (isset($this->_optionTemplates[$name])) {
            if ($name == self::PAGECACHE
                && (!isset($this->_optionTemplates[$name]['backend']['options']['tag_cache'])
                || !$this->_optionTemplates[$name]['backend']['options']['tag_cache'] instanceof Zend_Cache_Core)
            ) {
                $this->_optionTemplates[$name]['backend']['options']['tag_cache']
                    = $this->getCache(self::PAGETAGCACHE);
            }

            $this->_caches[$name] = Zend_Cache::factory(
                $this->_optionTemplates[$name]['frontend']['name'],
                $this->_optionTemplates[$name]['backend']['name'],
                isset($this->_optionTemplates[$name]['frontend']['options']) ? $this->_optionTemplates[$name]['frontend']['options'] : array(),
                isset($this->_optionTemplates[$name]['backend']['options']) ? $this->_optionTemplates[$name]['backend']['options'] : array(),
                isset($this->_optionTemplates[$name]['frontend']['customFrontendNaming']) ? $this->_optionTemplates[$name]['frontend']['customFrontendNaming'] : false,
                isset($this->_optionTemplates[$name]['backend']['customBackendNaming']) ? $this->_optionTemplates[$name]['backend']['customBackendNaming'] : false,
                isset($this->_optionTemplates[$name]['frontendBackendAutoload']) ? $this->_optionTemplates[$name]['frontendBackendAutoload'] : false
            );

            return $this->_caches[$name];
        }
    }

    /**
     * Fetch all available caches
     *
     * @return array An array of all available caches with it's names as key
     */
    public function getCaches()
    {
        $caches = $this->_caches;
        foreach ($this->_optionTemplates as $name => $tmp) {
            if (!isset($caches[$name])) {
                $caches[$name] = $this->getCache($name);
            }
        }
        return $caches;
    }

    /**
     * Set a named configuration template from which a cache object can later
     * be lazy loaded
     *
     * @param  string $name
     * @param  array $options
     * @return Zend_Cache_Manager
     */
    public function setCacheTemplate($name, $options)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        } elseif (!is_array($options)) {
            require_once 'Zend/Cache/Exception.php';
            throw new Zend_Cache_Exception('Options passed must be in'
                . ' an associative array or instance of Zend_Config');
        }
        $this->_optionTemplates[$name] = $options;
        return $this;
    }

    /**
     * Check if the named configuration template
     *
     * @param  string $name
     * @return bool
     */
    public function hasCacheTemplate($name)
    {
        if (isset($this->_optionTemplates[$name])) {
            return true;
        }
        return false;
    }

    /**
     * Get the named configuration template
     *
     * @param  string $name
     * @return array
     */
    public function getCacheTemplate($name)
    {
        if (isset($this->_optionTemplates[$name])) {
            return $this->_optionTemplates[$name];
        }
    }

    /**
     * Pass an array containing changes to be applied to a named
     * configuration
     * template
     *
     * @param  string $name
     * @param  array $options
     * @return Zend_Cache_Manager
     * @throws Zend_Cache_Exception for invalid options format or if option templates do not have $name
     */
    public function setTemplateOptions($name, $options)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        } elseif (!is_array($options)) {
            require_once 'Zend/Cache/Exception.php';
            throw new Zend_Cache_Exception('Options passed must be in'
                . ' an associative array or instance of Zend_Config');
        }
        if (!isset($this->_optionTemplates[$name])) {
            throw new Zend_Cache_Exception('A cache configuration template'
                . 'does not exist with the name "' . $name . '"');
        }
        $this->_optionTemplates[$name]
            = $this->_mergeOptions($this->_optionTemplates[$name], $options);
        return $this;
    }

    /**
     * Simple method to merge two configuration arrays
     *
     * @param  array $current
     * @param  array $options
     * @return array
     */
    protected function _mergeOptions(array $current, array $options)
    {
        if (isset($options['frontend']['name'])) {
            $current['frontend']['name'] = $options['frontend']['name'];
        }
        if (isset($options['backend']['name'])) {
            $current['backend']['name'] = $options['backend']['name'];
        }
        if (isset($options['frontend']['options'])) {
            foreach ($options['frontend']['options'] as $key=>$value) {
                $current['frontend']['options'][$key] = $value;
            }
        }
        if (isset($options['backend']['options'])) {
            foreach ($options['backend']['options'] as $key=>$value) {
                $current['backend']['options'][$key] = $value;
            }
        }
        return $current;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Cache
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Core.php 23800 2011-03-10 20:52:08Z mabe $
 */

/**
 * @package    Zend_Cache
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Cache_Core
{
    /**
     * Messages
     */
    const BACKEND_NOT_SUPPORTS_TAG = 'tags are not supported by the current backend';
    const BACKEND_NOT_IMPLEMENTS_EXTENDED_IF = 'Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available';

    /**
     * Backend Object
     *
     * @var Zend_Cache_Backend_Interface $_backend
     */
    protected $_backend = null;

    /**
     * Available options
     *
     * ====> (boolean) write_control :
     * - Enable / disable write control (the cache is read just after writing to detect corrupt entries)
     * - Enable write control will lightly slow the cache writing but not the cache reading
     * Write control can detect some corrupt cache files but maybe it's not a perfect control
     *
     * ====> (boolean) caching :
     * - Enable / disable caching
     * (can be very useful for the debug of cached scripts)
     *
     * =====> (string) cache_id_prefix :
     * - prefix for cache ids (namespace)
     *
     * ====> (boolean) automatic_serialization :
     * - Enable / disable automatic serialization
     * - It can be used to save directly datas which aren't strings (but it's slower)
     *
     * ====> (int) automatic_cleaning_factor :
     * - Disable / Tune the automatic cleaning process
     * - The automatic cleaning process destroy too old (for the given life time)
     *   cache files when a new cache file is written :
     *     0               => no automatic cache cleaning
     *     1               => systematic cache cleaning
     *     x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
     *
     * ====> (int) lifetime :
     * - Cache lifetime (in seconds)
     * - If null, the cache is valid forever.
     *
     * ====> (boolean) logging :
     * - If set to true, logging is activated (but the system is slower)
     *
     * ====> (boolean) ignore_user_abort
     * - If set to true, the core will set the ignore_user_abort PHP flag inside the
     *   save() method to avoid cache corruptions in some cases (default false)
     *
     * @var array $_options available options
     */
    protected $_options = array(
        'write_control'             => true,
        'caching'                   => true,
        'cache_id_prefix'           => null,
        'automatic_serialization'   => false,
        'automatic_cleaning_factor' => 10,
        'lifetime'                  => 3600,
        'logging'                   => false,
        'logger'                    => null,
        'ignore_user_abort'         => false
    );

    /**
     * Array of options which have to be transfered to backend
     *
     * @var array $_directivesList
     */
    protected static $_directivesList = array('lifetime', 'logging', 'logger');

    /**
     * Not used for the core, just a sort a hint to get a common setOption() method (for the core and for frontends)
     *
     * @var array $_specificOptions
     */
    protected $_specificOptions = array();

    /**
     * Last used cache id
     *
     * @var string $_lastId
     */
    private $_lastId = null;

    /**
     * True if the backend implements Zend_Cache_Backend_ExtendedInterface
     *
     * @var boolean $_extendedBackend
     */
    protected $_extendedBackend = false;

    /**
     * Array of capabilities of the backend (only if it implements Zend_Cache_Backend_ExtendedInterface)
     *
     * @var array
     */
    protected $_backendCapabilities = array();

    /**
     * Constructor
     *
     * @param  array|Zend_Config $options Associative array of options or Zend_Config instance
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function __construct($options = array())
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        }
        if (!is_array($options)) {
            Zend_Cache::throwException("Options passed were not an array"
            . " or Zend_Config instance.");
        }
        while (list($name, $value) = each($options)) {
            $this->setOption($name, $value);
        }
        $this->_loggerSanity();
    }

    /**
     * Set options using an instance of type Zend_Config
     *
     * @param Zend_Config $config
     * @return Zend_Cache_Core
     */
    public function setConfig(Zend_Config $config)
    {
        $options = $config->toArray();
        while (list($name, $value) = each($options)) {
            $this->setOption($name, $value);
        }
        return $this;
    }

    /**
     * Set the backend
     *
     * @param  Zend_Cache_Backend $backendObject
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function setBackend(Zend_Cache_Backend $backendObject)
    {
        $this->_backend= $backendObject;
        // some options (listed in $_directivesList) have to be given
        // to the backend too (even if they are not "backend specific")
        $directives = array();
        foreach (Zend_Cache_Core::$_directivesList as $directive) {
            $directives[$directive] = $this->_options[$directive];
        }
        $this->_backend->setDirectives($directives);
        if (in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_backend))) {
            $this->_extendedBackend = true;
            $this->_backendCapabilities = $this->_backend->getCapabilities();
        }

    }

    /**
     * Returns the backend
     *
     * @return Zend_Cache_Backend backend object
     */
    public function getBackend()
    {
        return $this->_backend;
    }

    /**
     * Public frontend to set an option
     *
     * There is an additional validation (relatively to the protected _setOption method)
     *
     * @param  string $name  Name of the option
     * @param  mixed  $value Value of the option
     * @throws Zend_Cache_Exception
     * @return void
     */
    public function setOption($name, $value)
    {
        if (!is_string($name)) {
            Zend_Cache::throwException("Incorrect option name : $name");
        }
        $name = strtolower($name);
        if (array_key_exists($name, $this->_options)) {
            // This is a Core option
            $this->_setOption($name, $value);
            return;
        }
        if (array_key_exists($name, $this->_specificOptions)) {
            // This a specic option of this frontend
            $this->_specificOptions[$name] = $value;
            return;
        }
    }

    /**
     * Public frontend to get an option value
     *
     * @param  string $name  Name of the option
     * @throws Zend_Cache_Exception
     * @return mixed option value
     */
    public function getOption($name)
    {
        if (is_string($name)) {
            $name = strtolower($name);
            if (array_key_exists($name, $this->_options)) {
                // This is a Core option
                return $this->_options[$name];
            }
            if (array_key_exists($name, $this->_specificOptions)) {
                // This a specic option of this frontend
                return $this->_specificOptions[$name];
            }
        }
        Zend_Cache::throwException("Incorrect option name : $name");
    }

    /**
     * Set an option
     *
     * @param  string $name  Name of the option
     * @param  mixed  $value Value of the option
     * @throws Zend_Cache_Exception
     * @return void
     */
    private function _setOption($name, $value)
    {
        if (!is_string($name) || !array_key_exists($name, $this->_options)) {
            Zend_Cache::throwException("Incorrect option name : $name");
        }
        if ($name == 'lifetime' && empty($value)) {
            $value = null;
        }
        $this->_options[$name] = $value;
    }

    /**
     * Force a new lifetime
     *
     * The new value is set for the core/frontend but for the backend too (directive)
     *
     * @param  int $newLifetime New lifetime (in seconds)
     * @return void
     */
    public function setLifetime($newLifetime)
    {
        $this->_options['lifetime'] = $newLifetime;
        $this->_backend->setDirectives(array(
            'lifetime' => $newLifetime
        ));
    }

    /**
     * Test if a cache is available for the given id and (if yes) return it (false else)
     *
     * @param  string  $id                     Cache id
     * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
     * @param  boolean $doNotUnserialize       Do not serialize (even if automatic_serialization is true) => for internal use
     * @return mixed|false Cached datas
     */
    public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false)
    {
        if (!$this->_options['caching']) {
            return false;
        }
        $id = $this->_id($id); // cache id may need prefix
        $this->_lastId = $id;
        self::_validateIdOrTag($id);

        $this->_log("Zend_Cache_Core: load item '{$id}'", 7);
        $data = $this->_backend->load($id, $doNotTestCacheValidity);
        if ($data===false) {
            // no cache available
            return false;
        }
        if ((!$doNotUnserialize) && $this->_options['automatic_serialization']) {
            // we need to unserialize before sending the result
            return unserialize($data);
        }
        return $data;
    }

    /**
     * Test if a cache is available for the given id
     *
     * @param  string $id Cache id
     * @return int|false Last modified time of cache entry if it is available, false otherwise
     */
    public function test($id)
    {
        if (!$this->_options['caching']) {
            return false;
        }
        $id = $this->_id($id); // cache id may need prefix
        self::_validateIdOrTag($id);
        $this->_lastId = $id;

        $this->_log("Zend_Cache_Core: test item '{$id}'", 7);
        return $this->_backend->test($id);
    }

    /**
     * Save some data in a cache
     *
     * @param  mixed $data           Data to put in cache (can be another type than string if automatic_serialization is on)
     * @param  string $id             Cache id (if not set, the last cache id will be used)
     * @param  array $tags           Cache tags
     * @param  int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
     * @param  int   $priority         integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
     * @throws Zend_Cache_Exception
     * @return boolean True if no problem
     */
    public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8)
    {
        if (!$this->_options['caching']) {
            return true;
        }
        if ($id === null) {
            $id = $this->_lastId;
        } else {
            $id = $this->_id($id);
        }
        self::_validateIdOrTag($id);
        self::_validateTagsArray($tags);
        if ($this->_options['automatic_serialization']) {
            // we need to serialize datas before storing them
            $data = serialize($data);
        } else {
            if (!is_string($data)) {
                Zend_Cache::throwException("Datas must be string or set automatic_serialization = true");
            }
        }

        // automatic cleaning
        if ($this->_options['automatic_cleaning_factor'] > 0) {
            $rand = rand(1, $this->_options['automatic_cleaning_factor']);
            if ($rand==1) {
                //  new way                 || deprecated way
                if ($this->_extendedBackend || method_exists($this->_backend, 'isAutomaticCleaningAvailable')) {
                    $this->_log("Zend_Cache_Core::save(): automatic cleaning running", 7);
                    $this->clean(Zend_Cache::CLEANING_MODE_OLD);
                } else {
                    $this->_log("Zend_Cache_Core::save(): automatic cleaning is not available/necessary with current backend", 4);
                }
            }
        }

        $this->_log("Zend_Cache_Core: save item '{$id}'", 7);
        if ($this->_options['ignore_user_abort']) {
            $abort = ignore_user_abort(true);
        }
        if (($this->_extendedBackend) && ($this->_backendCapabilities['priority'])) {
            $result = $this->_backend->save($data, $id, $tags, $specificLifetime, $priority);
        } else {
            $result = $this->_backend->save($data, $id, $tags, $specificLifetime);
        }
        if ($this->_options['ignore_user_abort']) {
            ignore_user_abort($abort);
        }

        if (!$result) {
            // maybe the cache is corrupted, so we remove it !
            $this->_log("Zend_Cache_Core::save(): failed to save item '{$id}' -> removing it", 4);
            $this->_backend->remove($id);
            return false;
        }

        if ($this->_options['write_control']) {
            $data2 = $this->_backend->load($id, true);
            if ($data!=$data2) {
                $this->_log("Zend_Cache_Core::save(): write control of item '{$id}' failed -> removing it", 4);
                $this->_backend->remove($id);
                return false;
            }
        }

        return true;
    }

    /**
     * Remove a cache
     *
     * @param  string $id Cache id to remove
     * @return boolean True if ok
     */
    public function remove($id)
    {
        if (!$this->_options['caching']) {
            return true;
        }
        $id = $this->_id($id); // cache id may need prefix
        self::_validateIdOrTag($id);

        $this->_log("Zend_Cache_Core: remove item '{$id}'", 7);
        return $this->_backend->remove($id);
    }

    /**
     * Clean cache entries
     *
     * Available modes are :
     * 'all' (default)  => remove all cache entries ($tags is not used)
     * 'old'            => remove too old cache entries ($tags is not used)
     * 'matchingTag'    => remove cache entries matching all given tags
     *                     ($tags can be an array of strings or a single string)
     * 'notMatchingTag' => remove cache entries not matching one of the given tags
     *                     ($tags can be an array of strings or a single string)
     * 'matchingAnyTag' => remove cache entries matching any given tags
     *                     ($tags can be an array of strings or a single string)
     *
     * @param  string       $mode
     * @param  array|string $tags
     * @throws Zend_Cache_Exception
     * @return boolean True if ok
     */
    public function clean($mode = 'all', $tags = array())
    {
        if (!$this->_options['caching']) {
            return true;
        }
        if (!in_array($mode, array(Zend_Cache::CLEANING_MODE_ALL,
                                   Zend_Cache::CLEANING_MODE_OLD,
                                   Zend_Cache::CLEANING_MODE_MATCHING_TAG,
                                   Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG,
                                   Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG))) {
            Zend_Cache::throwException('Invalid cleaning mode');
        }
        self::_validateTagsArray($tags);

        return $this->_backend->clean($mode, $tags);
    }

    /**
     * Return an array of stored cache ids which match given tags
     *
     * In case of multiple tags, a logical AND is made between tags
     *
     * @param array $tags array of tags
     * @return array array of matching cache ids (string)
     */
    public function getIdsMatchingTags($tags = array())
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        if (!($this->_backendCapabilities['tags'])) {
            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
        }

        $ids = $this->_backend->getIdsMatchingTags($tags);

        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
            $prefix    = & $this->_options['cache_id_prefix'];
            $prefixLen = strlen($prefix);
            foreach ($ids as &$id) {
                if (strpos($id, $prefix) === 0) {
                    $id = substr($id, $prefixLen);
                }
            }
        }

        return $ids;
    }

    /**
     * Return an array of stored cache ids which don't match given tags
     *
     * In case of multiple tags, a logical OR is made between tags
     *
     * @param array $tags array of tags
     * @return array array of not matching cache ids (string)
     */
    public function getIdsNotMatchingTags($tags = array())
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        if (!($this->_backendCapabilities['tags'])) {
            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
        }

        $ids = $this->_backend->getIdsNotMatchingTags($tags);

        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
            $prefix    = & $this->_options['cache_id_prefix'];
            $prefixLen = strlen($prefix);
            foreach ($ids as &$id) {
                if (strpos($id, $prefix) === 0) {
                    $id = substr($id, $prefixLen);
                }
            }
        }

        return $ids;
    }

    /**
     * Return an array of stored cache ids which match any given tags
     *
     * In case of multiple tags, a logical OR is made between tags
     *
     * @param array $tags array of tags
     * @return array array of matching any cache ids (string)
     */
    public function getIdsMatchingAnyTags($tags = array())
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        if (!($this->_backendCapabilities['tags'])) {
            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
        }

        $ids = $this->_backend->getIdsMatchingAnyTags($tags);

        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
            $prefix    = & $this->_options['cache_id_prefix'];
            $prefixLen = strlen($prefix);
            foreach ($ids as &$id) {
                if (strpos($id, $prefix) === 0) {
                    $id = substr($id, $prefixLen);
                }
            }
        }

        return $ids;
    }

    /**
     * Return an array of stored cache ids
     *
     * @return array array of stored cache ids (string)
     */
    public function getIds()
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }

        $ids = $this->_backend->getIds();

        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
            $prefix    = & $this->_options['cache_id_prefix'];
            $prefixLen = strlen($prefix);
            foreach ($ids as &$id) {
                if (strpos($id, $prefix) === 0) {
                    $id = substr($id, $prefixLen);
                }
            }
        }

        return $ids;
    }

    /**
     * Return an array of stored tags
     *
     * @return array array of stored tags (string)
     */
    public function getTags()
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        if (!($this->_backendCapabilities['tags'])) {
            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
        }
        return $this->_backend->getTags();
    }

    /**
     * Return the filling percentage of the backend storage
     *
     * @return int integer between 0 and 100
     */
    public function getFillingPercentage()
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        return $this->_backend->getFillingPercentage();
    }

    /**
     * Return an array of metadatas for the given cache id
     *
     * The array will include these keys :
     * - expire : the expire timestamp
     * - tags : a string array of tags
     * - mtime : timestamp of last modification time
     *
     * @param string $id cache id
     * @return array array of metadatas (false if the cache id is not found)
     */
    public function getMetadatas($id)
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        $id = $this->_id($id); // cache id may need prefix
        return $this->_backend->getMetadatas($id);
    }

    /**
     * Give (if possible) an extra lifetime to the given cache id
     *
     * @param string $id cache id
     * @param int $extraLifetime
     * @return boolean true if ok
     */
    public function touch($id, $extraLifetime)
    {
        if (!$this->_extendedBackend) {
            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
        }
        $id = $this->_id($id); // cache id may need prefix

        $this->_log("Zend_Cache_Core: touch item '{$id}'", 7);
        return $this->_backend->touch($id, $extraLifetime);
    }

    /**
     * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)
     *
     * Throw an exception if a problem is found
     *
     * @param  string $string Cache id or tag
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected static function _validateIdOrTag($string)
    {
        if (!is_string($string)) {
            Zend_Cache::throwException('Invalid id or tag : must be a string');
        }
        if (substr($string, 0, 9) == 'internal-') {
            Zend_Cache::throwException('"internal-*" ids or tags are reserved');
        }
        if (!preg_match('~^[a-zA-Z0-9_]+$~D', $string)) {
            Zend_Cache::throwException("Invalid id or tag '$string' : must use only [a-zA-Z0-9_]");
        }
    }

    /**
     * Validate a tags array (security, reliable filenames, reserved prefixes...)
     *
     * Throw an exception if a problem is found
     *
     * @param  array $tags Array of tags
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected static function _validateTagsArray($tags)
    {
        if (!is_array($tags)) {
            Zend_Cache::throwException('Invalid tags array : must be an array');
        }
        foreach($tags as $tag) {
            self::_validateIdOrTag($tag);
        }
        reset($tags);
    }

    /**
     * Make sure if we enable logging that the Zend_Log class
     * is available.
     * Create a default log object if none is set.
     *
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected function _loggerSanity()
    {
        if (!isset($this->_options['logging']) || !$this->_options['logging']) {
            return;
        }

        if (isset($this->_options['logger']) && $this->_options['logger'] instanceof Zend_Log) {
            return;
        }

        // Create a default logger to the standard output stream
        require_once 'Zend/Log.php';
        require_once 'Zend/Log/Writer/Stream.php';
        require_once 'Zend/Log/Filter/Priority.php';
        $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
        $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
        $this->_options['logger'] = $logger;
    }

    /**
     * Log a message at the WARN (4) priority.
     *
     * @param string $message
     * @throws Zend_Cache_Exception
     * @return void
     */
    protected function _log($message, $priority = 4)
    {
        if (!$this->_options['logging']) {
            return;
        }
        if (!(isset($this->_options['logger']) || $this->_options['logger'] instanceof Zend_Log)) {
            Zend_Cache::throwException('Logging is enabled but logger is not set');
        }
        $logger = $this->_options['logger'];
        $logger->log($message, $priority);
    }

    /**
     * Make and return a cache id
     *
     * Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null
     *
     * @param  string $id Cache id
     * @return string Cache id (with or without prefix)
     */
    protected function _id($id)
    {
        if (($id !== null) && isset($this->_options['cache_id_prefix'])) {
            return $this->_options['cache_id_prefix'] . $id; // return with prefix
        }
        return $id; // no prefix, just return the $id passed
    }

}