File indexing completed on 2024-12-22 05:37:15

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  * @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 /**
0024  * @package    Zend_Cache
0025  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0026  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0027  */
0028 abstract class Zend_Cache
0029 {
0030 
0031     /**
0032      * Standard frontends
0033      *
0034      * @var array
0035      */
0036     public static $standardFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page');
0037 
0038     /**
0039      * Standard backends
0040      *
0041      * @var array
0042      */
0043     public static $standardBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform',
0044                                             'Xcache', 'TwoLevels', 'WinCache', 'ZendServer_Disk', 'ZendServer_ShMem');
0045 
0046     /**
0047      * Standard backends which implement the ExtendedInterface
0048      *
0049      * @var array
0050      */
0051     public static $standardExtendedBackends = array('File', 'Apc', 'TwoLevels', 'Memcached', 'Libmemcached', 'Sqlite', 'WinCache');
0052 
0053     /**
0054      * Only for backward compatibility (may be removed in next major release)
0055      *
0056      * @var array
0057      * @deprecated
0058      */
0059     public static $availableFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page');
0060 
0061     /**
0062      * Only for backward compatibility (may be removed in next major release)
0063      *
0064      * @var array
0065      * @deprecated
0066      */
0067     public static $availableBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform', 'Xcache', 'WinCache', 'TwoLevels');
0068 
0069     /**
0070      * Consts for clean() method
0071      */
0072     const CLEANING_MODE_ALL              = 'all';
0073     const CLEANING_MODE_OLD              = 'old';
0074     const CLEANING_MODE_MATCHING_TAG     = 'matchingTag';
0075     const CLEANING_MODE_NOT_MATCHING_TAG = 'notMatchingTag';
0076     const CLEANING_MODE_MATCHING_ANY_TAG = 'matchingAnyTag';
0077 
0078     /**
0079      * Factory
0080      *
0081      * @param mixed  $frontend        frontend name (string) or Zend_Cache_Frontend_ object
0082      * @param mixed  $backend         backend name (string) or Zend_Cache_Backend_ object
0083      * @param array  $frontendOptions associative array of options for the corresponding frontend constructor
0084      * @param array  $backendOptions  associative array of options for the corresponding backend constructor
0085      * @param boolean $customFrontendNaming if true, the frontend argument is used as a complete class name ; if false, the frontend argument is used as the end of "Zend_Cache_Frontend_[...]" class name
0086      * @param boolean $customBackendNaming if true, the backend argument is used as a complete class name ; if false, the backend argument is used as the end of "Zend_Cache_Backend_[...]" class name
0087      * @param boolean $autoload if true, there will no // require_once for backend and frontend (useful only for custom backends/frontends)
0088      * @throws Zend_Cache_Exception
0089      * @return Zend_Cache_Core|Zend_Cache_Frontend
0090      */
0091     public static function factory($frontend, $backend, $frontendOptions = array(), $backendOptions = array(), $customFrontendNaming = false, $customBackendNaming = false, $autoload = false)
0092     {
0093         if (is_string($backend)) {
0094             $backendObject = self::_makeBackend($backend, $backendOptions, $customBackendNaming, $autoload);
0095         } else {
0096             if ((is_object($backend)) && (in_array('Zend_Cache_Backend_Interface', class_implements($backend)))) {
0097                 $backendObject = $backend;
0098             } else {
0099                 self::throwException('backend must be a backend name (string) or an object which implements Zend_Cache_Backend_Interface');
0100             }
0101         }
0102         if (is_string($frontend)) {
0103             $frontendObject = self::_makeFrontend($frontend, $frontendOptions, $customFrontendNaming, $autoload);
0104         } else {
0105             if (is_object($frontend)) {
0106                 $frontendObject = $frontend;
0107             } else {
0108                 self::throwException('frontend must be a frontend name (string) or an object');
0109             }
0110         }
0111         $frontendObject->setBackend($backendObject);
0112         return $frontendObject;
0113     }
0114 
0115     /**
0116      * Backend Constructor
0117      *
0118      * @param string  $backend
0119      * @param array   $backendOptions
0120      * @param boolean $customBackendNaming
0121      * @param boolean $autoload
0122      * @return Zend_Cache_Backend
0123      */
0124     public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false)
0125     {
0126         if (!$customBackendNaming) {
0127             $backend  = self::_normalizeName($backend);
0128         }
0129         if (in_array($backend, Zend_Cache::$standardBackends)) {
0130             // we use a standard backend
0131             $backendClass = 'Zend_Cache_Backend_' . $backend;
0132             // security controls are explicit
0133             // require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
0134         } else {
0135             // we use a custom backend
0136             if (!preg_match('~^[\w\\\\]+$~D', $backend)) {
0137                 Zend_Cache::throwException("Invalid backend name [$backend]");
0138             }
0139             if (!$customBackendNaming) {
0140                 // we use this boolean to avoid an API break
0141                 $backendClass = 'Zend_Cache_Backend_' . $backend;
0142             } else {
0143                 $backendClass = $backend;
0144             }
0145             if (!$autoload) {
0146                 $file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
0147                 if (!(self::_isReadable($file))) {
0148                     self::throwException("file $file not found in include_path");
0149                 }
0150                 // require_once $file;
0151             }
0152         }
0153         return new $backendClass($backendOptions);
0154     }
0155 
0156     /**
0157      * Frontend Constructor
0158      *
0159      * @param string  $frontend
0160      * @param array   $frontendOptions
0161      * @param boolean $customFrontendNaming
0162      * @param boolean $autoload
0163      * @return Zend_Cache_Core|Zend_Cache_Frontend
0164      */
0165     public static function _makeFrontend($frontend, $frontendOptions = array(), $customFrontendNaming = false, $autoload = false)
0166     {
0167         if (!$customFrontendNaming) {
0168             $frontend = self::_normalizeName($frontend);
0169         }
0170         if (in_array($frontend, self::$standardFrontends)) {
0171             // we use a standard frontend
0172             // For perfs reasons, with frontend == 'Core', we can interact with the Core itself
0173             $frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend;
0174             // security controls are explicit
0175             // require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
0176         } else {
0177             // we use a custom frontend
0178             if (!preg_match('~^[\w\\\\]+$~D', $frontend)) {
0179                 Zend_Cache::throwException("Invalid frontend name [$frontend]");
0180             }
0181             if (!$customFrontendNaming) {
0182                 // we use this boolean to avoid an API break
0183                 $frontendClass = 'Zend_Cache_Frontend_' . $frontend;
0184             } else {
0185                 $frontendClass = $frontend;
0186             }
0187             if (!$autoload) {
0188                 $file = str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
0189                 if (!(self::_isReadable($file))) {
0190                     self::throwException("file $file not found in include_path");
0191                 }
0192                 // require_once $file;
0193             }
0194         }
0195         return new $frontendClass($frontendOptions);
0196     }
0197 
0198     /**
0199      * Throw an exception
0200      *
0201      * Note : for perf reasons, the "load" of Zend/Cache/Exception is dynamic
0202      * @param  string $msg  Message for the exception
0203      * @throws Zend_Cache_Exception
0204      */
0205     public static function throwException($msg, Exception $e = null)
0206     {
0207         // For perfs reasons, we use this dynamic inclusion
0208         // require_once 'Zend/Cache/Exception.php';
0209         throw new Zend_Cache_Exception($msg, 0, $e);
0210     }
0211 
0212     /**
0213      * Normalize frontend and backend names to allow multiple words TitleCased
0214      *
0215      * @param  string $name  Name to normalize
0216      * @return string
0217      */
0218     protected static function _normalizeName($name)
0219     {
0220         $name = ucfirst(strtolower($name));
0221         $name = str_replace(array('-', '_', '.'), ' ', $name);
0222         $name = ucwords($name);
0223         $name = str_replace(' ', '', $name);
0224         if (stripos($name, 'ZendServer') === 0) {
0225             $name = 'ZendServer_' . substr($name, strlen('ZendServer'));
0226         }
0227 
0228         return $name;
0229     }
0230 
0231     /**
0232      * Returns TRUE if the $filename is readable, or FALSE otherwise.
0233      * This function uses the PHP include_path, where PHP's is_readable()
0234      * does not.
0235      *
0236      * Note : this method comes from Zend_Loader (see #ZF-2891 for details)
0237      *
0238      * @param string   $filename
0239      * @return boolean
0240      */
0241     private static function _isReadable($filename)
0242     {
0243         if (!$fh = @fopen($filename, 'r', true)) {
0244             return false;
0245         }
0246         @fclose($fh);
0247         return true;
0248     }
0249 
0250 }