web/lib/Zend/Cache/Frontend/Function.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Cache
       
    17  * @subpackage Zend_Cache_Frontend
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Function.php 22648 2010-07-20 14:43:27Z mabe $
       
    21  */
       
    22 
       
    23 
       
    24 /**
       
    25  * @see Zend_Cache_Core
       
    26  */
       
    27 require_once 'Zend/Cache/Core.php';
       
    28 
       
    29 
       
    30 /**
       
    31  * @package    Zend_Cache
       
    32  * @subpackage Zend_Cache_Frontend
       
    33  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    34  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    35  */
       
    36 class Zend_Cache_Frontend_Function extends Zend_Cache_Core
       
    37 {
       
    38     /**
       
    39      * This frontend specific options
       
    40      *
       
    41      * ====> (boolean) cache_by_default :
       
    42      * - if true, function calls will be cached by default
       
    43      *
       
    44      * ====> (array) cached_functions :
       
    45      * - an array of function names which will be cached (even if cache_by_default = false)
       
    46      *
       
    47      * ====> (array) non_cached_functions :
       
    48      * - an array of function names which won't be cached (even if cache_by_default = true)
       
    49      *
       
    50      * @var array options
       
    51      */
       
    52     protected $_specificOptions = array(
       
    53         'cache_by_default' => true,
       
    54         'cached_functions' => array(),
       
    55         'non_cached_functions' => array()
       
    56     );
       
    57 
       
    58     /**
       
    59      * Constructor
       
    60      *
       
    61      * @param  array $options Associative array of options
       
    62      * @return void
       
    63      */
       
    64     public function __construct(array $options = array())
       
    65     {
       
    66         while (list($name, $value) = each($options)) {
       
    67             $this->setOption($name, $value);
       
    68         }
       
    69         $this->setOption('automatic_serialization', true);
       
    70     }
       
    71 
       
    72     /**
       
    73      * Main method : call the specified function or get the result from cache
       
    74      *
       
    75      * @param  callback $callback         A valid callback
       
    76      * @param  array    $parameters       Function parameters
       
    77      * @param  array    $tags             Cache tags
       
    78      * @param  int      $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
       
    79      * @param  int      $priority         integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
       
    80      * @return mixed Result
       
    81      */
       
    82     public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
       
    83     {
       
    84         if (!is_callable($callback, true, $name)) {
       
    85             Zend_Cache::throwException('Invalid callback');
       
    86         }
       
    87 
       
    88         $cacheBool1 = $this->_specificOptions['cache_by_default'];
       
    89         $cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']);
       
    90         $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']);
       
    91         $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
       
    92         if (!$cache) {
       
    93             // Caching of this callback is disabled
       
    94             return call_user_func_array($callback, $parameters);
       
    95         }
       
    96 
       
    97         $id = $this->_makeId($callback, $parameters);
       
    98         if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) {
       
    99             // A cache is available
       
   100             $output = $rs[0];
       
   101             $return = $rs[1];
       
   102         } else {
       
   103             // A cache is not available (or not valid for this frontend)
       
   104             ob_start();
       
   105             ob_implicit_flush(false);
       
   106             $return = call_user_func_array($callback, $parameters);
       
   107             $output = ob_get_contents();
       
   108             ob_end_clean();
       
   109             $data = array($output, $return);
       
   110             $this->save($data, $id, $tags, $specificLifetime, $priority);
       
   111         }
       
   112 
       
   113         echo $output;
       
   114         return $return;
       
   115     }
       
   116 
       
   117     /**
       
   118      * ZF-9970
       
   119      *
       
   120      * @deprecated
       
   121      */
       
   122     private function _makeId($callback, array $args)
       
   123     {
       
   124         return $this->makeId($callback, $args);
       
   125     }
       
   126 
       
   127     /**
       
   128      * Make a cache id from the function name and parameters
       
   129      *
       
   130      * @param  callback $callback A valid callback
       
   131      * @param  array    $args     Function parameters
       
   132      * @throws Zend_Cache_Exception
       
   133      * @return string Cache id
       
   134      */
       
   135     public function makeId($callback, array $args = array())
       
   136     {
       
   137         if (!is_callable($callback, true, $name)) {
       
   138             Zend_Cache::throwException('Invalid callback');
       
   139         }
       
   140 
       
   141         // functions, methods and classnames are case-insensitive
       
   142         $name = strtolower($name);
       
   143 
       
   144         // generate a unique id for object callbacks
       
   145         if (is_object($callback)) { // Closures & __invoke
       
   146             $object = $callback;
       
   147         } elseif (isset($callback[0])) { // array($object, 'method')
       
   148             $object = $callback[0];
       
   149         }
       
   150         if (isset($object)) {
       
   151             try {
       
   152                 $tmp = @serialize($callback);
       
   153             } catch (Exception $e) {
       
   154                 Zend_Cache::throwException($e->getMessage());
       
   155             }
       
   156             if (!$tmp) {
       
   157                 $lastErr = error_get_last();
       
   158                 Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}");
       
   159             }
       
   160             $name.= '__' . $tmp;
       
   161         }
       
   162 
       
   163         // generate a unique id for arguments
       
   164         $argsStr = '';
       
   165         if ($args) {
       
   166             try {
       
   167                 $argsStr = @serialize(array_values($args));
       
   168             } catch (Exception $e) {
       
   169                 Zend_Cache::throwException($e->getMessage());
       
   170             }
       
   171             if (!$argsStr) {
       
   172                 $lastErr = error_get_last();
       
   173                 throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}");
       
   174             }
       
   175         }
       
   176 
       
   177         return md5($name . $argsStr);
       
   178     }
       
   179 
       
   180 }