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 }