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 /**
0025  * @see Zend_Cache_Core
0026  */
0027 // require_once 'Zend/Cache/Core.php';
0028 
0029 
0030 /**
0031  * @package    Zend_Cache
0032  * @subpackage Zend_Cache_Frontend
0033  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0034  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0035  */
0036 class Zend_Cache_Frontend_Function extends Zend_Cache_Core
0037 {
0038     /**
0039      * This frontend specific options
0040      *
0041      * ====> (boolean) cache_by_default :
0042      * - if true, function calls will be cached by default
0043      *
0044      * ====> (array) cached_functions :
0045      * - an array of function names which will be cached (even if cache_by_default = false)
0046      *
0047      * ====> (array) non_cached_functions :
0048      * - an array of function names which won't be cached (even if cache_by_default = true)
0049      *
0050      * @var array options
0051      */
0052     protected $_specificOptions = array(
0053         'cache_by_default' => true,
0054         'cached_functions' => array(),
0055         'non_cached_functions' => array()
0056     );
0057 
0058     /**
0059      * Constructor
0060      *
0061      * @param  array $options Associative array of options
0062      * @return void
0063      */
0064     public function __construct(array $options = array())
0065     {
0066         foreach ($options as $name => $value) {
0067             $this->setOption($name, $value);
0068         }
0069         $this->setOption('automatic_serialization', true);
0070     }
0071 
0072     /**
0073      * Main method : call the specified function or get the result from cache
0074      *
0075      * @param  callback $callback         A valid callback
0076      * @param  array    $parameters       Function parameters
0077      * @param  array    $tags             Cache tags
0078      * @param  int      $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
0079      * @param  int      $priority         integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
0080      * @return mixed Result
0081      */
0082     public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
0083     {
0084         if (!is_callable($callback, true, $name)) {
0085             Zend_Cache::throwException('Invalid callback');
0086         }
0087 
0088         $cacheBool1 = $this->_specificOptions['cache_by_default'];
0089         $cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']);
0090         $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']);
0091         $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
0092         if (!$cache) {
0093             // Caching of this callback is disabled
0094             return call_user_func_array($callback, $parameters);
0095         }
0096 
0097         $id = $this->_makeId($callback, $parameters);
0098         if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) {
0099             // A cache is available
0100             $output = $rs[0];
0101             $return = $rs[1];
0102         } else {
0103             // A cache is not available (or not valid for this frontend)
0104             ob_start();
0105             ob_implicit_flush(false);
0106             $return = call_user_func_array($callback, $parameters);
0107             $output = ob_get_clean();
0108             $data = array($output, $return);
0109             $this->save($data, $id, $tags, $specificLifetime, $priority);
0110         }
0111 
0112         echo $output;
0113         return $return;
0114     }
0115 
0116     /**
0117      * ZF-9970
0118      *
0119      * @deprecated
0120      */
0121     private function _makeId($callback, array $args)
0122     {
0123         return $this->makeId($callback, $args);
0124     }
0125 
0126     /**
0127      * Make a cache id from the function name and parameters
0128      *
0129      * @param  callback $callback A valid callback
0130      * @param  array    $args     Function parameters
0131      * @throws Zend_Cache_Exception
0132      * @return string Cache id
0133      */
0134     public function makeId($callback, array $args = array())
0135     {
0136         if (!is_callable($callback, true, $name)) {
0137             Zend_Cache::throwException('Invalid callback');
0138         }
0139 
0140         // functions, methods and classnames are case-insensitive
0141         $name = strtolower($name);
0142 
0143         // generate a unique id for object callbacks
0144         if (is_object($callback)) { // Closures & __invoke
0145             $object = $callback;
0146         } elseif (isset($callback[0])) { // array($object, 'method')
0147             $object = $callback[0];
0148         }
0149         if (isset($object)) {
0150             try {
0151                 $tmp = @serialize($callback);
0152             } catch (Exception $e) {
0153                 Zend_Cache::throwException($e->getMessage());
0154             }
0155             if (!$tmp) {
0156                 $lastErr = error_get_last();
0157                 Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}");
0158             }
0159             $name.= '__' . $tmp;
0160         }
0161 
0162         // generate a unique id for arguments
0163         $argsStr = '';
0164         if ($args) {
0165             try {
0166                 $argsStr = @serialize(array_values($args));
0167             } catch (Exception $e) {
0168                 Zend_Cache::throwException($e->getMessage());
0169             }
0170             if (!$argsStr) {
0171                 $lastErr = error_get_last();
0172                 throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}");
0173             }
0174         }
0175 
0176         return md5($name . $argsStr);
0177     }
0178 
0179 }