Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Cache / Storage / Adapter / AbstractAdapter.php
blob3c2ea41d00dd981601c9d1eb4804bddfa558f35c
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-2013 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 ArrayObject;
13 use SplObjectStorage;
14 use stdClass;
15 use Traversable;
16 use Zend\Cache\Exception;
17 use Zend\Cache\Storage\Capabilities;
18 use Zend\Cache\Storage\Event;
19 use Zend\Cache\Storage\ExceptionEvent;
20 use Zend\Cache\Storage\Plugin;
21 use Zend\Cache\Storage\PostEvent;
22 use Zend\Cache\Storage\StorageInterface;
23 use Zend\EventManager\EventManager;
24 use Zend\EventManager\EventManagerInterface;
25 use Zend\EventManager\EventsCapableInterface;
27 abstract class AbstractAdapter implements StorageInterface, EventsCapableInterface
29 /**
30 * The used EventManager if any
32 * @var null|EventManagerInterface
34 protected $events = null;
36 /**
37 * Event handles of this adapter
38 * @var array
40 protected $eventHandles = array();
42 /**
43 * The plugin registry
45 * @var SplObjectStorage Registered plugins
47 protected $pluginRegistry;
49 /**
50 * Capabilities of this adapter
52 * @var null|Capabilities
54 protected $capabilities = null;
56 /**
57 * Marker to change capabilities
59 * @var null|object
61 protected $capabilityMarker;
63 /**
64 * options
66 * @var mixed
68 protected $options;
70 /**
71 * Constructor
73 * @param null|array|Traversable|AdapterOptions $options
74 * @throws Exception\ExceptionInterface
76 public function __construct($options = null)
78 if ($options) {
79 $this->setOptions($options);
83 /**
84 * Destructor
86 * detach all registered plugins to free
87 * event handles of event manager
89 * @return void
91 public function __destruct()
93 foreach ($this->getPluginRegistry() as $plugin) {
94 $this->removePlugin($plugin);
97 if ($this->eventHandles) {
98 $events = $this->getEventManager();
99 foreach ($this->eventHandles as $handle) {
100 $events->detach($handle);
105 /* configuration */
108 * Set options.
110 * @param array|Traversable|AdapterOptions $options
111 * @return AbstractAdapter
112 * @see getOptions()
114 public function setOptions($options)
116 if ($this->options !== $options) {
117 if (!$options instanceof AdapterOptions) {
118 $options = new AdapterOptions($options);
121 if ($this->options) {
122 $this->options->setAdapter(null);
124 $options->setAdapter($this);
125 $this->options = $options;
127 $event = new Event('option', $this, new ArrayObject($options->toArray()));
128 $this->getEventManager()->trigger($event);
130 return $this;
134 * Get options.
136 * @return AdapterOptions
137 * @see setOptions()
139 public function getOptions()
141 if (!$this->options) {
142 $this->setOptions(new AdapterOptions());
144 return $this->options;
148 * Enable/Disable caching.
150 * Alias of setWritable and setReadable.
152 * @see setWritable()
153 * @see setReadable()
154 * @param bool $flag
155 * @return AbstractAdapter
157 public function setCaching($flag)
159 $flag = (bool) $flag;
160 $options = $this->getOptions();
161 $options->setWritable($flag);
162 $options->setReadable($flag);
163 return $this;
167 * Get caching enabled.
169 * Alias of getWritable and getReadable.
171 * @see getWritable()
172 * @see getReadable()
173 * @return bool
175 public function getCaching()
177 $options = $this->getOptions();
178 return ($options->getWritable() && $options->getReadable());
181 /* Event/Plugin handling */
184 * Get the event manager
186 * @return EventManagerInterface
188 public function getEventManager()
190 if ($this->events === null) {
191 $this->events = new EventManager(array(__CLASS__, get_class($this)));
193 return $this->events;
197 * Trigger an pre event and return the event response collection
199 * @param string $eventName
200 * @param ArrayObject $args
201 * @return \Zend\EventManager\ResponseCollection All handler return values
203 protected function triggerPre($eventName, ArrayObject $args)
205 return $this->getEventManager()->trigger(new Event($eventName . '.pre', $this, $args));
209 * Triggers the PostEvent and return the result value.
211 * @param string $eventName
212 * @param ArrayObject $args
213 * @param mixed $result
214 * @return mixed
216 protected function triggerPost($eventName, ArrayObject $args, & $result)
218 $postEvent = new PostEvent($eventName . '.post', $this, $args, $result);
219 $eventRs = $this->getEventManager()->trigger($postEvent);
220 if ($eventRs->stopped()) {
221 return $eventRs->last();
224 return $postEvent->getResult();
228 * Trigger an exception event
230 * If the ExceptionEvent has the flag "throwException" enabled throw the
231 * exception after trigger else return the result.
233 * @param string $eventName
234 * @param ArrayObject $args
235 * @param mixed $result
236 * @param \Exception $exception
237 * @throws Exception\ExceptionInterface
238 * @return mixed
240 protected function triggerException($eventName, ArrayObject $args, & $result, \Exception $exception)
242 $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $exception);
243 $eventRs = $this->getEventManager()->trigger($exceptionEvent);
245 if ($exceptionEvent->getThrowException()) {
246 throw $exceptionEvent->getException();
249 if ($eventRs->stopped()) {
250 return $eventRs->last();
253 return $exceptionEvent->getResult();
257 * Check if a plugin is registered
259 * @param Plugin\PluginInterface $plugin
260 * @return bool
262 public function hasPlugin(Plugin\PluginInterface $plugin)
264 $registry = $this->getPluginRegistry();
265 return $registry->contains($plugin);
269 * Register a plugin
271 * @param Plugin\PluginInterface $plugin
272 * @param int $priority
273 * @return AbstractAdapter Fluent interface
274 * @throws Exception\LogicException
276 public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1)
278 $registry = $this->getPluginRegistry();
279 if ($registry->contains($plugin)) {
280 throw new Exception\LogicException(sprintf(
281 'Plugin of type "%s" already registered',
282 get_class($plugin)
286 $plugin->attach($this->getEventManager(), $priority);
287 $registry->attach($plugin);
289 return $this;
293 * Unregister an already registered plugin
295 * @param Plugin\PluginInterface $plugin
296 * @return AbstractAdapter Fluent interface
297 * @throws Exception\LogicException
299 public function removePlugin(Plugin\PluginInterface $plugin)
301 $registry = $this->getPluginRegistry();
302 if ($registry->contains($plugin)) {
303 $plugin->detach($this->getEventManager());
304 $registry->detach($plugin);
306 return $this;
310 * Return registry of plugins
312 * @return SplObjectStorage
314 public function getPluginRegistry()
316 if (!$this->pluginRegistry instanceof SplObjectStorage) {
317 $this->pluginRegistry = new SplObjectStorage();
319 return $this->pluginRegistry;
322 /* reading */
325 * Get an item.
327 * @param string $key
328 * @param bool $success
329 * @param mixed $casToken
330 * @return mixed Data on success, null on failure
331 * @throws Exception\ExceptionInterface
333 * @triggers getItem.pre(PreEvent)
334 * @triggers getItem.post(PostEvent)
335 * @triggers getItem.exception(ExceptionEvent)
337 public function getItem($key, & $success = null, & $casToken = null)
339 if (!$this->getOptions()->getReadable()) {
340 $success = false;
341 return null;
344 $this->normalizeKey($key);
346 $argn = func_num_args();
347 $args = array(
348 'key' => & $key,
350 if ($argn > 1) {
351 $args['success'] = & $success;
353 if ($argn > 2) {
354 $args['casToken'] = & $casToken;
356 $args = new ArrayObject($args);
358 try {
359 $eventRs = $this->triggerPre(__FUNCTION__, $args);
360 if ($eventRs->stopped()) {
361 return $eventRs->last();
364 if ($args->offsetExists('success') && $args->offsetExists('casToken')) {
365 $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']);
366 } elseif ($args->offsetExists('success')) {
367 $result = $this->internalGetItem($args['key'], $args['success']);
368 } else {
369 $result = $this->internalGetItem($args['key']);
371 return $this->triggerPost(__FUNCTION__, $args, $result);
372 } catch (\Exception $e) {
373 $result = false;
374 return $this->triggerException(__FUNCTION__, $args, $result, $e);
379 * Internal method to get an item.
381 * @param string $normalizedKey
382 * @param bool $success
383 * @param mixed $casToken
384 * @return mixed Data on success, null on failure
385 * @throws Exception\ExceptionInterface
387 abstract protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null);
390 * Get multiple items.
392 * @param array $keys
393 * @return array Associative array of keys and values
394 * @throws Exception\ExceptionInterface
396 * @triggers getItems.pre(PreEvent)
397 * @triggers getItems.post(PostEvent)
398 * @triggers getItems.exception(ExceptionEvent)
400 public function getItems(array $keys)
402 if (!$this->getOptions()->getReadable()) {
403 return array();
406 $this->normalizeKeys($keys);
407 $args = new ArrayObject(array(
408 'keys' => & $keys,
411 try {
412 $eventRs = $this->triggerPre(__FUNCTION__, $args);
413 if ($eventRs->stopped()) {
414 return $eventRs->last();
417 $result = $this->internalGetItems($args['keys']);
418 return $this->triggerPost(__FUNCTION__, $args, $result);
419 } catch (\Exception $e) {
420 $result = array();
421 return $this->triggerException(__FUNCTION__, $args, $result, $e);
426 * Internal method to get multiple items.
428 * @param array $normalizedKeys
429 * @return array Associative array of keys and values
430 * @throws Exception\ExceptionInterface
432 protected function internalGetItems(array & $normalizedKeys)
434 $success = null;
435 $result = array();
436 foreach ($normalizedKeys as $normalizedKey) {
437 $value = $this->internalGetItem($normalizedKey, $success);
438 if ($success) {
439 $result[$normalizedKey] = $value;
443 return $result;
447 * Test if an item exists.
449 * @param string $key
450 * @return bool
451 * @throws Exception\ExceptionInterface
453 * @triggers hasItem.pre(PreEvent)
454 * @triggers hasItem.post(PostEvent)
455 * @triggers hasItem.exception(ExceptionEvent)
457 public function hasItem($key)
459 if (!$this->getOptions()->getReadable()) {
460 return false;
463 $this->normalizeKey($key);
464 $args = new ArrayObject(array(
465 'key' => & $key,
468 try {
469 $eventRs = $this->triggerPre(__FUNCTION__, $args);
470 if ($eventRs->stopped()) {
471 return $eventRs->last();
474 $result = $this->internalHasItem($args['key']);
475 return $this->triggerPost(__FUNCTION__, $args, $result);
476 } catch (\Exception $e) {
477 $result = false;
478 return $this->triggerException(__FUNCTION__, $args, $result, $e);
483 * Internal method to test if an item exists.
485 * @param string $normalizedKey
486 * @return bool
487 * @throws Exception\ExceptionInterface
489 protected function internalHasItem(& $normalizedKey)
491 $success = null;
492 $this->internalGetItem($normalizedKey, $success);
493 return $success;
497 * Test multiple items.
499 * @param array $keys
500 * @return array Array of found keys
501 * @throws Exception\ExceptionInterface
503 * @triggers hasItems.pre(PreEvent)
504 * @triggers hasItems.post(PostEvent)
505 * @triggers hasItems.exception(ExceptionEvent)
507 public function hasItems(array $keys)
509 if (!$this->getOptions()->getReadable()) {
510 return array();
513 $this->normalizeKeys($keys);
514 $args = new ArrayObject(array(
515 'keys' => & $keys,
518 try {
519 $eventRs = $this->triggerPre(__FUNCTION__, $args);
520 if ($eventRs->stopped()) {
521 return $eventRs->last();
524 $result = $this->internalHasItems($args['keys']);
525 return $this->triggerPost(__FUNCTION__, $args, $result);
526 } catch (\Exception $e) {
527 $result = array();
528 return $this->triggerException(__FUNCTION__, $args, $result, $e);
533 * Internal method to test multiple items.
535 * @param array $normalizedKeys
536 * @return array Array of found keys
537 * @throws Exception\ExceptionInterface
539 protected function internalHasItems(array & $normalizedKeys)
541 $result = array();
542 foreach ($normalizedKeys as $normalizedKey) {
543 if ($this->internalHasItem($normalizedKey)) {
544 $result[] = $normalizedKey;
547 return $result;
551 * Get metadata of an item.
553 * @param string $key
554 * @return array|bool Metadata on success, false on failure
555 * @throws Exception\ExceptionInterface
557 * @triggers getMetadata.pre(PreEvent)
558 * @triggers getMetadata.post(PostEvent)
559 * @triggers getMetadata.exception(ExceptionEvent)
561 public function getMetadata($key)
563 if (!$this->getOptions()->getReadable()) {
564 return false;
567 $this->normalizeKey($key);
568 $args = new ArrayObject(array(
569 'key' => & $key,
572 try {
573 $eventRs = $this->triggerPre(__FUNCTION__, $args);
574 if ($eventRs->stopped()) {
575 return $eventRs->last();
578 $result = $this->internalGetMetadata($args['key']);
579 return $this->triggerPost(__FUNCTION__, $args, $result);
580 } catch (\Exception $e) {
581 $result = false;
582 return $this->triggerException(__FUNCTION__, $args, $result, $e);
587 * Internal method to get metadata of an item.
589 * @param string $normalizedKey
590 * @return array|bool Metadata on success, false on failure
591 * @throws Exception\ExceptionInterface
593 protected function internalGetMetadata(& $normalizedKey)
595 if (!$this->internalHasItem($normalizedKey)) {
596 return false;
599 return array();
603 * Get multiple metadata
605 * @param array $keys
606 * @return array Associative array of keys and metadata
607 * @throws Exception\ExceptionInterface
609 * @triggers getMetadatas.pre(PreEvent)
610 * @triggers getMetadatas.post(PostEvent)
611 * @triggers getMetadatas.exception(ExceptionEvent)
613 public function getMetadatas(array $keys)
615 if (!$this->getOptions()->getReadable()) {
616 return array();
619 $this->normalizeKeys($keys);
620 $args = new ArrayObject(array(
621 'keys' => & $keys,
624 try {
625 $eventRs = $this->triggerPre(__FUNCTION__, $args);
626 if ($eventRs->stopped()) {
627 return $eventRs->last();
630 $result = $this->internalGetMetadatas($args['keys']);
631 return $this->triggerPost(__FUNCTION__, $args, $result);
632 } catch (\Exception $e) {
633 $result = array();
634 return $this->triggerException(__FUNCTION__, $args, $result, $e);
639 * Internal method to get multiple metadata
641 * @param array $normalizedKeys
642 * @return array Associative array of keys and metadata
643 * @throws Exception\ExceptionInterface
645 protected function internalGetMetadatas(array & $normalizedKeys)
647 $result = array();
648 foreach ($normalizedKeys as $normalizedKey) {
649 $metadata = $this->internalGetMetadata($normalizedKey);
650 if ($metadata !== false) {
651 $result[$normalizedKey] = $metadata;
654 return $result;
657 /* writing */
660 * Store an item.
662 * @param string $key
663 * @param mixed $value
664 * @return bool
665 * @throws Exception\ExceptionInterface
667 * @triggers setItem.pre(PreEvent)
668 * @triggers setItem.post(PostEvent)
669 * @triggers setItem.exception(ExceptionEvent)
671 public function setItem($key, $value)
673 if (!$this->getOptions()->getWritable()) {
674 return false;
677 $this->normalizeKey($key);
678 $args = new ArrayObject(array(
679 'key' => & $key,
680 'value' => & $value,
683 try {
684 $eventRs = $this->triggerPre(__FUNCTION__, $args);
685 if ($eventRs->stopped()) {
686 return $eventRs->last();
689 $result = $this->internalSetItem($args['key'], $args['value']);
690 return $this->triggerPost(__FUNCTION__, $args, $result);
691 } catch (\Exception $e) {
692 $result = false;
693 return $this->triggerException(__FUNCTION__, $args, $result, $e);
698 * Internal method to store an item.
700 * @param string $normalizedKey
701 * @param mixed $value
702 * @return bool
703 * @throws Exception\ExceptionInterface
705 abstract protected function internalSetItem(& $normalizedKey, & $value);
708 * Store multiple items.
710 * @param array $keyValuePairs
711 * @return array Array of not stored keys
712 * @throws Exception\ExceptionInterface
714 * @triggers setItems.pre(PreEvent)
715 * @triggers setItems.post(PostEvent)
716 * @triggers setItems.exception(ExceptionEvent)
718 public function setItems(array $keyValuePairs)
720 if (!$this->getOptions()->getWritable()) {
721 return array_keys($keyValuePairs);
724 $this->normalizeKeyValuePairs($keyValuePairs);
725 $args = new ArrayObject(array(
726 'keyValuePairs' => & $keyValuePairs,
729 try {
730 $eventRs = $this->triggerPre(__FUNCTION__, $args);
731 if ($eventRs->stopped()) {
732 return $eventRs->last();
735 $result = $this->internalSetItems($args['keyValuePairs']);
736 return $this->triggerPost(__FUNCTION__, $args, $result);
737 } catch (\Exception $e) {
738 $result = array_keys($keyValuePairs);
739 return $this->triggerException(__FUNCTION__, $args, $result, $e);
744 * Internal method to store multiple items.
746 * @param array $normalizedKeyValuePairs
747 * @return array Array of not stored keys
748 * @throws Exception\ExceptionInterface
750 protected function internalSetItems(array & $normalizedKeyValuePairs)
752 $failedKeys = array();
753 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
754 if (!$this->internalSetItem($normalizedKey, $value)) {
755 $failedKeys[] = $normalizedKey;
758 return $failedKeys;
762 * Add an item.
764 * @param string $key
765 * @param mixed $value
766 * @return bool
767 * @throws Exception\ExceptionInterface
769 * @triggers addItem.pre(PreEvent)
770 * @triggers addItem.post(PostEvent)
771 * @triggers addItem.exception(ExceptionEvent)
773 public function addItem($key, $value)
775 if (!$this->getOptions()->getWritable()) {
776 return false;
779 $this->normalizeKey($key);
780 $args = new ArrayObject(array(
781 'key' => & $key,
782 'value' => & $value,
785 try {
786 $eventRs = $this->triggerPre(__FUNCTION__, $args);
787 if ($eventRs->stopped()) {
788 return $eventRs->last();
791 $result = $this->internalAddItem($args['key'], $args['value']);
792 return $this->triggerPost(__FUNCTION__, $args, $result);
793 } catch (\Exception $e) {
794 $result = false;
795 return $this->triggerException(__FUNCTION__, $args, $result, $e);
800 * Internal method to add an item.
802 * @param string $normalizedKey
803 * @param mixed $value
804 * @return bool
805 * @throws Exception\ExceptionInterface
807 protected function internalAddItem(& $normalizedKey, & $value)
809 if ($this->internalHasItem($normalizedKey)) {
810 return false;
812 return $this->internalSetItem($normalizedKey, $value);
816 * Add multiple items.
818 * @param array $keyValuePairs
819 * @return array Array of not stored keys
820 * @throws Exception\ExceptionInterface
822 * @triggers addItems.pre(PreEvent)
823 * @triggers addItems.post(PostEvent)
824 * @triggers addItems.exception(ExceptionEvent)
826 public function addItems(array $keyValuePairs)
828 if (!$this->getOptions()->getWritable()) {
829 return array_keys($keyValuePairs);
832 $this->normalizeKeyValuePairs($keyValuePairs);
833 $args = new ArrayObject(array(
834 'keyValuePairs' => & $keyValuePairs,
837 try {
838 $eventRs = $this->triggerPre(__FUNCTION__, $args);
839 if ($eventRs->stopped()) {
840 return $eventRs->last();
843 $result = $this->internalAddItems($args['keyValuePairs']);
844 return $this->triggerPost(__FUNCTION__, $args, $result);
845 } catch (\Exception $e) {
846 $result = array_keys($keyValuePairs);
847 return $this->triggerException(__FUNCTION__, $args, $result, $e);
852 * Internal method to add multiple items.
854 * @param array $normalizedKeyValuePairs
855 * @return array Array of not stored keys
856 * @throws Exception\ExceptionInterface
858 protected function internalAddItems(array & $normalizedKeyValuePairs)
860 $result = array();
861 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
862 if (!$this->internalAddItem($normalizedKey, $value)) {
863 $result[] = $normalizedKey;
866 return $result;
870 * Replace an existing item.
872 * @param string $key
873 * @param mixed $value
874 * @return bool
875 * @throws Exception\ExceptionInterface
877 * @triggers replaceItem.pre(PreEvent)
878 * @triggers replaceItem.post(PostEvent)
879 * @triggers replaceItem.exception(ExceptionEvent)
881 public function replaceItem($key, $value)
883 if (!$this->getOptions()->getWritable()) {
884 return false;
887 $this->normalizeKey($key);
888 $args = new ArrayObject(array(
889 'key' => & $key,
890 'value' => & $value,
893 try {
894 $eventRs = $this->triggerPre(__FUNCTION__, $args);
895 if ($eventRs->stopped()) {
896 return $eventRs->last();
899 $result = $this->internalReplaceItem($args['key'], $args['value']);
900 return $this->triggerPost(__FUNCTION__, $args, $result);
901 } catch (\Exception $e) {
902 $result = false;
903 return $this->triggerException(__FUNCTION__, $args, $result, $e);
908 * Internal method to replace an existing item.
910 * @param string $normalizedKey
911 * @param mixed $value
912 * @return bool
913 * @throws Exception\ExceptionInterface
915 protected function internalReplaceItem(& $normalizedKey, & $value)
917 if (!$this->internalhasItem($normalizedKey)) {
918 return false;
921 return $this->internalSetItem($normalizedKey, $value);
925 * Replace multiple existing items.
927 * @param array $keyValuePairs
928 * @return array Array of not stored keys
929 * @throws Exception\ExceptionInterface
931 * @triggers replaceItems.pre(PreEvent)
932 * @triggers replaceItems.post(PostEvent)
933 * @triggers replaceItems.exception(ExceptionEvent)
935 public function replaceItems(array $keyValuePairs)
937 if (!$this->getOptions()->getWritable()) {
938 return array_keys($keyValuePairs);
941 $this->normalizeKeyValuePairs($keyValuePairs);
942 $args = new ArrayObject(array(
943 'keyValuePairs' => & $keyValuePairs,
946 try {
947 $eventRs = $this->triggerPre(__FUNCTION__, $args);
948 if ($eventRs->stopped()) {
949 return $eventRs->last();
952 $result = $this->internalReplaceItems($args['keyValuePairs']);
953 return $this->triggerPost(__FUNCTION__, $args, $result);
954 } catch (\Exception $e) {
955 $result = array_keys($keyValuePairs);
956 return $this->triggerException(__FUNCTION__, $args, $result, $e);
961 * Internal method to replace multiple existing items.
963 * @param array $normalizedKeyValuePairs
964 * @return array Array of not stored keys
965 * @throws Exception\ExceptionInterface
967 protected function internalReplaceItems(array & $normalizedKeyValuePairs)
969 $result = array();
970 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
971 if (!$this->internalReplaceItem($normalizedKey, $value)) {
972 $result[] = $normalizedKey;
975 return $result;
979 * Set an item only if token matches
981 * It uses the token received from getItem() to check if the item has
982 * changed before overwriting it.
984 * @param mixed $token
985 * @param string $key
986 * @param mixed $value
987 * @return bool
988 * @throws Exception\ExceptionInterface
989 * @see getItem()
990 * @see setItem()
992 public function checkAndSetItem($token, $key, $value)
994 if (!$this->getOptions()->getWritable()) {
995 return false;
998 $this->normalizeKey($key);
999 $args = new ArrayObject(array(
1000 'token' => & $token,
1001 'key' => & $key,
1002 'value' => & $value,
1005 try {
1006 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1007 if ($eventRs->stopped()) {
1008 return $eventRs->last();
1011 $result = $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']);
1012 return $this->triggerPost(__FUNCTION__, $args, $result);
1013 } catch (\Exception $e) {
1014 $result = false;
1015 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1020 * Internal method to set an item only if token matches
1022 * @param mixed $token
1023 * @param string $normalizedKey
1024 * @param mixed $value
1025 * @return bool
1026 * @throws Exception\ExceptionInterface
1027 * @see getItem()
1028 * @see setItem()
1030 protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
1032 $oldValue = $this->internalGetItem($normalizedKey);
1033 if ($oldValue !== $token) {
1034 return false;
1037 return $this->internalSetItem($normalizedKey, $value);
1041 * Reset lifetime of an item
1043 * @param string $key
1044 * @return bool
1045 * @throws Exception\ExceptionInterface
1047 * @triggers touchItem.pre(PreEvent)
1048 * @triggers touchItem.post(PostEvent)
1049 * @triggers touchItem.exception(ExceptionEvent)
1051 public function touchItem($key)
1053 if (!$this->getOptions()->getWritable()) {
1054 return false;
1057 $this->normalizeKey($key);
1058 $args = new ArrayObject(array(
1059 'key' => & $key,
1062 try {
1063 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1064 if ($eventRs->stopped()) {
1065 return $eventRs->last();
1068 $result = $this->internalTouchItem($args['key']);
1069 return $this->triggerPost(__FUNCTION__, $args, $result);
1070 } catch (\Exception $e) {
1071 $result = false;
1072 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1077 * Internal method to reset lifetime of an item
1079 * @param string $normalizedKey
1080 * @return bool
1081 * @throws Exception\ExceptionInterface
1083 protected function internalTouchItem(& $normalizedKey)
1085 $success = null;
1086 $value = $this->internalGetItem($normalizedKey, $success);
1087 if (!$success) {
1088 return false;
1091 return $this->internalReplaceItem($normalizedKey, $value);
1095 * Reset lifetime of multiple items.
1097 * @param array $keys
1098 * @return array Array of not updated keys
1099 * @throws Exception\ExceptionInterface
1101 * @triggers touchItems.pre(PreEvent)
1102 * @triggers touchItems.post(PostEvent)
1103 * @triggers touchItems.exception(ExceptionEvent)
1105 public function touchItems(array $keys)
1107 if (!$this->getOptions()->getWritable()) {
1108 return $keys;
1111 $this->normalizeKeys($keys);
1112 $args = new ArrayObject(array(
1113 'keys' => & $keys,
1116 try {
1117 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1118 if ($eventRs->stopped()) {
1119 return $eventRs->last();
1122 $result = $this->internalTouchItems($args['keys']);
1123 return $this->triggerPost(__FUNCTION__, $args, $result);
1124 } catch (\Exception $e) {
1125 return $this->triggerException(__FUNCTION__, $args, $keys, $e);
1130 * Internal method to reset lifetime of multiple items.
1132 * @param array $normalizedKeys
1133 * @return array Array of not updated keys
1134 * @throws Exception\ExceptionInterface
1136 protected function internalTouchItems(array & $normalizedKeys)
1138 $result = array();
1139 foreach ($normalizedKeys as $normalizedKey) {
1140 if (!$this->internalTouchItem($normalizedKey)) {
1141 $result[] = $normalizedKey;
1144 return $result;
1148 * Remove an item.
1150 * @param string $key
1151 * @return bool
1152 * @throws Exception\ExceptionInterface
1154 * @triggers removeItem.pre(PreEvent)
1155 * @triggers removeItem.post(PostEvent)
1156 * @triggers removeItem.exception(ExceptionEvent)
1158 public function removeItem($key)
1160 if (!$this->getOptions()->getWritable()) {
1161 return false;
1164 $this->normalizeKey($key);
1165 $args = new ArrayObject(array(
1166 'key' => & $key,
1169 try {
1170 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1171 if ($eventRs->stopped()) {
1172 return $eventRs->last();
1175 $result = $this->internalRemoveItem($args['key']);
1176 return $this->triggerPost(__FUNCTION__, $args, $result);
1177 } catch (\Exception $e) {
1178 $result = false;
1179 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1184 * Internal method to remove an item.
1186 * @param string $normalizedKey
1187 * @return bool
1188 * @throws Exception\ExceptionInterface
1190 abstract protected function internalRemoveItem(& $normalizedKey);
1193 * Remove multiple items.
1195 * @param array $keys
1196 * @return array Array of not removed keys
1197 * @throws Exception\ExceptionInterface
1199 * @triggers removeItems.pre(PreEvent)
1200 * @triggers removeItems.post(PostEvent)
1201 * @triggers removeItems.exception(ExceptionEvent)
1203 public function removeItems(array $keys)
1205 if (!$this->getOptions()->getWritable()) {
1206 return $keys;
1209 $this->normalizeKeys($keys);
1210 $args = new ArrayObject(array(
1211 'keys' => & $keys,
1214 try {
1215 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1216 if ($eventRs->stopped()) {
1217 return $eventRs->last();
1220 $result = $this->internalRemoveItems($args['keys']);
1221 return $this->triggerPost(__FUNCTION__, $args, $result);
1222 } catch (\Exception $e) {
1223 return $this->triggerException(__FUNCTION__, $args, $keys, $e);
1228 * Internal method to remove multiple items.
1230 * @param array $normalizedKeys
1231 * @return array Array of not removed keys
1232 * @throws Exception\ExceptionInterface
1234 protected function internalRemoveItems(array & $normalizedKeys)
1236 $result = array();
1237 foreach ($normalizedKeys as $normalizedKey) {
1238 if (!$this->internalRemoveItem($normalizedKey)) {
1239 $result[] = $normalizedKey;
1242 return $result;
1246 * Increment an item.
1248 * @param string $key
1249 * @param int $value
1250 * @return int|bool The new value on success, false on failure
1251 * @throws Exception\ExceptionInterface
1253 * @triggers incrementItem.pre(PreEvent)
1254 * @triggers incrementItem.post(PostEvent)
1255 * @triggers incrementItem.exception(ExceptionEvent)
1257 public function incrementItem($key, $value)
1259 if (!$this->getOptions()->getWritable()) {
1260 return false;
1263 $this->normalizeKey($key);
1264 $args = new ArrayObject(array(
1265 'key' => & $key,
1266 'value' => & $value,
1269 try {
1270 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1271 if ($eventRs->stopped()) {
1272 return $eventRs->last();
1275 $result = $this->internalIncrementItem($args['key'], $args['value']);
1276 return $this->triggerPost(__FUNCTION__, $args, $result);
1277 } catch (\Exception $e) {
1278 $result = false;
1279 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1284 * Internal method to increment an item.
1286 * @param string $normalizedKey
1287 * @param int $value
1288 * @return int|bool The new value on success, false on failure
1289 * @throws Exception\ExceptionInterface
1291 protected function internalIncrementItem(& $normalizedKey, & $value)
1293 $success = null;
1294 $value = (int) $value;
1295 $get = (int) $this->internalGetItem($normalizedKey, $success);
1296 $newValue = $get + $value;
1298 if ($success) {
1299 $this->internalReplaceItem($normalizedKey, $newValue);
1300 } else {
1301 $this->internalAddItem($normalizedKey, $newValue);
1304 return $newValue;
1308 * Increment multiple items.
1310 * @param array $keyValuePairs
1311 * @return array Associative array of keys and new values
1312 * @throws Exception\ExceptionInterface
1314 * @triggers incrementItems.pre(PreEvent)
1315 * @triggers incrementItems.post(PostEvent)
1316 * @triggers incrementItems.exception(ExceptionEvent)
1318 public function incrementItems(array $keyValuePairs)
1320 if (!$this->getOptions()->getWritable()) {
1321 return array();
1324 $this->normalizeKeyValuePairs($keyValuePairs);
1325 $args = new ArrayObject(array(
1326 'keyValuePairs' => & $keyValuePairs,
1329 try {
1330 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1331 if ($eventRs->stopped()) {
1332 return $eventRs->last();
1335 $result = $this->internalIncrementItems($args['keyValuePairs']);
1336 return $this->triggerPost(__FUNCTION__, $args, $result);
1337 } catch (\Exception $e) {
1338 $result = array();
1339 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1344 * Internal method to increment multiple items.
1346 * @param array $normalizedKeyValuePairs
1347 * @return array Associative array of keys and new values
1348 * @throws Exception\ExceptionInterface
1350 protected function internalIncrementItems(array & $normalizedKeyValuePairs)
1352 $result = array();
1353 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
1354 $newValue = $this->internalIncrementItem($normalizedKey, $value);
1355 if ($newValue !== false) {
1356 $result[$normalizedKey] = $newValue;
1359 return $result;
1363 * Decrement an item.
1365 * @param string $key
1366 * @param int $value
1367 * @return int|bool The new value on success, false on failure
1368 * @throws Exception\ExceptionInterface
1370 * @triggers decrementItem.pre(PreEvent)
1371 * @triggers decrementItem.post(PostEvent)
1372 * @triggers decrementItem.exception(ExceptionEvent)
1374 public function decrementItem($key, $value)
1376 if (!$this->getOptions()->getWritable()) {
1377 return false;
1380 $this->normalizeKey($key);
1381 $args = new ArrayObject(array(
1382 'key' => & $key,
1383 'value' => & $value,
1386 try {
1387 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1388 if ($eventRs->stopped()) {
1389 return $eventRs->last();
1392 $result = $this->internalDecrementItem($args['key'], $args['value']);
1393 return $this->triggerPost(__FUNCTION__, $args, $result);
1394 } catch (\Exception $e) {
1395 $result = false;
1396 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1401 * Internal method to decrement an item.
1403 * @param string $normalizedKey
1404 * @param int $value
1405 * @return int|bool The new value on success, false on failure
1406 * @throws Exception\ExceptionInterface
1408 protected function internalDecrementItem(& $normalizedKey, & $value)
1410 $success = null;
1411 $value = (int) $value;
1412 $get = (int) $this->internalGetItem($normalizedKey, $success);
1413 $newValue = $get - $value;
1415 if ($success) {
1416 $this->internalReplaceItem($normalizedKey, $newValue);
1417 } else {
1418 $this->internalAddItem($normalizedKey, $newValue);
1421 return $newValue;
1425 * Decrement multiple items.
1427 * @param array $keyValuePairs
1428 * @return array Associative array of keys and new values
1429 * @throws Exception\ExceptionInterface
1431 * @triggers incrementItems.pre(PreEvent)
1432 * @triggers incrementItems.post(PostEvent)
1433 * @triggers incrementItems.exception(ExceptionEvent)
1435 public function decrementItems(array $keyValuePairs)
1437 if (!$this->getOptions()->getWritable()) {
1438 return array();
1441 $this->normalizeKeyValuePairs($keyValuePairs);
1442 $args = new ArrayObject(array(
1443 'keyValuePairs' => & $keyValuePairs,
1446 try {
1447 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1448 if ($eventRs->stopped()) {
1449 return $eventRs->last();
1452 $result = $this->internalDecrementItems($args['keyValuePairs']);
1453 return $this->triggerPost(__FUNCTION__, $args, $result);
1454 } catch (\Exception $e) {
1455 $result = array();
1456 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1461 * Internal method to decrement multiple items.
1463 * @param array $normalizedKeyValuePairs
1464 * @return array Associative array of keys and new values
1465 * @throws Exception\ExceptionInterface
1467 protected function internalDecrementItems(array & $normalizedKeyValuePairs)
1469 $result = array();
1470 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
1471 $newValue = $this->decrementItem($normalizedKey, $value);
1472 if ($newValue !== false) {
1473 $result[$normalizedKey] = $newValue;
1476 return $result;
1479 /* status */
1482 * Get capabilities of this adapter
1484 * @return Capabilities
1485 * @triggers getCapabilities.pre(PreEvent)
1486 * @triggers getCapabilities.post(PostEvent)
1487 * @triggers getCapabilities.exception(ExceptionEvent)
1489 public function getCapabilities()
1491 $args = new ArrayObject();
1493 try {
1494 $eventRs = $this->triggerPre(__FUNCTION__, $args);
1495 if ($eventRs->stopped()) {
1496 return $eventRs->last();
1499 $result = $this->internalGetCapabilities();
1500 return $this->triggerPost(__FUNCTION__, $args, $result);
1501 } catch (\Exception $e) {
1502 $result = false;
1503 return $this->triggerException(__FUNCTION__, $args, $result, $e);
1508 * Internal method to get capabilities of this adapter
1510 * @return Capabilities
1512 protected function internalGetCapabilities()
1514 if ($this->capabilities === null) {
1515 $this->capabilityMarker = new stdClass();
1516 $this->capabilities = new Capabilities($this, $this->capabilityMarker);
1518 return $this->capabilities;
1521 /* internal */
1524 * Validates and normalizes a key
1526 * @param string $key
1527 * @return void
1528 * @throws Exception\InvalidArgumentException On an invalid key
1530 protected function normalizeKey(& $key)
1532 $key = (string) $key;
1534 if ($key === '') {
1535 throw new Exception\InvalidArgumentException(
1536 "An empty key isn't allowed"
1538 } elseif (($p = $this->getOptions()->getKeyPattern()) && !preg_match($p, $key)) {
1539 throw new Exception\InvalidArgumentException(
1540 "The key '{$key}' doesn't match agains pattern '{$p}'"
1546 * Validates and normalizes multiple keys
1548 * @param array $keys
1549 * @return void
1550 * @throws Exception\InvalidArgumentException On an invalid key
1552 protected function normalizeKeys(array & $keys)
1554 if (!$keys) {
1555 throw new Exception\InvalidArgumentException(
1556 "An empty list of keys isn't allowed"
1560 array_walk($keys, array($this, 'normalizeKey'));
1561 $keys = array_values(array_unique($keys));
1565 * Validates and normalizes an array of key-value pairs
1567 * @param array $keyValuePairs
1568 * @return void
1569 * @throws Exception\InvalidArgumentException On an invalid key
1571 protected function normalizeKeyValuePairs(array & $keyValuePairs)
1573 $normalizedKeyValuePairs = array();
1574 foreach ($keyValuePairs as $key => $value) {
1575 $this->normalizeKey($key);
1576 $normalizedKeyValuePairs[$key] = $value;
1578 $keyValuePairs = $normalizedKeyValuePairs;