fix calendar css, take 2. (#213)
[openemr.git] / interface / modules / zend_modules / library / Zend / Cache / Storage / Adapter / XCache.php
blob57ac50fc5ab3cd227c9c3bc05c5776daa7df243b
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Cache\Storage\Adapter;
12 use stdClass;
13 use Traversable;
14 use Zend\Cache\Exception;
15 use Zend\Cache\Storage\AvailableSpaceCapableInterface;
16 use Zend\Cache\Storage\Capabilities;
17 use Zend\Cache\Storage\ClearByNamespaceInterface;
18 use Zend\Cache\Storage\ClearByPrefixInterface;
19 use Zend\Cache\Storage\FlushableInterface;
20 use Zend\Cache\Storage\IterableInterface;
21 use Zend\Cache\Storage\TotalSpaceCapableInterface;
23 class XCache extends AbstractAdapter implements
24 AvailableSpaceCapableInterface,
25 ClearByNamespaceInterface,
26 ClearByPrefixInterface,
27 FlushableInterface,
28 IterableInterface,
29 TotalSpaceCapableInterface
31 /**
32 * Backup HTTP authentication properties of $_SERVER array
34 * @var array
36 protected $backupAuth = array();
38 /**
39 * Total space in bytes
41 * @var int|float
43 protected $totalSpace;
45 /**
46 * Constructor
48 * @param null|array|Traversable|XCacheOptions $options
49 * @throws Exception\ExceptionInterface
51 public function __construct($options = null)
53 if (!extension_loaded('xcache')) {
54 throw new Exception\ExtensionNotLoadedException('Missing ext/xcache');
57 if (PHP_SAPI == 'cli') {
58 throw new Exception\ExtensionNotLoadedException(
59 "ext/xcache isn't available on SAPI 'cli'"
63 if (ini_get('xcache.var_size') <= 0) {
64 throw new Exception\ExtensionNotLoadedException(
65 "ext/xcache is disabled - see 'xcache.var_size'"
69 parent::__construct($options);
72 /* options */
74 /**
75 * Set options.
77 * @param array|Traversable|XCacheOptions $options
78 * @return XCache
79 * @see getOptions()
81 public function setOptions($options)
83 if (!$options instanceof XCacheOptions) {
84 $options = new XCacheOptions($options);
87 return parent::setOptions($options);
90 /**
91 * Get options.
93 * @return XCacheOptions
94 * @see setOptions()
96 public function getOptions()
98 if (!$this->options) {
99 $this->setOptions(new XCacheOptions());
101 return $this->options;
104 /* TotalSpaceCapableInterface */
107 * Get total space in bytes
109 * @return int|float
111 public function getTotalSpace()
113 if ($this->totalSpace === null) {
114 $this->totalSpace = 0;
116 $this->initAdminAuth();
117 $cnt = xcache_count(XC_TYPE_VAR);
118 for ($i=0; $i < $cnt; $i++) {
119 $info = xcache_info(XC_TYPE_VAR, $i);
120 $this->totalSpace+= $info['size'];
122 $this->resetAdminAuth();
125 return $this->totalSpace;
128 /* AvailableSpaceCapableInterface */
131 * Get available space in bytes
133 * @return int|float
135 public function getAvailableSpace()
137 $availableSpace = 0;
139 $this->initAdminAuth();
140 $cnt = xcache_count(XC_TYPE_VAR);
141 for ($i = 0; $i < $cnt; $i++) {
142 $info = xcache_info(XC_TYPE_VAR, $i);
143 $availableSpace+= $info['avail'];
145 $this->resetAdminAuth();
147 return $availableSpace;
150 /* ClearByNamespaceInterface */
153 * Remove items by given namespace
155 * @param string $namespace
156 * @return bool
158 public function clearByNamespace($namespace)
160 $namespace = (string) $namespace;
161 if ($namespace === '') {
162 throw new Exception\InvalidArgumentException('No namespace given');
165 $options = $this->getOptions();
166 $prefix = $namespace . $options->getNamespaceSeparator();
168 xcache_unset_by_prefix($prefix);
169 return true;
172 /* ClearByPrefixInterface */
175 * Remove items matching given prefix
177 * @param string $prefix
178 * @return bool
180 public function clearByPrefix($prefix)
182 $prefix = (string) $prefix;
183 if ($prefix === '') {
184 throw new Exception\InvalidArgumentException('No prefix given');
187 $options = $this->getOptions();
188 $namespace = $options->getNamespace();
189 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator() . $prefix;
191 xcache_unset_by_prefix($prefix);
192 return true;
195 /* FlushableInterface */
198 * Flush the whole storage
200 * @return bool
202 public function flush()
204 $this->initAdminAuth();
205 $cnt = xcache_count(XC_TYPE_VAR);
206 for ($i = 0; $i < $cnt; $i++) {
207 xcache_clear_cache(XC_TYPE_VAR, $i);
209 $this->resetAdminAuth();
211 return true;
214 /* IterableInterface */
217 * Get the storage iterator
219 * @return KeyListIterator
221 public function getIterator()
223 $options = $this->getOptions();
224 $namespace = $options->getNamespace();
225 $keys = array();
227 $this->initAdminAuth();
229 if ($namespace === '') {
230 $cnt = xcache_count(XC_TYPE_VAR);
231 for ($i=0; $i < $cnt; $i++) {
232 $list = xcache_list(XC_TYPE_VAR, $i);
233 foreach ($list['cache_list'] as & $item) {
234 $keys[] = $item['name'];
237 } else {
238 $prefix = $namespace . $options->getNamespaceSeparator();
239 $prefixL = strlen($prefix);
241 $cnt = xcache_count(XC_TYPE_VAR);
242 for ($i=0; $i < $cnt; $i++) {
243 $list = xcache_list(XC_TYPE_VAR, $i);
244 foreach ($list['cache_list'] as & $item) {
245 $keys[] = substr($item['name'], $prefixL);
250 $this->resetAdminAuth();
252 return new KeyListIterator($this, $keys);
255 /* reading */
258 * Internal method to get an item.
260 * @param string $normalizedKey
261 * @param bool $success
262 * @param mixed $casToken
263 * @return mixed Data on success, null on failure
264 * @throws Exception\ExceptionInterface
266 protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
268 $options = $this->getOptions();
269 $namespace = $options->getNamespace();
270 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
271 $internalKey = $prefix . $normalizedKey;
273 $result = xcache_get($internalKey);
274 $success = ($result !== null);
276 if ($success) {
277 $casToken = $result;
280 return $result;
284 * Internal method to test if an item exists.
286 * @param string $normalizedKey
287 * @return bool
288 * @throws Exception\ExceptionInterface
290 protected function internalHasItem(& $normalizedKey)
292 $options = $this->getOptions();
293 $namespace = $options->getNamespace();
294 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
295 return xcache_isset($prefix . $normalizedKey);
299 * Get metadata of an item.
301 * @param string $normalizedKey
302 * @return array|bool Metadata on success, false on failure
303 * @throws Exception\ExceptionInterface
305 protected function internalGetMetadata(& $normalizedKey)
307 $options = $this->getOptions();
308 $namespace = $options->getNamespace();
309 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
310 $internalKey = $prefix . $normalizedKey;
312 if (xcache_isset($internalKey)) {
313 $this->initAdminAuth();
314 $cnt = xcache_count(XC_TYPE_VAR);
315 for ($i=0; $i < $cnt; $i++) {
316 $list = xcache_list(XC_TYPE_VAR, $i);
317 foreach ($list['cache_list'] as & $metadata) {
318 if ($metadata['name'] === $internalKey) {
319 $this->normalizeMetadata($metadata);
320 return $metadata;
324 $this->resetAdminAuth();
327 return false;
330 /* writing */
333 * Internal method to store an item.
335 * @param string $normalizedKey
336 * @param mixed $value
337 * @return bool
338 * @throws Exception\ExceptionInterface
340 protected function internalSetItem(& $normalizedKey, & $value)
342 $options = $this->getOptions();
343 $namespace = $options->getNamespace();
344 $prefix = ($options === '') ? '' : $namespace . $options->getNamespaceSeparator();
345 $internalKey = $prefix . $normalizedKey;
346 $ttl = $options->getTtl();
348 if (!xcache_set($internalKey, $value, $ttl)) {
349 $type = is_object($value) ? get_class($value) : gettype($value);
350 throw new Exception\RuntimeException(
351 "xcache_set('{$internalKey}', <{$type}>, {$ttl}) failed"
355 return true;
359 * Internal method to remove an item.
361 * @param string $normalizedKey
362 * @return bool
363 * @throws Exception\ExceptionInterface
365 protected function internalRemoveItem(& $normalizedKey)
367 $options = $this->getOptions();
368 $namespace = $options->getNamespace();
369 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
370 $internalKey = $prefix . $normalizedKey;
372 return xcache_unset($internalKey);
376 * Internal method to increment an item.
378 * @param string $normalizedKey
379 * @param int $value
380 * @return int|bool The new value on success, false on failure
381 * @throws Exception\ExceptionInterface
383 protected function internalIncrementItem(& $normalizedKey, & $value)
385 $options = $this->getOptions();
386 $namespace = $options->getNamespace();
387 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
388 $internalKey = $prefix . $normalizedKey;
389 $ttl = $options->getTtl();
390 $value = (int) $value;
392 return xcache_inc($internalKey, $value, $ttl);
396 * Internal method to decrement an item.
398 * @param string $normalizedKey
399 * @param int $value
400 * @return int|bool The new value on success, false on failure
401 * @throws Exception\ExceptionInterface
403 protected function internalDecrementItem(& $normalizedKey, & $value)
405 $options = $this->getOptions();
406 $namespace = $options->getNamespace();
407 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
408 $internalKey = $prefix . $normalizedKey;
409 $ttl = $options->getTtl();
410 $value = (int) $value;
412 return xcache_dec($internalKey, $value, $ttl);
415 /* status */
418 * Internal method to get capabilities of this adapter
420 * @return Capabilities
422 protected function internalGetCapabilities()
424 if ($this->capabilities === null) {
425 $marker = new stdClass();
426 $capabilities = new Capabilities(
427 $this,
428 $marker,
429 array(
430 'supportedDatatypes' => array(
431 'NULL' => false,
432 'boolean' => true,
433 'integer' => true,
434 'double' => true,
435 'string' => true,
436 'array' => true,
437 'object' => 'object',
438 'resource' => false,
440 'supportedMetadata' => array(
441 'internal_key',
442 'size', 'refcount', 'hits',
443 'ctime', 'atime', 'hvalue',
445 'minTtl' => 1,
446 'maxTtl' => (int)ini_get('xcache.var_maxttl'),
447 'staticTtl' => true,
448 'ttlPrecision' => 1,
449 'useRequestTime' => true,
450 'expiredRead' => false,
451 'maxKeyLength' => 5182,
452 'namespaceIsPrefix' => true,
453 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
457 // update namespace separator on change option
458 $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
459 $params = $event->getParams();
461 if (isset($params['namespace_separator'])) {
462 $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
466 $this->capabilities = $capabilities;
467 $this->capabilityMarker = $marker;
470 return $this->capabilities;
473 /* internal */
476 * Init authentication before calling admin functions
478 * @return void
480 protected function initAdminAuth()
482 $options = $this->getOptions();
484 if ($options->getAdminAuth()) {
485 $adminUser = $options->getAdminUser();
486 $adminPass = $options->getAdminPass();
488 // backup HTTP authentication properties
489 if (isset($_SERVER['PHP_AUTH_USER'])) {
490 $this->backupAuth['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER'];
492 if (isset($_SERVER['PHP_AUTH_PW'])) {
493 $this->backupAuth['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'];
496 // set authentication
497 $_SERVER['PHP_AUTH_USER'] = $adminUser;
498 $_SERVER['PHP_AUTH_PW'] = $adminPass;
503 * Reset authentication after calling admin functions
505 * @return void
507 protected function resetAdminAuth()
509 unset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
510 $_SERVER = $this->backupAuth + $_SERVER;
511 $this->backupAuth = array();
515 * Normalize metadata to work with XCache
517 * @param array $metadata
519 protected function normalizeMetadata(array & $metadata)
521 $metadata['internal_key'] = &$metadata['name'];
522 unset($metadata['name']);