File indexing completed on 2025-01-19 05:20:57
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Cache 0017 * @subpackage Zend_Cache_Frontend 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Cache_Core 0025 */ 0026 // require_once 'Zend/Cache/Core.php'; 0027 0028 0029 /** 0030 * @package Zend_Cache 0031 * @subpackage Zend_Cache_Frontend 0032 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0033 * @license http://framework.zend.com/license/new-bsd New BSD License 0034 */ 0035 class Zend_Cache_Frontend_Class extends Zend_Cache_Core 0036 { 0037 /** 0038 * Available options 0039 * 0040 * ====> (mixed) cached_entity : 0041 * - if set to a class name, we will cache an abstract class and will use only static calls 0042 * - if set to an object, we will cache this object methods 0043 * 0044 * ====> (boolean) cache_by_default : 0045 * - if true, method calls will be cached by default 0046 * 0047 * ====> (array) cached_methods : 0048 * - an array of method names which will be cached (even if cache_by_default = false) 0049 * 0050 * ====> (array) non_cached_methods : 0051 * - an array of method names which won't be cached (even if cache_by_default = true) 0052 * 0053 * @var array available options 0054 */ 0055 protected $_specificOptions = array( 0056 'cached_entity' => null, 0057 'cache_by_default' => true, 0058 'cached_methods' => array(), 0059 'non_cached_methods' => array() 0060 ); 0061 0062 /** 0063 * Tags array 0064 * 0065 * @var array 0066 */ 0067 protected $_tags = array(); 0068 0069 /** 0070 * SpecificLifetime value 0071 * 0072 * false => no specific life time 0073 * 0074 * @var bool|int 0075 */ 0076 protected $_specificLifetime = false; 0077 0078 /** 0079 * The cached object or the name of the cached abstract class 0080 * 0081 * @var mixed 0082 */ 0083 protected $_cachedEntity = null; 0084 0085 /** 0086 * The class name of the cached object or cached abstract class 0087 * 0088 * Used to differentiate between different classes with the same method calls. 0089 * 0090 * @var string 0091 */ 0092 protected $_cachedEntityLabel = ''; 0093 0094 /** 0095 * Priority (used by some particular backends) 0096 * 0097 * @var int 0098 */ 0099 protected $_priority = 8; 0100 0101 /** 0102 * Constructor 0103 * 0104 * @param array $options Associative array of options 0105 * @throws Zend_Cache_Exception 0106 */ 0107 public function __construct(array $options = array()) 0108 { 0109 foreach ($options as $name => $value) { 0110 $this->setOption($name, $value); 0111 } 0112 if ($this->_specificOptions['cached_entity'] === null) { 0113 Zend_Cache::throwException('cached_entity must be set !'); 0114 } 0115 $this->setCachedEntity($this->_specificOptions['cached_entity']); 0116 $this->setOption('automatic_serialization', true); 0117 } 0118 0119 /** 0120 * Set a specific life time 0121 * 0122 * @param bool|int $specificLifetime 0123 * @return void 0124 */ 0125 public function setSpecificLifetime($specificLifetime = false) 0126 { 0127 $this->_specificLifetime = $specificLifetime; 0128 } 0129 0130 /** 0131 * Set the priority (used by some particular backends) 0132 * 0133 * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) 0134 */ 0135 public function setPriority($priority) 0136 { 0137 $this->_priority = $priority; 0138 } 0139 0140 /** 0141 * Public frontend to set an option 0142 * 0143 * Just a wrapper to get a specific behaviour for cached_entity 0144 * 0145 * @param string $name Name of the option 0146 * @param mixed $value Value of the option 0147 * @throws Zend_Cache_Exception 0148 * @return void 0149 */ 0150 public function setOption($name, $value) 0151 { 0152 if ($name == 'cached_entity') { 0153 $this->setCachedEntity($value); 0154 } else { 0155 parent::setOption($name, $value); 0156 } 0157 } 0158 0159 /** 0160 * Specific method to set the cachedEntity 0161 * 0162 * if set to a class name, we will cache an abstract class and will use only static calls 0163 * if set to an object, we will cache this object methods 0164 * 0165 * @param mixed $cachedEntity 0166 */ 0167 public function setCachedEntity($cachedEntity) 0168 { 0169 if (!is_string($cachedEntity) && !is_object($cachedEntity)) { 0170 Zend_Cache::throwException( 0171 'cached_entity must be an object or a class name' 0172 ); 0173 } 0174 0175 $this->_cachedEntity = $cachedEntity; 0176 $this->_specificOptions['cached_entity'] = $cachedEntity; 0177 0178 if (is_string($this->_cachedEntity)) { 0179 $this->_cachedEntityLabel = $this->_cachedEntity; 0180 } else { 0181 $ro = new ReflectionObject($this->_cachedEntity); 0182 $this->_cachedEntityLabel = $ro->getName(); 0183 } 0184 } 0185 0186 /** 0187 * Set the cache array 0188 * 0189 * @param array $tags 0190 * @return void 0191 */ 0192 public function setTagsArray($tags = array()) 0193 { 0194 $this->_tags = $tags; 0195 } 0196 0197 /** 0198 * Main method : call the specified method or get the result from cache 0199 * 0200 * @param string $name Method name 0201 * @param array $parameters Method parameters 0202 * @return mixed Result 0203 * @throws Exception 0204 */ 0205 public function __call($name, $parameters) 0206 { 0207 $callback = array($this->_cachedEntity, $name); 0208 0209 if (!is_callable($callback, false)) { 0210 Zend_Cache::throwException('Invalid callback'); 0211 } 0212 0213 $cacheBool1 = $this->_specificOptions['cache_by_default']; 0214 $cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']); 0215 $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']); 0216 $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); 0217 0218 if (!$cache) { 0219 // We do not have not cache 0220 return call_user_func_array($callback, $parameters); 0221 } 0222 0223 $id = $this->makeId($name, $parameters); 0224 if (($rs = $this->load($id)) && (array_key_exists(0, $rs)) 0225 && (array_key_exists(1, $rs)) 0226 ) { 0227 // A cache is available 0228 $output = $rs[0]; 0229 $return = $rs[1]; 0230 } else { 0231 // A cache is not available (or not valid for this frontend) 0232 ob_start(); 0233 ob_implicit_flush(false); 0234 0235 try { 0236 $return = call_user_func_array($callback, $parameters); 0237 $output = ob_get_clean(); 0238 $data = array($output, $return); 0239 0240 $this->save( 0241 $data, $id, $this->_tags, $this->_specificLifetime, 0242 $this->_priority 0243 ); 0244 } catch (Exception $e) { 0245 ob_end_clean(); 0246 throw $e; 0247 } 0248 } 0249 0250 echo $output; 0251 return $return; 0252 } 0253 0254 /** 0255 * ZF-9970 0256 * 0257 * @deprecated 0258 */ 0259 private function _makeId($name, $args) 0260 { 0261 return $this->makeId($name, $args); 0262 } 0263 0264 /** 0265 * Make a cache id from the method name and parameters 0266 * 0267 * @param string $name Method name 0268 * @param array $args Method parameters 0269 * @return string Cache id 0270 */ 0271 public function makeId($name, array $args = array()) 0272 { 0273 return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($args)); 0274 } 0275 }