diff options
Diffstat (limited to '')
-rw-r--r-- | library/vendor/Zend/Cache/Frontend/Capture.php | 87 | ||||
-rw-r--r-- | library/vendor/Zend/Cache/Frontend/Class.php | 274 | ||||
-rw-r--r-- | library/vendor/Zend/Cache/Frontend/File.php | 221 | ||||
-rw-r--r-- | library/vendor/Zend/Cache/Frontend/Function.php | 178 | ||||
-rw-r--r-- | library/vendor/Zend/Cache/Frontend/Output.php | 104 | ||||
-rw-r--r-- | library/vendor/Zend/Cache/Frontend/Page.php | 403 |
6 files changed, 1267 insertions, 0 deletions
diff --git a/library/vendor/Zend/Cache/Frontend/Capture.php b/library/vendor/Zend/Cache/Frontend/Capture.php new file mode 100644 index 0000000..4b70da4 --- /dev/null +++ b/library/vendor/Zend/Cache/Frontend/Capture.php @@ -0,0 +1,87 @@ +<?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_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * @see Zend_Cache_Core + */ + + +/** + * @package Zend_Cache + * @subpackage Zend_Cache_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Cache_Frontend_Capture extends Zend_Cache_Core +{ + /** + * Page identifiers + * @var array + */ + protected $_idStack = array(); + + /** + * Tags + * @var array + */ + protected $_tags = array(); + + protected $_extension = null; + + /** + * Start the cache + * + * @param string $id Cache id + * @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas) + */ + public function start($id, array $tags, $extension = null) + { + $this->_tags = $tags; + $this->_extension = $extension; + ob_start(array($this, '_flush')); + ob_implicit_flush(false); + $this->_idStack[] = $id; + return false; + } + + /** + * callback for output buffering + * (shouldn't really be called manually) + * + * @param string $data Buffered output + * @return string Data to send to browser + */ + public function _flush($data) + { + $id = array_pop($this->_idStack); + if ($id === null) { + Zend_Cache::throwException('use of _flush() without a start()'); + } + if ($this->_extension) { + $this->save(serialize(array($data, $this->_extension)), $id, $this->_tags); + } else { + $this->save($data, $id, $this->_tags); + } + return $data; + } +} diff --git a/library/vendor/Zend/Cache/Frontend/Class.php b/library/vendor/Zend/Cache/Frontend/Class.php new file mode 100644 index 0000000..c7208a1 --- /dev/null +++ b/library/vendor/Zend/Cache/Frontend/Class.php @@ -0,0 +1,274 @@ +<?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_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + +/** + * @see Zend_Cache_Core + */ + + +/** + * @package Zend_Cache + * @subpackage Zend_Cache_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Cache_Frontend_Class extends Zend_Cache_Core +{ + /** + * Available options + * + * ====> (mixed) cached_entity : + * - if set to a class name, we will cache an abstract class and will use only static calls + * - if set to an object, we will cache this object methods + * + * ====> (boolean) cache_by_default : + * - if true, method calls will be cached by default + * + * ====> (array) cached_methods : + * - an array of method names which will be cached (even if cache_by_default = false) + * + * ====> (array) non_cached_methods : + * - an array of method names which won't be cached (even if cache_by_default = true) + * + * @var array available options + */ + protected $_specificOptions = array( + 'cached_entity' => null, + 'cache_by_default' => true, + 'cached_methods' => array(), + 'non_cached_methods' => array() + ); + + /** + * Tags array + * + * @var array + */ + protected $_tags = array(); + + /** + * SpecificLifetime value + * + * false => no specific life time + * + * @var bool|int + */ + protected $_specificLifetime = false; + + /** + * The cached object or the name of the cached abstract class + * + * @var mixed + */ + protected $_cachedEntity = null; + + /** + * The class name of the cached object or cached abstract class + * + * Used to differentiate between different classes with the same method calls. + * + * @var string + */ + protected $_cachedEntityLabel = ''; + + /** + * Priority (used by some particular backends) + * + * @var int + */ + protected $_priority = 8; + + /** + * Constructor + * + * @param array $options Associative array of options + * @throws Zend_Cache_Exception + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + if ($this->_specificOptions['cached_entity'] === null) { + Zend_Cache::throwException('cached_entity must be set !'); + } + $this->setCachedEntity($this->_specificOptions['cached_entity']); + $this->setOption('automatic_serialization', true); + } + + /** + * Set a specific life time + * + * @param bool|int $specificLifetime + * @return void + */ + public function setSpecificLifetime($specificLifetime = false) + { + $this->_specificLifetime = $specificLifetime; + } + + /** + * Set the priority (used by some particular backends) + * + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) + */ + public function setPriority($priority) + { + $this->_priority = $priority; + } + + /** + * Public frontend to set an option + * + * Just a wrapper to get a specific behaviour for cached_entity + * + * @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 ($name == 'cached_entity') { + $this->setCachedEntity($value); + } else { + parent::setOption($name, $value); + } + } + + /** + * Specific method to set the cachedEntity + * + * if set to a class name, we will cache an abstract class and will use only static calls + * if set to an object, we will cache this object methods + * + * @param mixed $cachedEntity + */ + public function setCachedEntity($cachedEntity) + { + if (!is_string($cachedEntity) && !is_object($cachedEntity)) { + Zend_Cache::throwException( + 'cached_entity must be an object or a class name' + ); + } + + $this->_cachedEntity = $cachedEntity; + $this->_specificOptions['cached_entity'] = $cachedEntity; + + if (is_string($this->_cachedEntity)) { + $this->_cachedEntityLabel = $this->_cachedEntity; + } else { + $ro = new ReflectionObject($this->_cachedEntity); + $this->_cachedEntityLabel = $ro->getName(); + } + } + + /** + * Set the cache array + * + * @param array $tags + * @return void + */ + public function setTagsArray($tags = array()) + { + $this->_tags = $tags; + } + + /** + * Main method : call the specified method or get the result from cache + * + * @param string $name Method name + * @param array $parameters Method parameters + * @return mixed Result + * @throws Exception + */ + public function __call($name, $parameters) + { + $callback = array($this->_cachedEntity, $name); + + if (!is_callable($callback, false)) { + Zend_Cache::throwException('Invalid callback'); + } + + $cacheBool1 = $this->_specificOptions['cache_by_default']; + $cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']); + $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']); + $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); + + if (!$cache) { + // We do not have not cache + return call_user_func_array($callback, $parameters); + } + + $id = $this->makeId($name, $parameters); + if (($rs = $this->load($id)) && (array_key_exists(0, $rs)) + && (array_key_exists(1, $rs)) + ) { + // A cache is available + $output = $rs[0]; + $return = $rs[1]; + } else { + // A cache is not available (or not valid for this frontend) + ob_start(); + ob_implicit_flush(false); + + try { + $return = call_user_func_array($callback, $parameters); + $output = ob_get_clean(); + $data = array($output, $return); + + $this->save( + $data, $id, $this->_tags, $this->_specificLifetime, + $this->_priority + ); + } catch (Exception $e) { + ob_end_clean(); + throw $e; + } + } + + echo $output; + return $return; + } + + /** + * ZF-9970 + * + * @deprecated + */ + private function _makeId($name, $args) + { + return $this->makeId($name, $args); + } + + /** + * Make a cache id from the method name and parameters + * + * @param string $name Method name + * @param array $args Method parameters + * @return string Cache id + */ + public function makeId($name, array $args = array()) + { + return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($args)); + } +} diff --git a/library/vendor/Zend/Cache/Frontend/File.php b/library/vendor/Zend/Cache/Frontend/File.php new file mode 100644 index 0000000..98cd5a3 --- /dev/null +++ b/library/vendor/Zend/Cache/Frontend/File.php @@ -0,0 +1,221 @@ +<?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_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * @see Zend_Cache_Core + */ + + +/** + * @package Zend_Cache + * @subpackage Zend_Cache_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Cache_Frontend_File extends Zend_Cache_Core +{ + + /** + * Consts for master_files_mode + */ + const MODE_AND = 'AND'; + const MODE_OR = 'OR'; + + /** + * Available options + * + * ====> (string) master_file : + * - a complete path of the master file + * - deprecated (see master_files) + * + * ====> (array) master_files : + * - an array of complete path of master files + * - this option has to be set ! + * + * ====> (string) master_files_mode : + * - Zend_Cache_Frontend_File::MODE_AND or Zend_Cache_Frontend_File::MODE_OR + * - if MODE_AND, then all master files have to be touched to get a cache invalidation + * - if MODE_OR (default), then a single touched master file is enough to get a cache invalidation + * + * ====> (boolean) ignore_missing_master_files + * - if set to true, missing master files are ignored silently + * - if set to false (default), an exception is thrown if there is a missing master file + * @var array available options + */ + protected $_specificOptions = array( + 'master_file' => null, + 'master_files' => null, + 'master_files_mode' => 'OR', + 'ignore_missing_master_files' => false + ); + + /** + * Master file mtimes + * + * Array of int + * + * @var array + */ + private $_masterFile_mtimes = null; + + /** + * Constructor + * + * @param array $options Associative array of options + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + if (!isset($this->_specificOptions['master_files'])) { + Zend_Cache::throwException('master_files option must be set'); + } + } + + /** + * Change the master_files option + * + * @param array $masterFiles the complete paths and name of the master files + */ + public function setMasterFiles(array $masterFiles) + { + $this->_specificOptions['master_file'] = null; // to keep a compatibility + $this->_specificOptions['master_files'] = null; + $this->_masterFile_mtimes = array(); + + clearstatcache(); + $i = 0; + foreach ($masterFiles as $masterFile) { + if (file_exists($masterFile)) { + $mtime = filemtime($masterFile); + } else { + $mtime = false; + } + + if (!$this->_specificOptions['ignore_missing_master_files'] && !$mtime) { + Zend_Cache::throwException('Unable to read master_file : ' . $masterFile); + } + + $this->_masterFile_mtimes[$i] = $mtime; + $this->_specificOptions['master_files'][$i] = $masterFile; + if ($i === 0) { // to keep a compatibility + $this->_specificOptions['master_file'] = $masterFile; + } + + $i++; + } + } + + /** + * Change the master_file option + * + * To keep the compatibility + * + * @deprecated + * @param string $masterFile the complete path and name of the master file + */ + public function setMasterFile($masterFile) + { + $this->setMasterFiles(array($masterFile)); + } + + /** + * Public frontend to set an option + * + * Just a wrapper to get a specific behaviour for master_file + * + * @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 ($name == 'master_file') { + $this->setMasterFile($value); + } else if ($name == 'master_files') { + $this->setMasterFiles($value); + } else { + parent::setOption($name, $value); + } + } + + /** + * 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 (!$doNotTestCacheValidity) { + if ($this->test($id)) { + return parent::load($id, true, $doNotUnserialize); + } + return false; + } + return parent::load($id, true, $doNotUnserialize); + } + + /** + * 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) + { + $lastModified = parent::test($id); + if ($lastModified) { + if ($this->_specificOptions['master_files_mode'] == self::MODE_AND) { + // MODE_AND + foreach($this->_masterFile_mtimes as $masterFileMTime) { + if ($masterFileMTime) { + if ($lastModified > $masterFileMTime) { + return $lastModified; + } + } + } + } else { + // MODE_OR + $res = true; + foreach($this->_masterFile_mtimes as $masterFileMTime) { + if ($masterFileMTime) { + if ($lastModified <= $masterFileMTime) { + return false; + } + } + } + return $lastModified; + } + } + return false; + } + +} + diff --git a/library/vendor/Zend/Cache/Frontend/Function.php b/library/vendor/Zend/Cache/Frontend/Function.php new file mode 100644 index 0000000..3dc7fd8 --- /dev/null +++ b/library/vendor/Zend/Cache/Frontend/Function.php @@ -0,0 +1,178 @@ +<?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_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * @see Zend_Cache_Core + */ + + +/** + * @package Zend_Cache + * @subpackage Zend_Cache_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Cache_Frontend_Function extends Zend_Cache_Core +{ + /** + * This frontend specific options + * + * ====> (boolean) cache_by_default : + * - if true, function calls will be cached by default + * + * ====> (array) cached_functions : + * - an array of function names which will be cached (even if cache_by_default = false) + * + * ====> (array) non_cached_functions : + * - an array of function names which won't be cached (even if cache_by_default = true) + * + * @var array options + */ + protected $_specificOptions = array( + 'cache_by_default' => true, + 'cached_functions' => array(), + 'non_cached_functions' => array() + ); + + /** + * Constructor + * + * @param array $options Associative array of options + * @return void + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + $this->setOption('automatic_serialization', true); + } + + /** + * Main method : call the specified function or get the result from cache + * + * @param callback $callback A valid callback + * @param array $parameters Function parameters + * @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 + * @return mixed Result + */ + public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8) + { + if (!is_callable($callback, true, $name)) { + Zend_Cache::throwException('Invalid callback'); + } + + $cacheBool1 = $this->_specificOptions['cache_by_default']; + $cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']); + $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']); + $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); + if (!$cache) { + // Caching of this callback is disabled + return call_user_func_array($callback, $parameters); + } + + $id = $this->_makeId($callback, $parameters); + if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) { + // A cache is available + $output = $rs[0]; + $return = $rs[1]; + } else { + // A cache is not available (or not valid for this frontend) + ob_start(); + ob_implicit_flush(false); + $return = call_user_func_array($callback, $parameters); + $output = ob_get_clean(); + $data = array($output, $return); + $this->save($data, $id, $tags, $specificLifetime, $priority); + } + + echo $output; + return $return; + } + + /** + * ZF-9970 + * + * @deprecated + */ + private function _makeId($callback, array $args) + { + return $this->makeId($callback, $args); + } + + /** + * Make a cache id from the function name and parameters + * + * @param callback $callback A valid callback + * @param array $args Function parameters + * @throws Zend_Cache_Exception + * @return string Cache id + */ + public function makeId($callback, array $args = array()) + { + if (!is_callable($callback, true, $name)) { + Zend_Cache::throwException('Invalid callback'); + } + + // functions, methods and classnames are case-insensitive + $name = strtolower($name); + + // generate a unique id for object callbacks + if (is_object($callback)) { // Closures & __invoke + $object = $callback; + } elseif (isset($callback[0])) { // array($object, 'method') + $object = $callback[0]; + } + if (isset($object)) { + try { + $tmp = @serialize($callback); + } catch (Exception $e) { + Zend_Cache::throwException($e->getMessage()); + } + if (!$tmp) { + $lastErr = error_get_last(); + Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}"); + } + $name.= '__' . $tmp; + } + + // generate a unique id for arguments + $argsStr = ''; + if ($args) { + try { + $argsStr = @serialize(array_values($args)); + } catch (Exception $e) { + Zend_Cache::throwException($e->getMessage()); + } + if (!$argsStr) { + $lastErr = error_get_last(); + throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}"); + } + } + + return md5($name . $argsStr); + } + +} diff --git a/library/vendor/Zend/Cache/Frontend/Output.php b/library/vendor/Zend/Cache/Frontend/Output.php new file mode 100644 index 0000000..dd8fe8d --- /dev/null +++ b/library/vendor/Zend/Cache/Frontend/Output.php @@ -0,0 +1,104 @@ +<?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_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * @see Zend_Cache_Core + */ + + +/** + * @package Zend_Cache + * @subpackage Zend_Cache_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Cache_Frontend_Output extends Zend_Cache_Core +{ + + private $_idStack = array(); + + /** + * Constructor + * + * @param array $options Associative array of options + * @return void + */ + public function __construct(array $options = array()) + { + parent::__construct($options); + $this->_idStack = array(); + } + + /** + * Start the cache + * + * @param string $id Cache id + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @param boolean $echoData If set to true, datas are sent to the browser if the cache is hit (simply returned else) + * @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas) + */ + public function start($id, $doNotTestCacheValidity = false, $echoData = true) + { + $data = $this->load($id, $doNotTestCacheValidity); + if ($data !== false) { + if ( $echoData ) { + echo($data); + return true; + } else { + return $data; + } + } + ob_start(); + ob_implicit_flush(false); + $this->_idStack[] = $id; + return false; + } + + /** + * Stop the cache + * + * @param array $tags Tags array + * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @param string $forcedDatas If not null, force written datas with this + * @param boolean $echoData If set to true, datas are sent to the browser + * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends + * @return void + */ + public function end($tags = array(), $specificLifetime = false, $forcedDatas = null, $echoData = true, $priority = 8) + { + if ($forcedDatas === null) { + $data = ob_get_clean(); + } else { + $data =& $forcedDatas; + } + $id = array_pop($this->_idStack); + if ($id === null) { + Zend_Cache::throwException('use of end() without a start()'); + } + $this->save($data, $id, $tags, $specificLifetime, $priority); + if ($echoData) { + echo($data); + } + } + +} diff --git a/library/vendor/Zend/Cache/Frontend/Page.php b/library/vendor/Zend/Cache/Frontend/Page.php new file mode 100644 index 0000000..8326281 --- /dev/null +++ b/library/vendor/Zend/Cache/Frontend/Page.php @@ -0,0 +1,403 @@ +<?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_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + */ + + +/** + * @see Zend_Cache_Core + */ + + +/** + * @package Zend_Cache + * @subpackage Zend_Cache_Frontend + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Cache_Frontend_Page extends Zend_Cache_Core +{ + /** + * This frontend specific options + * + * ====> (boolean) http_conditional : + * - if true, http conditional mode is on + * WARNING : http_conditional OPTION IS NOT IMPLEMENTED FOR THE MOMENT (TODO) + * + * ====> (boolean) debug_header : + * - if true, a debug text is added before each cached pages + * + * ====> (boolean) content_type_memorization : + * - deprecated => use memorize_headers instead + * - if the Content-Type header is sent after the cache was started, the + * corresponding value can be memorized and replayed when the cache is hit + * (if false (default), the frontend doesn't take care of Content-Type header) + * + * ====> (array) memorize_headers : + * - an array of strings corresponding to some HTTP headers name. Listed headers + * will be stored with cache datas and "replayed" when the cache is hit + * + * ====> (array) default_options : + * - an associative array of default options : + * - (boolean) cache : cache is on by default if true + * - (boolean) cacheWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') : + * if true, cache is still on even if there are some variables in this superglobal array + * if false, cache is off if there are some variables in this superglobal array + * - (boolean) makeIdWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') : + * if true, we have to use the content of this superglobal array to make a cache id + * if false, the cache id won't be dependent of the content of this superglobal array + * - (int) specific_lifetime : cache specific lifetime + * (false => global lifetime is used, null => infinite lifetime, + * integer => this lifetime is used), this "lifetime" is probably only + * usefull when used with "regexps" array + * - (array) tags : array of tags (strings) + * - (int) priority : integer between 0 (very low priority) and 10 (maximum priority) used by + * some particular backends + * + * ====> (array) regexps : + * - an associative array to set options only for some REQUEST_URI + * - keys are (pcre) regexps + * - values are associative array with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI'] + * (see default_options for the list of available options) + * - if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used + * + * @var array options + */ + protected $_specificOptions = array( + 'http_conditional' => false, + 'debug_header' => false, + 'content_type_memorization' => false, + 'memorize_headers' => array(), + 'default_options' => array( + 'cache_with_get_variables' => false, + 'cache_with_post_variables' => false, + 'cache_with_session_variables' => false, + 'cache_with_files_variables' => false, + 'cache_with_cookie_variables' => false, + 'make_id_with_get_variables' => true, + 'make_id_with_post_variables' => true, + 'make_id_with_session_variables' => true, + 'make_id_with_files_variables' => true, + 'make_id_with_cookie_variables' => true, + 'cache' => true, + 'specific_lifetime' => false, + 'tags' => array(), + 'priority' => null + ), + 'regexps' => array() + ); + + /** + * Internal array to store some options + * + * @var array associative array of options + */ + protected $_activeOptions = array(); + + /** + * If true, the page won't be cached + * + * @var boolean + */ + protected $_cancel = false; + + /** + * Constructor + * + * @param array $options Associative array of options + * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested + * @throws Zend_Cache_Exception + * @return void + */ + public function __construct(array $options = array()) + { + foreach ($options as $name => $value) { + $name = strtolower($name); + switch ($name) { + case 'regexps': + $this->_setRegexps($value); + break; + case 'default_options': + $this->_setDefaultOptions($value); + break; + case 'content_type_memorization': + $this->_setContentTypeMemorization($value); + break; + default: + $this->setOption($name, $value); + } + } + if (isset($this->_specificOptions['http_conditional'])) { + if ($this->_specificOptions['http_conditional']) { + Zend_Cache::throwException('http_conditional is not implemented for the moment !'); + } + } + $this->setOption('automatic_serialization', true); + } + + /** + * Specific setter for the 'default_options' option (with some additional tests) + * + * @param array $options Associative array + * @throws Zend_Cache_Exception + * @return void + */ + protected function _setDefaultOptions($options) + { + if (!is_array($options)) { + Zend_Cache::throwException('default_options must be an array !'); + } + foreach ($options as $key=>$value) { + if (!is_string($key)) { + Zend_Cache::throwException("invalid option [$key] !"); + } + $key = strtolower($key); + if (isset($this->_specificOptions['default_options'][$key])) { + $this->_specificOptions['default_options'][$key] = $value; + } + } + } + + /** + * Set the deprecated contentTypeMemorization option + * + * @param boolean $value value + * @return void + * @deprecated + */ + protected function _setContentTypeMemorization($value) + { + $found = null; + foreach ($this->_specificOptions['memorize_headers'] as $key => $value) { + if (strtolower($value) == 'content-type') { + $found = $key; + } + } + if ($value) { + if (!$found) { + $this->_specificOptions['memorize_headers'][] = 'Content-Type'; + } + } else { + if ($found) { + unset($this->_specificOptions['memorize_headers'][$found]); + } + } + } + + /** + * Specific setter for the 'regexps' option (with some additional tests) + * + * @param array $options Associative array + * @throws Zend_Cache_Exception + * @return void + */ + protected function _setRegexps($regexps) + { + if (!is_array($regexps)) { + Zend_Cache::throwException('regexps option must be an array !'); + } + foreach ($regexps as $regexp=>$conf) { + if (!is_array($conf)) { + Zend_Cache::throwException('regexps option must be an array of arrays !'); + } + $validKeys = array_keys($this->_specificOptions['default_options']); + foreach ($conf as $key=>$value) { + if (!is_string($key)) { + Zend_Cache::throwException("unknown option [$key] !"); + } + $key = strtolower($key); + if (!in_array($key, $validKeys)) { + unset($regexps[$regexp][$key]); + } + } + } + $this->setOption('regexps', $regexps); + } + + /** + * Start the cache + * + * @param string $id (optional) A cache id (if you set a value here, maybe you have to use Output frontend instead) + * @param boolean $doNotDie For unit testing only ! + * @return boolean True if the cache is hit (false else) + */ + public function start($id = false, $doNotDie = false) + { + $this->_cancel = false; + $lastMatchingRegexp = null; + if (isset($_SERVER['REQUEST_URI'])) { + foreach ($this->_specificOptions['regexps'] as $regexp => $conf) { + if (preg_match("`$regexp`", $_SERVER['REQUEST_URI'])) { + $lastMatchingRegexp = $regexp; + } + } + } + $this->_activeOptions = $this->_specificOptions['default_options']; + if ($lastMatchingRegexp !== null) { + $conf = $this->_specificOptions['regexps'][$lastMatchingRegexp]; + foreach ($conf as $key=>$value) { + $this->_activeOptions[$key] = $value; + } + } + if (!($this->_activeOptions['cache'])) { + return false; + } + if (!$id) { + $id = $this->_makeId(); + if (!$id) { + return false; + } + } + $array = $this->load($id); + if ($array !== false) { + $data = $array['data']; + $headers = $array['headers']; + if (!headers_sent()) { + foreach ($headers as $key=>$headerCouple) { + $name = $headerCouple[0]; + $value = $headerCouple[1]; + header("$name: $value"); + } + } + if ($this->_specificOptions['debug_header']) { + echo 'DEBUG HEADER : This is a cached page !'; + } + echo $data; + if ($doNotDie) { + return true; + } + die(); + } + ob_start(array($this, '_flush')); + ob_implicit_flush(false); + return false; + } + + /** + * Cancel the current caching process + */ + public function cancel() + { + $this->_cancel = true; + } + + /** + * callback for output buffering + * (shouldn't really be called manually) + * + * @param string $data Buffered output + * @return string Data to send to browser + */ + public function _flush($data) + { + if ($this->_cancel) { + return $data; + } + $contentType = null; + $storedHeaders = array(); + $headersList = headers_list(); + foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) { + foreach ($headersList as $headerSent) { + $tmp = explode(':', $headerSent); + $headerSentName = trim(array_shift($tmp)); + if (strtolower($headerName) == strtolower($headerSentName)) { + $headerSentValue = trim(implode(':', $tmp)); + $storedHeaders[] = array($headerSentName, $headerSentValue); + } + } + } + $array = array( + 'data' => $data, + 'headers' => $storedHeaders + ); + $this->save($array, null, $this->_activeOptions['tags'], $this->_activeOptions['specific_lifetime'], $this->_activeOptions['priority']); + return $data; + } + + /** + * Make an id depending on REQUEST_URI and superglobal arrays (depending on options) + * + * @return mixed|false a cache id (string), false if the cache should have not to be used + */ + protected function _makeId() + { + $tmp = $_SERVER['REQUEST_URI']; + $array = explode('?', $tmp, 2); + $tmp = $array[0]; + foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) { + $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']); + if ($tmp2===false) { + return false; + } + $tmp = $tmp . $tmp2; + } + return md5($tmp); + } + + /** + * Make a partial id depending on options + * + * @param string $arrayName Superglobal array name + * @param bool $bool1 If true, cache is still on even if there are some variables in the superglobal array + * @param bool $bool2 If true, we have to use the content of the superglobal array to make a partial id + * @return mixed|false Partial id (string) or false if the cache should have not to be used + */ + protected function _makePartialId($arrayName, $bool1, $bool2) + { + switch ($arrayName) { + case 'Get': + $var = $_GET; + break; + case 'Post': + $var = $_POST; + break; + case 'Session': + if (isset($_SESSION)) { + $var = $_SESSION; + } else { + $var = null; + } + break; + case 'Cookie': + if (isset($_COOKIE)) { + $var = $_COOKIE; + } else { + $var = null; + } + break; + case 'Files': + $var = $_FILES; + break; + default: + return false; + } + if ($bool1) { + if ($bool2) { + return serialize($var); + } + return ''; + } + if (count($var) > 0) { + return false; + } + return ''; + } + +} |