|
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 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Cache.php 23154 2010-10-18 17:41:06Z mabe $ |
|
20 */ |
|
21 |
|
22 |
|
23 /** |
|
24 * @package Zend_Cache |
|
25 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
26 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
27 */ |
|
28 abstract class Zend_Cache |
|
29 { |
|
30 |
|
31 /** |
|
32 * Standard frontends |
|
33 * |
|
34 * @var array |
|
35 */ |
|
36 public static $standardFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page'); |
|
37 |
|
38 /** |
|
39 * Standard backends |
|
40 * |
|
41 * @var array |
|
42 */ |
|
43 public static $standardBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform', |
|
44 'Xcache', 'TwoLevels', 'ZendServer_Disk', 'ZendServer_ShMem'); |
|
45 |
|
46 /** |
|
47 * Standard backends which implement the ExtendedInterface |
|
48 * |
|
49 * @var array |
|
50 */ |
|
51 public static $standardExtendedBackends = array('File', 'Apc', 'TwoLevels', 'Memcached', 'Libmemcached', 'Sqlite'); |
|
52 |
|
53 /** |
|
54 * Only for backward compatibility (may be removed in next major release) |
|
55 * |
|
56 * @var array |
|
57 * @deprecated |
|
58 */ |
|
59 public static $availableFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page'); |
|
60 |
|
61 /** |
|
62 * Only for backward compatibility (may be removed in next major release) |
|
63 * |
|
64 * @var array |
|
65 * @deprecated |
|
66 */ |
|
67 public static $availableBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform', 'Xcache', 'TwoLevels'); |
|
68 |
|
69 /** |
|
70 * Consts for clean() method |
|
71 */ |
|
72 const CLEANING_MODE_ALL = 'all'; |
|
73 const CLEANING_MODE_OLD = 'old'; |
|
74 const CLEANING_MODE_MATCHING_TAG = 'matchingTag'; |
|
75 const CLEANING_MODE_NOT_MATCHING_TAG = 'notMatchingTag'; |
|
76 const CLEANING_MODE_MATCHING_ANY_TAG = 'matchingAnyTag'; |
|
77 |
|
78 /** |
|
79 * Factory |
|
80 * |
|
81 * @param mixed $frontend frontend name (string) or Zend_Cache_Frontend_ object |
|
82 * @param mixed $backend backend name (string) or Zend_Cache_Backend_ object |
|
83 * @param array $frontendOptions associative array of options for the corresponding frontend constructor |
|
84 * @param array $backendOptions associative array of options for the corresponding backend constructor |
|
85 * @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 |
|
86 * @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 |
|
87 * @param boolean $autoload if true, there will no require_once for backend and frontend (useful only for custom backends/frontends) |
|
88 * @throws Zend_Cache_Exception |
|
89 * @return Zend_Cache_Core|Zend_Cache_Frontend |
|
90 */ |
|
91 public static function factory($frontend, $backend, $frontendOptions = array(), $backendOptions = array(), $customFrontendNaming = false, $customBackendNaming = false, $autoload = false) |
|
92 { |
|
93 if (is_string($backend)) { |
|
94 $backendObject = self::_makeBackend($backend, $backendOptions, $customBackendNaming, $autoload); |
|
95 } else { |
|
96 if ((is_object($backend)) && (in_array('Zend_Cache_Backend_Interface', class_implements($backend)))) { |
|
97 $backendObject = $backend; |
|
98 } else { |
|
99 self::throwException('backend must be a backend name (string) or an object which implements Zend_Cache_Backend_Interface'); |
|
100 } |
|
101 } |
|
102 if (is_string($frontend)) { |
|
103 $frontendObject = self::_makeFrontend($frontend, $frontendOptions, $customFrontendNaming, $autoload); |
|
104 } else { |
|
105 if (is_object($frontend)) { |
|
106 $frontendObject = $frontend; |
|
107 } else { |
|
108 self::throwException('frontend must be a frontend name (string) or an object'); |
|
109 } |
|
110 } |
|
111 $frontendObject->setBackend($backendObject); |
|
112 return $frontendObject; |
|
113 } |
|
114 |
|
115 /** |
|
116 * Backend Constructor |
|
117 * |
|
118 * @param string $backend |
|
119 * @param array $backendOptions |
|
120 * @param boolean $customBackendNaming |
|
121 * @param boolean $autoload |
|
122 * @return Zend_Cache_Backend |
|
123 */ |
|
124 public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false) |
|
125 { |
|
126 if (!$customBackendNaming) { |
|
127 $backend = self::_normalizeName($backend); |
|
128 } |
|
129 if (in_array($backend, Zend_Cache::$standardBackends)) { |
|
130 // we use a standard backend |
|
131 $backendClass = 'Zend_Cache_Backend_' . $backend; |
|
132 // security controls are explicit |
|
133 require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php'; |
|
134 } else { |
|
135 // we use a custom backend |
|
136 if (!preg_match('~^[\w]+$~D', $backend)) { |
|
137 Zend_Cache::throwException("Invalid backend name [$backend]"); |
|
138 } |
|
139 if (!$customBackendNaming) { |
|
140 // we use this boolean to avoid an API break |
|
141 $backendClass = 'Zend_Cache_Backend_' . $backend; |
|
142 } else { |
|
143 $backendClass = $backend; |
|
144 } |
|
145 if (!$autoload) { |
|
146 $file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php'; |
|
147 if (!(self::_isReadable($file))) { |
|
148 self::throwException("file $file not found in include_path"); |
|
149 } |
|
150 require_once $file; |
|
151 } |
|
152 } |
|
153 return new $backendClass($backendOptions); |
|
154 } |
|
155 |
|
156 /** |
|
157 * Frontend Constructor |
|
158 * |
|
159 * @param string $frontend |
|
160 * @param array $frontendOptions |
|
161 * @param boolean $customFrontendNaming |
|
162 * @param boolean $autoload |
|
163 * @return Zend_Cache_Core|Zend_Cache_Frontend |
|
164 */ |
|
165 public static function _makeFrontend($frontend, $frontendOptions = array(), $customFrontendNaming = false, $autoload = false) |
|
166 { |
|
167 if (!$customFrontendNaming) { |
|
168 $frontend = self::_normalizeName($frontend); |
|
169 } |
|
170 if (in_array($frontend, self::$standardFrontends)) { |
|
171 // we use a standard frontend |
|
172 // For perfs reasons, with frontend == 'Core', we can interact with the Core itself |
|
173 $frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend; |
|
174 // security controls are explicit |
|
175 require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php'; |
|
176 } else { |
|
177 // we use a custom frontend |
|
178 if (!preg_match('~^[\w]+$~D', $frontend)) { |
|
179 Zend_Cache::throwException("Invalid frontend name [$frontend]"); |
|
180 } |
|
181 if (!$customFrontendNaming) { |
|
182 // we use this boolean to avoid an API break |
|
183 $frontendClass = 'Zend_Cache_Frontend_' . $frontend; |
|
184 } else { |
|
185 $frontendClass = $frontend; |
|
186 } |
|
187 if (!$autoload) { |
|
188 $file = str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php'; |
|
189 if (!(self::_isReadable($file))) { |
|
190 self::throwException("file $file not found in include_path"); |
|
191 } |
|
192 require_once $file; |
|
193 } |
|
194 } |
|
195 return new $frontendClass($frontendOptions); |
|
196 } |
|
197 |
|
198 /** |
|
199 * Throw an exception |
|
200 * |
|
201 * Note : for perf reasons, the "load" of Zend/Cache/Exception is dynamic |
|
202 * @param string $msg Message for the exception |
|
203 * @throws Zend_Cache_Exception |
|
204 */ |
|
205 public static function throwException($msg, Exception $e = null) |
|
206 { |
|
207 // For perfs reasons, we use this dynamic inclusion |
|
208 require_once 'Zend/Cache/Exception.php'; |
|
209 throw new Zend_Cache_Exception($msg, 0, $e); |
|
210 } |
|
211 |
|
212 /** |
|
213 * Normalize frontend and backend names to allow multiple words TitleCased |
|
214 * |
|
215 * @param string $name Name to normalize |
|
216 * @return string |
|
217 */ |
|
218 protected static function _normalizeName($name) |
|
219 { |
|
220 $name = ucfirst(strtolower($name)); |
|
221 $name = str_replace(array('-', '_', '.'), ' ', $name); |
|
222 $name = ucwords($name); |
|
223 $name = str_replace(' ', '', $name); |
|
224 if (stripos($name, 'ZendServer') === 0) { |
|
225 $name = 'ZendServer_' . substr($name, strlen('ZendServer')); |
|
226 } |
|
227 |
|
228 return $name; |
|
229 } |
|
230 |
|
231 /** |
|
232 * Returns TRUE if the $filename is readable, or FALSE otherwise. |
|
233 * This function uses the PHP include_path, where PHP's is_readable() |
|
234 * does not. |
|
235 * |
|
236 * Note : this method comes from Zend_Loader (see #ZF-2891 for details) |
|
237 * |
|
238 * @param string $filename |
|
239 * @return boolean |
|
240 */ |
|
241 private static function _isReadable($filename) |
|
242 { |
|
243 if (!$fh = @fopen($filename, 'r', true)) { |
|
244 return false; |
|
245 } |
|
246 @fclose($fh); |
|
247 return true; |
|
248 } |
|
249 |
|
250 } |