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
10 namespace Zend\Cache\Storage\Adapter
;
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
30 * The used EventManager if any
32 * @var null|EventManagerInterface
34 protected $events = null;
37 * Event handles of this adapter
40 protected $eventHandles = array();
45 * @var SplObjectStorage Registered plugins
47 protected $pluginRegistry;
50 * Capabilities of this adapter
52 * @var null|Capabilities
54 protected $capabilities = null;
57 * Marker to change capabilities
61 protected $capabilityMarker;
73 * @param null|array|Traversable|AdapterOptions $options
74 * @throws Exception\ExceptionInterface
76 public function __construct($options = null)
79 $this->setOptions($options);
86 * detach all registered plugins to free
87 * event handles of event manager
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);
110 * @param array|Traversable|AdapterOptions $options
111 * @return AbstractAdapter
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);
136 * @return AdapterOptions
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.
155 * @return AbstractAdapter
157 public function setCaching($flag)
159 $flag = (bool) $flag;
160 $options = $this->getOptions();
161 $options->setWritable($flag);
162 $options->setReadable($flag);
167 * Get caching enabled.
169 * Alias of getWritable and getReadable.
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
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
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
262 public function hasPlugin(Plugin\PluginInterface
$plugin)
264 $registry = $this->getPluginRegistry();
265 return $registry->contains($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',
286 $plugin->attach($this->getEventManager(), $priority);
287 $registry->attach($plugin);
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);
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
;
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()) {
344 $this->normalizeKey($key);
346 $argn = func_num_args();
351 $args['success'] = & $success;
354 $args['casToken'] = & $casToken;
356 $args = new ArrayObject($args);
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']);
369 $result = $this->internalGetItem($args['key']);
371 return $this->triggerPost(__FUNCTION__
, $args, $result);
372 } catch (\Exception
$e) {
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.
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()) {
406 $this->normalizeKeys($keys);
407 $args = new ArrayObject(array(
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) {
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)
436 foreach ($normalizedKeys as $normalizedKey) {
437 $value = $this->internalGetItem($normalizedKey, $success);
439 $result[$normalizedKey] = $value;
447 * Test if an item exists.
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()) {
463 $this->normalizeKey($key);
464 $args = new ArrayObject(array(
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) {
478 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
483 * Internal method to test if an item exists.
485 * @param string $normalizedKey
487 * @throws Exception\ExceptionInterface
489 protected function internalHasItem(& $normalizedKey)
492 $this->internalGetItem($normalizedKey, $success);
497 * Test multiple items.
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()) {
513 $this->normalizeKeys($keys);
514 $args = new ArrayObject(array(
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) {
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)
542 foreach ($normalizedKeys as $normalizedKey) {
543 if ($this->internalHasItem($normalizedKey)) {
544 $result[] = $normalizedKey;
551 * Get metadata of an item.
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()) {
567 $this->normalizeKey($key);
568 $args = new ArrayObject(array(
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) {
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)) {
603 * Get multiple metadata
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()) {
619 $this->normalizeKeys($keys);
620 $args = new ArrayObject(array(
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) {
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)
648 foreach ($normalizedKeys as $normalizedKey) {
649 $metadata = $this->internalGetMetadata($normalizedKey);
650 if ($metadata !== false) {
651 $result[$normalizedKey] = $metadata;
663 * @param mixed $value
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()) {
677 $this->normalizeKey($key);
678 $args = new ArrayObject(array(
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) {
693 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
698 * Internal method to store an item.
700 * @param string $normalizedKey
701 * @param mixed $value
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,
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;
765 * @param mixed $value
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()) {
779 $this->normalizeKey($key);
780 $args = new ArrayObject(array(
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) {
795 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
800 * Internal method to add an item.
802 * @param string $normalizedKey
803 * @param mixed $value
805 * @throws Exception\ExceptionInterface
807 protected function internalAddItem(& $normalizedKey, & $value)
809 if ($this->internalHasItem($normalizedKey)) {
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,
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)
861 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
862 if (!$this->internalAddItem($normalizedKey, $value)) {
863 $result[] = $normalizedKey;
870 * Replace an existing item.
873 * @param mixed $value
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()) {
887 $this->normalizeKey($key);
888 $args = new ArrayObject(array(
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) {
903 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
908 * Internal method to replace an existing item.
910 * @param string $normalizedKey
911 * @param mixed $value
913 * @throws Exception\ExceptionInterface
915 protected function internalReplaceItem(& $normalizedKey, & $value)
917 if (!$this->internalhasItem($normalizedKey)) {
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,
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)
970 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
971 if (!$this->internalReplaceItem($normalizedKey, $value)) {
972 $result[] = $normalizedKey;
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
986 * @param mixed $value
988 * @throws Exception\ExceptionInterface
992 public function checkAndSetItem($token, $key, $value)
994 if (!$this->getOptions()->getWritable()) {
998 $this->normalizeKey($key);
999 $args = new ArrayObject(array(
1000 'token' => & $token,
1002 'value' => & $value,
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) {
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
1026 * @throws Exception\ExceptionInterface
1030 protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
1032 $oldValue = $this->internalGetItem($normalizedKey);
1033 if ($oldValue !== $token) {
1037 return $this->internalSetItem($normalizedKey, $value);
1041 * Reset lifetime of an item
1043 * @param string $key
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()) {
1057 $this->normalizeKey($key);
1058 $args = new ArrayObject(array(
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) {
1072 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
1077 * Internal method to reset lifetime of an item
1079 * @param string $normalizedKey
1081 * @throws Exception\ExceptionInterface
1083 protected function internalTouchItem(& $normalizedKey)
1086 $value = $this->internalGetItem($normalizedKey, $success);
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()) {
1111 $this->normalizeKeys($keys);
1112 $args = new ArrayObject(array(
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)
1139 foreach ($normalizedKeys as $normalizedKey) {
1140 if (!$this->internalTouchItem($normalizedKey)) {
1141 $result[] = $normalizedKey;
1150 * @param string $key
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()) {
1164 $this->normalizeKey($key);
1165 $args = new ArrayObject(array(
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) {
1179 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
1184 * Internal method to remove an item.
1186 * @param string $normalizedKey
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()) {
1209 $this->normalizeKeys($keys);
1210 $args = new ArrayObject(array(
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)
1237 foreach ($normalizedKeys as $normalizedKey) {
1238 if (!$this->internalRemoveItem($normalizedKey)) {
1239 $result[] = $normalizedKey;
1246 * Increment an item.
1248 * @param string $key
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()) {
1263 $this->normalizeKey($key);
1264 $args = new ArrayObject(array(
1266 'value' => & $value,
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) {
1279 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
1284 * Internal method to increment an item.
1286 * @param string $normalizedKey
1288 * @return int|bool The new value on success, false on failure
1289 * @throws Exception\ExceptionInterface
1291 protected function internalIncrementItem(& $normalizedKey, & $value)
1294 $value = (int) $value;
1295 $get = (int) $this->internalGetItem($normalizedKey, $success);
1296 $newValue = $get +
$value;
1299 $this->internalReplaceItem($normalizedKey, $newValue);
1301 $this->internalAddItem($normalizedKey, $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()) {
1324 $this->normalizeKeyValuePairs($keyValuePairs);
1325 $args = new ArrayObject(array(
1326 'keyValuePairs' => & $keyValuePairs,
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) {
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)
1353 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
1354 $newValue = $this->internalIncrementItem($normalizedKey, $value);
1355 if ($newValue !== false) {
1356 $result[$normalizedKey] = $newValue;
1363 * Decrement an item.
1365 * @param string $key
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()) {
1380 $this->normalizeKey($key);
1381 $args = new ArrayObject(array(
1383 'value' => & $value,
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) {
1396 return $this->triggerException(__FUNCTION__
, $args, $result, $e);
1401 * Internal method to decrement an item.
1403 * @param string $normalizedKey
1405 * @return int|bool The new value on success, false on failure
1406 * @throws Exception\ExceptionInterface
1408 protected function internalDecrementItem(& $normalizedKey, & $value)
1411 $value = (int) $value;
1412 $get = (int) $this->internalGetItem($normalizedKey, $success);
1413 $newValue = $get - $value;
1416 $this->internalReplaceItem($normalizedKey, $newValue);
1418 $this->internalAddItem($normalizedKey, $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()) {
1441 $this->normalizeKeyValuePairs($keyValuePairs);
1442 $args = new ArrayObject(array(
1443 'keyValuePairs' => & $keyValuePairs,
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) {
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)
1470 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
1471 $newValue = $this->decrementItem($normalizedKey, $value);
1472 if ($newValue !== false) {
1473 $result[$normalizedKey] = $newValue;
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();
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) {
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
;
1524 * Validates and normalizes a key
1526 * @param string $key
1528 * @throws Exception\InvalidArgumentException On an invalid key
1530 protected function normalizeKey(& $key)
1532 $key = (string) $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
1550 * @throws Exception\InvalidArgumentException On an invalid key
1552 protected function normalizeKeys(array & $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
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;