aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/3rdparty/libraries/Zend
diff options
context:
space:
mode:
Diffstat (limited to 'inc/3rdparty/libraries/Zend')
-rw-r--r--inc/3rdparty/libraries/Zend/Cache.php250
-rw-r--r--inc/3rdparty/libraries/Zend/Cache/Backend.php290
-rw-r--r--inc/3rdparty/libraries/Zend/Cache/Backend/ExtendedInterface.php127
-rw-r--r--inc/3rdparty/libraries/Zend/Cache/Backend/File.php1034
-rw-r--r--inc/3rdparty/libraries/Zend/Cache/Backend/Interface.php99
-rw-r--r--inc/3rdparty/libraries/Zend/Cache/Core.php765
-rw-r--r--inc/3rdparty/libraries/Zend/Cache/Exception.php32
-rw-r--r--inc/3rdparty/libraries/Zend/Exception.php96
8 files changed, 2693 insertions, 0 deletions
diff --git a/inc/3rdparty/libraries/Zend/Cache.php b/inc/3rdparty/libraries/Zend/Cache.php
new file mode 100644
index 00000000..d28cb559
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache.php
@@ -0,0 +1,250 @@
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-2012 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 24656 2012-02-26 06:02:53Z adamlundrigan $
20 */
21
22
23/**
24 * @package Zend_Cache
25 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
26 * @license http://framework.zend.com/license/new-bsd New BSD License
27 */
28abstract 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', 'WinCache', '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', 'WinCache');
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', 'WinCache', '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 realpath(dirname(__FILE__).'/..').DIRECTORY_SEPARATOR.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 realpath(dirname(__FILE__).'/..').DIRECTORY_SEPARATOR.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}
diff --git a/inc/3rdparty/libraries/Zend/Cache/Backend.php b/inc/3rdparty/libraries/Zend/Cache/Backend.php
new file mode 100644
index 00000000..803fd446
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache/Backend.php
@@ -0,0 +1,290 @@
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_Backend
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Backend.php 24989 2012-06-21 07:24:13Z mabe $
21 */
22
23
24/**
25 * @package Zend_Cache
26 * @subpackage Zend_Cache_Backend
27 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
28 * @license http://framework.zend.com/license/new-bsd New BSD License
29 */
30class Zend_Cache_Backend
31{
32 /**
33 * Frontend or Core directives
34 *
35 * =====> (int) lifetime :
36 * - Cache lifetime (in seconds)
37 * - If null, the cache is valid forever
38 *
39 * =====> (int) logging :
40 * - if set to true, a logging is activated throw Zend_Log
41 *
42 * @var array directives
43 */
44 protected $_directives = array(
45 'lifetime' => 3600,
46 'logging' => false,
47 'logger' => null
48 );
49
50 /**
51 * Available options
52 *
53 * @var array available options
54 */
55 protected $_options = array();
56
57 /**
58 * Constructor
59 *
60 * @param array $options Associative array of options
61 * @throws Zend_Cache_Exception
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 }
70
71 /**
72 * Set the frontend directives
73 *
74 * @param array $directives Assoc of directives
75 * @throws Zend_Cache_Exception
76 * @return void
77 */
78 public function setDirectives($directives)
79 {
80 if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array');
81 while (list($name, $value) = each($directives)) {
82 if (!is_string($name)) {
83 Zend_Cache::throwException("Incorrect option name : $name");
84 }
85 $name = strtolower($name);
86 if (array_key_exists($name, $this->_directives)) {
87 $this->_directives[$name] = $value;
88 }
89
90 }
91
92 $this->_loggerSanity();
93 }
94
95 /**
96 * Set an option
97 *
98 * @param string $name
99 * @param mixed $value
100 * @throws Zend_Cache_Exception
101 * @return void
102 */
103 public function setOption($name, $value)
104 {
105 if (!is_string($name)) {
106 Zend_Cache::throwException("Incorrect option name : $name");
107 }
108 $name = strtolower($name);
109 if (array_key_exists($name, $this->_options)) {
110 $this->_options[$name] = $value;
111 }
112 }
113
114 /**
115 * Returns an option
116 *
117 * @param string $name Optional, the options name to return
118 * @throws Zend_Cache_Exceptions
119 * @return mixed
120 */
121 public function getOption($name)
122 {
123 $name = strtolower($name);
124
125 if (array_key_exists($name, $this->_options)) {
126 return $this->_options[$name];
127 }
128
129 if (array_key_exists($name, $this->_directives)) {
130 return $this->_directives[$name];
131 }
132
133 Zend_Cache::throwException("Incorrect option name : {$name}");
134 }
135
136 /**
137 * Get the life time
138 *
139 * if $specificLifetime is not false, the given specific life time is used
140 * else, the global lifetime is used
141 *
142 * @param int $specificLifetime
143 * @return int Cache life time
144 */
145 public function getLifetime($specificLifetime)
146 {
147 if ($specificLifetime === false) {
148 return $this->_directives['lifetime'];
149 }
150 return $specificLifetime;
151 }
152
153 /**
154 * Return true if the automatic cleaning is available for the backend
155 *
156 * DEPRECATED : use getCapabilities() instead
157 *
158 * @deprecated
159 * @return boolean
160 */
161 public function isAutomaticCleaningAvailable()
162 {
163 return true;
164 }
165
166 /**
167 * Determine system TMP directory and detect if we have read access
168 *
169 * inspired from Zend_File_Transfer_Adapter_Abstract
170 *
171 * @return string
172 * @throws Zend_Cache_Exception if unable to determine directory
173 */
174 public function getTmpDir()
175 {
176 $tmpdir = array();
177 foreach (array($_ENV, $_SERVER) as $tab) {
178 foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
179 if (isset($tab[$key]) && is_string($tab[$key])) {
180 if (($key == 'windir') or ($key == 'SystemRoot')) {
181 $dir = realpath($tab[$key] . '\\temp');
182 } else {
183 $dir = realpath($tab[$key]);
184 }
185 if ($this->_isGoodTmpDir($dir)) {
186 return $dir;
187 }
188 }
189 }
190 }
191 $upload = ini_get('upload_tmp_dir');
192 if ($upload) {
193 $dir = realpath($upload);
194 if ($this->_isGoodTmpDir($dir)) {
195 return $dir;
196 }
197 }
198 if (function_exists('sys_get_temp_dir')) {
199 $dir = sys_get_temp_dir();
200 if ($this->_isGoodTmpDir($dir)) {
201 return $dir;
202 }
203 }
204 // Attemp to detect by creating a temporary file
205 $tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
206 if ($tempFile) {
207 $dir = realpath(dirname($tempFile));
208 unlink($tempFile);
209 if ($this->_isGoodTmpDir($dir)) {
210 return $dir;
211 }
212 }
213 if ($this->_isGoodTmpDir('/tmp')) {
214 return '/tmp';
215 }
216 if ($this->_isGoodTmpDir('\\temp')) {
217 return '\\temp';
218 }
219 Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
220 }
221
222 /**
223 * Verify if the given temporary directory is readable and writable
224 *
225 * @param string $dir temporary directory
226 * @return boolean true if the directory is ok
227 */
228 protected function _isGoodTmpDir($dir)
229 {
230 if (is_readable($dir)) {
231 if (is_writable($dir)) {
232 return true;
233 }
234 }
235 return false;
236 }
237
238 /**
239 * Make sure if we enable logging that the Zend_Log class
240 * is available.
241 * Create a default log object if none is set.
242 *
243 * @throws Zend_Cache_Exception
244 * @return void
245 */
246 protected function _loggerSanity()
247 {
248 if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {
249 return;
250 }
251
252 if (isset($this->_directives['logger'])) {
253 if ($this->_directives['logger'] instanceof Zend_Log) {
254 return;
255 }
256 Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
257 }
258
259 // Create a default logger to the standard output stream
260 require_once 'Zend/Log.php';
261 require_once 'Zend/Log/Writer/Stream.php';
262 require_once 'Zend/Log/Filter/Priority.php';
263 $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
264 $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
265 $this->_directives['logger'] = $logger;
266 }
267
268 /**
269 * Log a message at the WARN (4) priority.
270 *
271 * @param string $message
272 * @throws Zend_Cache_Exception
273 * @return void
274 */
275 protected function _log($message, $priority = 4)
276 {
277 if (!$this->_directives['logging']) {
278 return;
279 }
280
281 if (!isset($this->_directives['logger'])) {
282 Zend_Cache::throwException('Logging is enabled but logger is not set.');
283 }
284 $logger = $this->_directives['logger'];
285 if (!$logger instanceof Zend_Log) {
286 Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
287 }
288 $logger->log($message, $priority);
289 }
290}
diff --git a/inc/3rdparty/libraries/Zend/Cache/Backend/ExtendedInterface.php b/inc/3rdparty/libraries/Zend/Cache/Backend/ExtendedInterface.php
new file mode 100644
index 00000000..c192baaf
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache/Backend/ExtendedInterface.php
@@ -0,0 +1,127 @@
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_Backend
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: ExtendedInterface.php 24593 2012-01-05 20:35:02Z matthew $
21 */
22
23/**
24 * @see Zend_Cache_Backend_Interface
25 */
26//require_once 'Zend/Cache/Backend/Interface.php';
27require_once dirname(__FILE__).'/Interface.php';
28
29/**
30 * @package Zend_Cache
31 * @subpackage Zend_Cache_Backend
32 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
33 * @license http://framework.zend.com/license/new-bsd New BSD License
34 */
35interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interface
36{
37
38 /**
39 * Return an array of stored cache ids
40 *
41 * @return array array of stored cache ids (string)
42 */
43 public function getIds();
44
45 /**
46 * Return an array of stored tags
47 *
48 * @return array array of stored tags (string)
49 */
50 public function getTags();
51
52 /**
53 * Return an array of stored cache ids which match given tags
54 *
55 * In case of multiple tags, a logical AND is made between tags
56 *
57 * @param array $tags array of tags
58 * @return array array of matching cache ids (string)
59 */
60 public function getIdsMatchingTags($tags = array());
61
62 /**
63 * Return an array of stored cache ids which don't match given tags
64 *
65 * In case of multiple tags, a logical OR is made between tags
66 *
67 * @param array $tags array of tags
68 * @return array array of not matching cache ids (string)
69 */
70 public function getIdsNotMatchingTags($tags = array());
71
72 /**
73 * Return an array of stored cache ids which match any given tags
74 *
75 * In case of multiple tags, a logical AND is made between tags
76 *
77 * @param array $tags array of tags
78 * @return array array of any matching cache ids (string)
79 */
80 public function getIdsMatchingAnyTags($tags = array());
81
82 /**
83 * Return the filling percentage of the backend storage
84 *
85 * @return int integer between 0 and 100
86 */
87 public function getFillingPercentage();
88
89 /**
90 * Return an array of metadatas for the given cache id
91 *
92 * The array must include these keys :
93 * - expire : the expire timestamp
94 * - tags : a string array of tags
95 * - mtime : timestamp of last modification time
96 *
97 * @param string $id cache id
98 * @return array array of metadatas (false if the cache id is not found)
99 */
100 public function getMetadatas($id);
101
102 /**
103 * Give (if possible) an extra lifetime to the given cache id
104 *
105 * @param string $id cache id
106 * @param int $extraLifetime
107 * @return boolean true if ok
108 */
109 public function touch($id, $extraLifetime);
110
111 /**
112 * Return an associative array of capabilities (booleans) of the backend
113 *
114 * The array must include these keys :
115 * - automatic_cleaning (is automating cleaning necessary)
116 * - tags (are tags supported)
117 * - expired_read (is it possible to read expired cache records
118 * (for doNotTestCacheValidity option for example))
119 * - priority does the backend deal with priority when saving
120 * - infinite_lifetime (is infinite lifetime can work with this backend)
121 * - get_list (is it possible to get the list of cache ids and the complete list of tags)
122 *
123 * @return array associative of with capabilities
124 */
125 public function getCapabilities();
126
127}
diff --git a/inc/3rdparty/libraries/Zend/Cache/Backend/File.php b/inc/3rdparty/libraries/Zend/Cache/Backend/File.php
new file mode 100644
index 00000000..5affbcb3
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache/Backend/File.php
@@ -0,0 +1,1034 @@
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_Backend
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: File.php 24844 2012-05-31 19:01:36Z rob $
21 */
22
23/**
24 * @see Zend_Cache_Backend_Interface
25 */
26//require_once 'Zend/Cache/Backend/ExtendedInterface.php';
27require_once dirname(__FILE__).'/ExtendedInterface.php';
28
29/**
30 * @see Zend_Cache_Backend
31 */
32//require_once 'Zend/Cache/Backend.php';
33require_once realpath(dirname(__FILE__).'/..').DIRECTORY_SEPARATOR.'Backend.php';
34
35
36
37/**
38 * @package Zend_Cache
39 * @subpackage Zend_Cache_Backend
40 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
41 * @license http://framework.zend.com/license/new-bsd New BSD License
42 */
43class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
44{
45 /**
46 * Available options
47 *
48 * =====> (string) cache_dir :
49 * - Directory where to put the cache files
50 *
51 * =====> (boolean) file_locking :
52 * - Enable / disable file_locking
53 * - Can avoid cache corruption under bad circumstances but it doesn't work on multithread
54 * webservers and on NFS filesystems for example
55 *
56 * =====> (boolean) read_control :
57 * - Enable / disable read control
58 * - If enabled, a control key is embeded in cache file and this key is compared with the one
59 * calculated after the reading.
60 *
61 * =====> (string) read_control_type :
62 * - Type of read control (only if read control is enabled). Available values are :
63 * 'md5' for a md5 hash control (best but slowest)
64 * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
65 * 'adler32' for an adler32 hash control (excellent choice too, faster than crc32)
66 * 'strlen' for a length only test (fastest)
67 *
68 * =====> (int) hashed_directory_level :
69 * - Hashed directory level
70 * - Set the hashed directory structure level. 0 means "no hashed directory
71 * structure", 1 means "one level of directory", 2 means "two levels"...
72 * This option can speed up the cache only when you have many thousands of
73 * cache file. Only specific benchs can help you to choose the perfect value
74 * for you. Maybe, 1 or 2 is a good start.
75 *
76 * =====> (int) hashed_directory_umask :
77 * - deprecated
78 * - Permissions for hashed directory structure
79 *
80 * =====> (int) hashed_directory_perm :
81 * - Permissions for hashed directory structure
82 *
83 * =====> (string) file_name_prefix :
84 * - prefix for cache files
85 * - be really carefull with this option because a too generic value in a system cache dir
86 * (like /tmp) can cause disasters when cleaning the cache
87 *
88 * =====> (int) cache_file_umask :
89 * - deprecated
90 * - Permissions for cache files
91 *
92 * =====> (int) cache_file_perm :
93 * - Permissions for cache files
94 *
95 * =====> (int) metatadatas_array_max_size :
96 * - max size for the metadatas array (don't change this value unless you
97 * know what you are doing)
98 *
99 * @var array available options
100 */
101 protected $_options = array(
102 'cache_dir' => null,
103 'file_locking' => true,
104 'read_control' => true,
105 'read_control_type' => 'crc32',
106 'hashed_directory_level' => 0,
107 'hashed_directory_perm' => 0700,
108 'file_name_prefix' => 'zend_cache',
109 'cache_file_perm' => 0600,
110 'metadatas_array_max_size' => 100
111 );
112
113 /**
114 * Array of metadatas (each item is an associative array)
115 *
116 * @var array
117 */
118 protected $_metadatasArray = array();
119
120
121 /**
122 * Constructor
123 *
124 * @param array $options associative array of options
125 * @throws Zend_Cache_Exception
126 * @return void
127 */
128 public function __construct(array $options = array())
129 {
130 parent::__construct($options);
131 if ($this->_options['cache_dir'] !== null) { // particular case for this option
132 $this->setCacheDir($this->_options['cache_dir']);
133 } else {
134 $this->setCacheDir(self::getTmpDir() . DIRECTORY_SEPARATOR, false);
135 }
136 if (isset($this->_options['file_name_prefix'])) { // particular case for this option
137 if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->_options['file_name_prefix'])) {
138 Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-Z0-9_]');
139 }
140 }
141 if ($this->_options['metadatas_array_max_size'] < 10) {
142 Zend_Cache::throwException('Invalid metadatas_array_max_size, must be > 10');
143 }
144
145 if (isset($options['hashed_directory_umask'])) {
146 // See #ZF-12047
147 trigger_error("'hashed_directory_umask' is deprecated -> please use 'hashed_directory_perm' instead", E_USER_NOTICE);
148 if (!isset($options['hashed_directory_perm'])) {
149 $options['hashed_directory_perm'] = $options['hashed_directory_umask'];
150 }
151 }
152 if (isset($options['hashed_directory_perm']) && is_string($options['hashed_directory_perm'])) {
153 // See #ZF-4422
154 $this->_options['hashed_directory_perm'] = octdec($this->_options['hashed_directory_perm']);
155 }
156
157 if (isset($options['cache_file_umask'])) {
158 // See #ZF-12047
159 trigger_error("'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead", E_USER_NOTICE);
160 if (!isset($options['cache_file_perm'])) {
161 $options['cache_file_perm'] = $options['cache_file_umask'];
162 }
163 }
164 if (isset($options['cache_file_perm']) && is_string($options['cache_file_perm'])) {
165 // See #ZF-4422
166 $this->_options['cache_file_perm'] = octdec($this->_options['cache_file_perm']);
167 }
168 }
169
170 /**
171 * Set the cache_dir (particular case of setOption() method)
172 *
173 * @param string $value
174 * @param boolean $trailingSeparator If true, add a trailing separator is necessary
175 * @throws Zend_Cache_Exception
176 * @return void
177 */
178 public function setCacheDir($value, $trailingSeparator = true)
179 {
180 if (!is_dir($value)) {
181 Zend_Cache::throwException(sprintf('cache_dir "%s" must be a directory', $value));
182 }
183 if (!is_writable($value)) {
184 Zend_Cache::throwException(sprintf('cache_dir "%s" is not writable', $value));
185 }
186 if ($trailingSeparator) {
187 // add a trailing DIRECTORY_SEPARATOR if necessary
188 $value = rtrim(realpath($value), '\\/') . DIRECTORY_SEPARATOR;
189 }
190 $this->_options['cache_dir'] = $value;
191 }
192
193 /**
194 * Test if a cache is available for the given id and (if yes) return it (false else)
195 *
196 * @param string $id cache id
197 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
198 * @return string|false cached datas
199 */
200 public function load($id, $doNotTestCacheValidity = false)
201 {
202 if (!($this->_test($id, $doNotTestCacheValidity))) {
203 // The cache is not hit !
204 return false;
205 }
206 $metadatas = $this->_getMetadatas($id);
207 $file = $this->_file($id);
208 $data = $this->_fileGetContents($file);
209 if ($this->_options['read_control']) {
210 $hashData = $this->_hash($data, $this->_options['read_control_type']);
211 $hashControl = $metadatas['hash'];
212 if ($hashData != $hashControl) {
213 // Problem detected by the read control !
214 $this->_log('Zend_Cache_Backend_File::load() / read_control : stored hash and computed hash do not match');
215 $this->remove($id);
216 return false;
217 }
218 }
219 return $data;
220 }
221
222 /**
223 * Test if a cache is available or not (for the given id)
224 *
225 * @param string $id cache id
226 * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
227 */
228 public function test($id)
229 {
230 clearstatcache();
231 return $this->_test($id, false);
232 }
233
234 /**
235 * Save some string datas into a cache record
236 *
237 * Note : $data is always "string" (serialization is done by the
238 * core not by the backend)
239 *
240 * @param string $data Datas to cache
241 * @param string $id Cache id
242 * @param array $tags Array of strings, the cache record will be tagged by each string entry
243 * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
244 * @return boolean true if no problem
245 */
246 public function save($data, $id, $tags = array(), $specificLifetime = false)
247 {
248 clearstatcache();
249 $file = $this->_file($id);
250 $path = $this->_path($id);
251 if ($this->_options['hashed_directory_level'] > 0) {
252 if (!is_writable($path)) {
253 // maybe, we just have to build the directory structure
254 $this->_recursiveMkdirAndChmod($id);
255 }
256 if (!is_writable($path)) {
257 return false;
258 }
259 }
260 if ($this->_options['read_control']) {
261 $hash = $this->_hash($data, $this->_options['read_control_type']);
262 } else {
263 $hash = '';
264 }
265 $metadatas = array(
266 'hash' => $hash,
267 'mtime' => time(),
268 'expire' => $this->_expireTime($this->getLifetime($specificLifetime)),
269 'tags' => $tags
270 );
271 $res = $this->_setMetadatas($id, $metadatas);
272 if (!$res) {
273 $this->_log('Zend_Cache_Backend_File::save() / error on saving metadata');
274 return false;
275 }
276 $res = $this->_filePutContents($file, $data);
277 return $res;
278 }
279
280 /**
281 * Remove a cache record
282 *
283 * @param string $id cache id
284 * @return boolean true if no problem
285 */
286 public function remove($id)
287 {
288 $file = $this->_file($id);
289 $boolRemove = $this->_remove($file);
290 $boolMetadata = $this->_delMetadatas($id);
291 return $boolMetadata && $boolRemove;
292 }
293
294 /**
295 * Clean some cache records
296 *
297 * Available modes are :
298 *
299 * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
300 * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
301 * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
302 * ($tags can be an array of strings or a single string)
303 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
304 * ($tags can be an array of strings or a single string)
305 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
306 * ($tags can be an array of strings or a single string)
307 *
308 * @param string $mode clean mode
309 * @param tags array $tags array of tags
310 * @return boolean true if no problem
311 */
312 public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
313 {
314 // We use this protected method to hide the recursive stuff
315 clearstatcache();
316 return $this->_clean($this->_options['cache_dir'], $mode, $tags);
317 }
318
319 /**
320 * Return an array of stored cache ids
321 *
322 * @return array array of stored cache ids (string)
323 */
324 public function getIds()
325 {
326 return $this->_get($this->_options['cache_dir'], 'ids', array());
327 }
328
329 /**
330 * Return an array of stored tags
331 *
332 * @return array array of stored tags (string)
333 */
334 public function getTags()
335 {
336 return $this->_get($this->_options['cache_dir'], 'tags', array());
337 }
338
339 /**
340 * Return an array of stored cache ids which match given tags
341 *
342 * In case of multiple tags, a logical AND is made between tags
343 *
344 * @param array $tags array of tags
345 * @return array array of matching cache ids (string)
346 */
347 public function getIdsMatchingTags($tags = array())
348 {
349 return $this->_get($this->_options['cache_dir'], 'matching', $tags);
350 }
351
352 /**
353 * Return an array of stored cache ids which don't match given tags
354 *
355 * In case of multiple tags, a logical OR is made between tags
356 *
357 * @param array $tags array of tags
358 * @return array array of not matching cache ids (string)
359 */
360 public function getIdsNotMatchingTags($tags = array())
361 {
362 return $this->_get($this->_options['cache_dir'], 'notMatching', $tags);
363 }
364
365 /**
366 * Return an array of stored cache ids which match any given tags
367 *
368 * In case of multiple tags, a logical AND is made between tags
369 *
370 * @param array $tags array of tags
371 * @return array array of any matching cache ids (string)
372 */
373 public function getIdsMatchingAnyTags($tags = array())
374 {
375 return $this->_get($this->_options['cache_dir'], 'matchingAny', $tags);
376 }
377
378 /**
379 * Return the filling percentage of the backend storage
380 *
381 * @throws Zend_Cache_Exception
382 * @return int integer between 0 and 100
383 */
384 public function getFillingPercentage()
385 {
386 $free = disk_free_space($this->_options['cache_dir']);
387 $total = disk_total_space($this->_options['cache_dir']);
388 if ($total == 0) {
389 Zend_Cache::throwException('can\'t get disk_total_space');
390 } else {
391 if ($free >= $total) {
392 return 100;
393 }
394 return ((int) (100. * ($total - $free) / $total));
395 }
396 }
397
398 /**
399 * Return an array of metadatas for the given cache id
400 *
401 * The array must include these keys :
402 * - expire : the expire timestamp
403 * - tags : a string array of tags
404 * - mtime : timestamp of last modification time
405 *
406 * @param string $id cache id
407 * @return array array of metadatas (false if the cache id is not found)
408 */
409 public function getMetadatas($id)
410 {
411 $metadatas = $this->_getMetadatas($id);
412 if (!$metadatas) {
413 return false;
414 }
415 if (time() > $metadatas['expire']) {
416 return false;
417 }
418 return array(
419 'expire' => $metadatas['expire'],
420 'tags' => $metadatas['tags'],
421 'mtime' => $metadatas['mtime']
422 );
423 }
424
425 /**
426 * Give (if possible) an extra lifetime to the given cache id
427 *
428 * @param string $id cache id
429 * @param int $extraLifetime
430 * @return boolean true if ok
431 */
432 public function touch($id, $extraLifetime)
433 {
434 $metadatas = $this->_getMetadatas($id);
435 if (!$metadatas) {
436 return false;
437 }
438 if (time() > $metadatas['expire']) {
439 return false;
440 }
441 $newMetadatas = array(
442 'hash' => $metadatas['hash'],
443 'mtime' => time(),
444 'expire' => $metadatas['expire'] + $extraLifetime,
445 'tags' => $metadatas['tags']
446 );
447 $res = $this->_setMetadatas($id, $newMetadatas);
448 if (!$res) {
449 return false;
450 }
451 return true;
452 }
453
454 /**
455 * Return an associative array of capabilities (booleans) of the backend
456 *
457 * The array must include these keys :
458 * - automatic_cleaning (is automating cleaning necessary)
459 * - tags (are tags supported)
460 * - expired_read (is it possible to read expired cache records
461 * (for doNotTestCacheValidity option for example))
462 * - priority does the backend deal with priority when saving
463 * - infinite_lifetime (is infinite lifetime can work with this backend)
464 * - get_list (is it possible to get the list of cache ids and the complete list of tags)
465 *
466 * @return array associative of with capabilities
467 */
468 public function getCapabilities()
469 {
470 return array(
471 'automatic_cleaning' => true,
472 'tags' => true,
473 'expired_read' => true,
474 'priority' => false,
475 'infinite_lifetime' => true,
476 'get_list' => true
477 );
478 }
479
480 /**
481 * PUBLIC METHOD FOR UNIT TESTING ONLY !
482 *
483 * Force a cache record to expire
484 *
485 * @param string $id cache id
486 */
487 public function ___expire($id)
488 {
489 $metadatas = $this->_getMetadatas($id);
490 if ($metadatas) {
491 $metadatas['expire'] = 1;
492 $this->_setMetadatas($id, $metadatas);
493 }
494 }
495
496 /**
497 * Get a metadatas record
498 *
499 * @param string $id Cache id
500 * @return array|false Associative array of metadatas
501 */
502 protected function _getMetadatas($id)
503 {
504 if (isset($this->_metadatasArray[$id])) {
505 return $this->_metadatasArray[$id];
506 } else {
507 $metadatas = $this->_loadMetadatas($id);
508 if (!$metadatas) {
509 return false;
510 }
511 $this->_setMetadatas($id, $metadatas, false);
512 return $metadatas;
513 }
514 }
515
516 /**
517 * Set a metadatas record
518 *
519 * @param string $id Cache id
520 * @param array $metadatas Associative array of metadatas
521 * @param boolean $save optional pass false to disable saving to file
522 * @return boolean True if no problem
523 */
524 protected function _setMetadatas($id, $metadatas, $save = true)
525 {
526 if (count($this->_metadatasArray) >= $this->_options['metadatas_array_max_size']) {
527 $n = (int) ($this->_options['metadatas_array_max_size'] / 10);
528 $this->_metadatasArray = array_slice($this->_metadatasArray, $n);
529 }
530 if ($save) {
531 $result = $this->_saveMetadatas($id, $metadatas);
532 if (!$result) {
533 return false;
534 }
535 }
536 $this->_metadatasArray[$id] = $metadatas;
537 return true;
538 }
539
540 /**
541 * Drop a metadata record
542 *
543 * @param string $id Cache id
544 * @return boolean True if no problem
545 */
546 protected function _delMetadatas($id)
547 {
548 if (isset($this->_metadatasArray[$id])) {
549 unset($this->_metadatasArray[$id]);
550 }
551 $file = $this->_metadatasFile($id);
552 return $this->_remove($file);
553 }
554
555 /**
556 * Clear the metadatas array
557 *
558 * @return void
559 */
560 protected function _cleanMetadatas()
561 {
562 $this->_metadatasArray = array();
563 }
564
565 /**
566 * Load metadatas from disk
567 *
568 * @param string $id Cache id
569 * @return array|false Metadatas associative array
570 */
571 protected function _loadMetadatas($id)
572 {
573 $file = $this->_metadatasFile($id);
574 $result = $this->_fileGetContents($file);
575 if (!$result) {
576 return false;
577 }
578 $tmp = @unserialize($result);
579 return $tmp;
580 }
581
582 /**
583 * Save metadatas to disk
584 *
585 * @param string $id Cache id
586 * @param array $metadatas Associative array
587 * @return boolean True if no problem
588 */
589 protected function _saveMetadatas($id, $metadatas)
590 {
591 $file = $this->_metadatasFile($id);
592 $result = $this->_filePutContents($file, serialize($metadatas));
593 if (!$result) {
594 return false;
595 }
596 return true;
597 }
598
599 /**
600 * Make and return a file name (with path) for metadatas
601 *
602 * @param string $id Cache id
603 * @return string Metadatas file name (with path)
604 */
605 protected function _metadatasFile($id)
606 {
607 $path = $this->_path($id);
608 $fileName = $this->_idToFileName('internal-metadatas---' . $id);
609 return $path . $fileName;
610 }
611
612 /**
613 * Check if the given filename is a metadatas one
614 *
615 * @param string $fileName File name
616 * @return boolean True if it's a metadatas one
617 */
618 protected function _isMetadatasFile($fileName)
619 {
620 $id = $this->_fileNameToId($fileName);
621 if (substr($id, 0, 21) == 'internal-metadatas---') {
622 return true;
623 } else {
624 return false;
625 }
626 }
627
628 /**
629 * Remove a file
630 *
631 * If we can't remove the file (because of locks or any problem), we will touch
632 * the file to invalidate it
633 *
634 * @param string $file Complete file path
635 * @return boolean True if ok
636 */
637 protected function _remove($file)
638 {
639 if (!is_file($file)) {
640 return false;
641 }
642 if (!@unlink($file)) {
643 # we can't remove the file (because of locks or any problem)
644 $this->_log("Zend_Cache_Backend_File::_remove() : we can't remove $file");
645 return false;
646 }
647 return true;
648 }
649
650 /**
651 * Clean some cache records (protected method used for recursive stuff)
652 *
653 * Available modes are :
654 * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
655 * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
656 * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
657 * ($tags can be an array of strings or a single string)
658 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
659 * ($tags can be an array of strings or a single string)
660 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
661 * ($tags can be an array of strings or a single string)
662 *
663 * @param string $dir Directory to clean
664 * @param string $mode Clean mode
665 * @param array $tags Array of tags
666 * @throws Zend_Cache_Exception
667 * @return boolean True if no problem
668 */
669 protected function _clean($dir, $mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
670 {
671 if (!is_dir($dir)) {
672 return false;
673 }
674 $result = true;
675 $prefix = $this->_options['file_name_prefix'];
676 $glob = @glob($dir . $prefix . '--*');
677 if ($glob === false) {
678 // On some systems it is impossible to distinguish between empty match and an error.
679 return true;
680 }
681 foreach ($glob as $file) {
682 if (is_file($file)) {
683 $fileName = basename($file);
684 if ($this->_isMetadatasFile($fileName)) {
685 // in CLEANING_MODE_ALL, we drop anything, even remainings old metadatas files
686 if ($mode != Zend_Cache::CLEANING_MODE_ALL) {
687 continue;
688 }
689 }
690 $id = $this->_fileNameToId($fileName);
691 $metadatas = $this->_getMetadatas($id);
692 if ($metadatas === FALSE) {
693 $metadatas = array('expire' => 1, 'tags' => array());
694 }
695 switch ($mode) {
696 case Zend_Cache::CLEANING_MODE_ALL:
697 $res = $this->remove($id);
698 if (!$res) {
699 // in this case only, we accept a problem with the metadatas file drop
700 $res = $this->_remove($file);
701 }
702 $result = $result && $res;
703 break;
704 case Zend_Cache::CLEANING_MODE_OLD:
705 if (time() > $metadatas['expire']) {
706 $result = $this->remove($id) && $result;
707 }
708 break;
709 case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
710 $matching = true;
711 foreach ($tags as $tag) {
712 if (!in_array($tag, $metadatas['tags'])) {
713 $matching = false;
714 break;
715 }
716 }
717 if ($matching) {
718 $result = $this->remove($id) && $result;
719 }
720 break;
721 case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
722 $matching = false;
723 foreach ($tags as $tag) {
724 if (in_array($tag, $metadatas['tags'])) {
725 $matching = true;
726 break;
727 }
728 }
729 if (!$matching) {
730 $result = $this->remove($id) && $result;
731 }
732 break;
733 case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
734 $matching = false;
735 foreach ($tags as $tag) {
736 if (in_array($tag, $metadatas['tags'])) {
737 $matching = true;
738 break;
739 }
740 }
741 if ($matching) {
742 $result = $this->remove($id) && $result;
743 }
744 break;
745 default:
746 Zend_Cache::throwException('Invalid mode for clean() method');
747 break;
748 }
749 }
750 if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
751 // Recursive call
752 $result = $this->_clean($file . DIRECTORY_SEPARATOR, $mode, $tags) && $result;
753 if ($mode == Zend_Cache::CLEANING_MODE_ALL) {
754 // we try to drop the structure too
755 @rmdir($file);
756 }
757 }
758 }
759 return $result;
760 }
761
762 protected function _get($dir, $mode, $tags = array())
763 {
764 if (!is_dir($dir)) {
765 return false;
766 }
767 $result = array();
768 $prefix = $this->_options['file_name_prefix'];
769 $glob = @glob($dir . $prefix . '--*');
770 if ($glob === false) {
771 // On some systems it is impossible to distinguish between empty match and an error.
772 return array();
773 }
774 foreach ($glob as $file) {
775 if (is_file($file)) {
776 $fileName = basename($file);
777 $id = $this->_fileNameToId($fileName);
778 $metadatas = $this->_getMetadatas($id);
779 if ($metadatas === FALSE) {
780 continue;
781 }
782 if (time() > $metadatas['expire']) {
783 continue;
784 }
785 switch ($mode) {
786 case 'ids':
787 $result[] = $id;
788 break;
789 case 'tags':
790 $result = array_unique(array_merge($result, $metadatas['tags']));
791 break;
792 case 'matching':
793 $matching = true;
794 foreach ($tags as $tag) {
795 if (!in_array($tag, $metadatas['tags'])) {
796 $matching = false;
797 break;
798 }
799 }
800 if ($matching) {
801 $result[] = $id;
802 }
803 break;
804 case 'notMatching':
805 $matching = false;
806 foreach ($tags as $tag) {
807 if (in_array($tag, $metadatas['tags'])) {
808 $matching = true;
809 break;
810 }
811 }
812 if (!$matching) {
813 $result[] = $id;
814 }
815 break;
816 case 'matchingAny':
817 $matching = false;
818 foreach ($tags as $tag) {
819 if (in_array($tag, $metadatas['tags'])) {
820 $matching = true;
821 break;
822 }
823 }
824 if ($matching) {
825 $result[] = $id;
826 }
827 break;
828 default:
829 Zend_Cache::throwException('Invalid mode for _get() method');
830 break;
831 }
832 }
833 if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
834 // Recursive call
835 $recursiveRs = $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags);
836 if ($recursiveRs === false) {
837 $this->_log('Zend_Cache_Backend_File::_get() / recursive call : can\'t list entries of "'.$file.'"');
838 } else {
839 $result = array_unique(array_merge($result, $recursiveRs));
840 }
841 }
842 }
843 return array_unique($result);
844 }
845
846 /**
847 * Compute & return the expire time
848 *
849 * @return int expire time (unix timestamp)
850 */
851 protected function _expireTime($lifetime)
852 {
853 if ($lifetime === null) {
854 return 9999999999;
855 }
856 return time() + $lifetime;
857 }
858
859 /**
860 * Make a control key with the string containing datas
861 *
862 * @param string $data Data
863 * @param string $controlType Type of control 'md5', 'crc32' or 'strlen'
864 * @throws Zend_Cache_Exception
865 * @return string Control key
866 */
867 protected function _hash($data, $controlType)
868 {
869 switch ($controlType) {
870 case 'md5':
871 return md5($data);
872 case 'crc32':
873 return crc32($data);
874 case 'strlen':
875 return strlen($data);
876 case 'adler32':
877 return hash('adler32', $data);
878 default:
879 Zend_Cache::throwException("Incorrect hash function : $controlType");
880 }
881 }
882
883 /**
884 * Transform a cache id into a file name and return it
885 *
886 * @param string $id Cache id
887 * @return string File name
888 */
889 protected function _idToFileName($id)
890 {
891 $prefix = $this->_options['file_name_prefix'];
892 $result = $prefix . '---' . $id;
893 return $result;
894 }
895
896 /**
897 * Make and return a file name (with path)
898 *
899 * @param string $id Cache id
900 * @return string File name (with path)
901 */
902 protected function _file($id)
903 {
904 $path = $this->_path($id);
905 $fileName = $this->_idToFileName($id);
906 return $path . $fileName;
907 }
908
909 /**
910 * Return the complete directory path of a filename (including hashedDirectoryStructure)
911 *
912 * @param string $id Cache id
913 * @param boolean $parts if true, returns array of directory parts instead of single string
914 * @return string Complete directory path
915 */
916 protected function _path($id, $parts = false)
917 {
918 $partsArray = array();
919 $root = $this->_options['cache_dir'];
920 $prefix = $this->_options['file_name_prefix'];
921 if ($this->_options['hashed_directory_level']>0) {
922 $hash = hash('adler32', $id);
923 for ($i=0 ; $i < $this->_options['hashed_directory_level'] ; $i++) {
924 $root = $root . $prefix . '--' . substr($hash, 0, $i + 1) . DIRECTORY_SEPARATOR;
925 $partsArray[] = $root;
926 }
927 }
928 if ($parts) {
929 return $partsArray;
930 } else {
931 return $root;
932 }
933 }
934
935 /**
936 * Make the directory strucuture for the given id
937 *
938 * @param string $id cache id
939 * @return boolean true
940 */
941 protected function _recursiveMkdirAndChmod($id)
942 {
943 if ($this->_options['hashed_directory_level'] <=0) {
944 return true;
945 }
946 $partsArray = $this->_path($id, true);
947 foreach ($partsArray as $part) {
948 if (!is_dir($part)) {
949 @mkdir($part, $this->_options['hashed_directory_perm']);
950 @chmod($part, $this->_options['hashed_directory_perm']); // see #ZF-320 (this line is required in some configurations)
951 }
952 }
953 return true;
954 }
955
956 /**
957 * Test if the given cache id is available (and still valid as a cache record)
958 *
959 * @param string $id Cache id
960 * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
961 * @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
962 */
963 protected function _test($id, $doNotTestCacheValidity)
964 {
965 $metadatas = $this->_getMetadatas($id);
966 if (!$metadatas) {
967 return false;
968 }
969 if ($doNotTestCacheValidity || (time() <= $metadatas['expire'])) {
970 return $metadatas['mtime'];
971 }
972 return false;
973 }
974
975 /**
976 * Return the file content of the given file
977 *
978 * @param string $file File complete path
979 * @return string File content (or false if problem)
980 */
981 protected function _fileGetContents($file)
982 {
983 $result = false;
984 if (!is_file($file)) {
985 return false;
986 }
987 $f = @fopen($file, 'rb');
988 if ($f) {
989 if ($this->_options['file_locking']) @flock($f, LOCK_SH);
990 $result = stream_get_contents($f);
991 if ($this->_options['file_locking']) @flock($f, LOCK_UN);
992 @fclose($f);
993 }
994 return $result;
995 }
996
997 /**
998 * Put the given string into the given file
999 *
1000 * @param string $file File complete path
1001 * @param string $string String to put in file
1002 * @return boolean true if no problem
1003 */
1004 protected function _filePutContents($file, $string)
1005 {
1006 $result = false;
1007 $f = @fopen($file, 'ab+');
1008 if ($f) {
1009 if ($this->_options['file_locking']) @flock($f, LOCK_EX);
1010 fseek($f, 0);
1011 ftruncate($f, 0);
1012 $tmp = @fwrite($f, $string);
1013 if (!($tmp === FALSE)) {
1014 $result = true;
1015 }
1016 @fclose($f);
1017 }
1018 @chmod($file, $this->_options['cache_file_perm']);
1019 return $result;
1020 }
1021
1022 /**
1023 * Transform a file name into cache id and return it
1024 *
1025 * @param string $fileName File name
1026 * @return string Cache id
1027 */
1028 protected function _fileNameToId($fileName)
1029 {
1030 $prefix = $this->_options['file_name_prefix'];
1031 return preg_replace('~^' . $prefix . '---(.*)$~', '$1', $fileName);
1032 }
1033
1034}
diff --git a/inc/3rdparty/libraries/Zend/Cache/Backend/Interface.php b/inc/3rdparty/libraries/Zend/Cache/Backend/Interface.php
new file mode 100644
index 00000000..3f44e2e1
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache/Backend/Interface.php
@@ -0,0 +1,99 @@
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_Backend
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Interface.php 24593 2012-01-05 20:35:02Z matthew $
21 */
22
23
24/**
25 * @package Zend_Cache
26 * @subpackage Zend_Cache_Backend
27 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
28 * @license http://framework.zend.com/license/new-bsd New BSD License
29 */
30interface Zend_Cache_Backend_Interface
31{
32 /**
33 * Set the frontend directives
34 *
35 * @param array $directives assoc of directives
36 */
37 public function setDirectives($directives);
38
39 /**
40 * Test if a cache is available for the given id and (if yes) return it (false else)
41 *
42 * Note : return value is always "string" (unserialization is done by the core not by the backend)
43 *
44 * @param string $id Cache id
45 * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
46 * @return string|false cached datas
47 */
48 public function load($id, $doNotTestCacheValidity = false);
49
50 /**
51 * Test if a cache is available or not (for the given id)
52 *
53 * @param string $id cache id
54 * @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
55 */
56 public function test($id);
57
58 /**
59 * Save some string datas into a cache record
60 *
61 * Note : $data is always "string" (serialization is done by the
62 * core not by the backend)
63 *
64 * @param string $data Datas to cache
65 * @param string $id Cache id
66 * @param array $tags Array of strings, the cache record will be tagged by each string entry
67 * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
68 * @return boolean true if no problem
69 */
70 public function save($data, $id, $tags = array(), $specificLifetime = false);
71
72 /**
73 * Remove a cache record
74 *
75 * @param string $id Cache id
76 * @return boolean True if no problem
77 */
78 public function remove($id);
79
80 /**
81 * Clean some cache records
82 *
83 * Available modes are :
84 * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
85 * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
86 * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
87 * ($tags can be an array of strings or a single string)
88 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
89 * ($tags can be an array of strings or a single string)
90 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
91 * ($tags can be an array of strings or a single string)
92 *
93 * @param string $mode Clean mode
94 * @param array $tags Array of tags
95 * @return boolean true if no problem
96 */
97 public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array());
98
99}
diff --git a/inc/3rdparty/libraries/Zend/Cache/Core.php b/inc/3rdparty/libraries/Zend/Cache/Core.php
new file mode 100644
index 00000000..e3588636
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache/Core.php
@@ -0,0 +1,765 @@
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-2012 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
19 * @version $Id: Core.php 24989 2012-06-21 07:24:13Z mabe $
20 */
21
22
23/**
24 * @package Zend_Cache
25 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
26 * @license http://framework.zend.com/license/new-bsd New BSD License
27 */
28class Zend_Cache_Core
29{
30 /**
31 * Messages
32 */
33 const BACKEND_NOT_SUPPORTS_TAG = 'tags are not supported by the current backend';
34 const BACKEND_NOT_IMPLEMENTS_EXTENDED_IF = 'Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available';
35
36 /**
37 * Backend Object
38 *
39 * @var Zend_Cache_Backend_Interface $_backend
40 */
41 protected $_backend = null;
42
43 /**
44 * Available options
45 *
46 * ====> (boolean) write_control :
47 * - Enable / disable write control (the cache is read just after writing to detect corrupt entries)
48 * - Enable write control will lightly slow the cache writing but not the cache reading
49 * Write control can detect some corrupt cache files but maybe it's not a perfect control
50 *
51 * ====> (boolean) caching :
52 * - Enable / disable caching
53 * (can be very useful for the debug of cached scripts)
54 *
55 * =====> (string) cache_id_prefix :
56 * - prefix for cache ids (namespace)
57 *
58 * ====> (boolean) automatic_serialization :
59 * - Enable / disable automatic serialization
60 * - It can be used to save directly datas which aren't strings (but it's slower)
61 *
62 * ====> (int) automatic_cleaning_factor :
63 * - Disable / Tune the automatic cleaning process
64 * - The automatic cleaning process destroy too old (for the given life time)
65 * cache files when a new cache file is written :
66 * 0 => no automatic cache cleaning
67 * 1 => systematic cache cleaning
68 * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
69 *
70 * ====> (int) lifetime :
71 * - Cache lifetime (in seconds)
72 * - If null, the cache is valid forever.
73 *
74 * ====> (boolean) logging :
75 * - If set to true, logging is activated (but the system is slower)
76 *
77 * ====> (boolean) ignore_user_abort
78 * - If set to true, the core will set the ignore_user_abort PHP flag inside the
79 * save() method to avoid cache corruptions in some cases (default false)
80 *
81 * @var array $_options available options
82 */
83 protected $_options = array(
84 'write_control' => true,
85 'caching' => true,
86 'cache_id_prefix' => null,
87 'automatic_serialization' => false,
88 'automatic_cleaning_factor' => 10,
89 'lifetime' => 3600,
90 'logging' => false,
91 'logger' => null,
92 'ignore_user_abort' => false
93 );
94
95 /**
96 * Array of options which have to be transfered to backend
97 *
98 * @var array $_directivesList
99 */
100 protected static $_directivesList = array('lifetime', 'logging', 'logger');
101
102 /**
103 * Not used for the core, just a sort a hint to get a common setOption() method (for the core and for frontends)
104 *
105 * @var array $_specificOptions
106 */
107 protected $_specificOptions = array();
108
109 /**
110 * Last used cache id
111 *
112 * @var string $_lastId
113 */
114 private $_lastId = null;
115
116 /**
117 * True if the backend implements Zend_Cache_Backend_ExtendedInterface
118 *
119 * @var boolean $_extendedBackend
120 */
121 protected $_extendedBackend = false;
122
123 /**
124 * Array of capabilities of the backend (only if it implements Zend_Cache_Backend_ExtendedInterface)
125 *
126 * @var array
127 */
128 protected $_backendCapabilities = array();
129
130 /**
131 * Constructor
132 *
133 * @param array|Zend_Config $options Associative array of options or Zend_Config instance
134 * @throws Zend_Cache_Exception
135 * @return void
136 */
137 public function __construct($options = array())
138 {
139 if ($options instanceof Zend_Config) {
140 $options = $options->toArray();
141 }
142 if (!is_array($options)) {
143 Zend_Cache::throwException("Options passed were not an array"
144 . " or Zend_Config instance.");
145 }
146 while (list($name, $value) = each($options)) {
147 $this->setOption($name, $value);
148 }
149 $this->_loggerSanity();
150 }
151
152 /**
153 * Set options using an instance of type Zend_Config
154 *
155 * @param Zend_Config $config
156 * @return Zend_Cache_Core
157 */
158 public function setConfig(Zend_Config $config)
159 {
160 $options = $config->toArray();
161 while (list($name, $value) = each($options)) {
162 $this->setOption($name, $value);
163 }
164 return $this;
165 }
166
167 /**
168 * Set the backend
169 *
170 * @param Zend_Cache_Backend $backendObject
171 * @throws Zend_Cache_Exception
172 * @return void
173 */
174 public function setBackend(Zend_Cache_Backend $backendObject)
175 {
176 $this->_backend= $backendObject;
177 // some options (listed in $_directivesList) have to be given
178 // to the backend too (even if they are not "backend specific")
179 $directives = array();
180 foreach (Zend_Cache_Core::$_directivesList as $directive) {
181 $directives[$directive] = $this->_options[$directive];
182 }
183 $this->_backend->setDirectives($directives);
184 if (in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_backend))) {
185 $this->_extendedBackend = true;
186 $this->_backendCapabilities = $this->_backend->getCapabilities();
187 }
188
189 }
190
191 /**
192 * Returns the backend
193 *
194 * @return Zend_Cache_Backend backend object
195 */
196 public function getBackend()
197 {
198 return $this->_backend;
199 }
200
201 /**
202 * Public frontend to set an option
203 *
204 * There is an additional validation (relatively to the protected _setOption method)
205 *
206 * @param string $name Name of the option
207 * @param mixed $value Value of the option
208 * @throws Zend_Cache_Exception
209 * @return void
210 */
211 public function setOption($name, $value)
212 {
213 if (!is_string($name)) {
214 Zend_Cache::throwException("Incorrect option name!");
215 }
216 $name = strtolower($name);
217 if (array_key_exists($name, $this->_options)) {
218 // This is a Core option
219 $this->_setOption($name, $value);
220 return;
221 }
222 if (array_key_exists($name, $this->_specificOptions)) {
223 // This a specic option of this frontend
224 $this->_specificOptions[$name] = $value;
225 return;
226 }
227 }
228
229 /**
230 * Public frontend to get an option value
231 *
232 * @param string $name Name of the option
233 * @throws Zend_Cache_Exception
234 * @return mixed option value
235 */
236 public function getOption($name)
237 {
238 $name = strtolower($name);
239
240 if (array_key_exists($name, $this->_options)) {
241 // This is a Core option
242 return $this->_options[$name];
243 }
244
245 if (array_key_exists($name, $this->_specificOptions)) {
246 // This a specic option of this frontend
247 return $this->_specificOptions[$name];
248 }
249
250 Zend_Cache::throwException("Incorrect option name : $name");
251 }
252
253 /**
254 * Set an option
255 *
256 * @param string $name Name of the option
257 * @param mixed $value Value of the option
258 * @throws Zend_Cache_Exception
259 * @return void
260 */
261 private function _setOption($name, $value)
262 {
263 if (!is_string($name) || !array_key_exists($name, $this->_options)) {
264 Zend_Cache::throwException("Incorrect option name : $name");
265 }
266 if ($name == 'lifetime' && empty($value)) {
267 $value = null;
268 }
269 $this->_options[$name] = $value;
270 }
271
272 /**
273 * Force a new lifetime
274 *
275 * The new value is set for the core/frontend but for the backend too (directive)
276 *
277 * @param int $newLifetime New lifetime (in seconds)
278 * @return void
279 */
280 public function setLifetime($newLifetime)
281 {
282 $this->_options['lifetime'] = $newLifetime;
283 $this->_backend->setDirectives(array(
284 'lifetime' => $newLifetime
285 ));
286 }
287
288 /**
289 * Test if a cache is available for the given id and (if yes) return it (false else)
290 *
291 * @param string $id Cache id
292 * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
293 * @param boolean $doNotUnserialize Do not serialize (even if automatic_serialization is true) => for internal use
294 * @return mixed|false Cached datas
295 */
296 public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false)
297 {
298 if (!$this->_options['caching']) {
299 return false;
300 }
301 $id = $this->_id($id); // cache id may need prefix
302 $this->_lastId = $id;
303 self::_validateIdOrTag($id);
304
305 $this->_log("Zend_Cache_Core: load item '{$id}'", 7);
306 $data = $this->_backend->load($id, $doNotTestCacheValidity);
307 if ($data===false) {
308 // no cache available
309 return false;
310 }
311 if ((!$doNotUnserialize) && $this->_options['automatic_serialization']) {
312 // we need to unserialize before sending the result
313 return unserialize($data);
314 }
315 return $data;
316 }
317
318 /**
319 * Test if a cache is available for the given id
320 *
321 * @param string $id Cache id
322 * @return int|false Last modified time of cache entry if it is available, false otherwise
323 */
324 public function test($id)
325 {
326 if (!$this->_options['caching']) {
327 return false;
328 }
329 $id = $this->_id($id); // cache id may need prefix
330 self::_validateIdOrTag($id);
331 $this->_lastId = $id;
332
333 $this->_log("Zend_Cache_Core: test item '{$id}'", 7);
334 return $this->_backend->test($id);
335 }
336
337 /**
338 * Save some data in a cache
339 *
340 * @param mixed $data Data to put in cache (can be another type than string if automatic_serialization is on)
341 * @param string $id Cache id (if not set, the last cache id will be used)
342 * @param array $tags Cache tags
343 * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
344 * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
345 * @throws Zend_Cache_Exception
346 * @return boolean True if no problem
347 */
348 public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8)
349 {
350 if (!$this->_options['caching']) {
351 return true;
352 }
353 if ($id === null) {
354 $id = $this->_lastId;
355 } else {
356 $id = $this->_id($id);
357 }
358 self::_validateIdOrTag($id);
359 self::_validateTagsArray($tags);
360 if ($this->_options['automatic_serialization']) {
361 // we need to serialize datas before storing them
362 $data = serialize($data);
363 } else {
364 if (!is_string($data)) {
365 Zend_Cache::throwException("Datas must be string or set automatic_serialization = true");
366 }
367 }
368
369 // automatic cleaning
370 if ($this->_options['automatic_cleaning_factor'] > 0) {
371 $rand = rand(1, $this->_options['automatic_cleaning_factor']);
372 if ($rand==1) {
373 // new way || deprecated way
374 if ($this->_extendedBackend || method_exists($this->_backend, 'isAutomaticCleaningAvailable')) {
375 $this->_log("Zend_Cache_Core::save(): automatic cleaning running", 7);
376 $this->clean(Zend_Cache::CLEANING_MODE_OLD);
377 } else {
378 $this->_log("Zend_Cache_Core::save(): automatic cleaning is not available/necessary with current backend", 4);
379 }
380 }
381 }
382
383 $this->_log("Zend_Cache_Core: save item '{$id}'", 7);
384 if ($this->_options['ignore_user_abort']) {
385 $abort = ignore_user_abort(true);
386 }
387 if (($this->_extendedBackend) && ($this->_backendCapabilities['priority'])) {
388 $result = $this->_backend->save($data, $id, $tags, $specificLifetime, $priority);
389 } else {
390 $result = $this->_backend->save($data, $id, $tags, $specificLifetime);
391 }
392 if ($this->_options['ignore_user_abort']) {
393 ignore_user_abort($abort);
394 }
395
396 if (!$result) {
397 // maybe the cache is corrupted, so we remove it !
398 $this->_log("Zend_Cache_Core::save(): failed to save item '{$id}' -> removing it", 4);
399 $this->_backend->remove($id);
400 return false;
401 }
402
403 if ($this->_options['write_control']) {
404 $data2 = $this->_backend->load($id, true);
405 if ($data!=$data2) {
406 $this->_log("Zend_Cache_Core::save(): write control of item '{$id}' failed -> removing it", 4);
407 $this->_backend->remove($id);
408 return false;
409 }
410 }
411
412 return true;
413 }
414
415 /**
416 * Remove a cache
417 *
418 * @param string $id Cache id to remove
419 * @return boolean True if ok
420 */
421 public function remove($id)
422 {
423 if (!$this->_options['caching']) {
424 return true;
425 }
426 $id = $this->_id($id); // cache id may need prefix
427 self::_validateIdOrTag($id);
428
429 $this->_log("Zend_Cache_Core: remove item '{$id}'", 7);
430 return $this->_backend->remove($id);
431 }
432
433 /**
434 * Clean cache entries
435 *
436 * Available modes are :
437 * 'all' (default) => remove all cache entries ($tags is not used)
438 * 'old' => remove too old cache entries ($tags is not used)
439 * 'matchingTag' => remove cache entries matching all given tags
440 * ($tags can be an array of strings or a single string)
441 * 'notMatchingTag' => remove cache entries not matching one of the given tags
442 * ($tags can be an array of strings or a single string)
443 * 'matchingAnyTag' => remove cache entries matching any given tags
444 * ($tags can be an array of strings or a single string)
445 *
446 * @param string $mode
447 * @param array|string $tags
448 * @throws Zend_Cache_Exception
449 * @return boolean True if ok
450 */
451 public function clean($mode = 'all', $tags = array())
452 {
453 if (!$this->_options['caching']) {
454 return true;
455 }
456 if (!in_array($mode, array(Zend_Cache::CLEANING_MODE_ALL,
457 Zend_Cache::CLEANING_MODE_OLD,
458 Zend_Cache::CLEANING_MODE_MATCHING_TAG,
459 Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG,
460 Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG))) {
461 Zend_Cache::throwException('Invalid cleaning mode');
462 }
463 self::_validateTagsArray($tags);
464
465 return $this->_backend->clean($mode, $tags);
466 }
467
468 /**
469 * Return an array of stored cache ids which match given tags
470 *
471 * In case of multiple tags, a logical AND is made between tags
472 *
473 * @param array $tags array of tags
474 * @return array array of matching cache ids (string)
475 */
476 public function getIdsMatchingTags($tags = array())
477 {
478 if (!$this->_extendedBackend) {
479 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
480 }
481 if (!($this->_backendCapabilities['tags'])) {
482 Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
483 }
484
485 $ids = $this->_backend->getIdsMatchingTags($tags);
486
487 // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
488 if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
489 $prefix = & $this->_options['cache_id_prefix'];
490 $prefixLen = strlen($prefix);
491 foreach ($ids as &$id) {
492 if (strpos($id, $prefix) === 0) {
493 $id = substr($id, $prefixLen);
494 }
495 }
496 }
497
498 return $ids;
499 }
500
501 /**
502 * Return an array of stored cache ids which don't match given tags
503 *
504 * In case of multiple tags, a logical OR is made between tags
505 *
506 * @param array $tags array of tags
507 * @return array array of not matching cache ids (string)
508 */
509 public function getIdsNotMatchingTags($tags = array())
510 {
511 if (!$this->_extendedBackend) {
512 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
513 }
514 if (!($this->_backendCapabilities['tags'])) {
515 Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
516 }
517
518 $ids = $this->_backend->getIdsNotMatchingTags($tags);
519
520 // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
521 if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
522 $prefix = & $this->_options['cache_id_prefix'];
523 $prefixLen = strlen($prefix);
524 foreach ($ids as &$id) {
525 if (strpos($id, $prefix) === 0) {
526 $id = substr($id, $prefixLen);
527 }
528 }
529 }
530
531 return $ids;
532 }
533
534 /**
535 * Return an array of stored cache ids which match any given tags
536 *
537 * In case of multiple tags, a logical OR is made between tags
538 *
539 * @param array $tags array of tags
540 * @return array array of matching any cache ids (string)
541 */
542 public function getIdsMatchingAnyTags($tags = array())
543 {
544 if (!$this->_extendedBackend) {
545 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
546 }
547 if (!($this->_backendCapabilities['tags'])) {
548 Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
549 }
550
551 $ids = $this->_backend->getIdsMatchingAnyTags($tags);
552
553 // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
554 if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
555 $prefix = & $this->_options['cache_id_prefix'];
556 $prefixLen = strlen($prefix);
557 foreach ($ids as &$id) {
558 if (strpos($id, $prefix) === 0) {
559 $id = substr($id, $prefixLen);
560 }
561 }
562 }
563
564 return $ids;
565 }
566
567 /**
568 * Return an array of stored cache ids
569 *
570 * @return array array of stored cache ids (string)
571 */
572 public function getIds()
573 {
574 if (!$this->_extendedBackend) {
575 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
576 }
577
578 $ids = $this->_backend->getIds();
579
580 // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
581 if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
582 $prefix = & $this->_options['cache_id_prefix'];
583 $prefixLen = strlen($prefix);
584 foreach ($ids as &$id) {
585 if (strpos($id, $prefix) === 0) {
586 $id = substr($id, $prefixLen);
587 }
588 }
589 }
590
591 return $ids;
592 }
593
594 /**
595 * Return an array of stored tags
596 *
597 * @return array array of stored tags (string)
598 */
599 public function getTags()
600 {
601 if (!$this->_extendedBackend) {
602 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
603 }
604 if (!($this->_backendCapabilities['tags'])) {
605 Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
606 }
607 return $this->_backend->getTags();
608 }
609
610 /**
611 * Return the filling percentage of the backend storage
612 *
613 * @return int integer between 0 and 100
614 */
615 public function getFillingPercentage()
616 {
617 if (!$this->_extendedBackend) {
618 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
619 }
620 return $this->_backend->getFillingPercentage();
621 }
622
623 /**
624 * Return an array of metadatas for the given cache id
625 *
626 * The array will include these keys :
627 * - expire : the expire timestamp
628 * - tags : a string array of tags
629 * - mtime : timestamp of last modification time
630 *
631 * @param string $id cache id
632 * @return array array of metadatas (false if the cache id is not found)
633 */
634 public function getMetadatas($id)
635 {
636 if (!$this->_extendedBackend) {
637 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
638 }
639 $id = $this->_id($id); // cache id may need prefix
640 return $this->_backend->getMetadatas($id);
641 }
642
643 /**
644 * Give (if possible) an extra lifetime to the given cache id
645 *
646 * @param string $id cache id
647 * @param int $extraLifetime
648 * @return boolean true if ok
649 */
650 public function touch($id, $extraLifetime)
651 {
652 if (!$this->_extendedBackend) {
653 Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
654 }
655 $id = $this->_id($id); // cache id may need prefix
656
657 $this->_log("Zend_Cache_Core: touch item '{$id}'", 7);
658 return $this->_backend->touch($id, $extraLifetime);
659 }
660
661 /**
662 * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)
663 *
664 * Throw an exception if a problem is found
665 *
666 * @param string $string Cache id or tag
667 * @throws Zend_Cache_Exception
668 * @return void
669 */
670 protected static function _validateIdOrTag($string)
671 {
672 if (!is_string($string)) {
673 Zend_Cache::throwException('Invalid id or tag : must be a string');
674 }
675 if (substr($string, 0, 9) == 'internal-') {
676 Zend_Cache::throwException('"internal-*" ids or tags are reserved');
677 }
678 if (!preg_match('~^[a-zA-Z0-9_]+$~D', $string)) {
679 Zend_Cache::throwException("Invalid id or tag '$string' : must use only [a-zA-Z0-9_]");
680 }
681 }
682
683 /**
684 * Validate a tags array (security, reliable filenames, reserved prefixes...)
685 *
686 * Throw an exception if a problem is found
687 *
688 * @param array $tags Array of tags
689 * @throws Zend_Cache_Exception
690 * @return void
691 */
692 protected static function _validateTagsArray($tags)
693 {
694 if (!is_array($tags)) {
695 Zend_Cache::throwException('Invalid tags array : must be an array');
696 }
697 foreach($tags as $tag) {
698 self::_validateIdOrTag($tag);
699 }
700 reset($tags);
701 }
702
703 /**
704 * Make sure if we enable logging that the Zend_Log class
705 * is available.
706 * Create a default log object if none is set.
707 *
708 * @throws Zend_Cache_Exception
709 * @return void
710 */
711 protected function _loggerSanity()
712 {
713 if (!isset($this->_options['logging']) || !$this->_options['logging']) {
714 return;
715 }
716
717 if (isset($this->_options['logger']) && $this->_options['logger'] instanceof Zend_Log) {
718 return;
719 }
720
721 // Create a default logger to the standard output stream
722 require_once 'Zend/Log.php';
723 require_once 'Zend/Log/Writer/Stream.php';
724 require_once 'Zend/Log/Filter/Priority.php';
725 $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
726 $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
727 $this->_options['logger'] = $logger;
728 }
729
730 /**
731 * Log a message at the WARN (4) priority.
732 *
733 * @param string $message
734 * @throws Zend_Cache_Exception
735 * @return void
736 */
737 protected function _log($message, $priority = 4)
738 {
739 if (!$this->_options['logging']) {
740 return;
741 }
742 if (!(isset($this->_options['logger']) || $this->_options['logger'] instanceof Zend_Log)) {
743 Zend_Cache::throwException('Logging is enabled but logger is not set');
744 }
745 $logger = $this->_options['logger'];
746 $logger->log($message, $priority);
747 }
748
749 /**
750 * Make and return a cache id
751 *
752 * Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null
753 *
754 * @param string $id Cache id
755 * @return string Cache id (with or without prefix)
756 */
757 protected function _id($id)
758 {
759 if (($id !== null) && isset($this->_options['cache_id_prefix'])) {
760 return $this->_options['cache_id_prefix'] . $id; // return with prefix
761 }
762 return $id; // no prefix, just return the $id passed
763 }
764
765}
diff --git a/inc/3rdparty/libraries/Zend/Cache/Exception.php b/inc/3rdparty/libraries/Zend/Cache/Exception.php
new file mode 100644
index 00000000..44884515
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Cache/Exception.php
@@ -0,0 +1,32 @@
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-2012 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
19 * @version $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $
20 */
21
22/**
23 * @see Zend_Exception
24 */
25require_once 'Zend/Exception.php';
26
27/**
28 * @package Zend_Cache
29 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
30 * @license http://framework.zend.com/license/new-bsd New BSD License
31 */
32class Zend_Cache_Exception extends Zend_Exception {}
diff --git a/inc/3rdparty/libraries/Zend/Exception.php b/inc/3rdparty/libraries/Zend/Exception.php
new file mode 100644
index 00000000..92b2e460
--- /dev/null
+++ b/inc/3rdparty/libraries/Zend/Exception.php
@@ -0,0 +1,96 @@
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
17 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
19 * @version $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $
20 */
21
22/**
23* @category Zend
24* @package Zend
25* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
26* @license http://framework.zend.com/license/new-bsd New BSD License
27*/
28class Zend_Exception extends Exception
29{
30 /**
31 * @var null|Exception
32 */
33 private $_previous = null;
34
35 /**
36 * Construct the exception
37 *
38 * @param string $msg
39 * @param int $code
40 * @param Exception $previous
41 * @return void
42 */
43 public function __construct($msg = '', $code = 0, Exception $previous = null)
44 {
45 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
46 parent::__construct($msg, (int) $code);
47 $this->_previous = $previous;
48 } else {
49 parent::__construct($msg, (int) $code, $previous);
50 }
51 }
52
53 /**
54 * Overloading
55 *
56 * For PHP < 5.3.0, provides access to the getPrevious() method.
57 *
58 * @param string $method
59 * @param array $args
60 * @return mixed
61 */
62 public function __call($method, array $args)
63 {
64 if ('getprevious' == strtolower($method)) {
65 return $this->_getPrevious();
66 }
67 return null;
68 }
69
70 /**
71 * String representation of the exception
72 *
73 * @return string
74 */
75 public function __toString()
76 {
77 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
78 if (null !== ($e = $this->getPrevious())) {
79 return $e->__toString()
80 . "\n\nNext "
81 . parent::__toString();
82 }
83 }
84 return parent::__toString();
85 }
86
87 /**
88 * Returns previous Exception
89 *
90 * @return Exception|null
91 */
92 protected function _getPrevious()
93 {
94 return $this->_previous;
95 }
96}