File indexing completed on 2024-12-29 05:27:31

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_Controller
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 /**
0023  * @see Zend_Controller_Action_Helper_Abstract
0024  */
0025 // require_once 'Zend/Controller/Action/Helper/Abstract.php';
0026 
0027 /**
0028  * @see Zend_Controller_Action_Exception
0029  */
0030 // require_once 'Zend/Controller/Action/Exception.php';
0031 
0032 /**
0033  * @see Zend_Cache_Manager
0034  */
0035 // require_once 'Zend/Cache/Manager.php';
0036 
0037 /**
0038  * @category   Zend
0039  * @package    Zend_Controller
0040  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0041  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0042  */
0043 class Zend_Controller_Action_Helper_Cache
0044     extends Zend_Controller_Action_Helper_Abstract
0045 {
0046 
0047     /**
0048      * Local Cache Manager object used by Helper
0049      *
0050      * @var Zend_Cache_Manager
0051      */
0052     protected $_manager = null;
0053 
0054     /**
0055      * Indexed map of Actions to attempt Page caching on by Controller
0056      *
0057      * @var array
0058      */
0059     protected $_caching = array();
0060 
0061     /**
0062      * Indexed map of Tags by Controller and Action
0063      *
0064      * @var array
0065      */
0066     protected $_tags = array();
0067 
0068     /**
0069      * Indexed map of Extensions by Controller and Action
0070      *
0071      * @var array
0072      */
0073     protected $_extensions = array();
0074 
0075     /**
0076      * Track output buffering condition
0077      */
0078     protected $_obStarted = false;
0079 
0080     /**
0081      * Tell the helper which actions are cacheable and under which
0082      * tags (if applicable) they should be recorded with
0083      *
0084      * @param array $actions
0085      * @param array $tags
0086      * @return void
0087      */
0088     public function direct(array $actions, array $tags = array(), $extension = null)
0089     {
0090         $controller = $this->getRequest()->getControllerName();
0091         $actions = array_unique($actions);
0092         if (!isset($this->_caching[$controller])) {
0093             $this->_caching[$controller] = array();
0094         }
0095         if (!empty($tags)) {
0096             $tags = array_unique($tags);
0097             if (!isset($this->_tags[$controller])) {
0098                 $this->_tags[$controller] = array();
0099             }
0100         }
0101         foreach ($actions as $action) {
0102             $this->_caching[$controller][] = $action;
0103             if (!empty($tags)) {
0104                 $this->_tags[$controller][$action] = array();
0105                 foreach ($tags as $tag) {
0106                     $this->_tags[$controller][$action][] = $tag;
0107                 }
0108             }
0109         }
0110         if ($extension) {
0111             if (!isset($this->_extensions[$controller])) {
0112                 $this->_extensions[$controller] = array();
0113             }
0114             foreach ($actions as $action) {
0115                 $this->_extensions[$controller][$action] = $extension;
0116             }
0117         }
0118     }
0119 
0120     /**
0121      * Remove a specific page cache static file based on its
0122      * relative URL from the application's public directory.
0123      * The file extension is not required here; usually matches
0124      * the original REQUEST_URI that was cached.
0125      *
0126      * @param string $relativeUrl
0127      * @param bool $recursive
0128      * @return mixed
0129      */
0130     public function removePage($relativeUrl, $recursive = false)
0131     {
0132         $cache = $this->getCache(Zend_Cache_Manager::PAGECACHE);
0133         $encodedCacheId = $this->_encodeCacheId($relativeUrl);
0134 
0135         if ($recursive) {
0136             $backend = $cache->getBackend();
0137             if (($backend instanceof Zend_Cache_Backend)
0138                 && method_exists($backend, 'removeRecursively')
0139             ) {
0140                 $result = $backend->removeRecursively($encodedCacheId);
0141                 if (is_null($result) ) {
0142                     $result = $backend->removeRecursively($relativeUrl);
0143                 }
0144                 return $result;
0145             }
0146         }
0147 
0148         $result = $cache->remove($encodedCacheId);
0149         if (is_null($result) ) {
0150             $result = $cache->remove($relativeUrl);
0151         }
0152         return $result;
0153     }
0154 
0155     /**
0156      * Remove a specific page cache static file based on its
0157      * relative URL from the application's public directory.
0158      * The file extension is not required here; usually matches
0159      * the original REQUEST_URI that was cached.
0160      *
0161      * @param array $tags
0162      * @return mixed
0163      */
0164     public function removePagesTagged(array $tags)
0165     {
0166         return $this->getCache(Zend_Cache_Manager::PAGECACHE)
0167             ->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags);
0168     }
0169 
0170     /**
0171      * Commence page caching for any cacheable actions
0172      *
0173      * @return void
0174      */
0175     public function preDispatch()
0176     {
0177         $controller = $this->getRequest()->getControllerName();
0178         $action = $this->getRequest()->getActionName();
0179         $stats = ob_get_status(true);
0180         foreach ($stats as $status) {
0181             if ($status['name'] == 'Zend_Cache_Frontend_Page::_flush'
0182             || $status['name'] == 'Zend_Cache_Frontend_Capture::_flush') {
0183                 $obStarted = true;
0184             }
0185         }
0186         if (!isset($obStarted) && isset($this->_caching[$controller]) &&
0187         in_array($action, $this->_caching[$controller])) {
0188             $reqUri = $this->getRequest()->getRequestUri();
0189             $tags = array();
0190             if (isset($this->_tags[$controller][$action])
0191             && !empty($this->_tags[$controller][$action])) {
0192                 $tags = array_unique($this->_tags[$controller][$action]);
0193             }
0194             $extension = null;
0195             if (isset($this->_extensions[$controller][$action])) {
0196                 $extension = $this->_extensions[$controller][$action];
0197             }
0198             $this->getCache(Zend_Cache_Manager::PAGECACHE)
0199                 ->start($this->_encodeCacheId($reqUri), $tags, $extension);
0200         }
0201     }
0202 
0203     /**
0204      * Encode a Cache ID as hexadecimal. This is a workaround because Backend ID validation
0205      * is trapped in the Frontend classes. Will try to get this reversed for ZF 2.0
0206      * because it's a major annoyance to have IDs so restricted!
0207      *
0208      * @return string
0209      * @param string $requestUri
0210      */
0211     protected function _encodeCacheId($requestUri)
0212     {
0213         return bin2hex($requestUri);
0214     }
0215 
0216     /**
0217      * Set an instance of the Cache Manager for this helper
0218      *
0219      * @param Zend_Cache_Manager $manager
0220      * @return void
0221      */
0222     public function setManager(Zend_Cache_Manager $manager)
0223     {
0224         $this->_manager = $manager;
0225         return $this;
0226     }
0227 
0228     /**
0229      * Get the Cache Manager instance or instantiate the object if not
0230      * exists. Attempts to load from bootstrap if available.
0231      *
0232      * @return Zend_Cache_Manager
0233      */
0234     public function getManager()
0235     {
0236         if ($this->_manager !== null) {
0237             return $this->_manager;
0238         }
0239         $front = Zend_Controller_Front::getInstance();
0240         if ($front->getParam('bootstrap')
0241         && $front->getParam('bootstrap')->getResource('CacheManager')) {
0242             return $front->getParam('bootstrap')
0243                 ->getResource('CacheManager');
0244         }
0245         $this->_manager = new Zend_Cache_Manager;
0246         return $this->_manager;
0247     }
0248 
0249     /**
0250      * Return a list of actions for the current Controller marked for
0251      * caching
0252      *
0253      * @return array
0254      */
0255     public function getCacheableActions()
0256     {
0257         return $this->_caching;
0258     }
0259 
0260     /**
0261      * Return a list of tags set for all cacheable actions
0262      *
0263      * @return array
0264      */
0265     public function getCacheableTags()
0266     {
0267         return $this->_tags;
0268     }
0269 
0270     /**
0271      * Proxy non-matched methods back to Zend_Cache_Manager where
0272      * appropriate
0273      *
0274      * @param string $method
0275      * @param array $args
0276      * @return mixed
0277      */
0278     public function __call($method, $args)
0279     {
0280         if (method_exists($this->getManager(), $method)) {
0281             return call_user_func_array(
0282                 array($this->getManager(), $method), $args
0283             );
0284         }
0285         throw new Zend_Controller_Action_Exception('Method does not exist:'
0286             . $method);
0287     }
0288 
0289 }