torrentpier-lts/library/Zend/Cache/Storage/Adapter/AbstractAdapter.php

1579 lines
44 KiB
PHP
Raw Normal View History

<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
2023-04-01 09:03:34 +03:00
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Cache\Storage\Adapter;
use ArrayObject;
use SplObjectStorage;
use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\Event;
use Zend\Cache\Storage\ExceptionEvent;
use Zend\Cache\Storage\Plugin;
use Zend\Cache\Storage\PostEvent;
use Zend\Cache\Storage\StorageInterface;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\EventsCapableInterface;
abstract class AbstractAdapter implements StorageInterface, EventsCapableInterface
{
/**
* The used EventManager if any
*
* @var null|EventManagerInterface
*/
protected $events = null;
/**
* Event handles of this adapter
* @var array
*/
protected $eventHandles = array();
/**
* The plugin registry
*
* @var SplObjectStorage Registered plugins
*/
protected $pluginRegistry;
/**
* Capabilities of this adapter
*
* @var null|Capabilities
*/
protected $capabilities = null;
/**
* Marker to change capabilities
*
* @var null|object
*/
protected $capabilityMarker;
/**
* options
*
* @var mixed
*/
protected $options;
/**
* Constructor
*
* @param null|array|Traversable|AdapterOptions $options
* @throws Exception\ExceptionInterface
*/
public function __construct($options = null)
{
if ($options) {
$this->setOptions($options);
}
}
/**
* Destructor
*
* detach all registered plugins to free
* event handles of event manager
*
* @return void
*/
public function __destruct()
{
foreach ($this->getPluginRegistry() as $plugin) {
$this->removePlugin($plugin);
}
if ($this->eventHandles) {
$events = $this->getEventManager();
foreach ($this->eventHandles as $handle) {
$events->detach($handle);
}
}
}
/* configuration */
/**
* Set options.
*
* @param array|Traversable|AdapterOptions $options
* @return AbstractAdapter
* @see getOptions()
*/
public function setOptions($options)
{
if ($this->options !== $options) {
if (!$options instanceof AdapterOptions) {
$options = new AdapterOptions($options);
}
if ($this->options) {
$this->options->setAdapter(null);
}
$options->setAdapter($this);
$this->options = $options;
$event = new Event('option', $this, new ArrayObject($options->toArray()));
$this->getEventManager()->trigger($event);
}
return $this;
}
/**
* Get options.
*
* @return AdapterOptions
* @see setOptions()
*/
public function getOptions()
{
if (!$this->options) {
$this->setOptions(new AdapterOptions());
}
return $this->options;
}
/**
* Enable/Disable caching.
*
* Alias of setWritable and setReadable.
*
* @see setWritable()
* @see setReadable()
* @param bool $flag
* @return AbstractAdapter
*/
public function setCaching($flag)
{
$flag = (bool) $flag;
$options = $this->getOptions();
$options->setWritable($flag);
$options->setReadable($flag);
return $this;
}
/**
* Get caching enabled.
*
* Alias of getWritable and getReadable.
*
* @see getWritable()
* @see getReadable()
* @return bool
*/
public function getCaching()
{
$options = $this->getOptions();
return ($options->getWritable() && $options->getReadable());
}
/* Event/Plugin handling */
/**
* Get the event manager
*
* @return EventManagerInterface
*/
public function getEventManager()
{
if ($this->events === null) {
$this->events = new EventManager(array(__CLASS__, get_class($this)));
}
return $this->events;
}
/**
* Trigger a pre event and return the event response collection
*
* @param string $eventName
* @param ArrayObject $args
* @return \Zend\EventManager\ResponseCollection All handler return values
*/
protected function triggerPre($eventName, ArrayObject $args)
{
return $this->getEventManager()->trigger(new Event($eventName . '.pre', $this, $args));
}
/**
* Triggers the PostEvent and return the result value.
*
* @param string $eventName
* @param ArrayObject $args
* @param mixed $result
* @return mixed
*/
protected function triggerPost($eventName, ArrayObject $args, & $result)
{
$postEvent = new PostEvent($eventName . '.post', $this, $args, $result);
$eventRs = $this->getEventManager()->trigger($postEvent);
2023-04-01 09:03:34 +03:00
return $eventRs->stopped()
? $eventRs->last()
: $postEvent->getResult();
}
/**
* Trigger an exception event
*
* If the ExceptionEvent has the flag "throwException" enabled throw the
* exception after trigger else return the result.
*
* @param string $eventName
* @param ArrayObject $args
* @param mixed $result
* @param \Exception $exception
* @throws Exception\ExceptionInterface
* @return mixed
*/
protected function triggerException($eventName, ArrayObject $args, & $result, \Exception $exception)
{
$exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $exception);
$eventRs = $this->getEventManager()->trigger($exceptionEvent);
if ($exceptionEvent->getThrowException()) {
throw $exceptionEvent->getException();
}
2023-04-01 09:03:34 +03:00
return $eventRs->stopped()
? $eventRs->last()
: $exceptionEvent->getResult();
}
/**
* Check if a plugin is registered
*
* @param Plugin\PluginInterface $plugin
* @return bool
*/
public function hasPlugin(Plugin\PluginInterface $plugin)
{
$registry = $this->getPluginRegistry();
return $registry->contains($plugin);
}
/**
* Register a plugin
*
* @param Plugin\PluginInterface $plugin
* @param int $priority
* @return AbstractAdapter Fluent interface
* @throws Exception\LogicException
*/
public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1)
{
$registry = $this->getPluginRegistry();
if ($registry->contains($plugin)) {
throw new Exception\LogicException(sprintf(
'Plugin of type "%s" already registered',
get_class($plugin)
));
}
$plugin->attach($this->getEventManager(), $priority);
$registry->attach($plugin);
return $this;
}
/**
* Unregister an already registered plugin
*
* @param Plugin\PluginInterface $plugin
* @return AbstractAdapter Fluent interface
* @throws Exception\LogicException
*/
public function removePlugin(Plugin\PluginInterface $plugin)
{
$registry = $this->getPluginRegistry();
if ($registry->contains($plugin)) {
$plugin->detach($this->getEventManager());
$registry->detach($plugin);
}
return $this;
}
/**
* Return registry of plugins
*
* @return SplObjectStorage
*/
public function getPluginRegistry()
{
if (!$this->pluginRegistry instanceof SplObjectStorage) {
$this->pluginRegistry = new SplObjectStorage();
}
return $this->pluginRegistry;
}
/* reading */
/**
* Get an item.
*
* @param string $key
* @param bool $success
* @param mixed $casToken
* @return mixed Data on success, null on failure
* @throws Exception\ExceptionInterface
*
* @triggers getItem.pre(PreEvent)
* @triggers getItem.post(PostEvent)
* @triggers getItem.exception(ExceptionEvent)
*/
public function getItem($key, & $success = null, & $casToken = null)
{
if (!$this->getOptions()->getReadable()) {
$success = false;
2023-04-01 09:03:34 +03:00
return;
}
$this->normalizeKey($key);
$argn = func_num_args();
$args = array(
'key' => & $key,
);
if ($argn > 1) {
$args['success'] = & $success;
}
if ($argn > 2) {
$args['casToken'] = & $casToken;
}
$args = new ArrayObject($args);
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
if ($eventRs->stopped()) {
$result = $eventRs->last();
} elseif ($args->offsetExists('success') && $args->offsetExists('casToken')) {
$result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']);
} elseif ($args->offsetExists('success')) {
$result = $this->internalGetItem($args['key'], $args['success']);
} else {
$result = $this->internalGetItem($args['key']);
}
2023-04-01 09:03:34 +03:00
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
2023-04-01 09:03:34 +03:00
$result = null;
$success = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to get an item.
*
* @param string $normalizedKey
* @param bool $success
* @param mixed $casToken
* @return mixed Data on success, null on failure
* @throws Exception\ExceptionInterface
*/
abstract protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null);
/**
* Get multiple items.
*
* @param array $keys
* @return array Associative array of keys and values
* @throws Exception\ExceptionInterface
*
* @triggers getItems.pre(PreEvent)
* @triggers getItems.post(PostEvent)
* @triggers getItems.exception(ExceptionEvent)
*/
public function getItems(array $keys)
{
if (!$this->getOptions()->getReadable()) {
return array();
}
$this->normalizeKeys($keys);
$args = new ArrayObject(array(
'keys' => & $keys,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array();
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to get multiple items.
*
* @param array $normalizedKeys
* @return array Associative array of keys and values
* @throws Exception\ExceptionInterface
*/
protected function internalGetItems(array & $normalizedKeys)
{
$success = null;
$result = array();
foreach ($normalizedKeys as $normalizedKey) {
$value = $this->internalGetItem($normalizedKey, $success);
if ($success) {
$result[$normalizedKey] = $value;
}
}
return $result;
}
/**
* Test if an item exists.
*
* @param string $key
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers hasItem.pre(PreEvent)
* @triggers hasItem.post(PostEvent)
* @triggers hasItem.exception(ExceptionEvent)
*/
public function hasItem($key)
{
if (!$this->getOptions()->getReadable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalHasItem($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to test if an item exists.
*
* @param string $normalizedKey
* @return bool
* @throws Exception\ExceptionInterface
*/
protected function internalHasItem(& $normalizedKey)
{
$success = null;
$this->internalGetItem($normalizedKey, $success);
return $success;
}
/**
* Test multiple items.
*
* @param array $keys
* @return array Array of found keys
* @throws Exception\ExceptionInterface
*
* @triggers hasItems.pre(PreEvent)
* @triggers hasItems.post(PostEvent)
* @triggers hasItems.exception(ExceptionEvent)
*/
public function hasItems(array $keys)
{
if (!$this->getOptions()->getReadable()) {
return array();
}
$this->normalizeKeys($keys);
$args = new ArrayObject(array(
'keys' => & $keys,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalHasItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array();
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to test multiple items.
*
* @param array $normalizedKeys
* @return array Array of found keys
* @throws Exception\ExceptionInterface
*/
protected function internalHasItems(array & $normalizedKeys)
{
$result = array();
foreach ($normalizedKeys as $normalizedKey) {
if ($this->internalHasItem($normalizedKey)) {
$result[] = $normalizedKey;
}
}
return $result;
}
/**
* Get metadata of an item.
*
* @param string $key
* @return array|bool Metadata on success, false on failure
* @throws Exception\ExceptionInterface
*
* @triggers getMetadata.pre(PreEvent)
* @triggers getMetadata.post(PostEvent)
* @triggers getMetadata.exception(ExceptionEvent)
*/
public function getMetadata($key)
{
if (!$this->getOptions()->getReadable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetMetadata($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to get metadata of an item.
*
* @param string $normalizedKey
* @return array|bool Metadata on success, false on failure
* @throws Exception\ExceptionInterface
*/
protected function internalGetMetadata(& $normalizedKey)
{
if (!$this->internalHasItem($normalizedKey)) {
return false;
}
return array();
}
/**
* Get multiple metadata
*
* @param array $keys
* @return array Associative array of keys and metadata
* @throws Exception\ExceptionInterface
*
* @triggers getMetadatas.pre(PreEvent)
* @triggers getMetadatas.post(PostEvent)
* @triggers getMetadatas.exception(ExceptionEvent)
*/
public function getMetadatas(array $keys)
{
if (!$this->getOptions()->getReadable()) {
return array();
}
$this->normalizeKeys($keys);
$args = new ArrayObject(array(
'keys' => & $keys,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetMetadatas($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array();
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to get multiple metadata
*
* @param array $normalizedKeys
* @return array Associative array of keys and metadata
* @throws Exception\ExceptionInterface
*/
protected function internalGetMetadatas(array & $normalizedKeys)
{
$result = array();
foreach ($normalizedKeys as $normalizedKey) {
$metadata = $this->internalGetMetadata($normalizedKey);
if ($metadata !== false) {
$result[$normalizedKey] = $metadata;
}
}
return $result;
}
/* writing */
/**
* Store an item.
*
* @param string $key
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers setItem.pre(PreEvent)
* @triggers setItem.post(PostEvent)
* @triggers setItem.exception(ExceptionEvent)
*/
public function setItem($key, $value)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
'value' => & $value,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalSetItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to store an item.
*
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*/
abstract protected function internalSetItem(& $normalizedKey, & $value);
/**
* Store multiple items.
*
* @param array $keyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*
* @triggers setItems.pre(PreEvent)
* @triggers setItems.post(PostEvent)
* @triggers setItems.exception(ExceptionEvent)
*/
public function setItems(array $keyValuePairs)
{
if (!$this->getOptions()->getWritable()) {
return array_keys($keyValuePairs);
}
$this->normalizeKeyValuePairs($keyValuePairs);
$args = new ArrayObject(array(
'keyValuePairs' => & $keyValuePairs,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalSetItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array_keys($keyValuePairs);
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to store multiple items.
*
* @param array $normalizedKeyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*/
protected function internalSetItems(array & $normalizedKeyValuePairs)
{
$failedKeys = array();
foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
if (!$this->internalSetItem($normalizedKey, $value)) {
$failedKeys[] = $normalizedKey;
}
}
return $failedKeys;
}
/**
* Add an item.
*
* @param string $key
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers addItem.pre(PreEvent)
* @triggers addItem.post(PostEvent)
* @triggers addItem.exception(ExceptionEvent)
*/
public function addItem($key, $value)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
'value' => & $value,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalAddItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to add an item.
*
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*/
protected function internalAddItem(& $normalizedKey, & $value)
{
if ($this->internalHasItem($normalizedKey)) {
return false;
}
return $this->internalSetItem($normalizedKey, $value);
}
/**
* Add multiple items.
*
* @param array $keyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*
* @triggers addItems.pre(PreEvent)
* @triggers addItems.post(PostEvent)
* @triggers addItems.exception(ExceptionEvent)
*/
public function addItems(array $keyValuePairs)
{
if (!$this->getOptions()->getWritable()) {
return array_keys($keyValuePairs);
}
$this->normalizeKeyValuePairs($keyValuePairs);
$args = new ArrayObject(array(
'keyValuePairs' => & $keyValuePairs,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalAddItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array_keys($keyValuePairs);
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to add multiple items.
*
* @param array $normalizedKeyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*/
protected function internalAddItems(array & $normalizedKeyValuePairs)
{
$result = array();
foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
if (!$this->internalAddItem($normalizedKey, $value)) {
$result[] = $normalizedKey;
}
}
return $result;
}
/**
* Replace an existing item.
*
* @param string $key
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers replaceItem.pre(PreEvent)
* @triggers replaceItem.post(PostEvent)
* @triggers replaceItem.exception(ExceptionEvent)
*/
public function replaceItem($key, $value)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
'value' => & $value,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalReplaceItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to replace an existing item.
*
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*/
protected function internalReplaceItem(& $normalizedKey, & $value)
{
if (!$this->internalhasItem($normalizedKey)) {
return false;
}
return $this->internalSetItem($normalizedKey, $value);
}
/**
* Replace multiple existing items.
*
* @param array $keyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*
* @triggers replaceItems.pre(PreEvent)
* @triggers replaceItems.post(PostEvent)
* @triggers replaceItems.exception(ExceptionEvent)
*/
public function replaceItems(array $keyValuePairs)
{
if (!$this->getOptions()->getWritable()) {
return array_keys($keyValuePairs);
}
$this->normalizeKeyValuePairs($keyValuePairs);
$args = new ArrayObject(array(
'keyValuePairs' => & $keyValuePairs,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalReplaceItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array_keys($keyValuePairs);
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to replace multiple existing items.
*
* @param array $normalizedKeyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*/
protected function internalReplaceItems(array & $normalizedKeyValuePairs)
{
$result = array();
foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
if (!$this->internalReplaceItem($normalizedKey, $value)) {
$result[] = $normalizedKey;
}
}
return $result;
}
/**
* Set an item only if token matches
*
* It uses the token received from getItem() to check if the item has
* changed before overwriting it.
*
* @param mixed $token
* @param string $key
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
* @see getItem()
* @see setItem()
*/
public function checkAndSetItem($token, $key, $value)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'token' => & $token,
'key' => & $key,
'value' => & $value,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to set an item only if token matches
*
* @param mixed $token
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
* @see getItem()
* @see setItem()
*/
protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
{
$oldValue = $this->internalGetItem($normalizedKey);
if ($oldValue !== $token) {
return false;
}
return $this->internalSetItem($normalizedKey, $value);
}
/**
* Reset lifetime of an item
*
* @param string $key
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers touchItem.pre(PreEvent)
* @triggers touchItem.post(PostEvent)
* @triggers touchItem.exception(ExceptionEvent)
*/
public function touchItem($key)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalTouchItem($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to reset lifetime of an item
*
* @param string $normalizedKey
* @return bool
* @throws Exception\ExceptionInterface
*/
protected function internalTouchItem(& $normalizedKey)
{
$success = null;
$value = $this->internalGetItem($normalizedKey, $success);
if (!$success) {
return false;
}
return $this->internalReplaceItem($normalizedKey, $value);
}
/**
* Reset lifetime of multiple items.
*
* @param array $keys
* @return array Array of not updated keys
* @throws Exception\ExceptionInterface
*
* @triggers touchItems.pre(PreEvent)
* @triggers touchItems.post(PostEvent)
* @triggers touchItems.exception(ExceptionEvent)
*/
public function touchItems(array $keys)
{
if (!$this->getOptions()->getWritable()) {
return $keys;
}
$this->normalizeKeys($keys);
$args = new ArrayObject(array(
'keys' => & $keys,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalTouchItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
return $this->triggerException(__FUNCTION__, $args, $keys, $e);
}
}
/**
* Internal method to reset lifetime of multiple items.
*
* @param array $normalizedKeys
* @return array Array of not updated keys
* @throws Exception\ExceptionInterface
*/
protected function internalTouchItems(array & $normalizedKeys)
{
$result = array();
foreach ($normalizedKeys as $normalizedKey) {
if (!$this->internalTouchItem($normalizedKey)) {
$result[] = $normalizedKey;
}
}
return $result;
}
/**
* Remove an item.
*
* @param string $key
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers removeItem.pre(PreEvent)
* @triggers removeItem.post(PostEvent)
* @triggers removeItem.exception(ExceptionEvent)
*/
public function removeItem($key)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalRemoveItem($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to remove an item.
*
* @param string $normalizedKey
* @return bool
* @throws Exception\ExceptionInterface
*/
abstract protected function internalRemoveItem(& $normalizedKey);
/**
* Remove multiple items.
*
* @param array $keys
* @return array Array of not removed keys
* @throws Exception\ExceptionInterface
*
* @triggers removeItems.pre(PreEvent)
* @triggers removeItems.post(PostEvent)
* @triggers removeItems.exception(ExceptionEvent)
*/
public function removeItems(array $keys)
{
if (!$this->getOptions()->getWritable()) {
return $keys;
}
$this->normalizeKeys($keys);
$args = new ArrayObject(array(
'keys' => & $keys,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalRemoveItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
return $this->triggerException(__FUNCTION__, $args, $keys, $e);
}
}
/**
* Internal method to remove multiple items.
*
* @param array $normalizedKeys
* @return array Array of not removed keys
* @throws Exception\ExceptionInterface
*/
protected function internalRemoveItems(array & $normalizedKeys)
{
$result = array();
foreach ($normalizedKeys as $normalizedKey) {
if (!$this->internalRemoveItem($normalizedKey)) {
$result[] = $normalizedKey;
}
}
return $result;
}
/**
* Increment an item.
*
* @param string $key
* @param int $value
* @return int|bool The new value on success, false on failure
* @throws Exception\ExceptionInterface
*
* @triggers incrementItem.pre(PreEvent)
* @triggers incrementItem.post(PostEvent)
* @triggers incrementItem.exception(ExceptionEvent)
*/
public function incrementItem($key, $value)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
'value' => & $value,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalIncrementItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to increment an item.
*
* @param string $normalizedKey
* @param int $value
* @return int|bool The new value on success, false on failure
* @throws Exception\ExceptionInterface
*/
protected function internalIncrementItem(& $normalizedKey, & $value)
{
$success = null;
$value = (int) $value;
$get = (int) $this->internalGetItem($normalizedKey, $success);
$newValue = $get + $value;
if ($success) {
$this->internalReplaceItem($normalizedKey, $newValue);
} else {
$this->internalAddItem($normalizedKey, $newValue);
}
return $newValue;
}
/**
* Increment multiple items.
*
* @param array $keyValuePairs
* @return array Associative array of keys and new values
* @throws Exception\ExceptionInterface
*
* @triggers incrementItems.pre(PreEvent)
* @triggers incrementItems.post(PostEvent)
* @triggers incrementItems.exception(ExceptionEvent)
*/
public function incrementItems(array $keyValuePairs)
{
if (!$this->getOptions()->getWritable()) {
return array();
}
$this->normalizeKeyValuePairs($keyValuePairs);
$args = new ArrayObject(array(
'keyValuePairs' => & $keyValuePairs,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalIncrementItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array();
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to increment multiple items.
*
* @param array $normalizedKeyValuePairs
* @return array Associative array of keys and new values
* @throws Exception\ExceptionInterface
*/
protected function internalIncrementItems(array & $normalizedKeyValuePairs)
{
$result = array();
foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
$newValue = $this->internalIncrementItem($normalizedKey, $value);
if ($newValue !== false) {
$result[$normalizedKey] = $newValue;
}
}
return $result;
}
/**
* Decrement an item.
*
* @param string $key
* @param int $value
* @return int|bool The new value on success, false on failure
* @throws Exception\ExceptionInterface
*
* @triggers decrementItem.pre(PreEvent)
* @triggers decrementItem.post(PostEvent)
* @triggers decrementItem.exception(ExceptionEvent)
*/
public function decrementItem($key, $value)
{
if (!$this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject(array(
'key' => & $key,
'value' => & $value,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalDecrementItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to decrement an item.
*
* @param string $normalizedKey
* @param int $value
* @return int|bool The new value on success, false on failure
* @throws Exception\ExceptionInterface
*/
protected function internalDecrementItem(& $normalizedKey, & $value)
{
$success = null;
$value = (int) $value;
$get = (int) $this->internalGetItem($normalizedKey, $success);
$newValue = $get - $value;
if ($success) {
$this->internalReplaceItem($normalizedKey, $newValue);
} else {
$this->internalAddItem($normalizedKey, $newValue);
}
return $newValue;
}
/**
* Decrement multiple items.
*
* @param array $keyValuePairs
* @return array Associative array of keys and new values
* @throws Exception\ExceptionInterface
*
* @triggers incrementItems.pre(PreEvent)
* @triggers incrementItems.post(PostEvent)
* @triggers incrementItems.exception(ExceptionEvent)
*/
public function decrementItems(array $keyValuePairs)
{
if (!$this->getOptions()->getWritable()) {
return array();
}
$this->normalizeKeyValuePairs($keyValuePairs);
$args = new ArrayObject(array(
'keyValuePairs' => & $keyValuePairs,
));
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalDecrementItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = array();
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to decrement multiple items.
*
* @param array $normalizedKeyValuePairs
* @return array Associative array of keys and new values
* @throws Exception\ExceptionInterface
*/
protected function internalDecrementItems(array & $normalizedKeyValuePairs)
{
$result = array();
foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
$newValue = $this->decrementItem($normalizedKey, $value);
if ($newValue !== false) {
$result[$normalizedKey] = $newValue;
}
}
return $result;
}
/* status */
/**
* Get capabilities of this adapter
*
* @return Capabilities
* @triggers getCapabilities.pre(PreEvent)
* @triggers getCapabilities.post(PostEvent)
* @triggers getCapabilities.exception(ExceptionEvent)
*/
public function getCapabilities()
{
$args = new ArrayObject();
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
2023-04-01 09:03:34 +03:00
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetCapabilities();
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to get capabilities of this adapter
*
* @return Capabilities
*/
protected function internalGetCapabilities()
{
if ($this->capabilities === null) {
$this->capabilityMarker = new stdClass();
$this->capabilities = new Capabilities($this, $this->capabilityMarker);
}
return $this->capabilities;
}
/* internal */
/**
* Validates and normalizes a key
*
* @param string $key
* @return void
* @throws Exception\InvalidArgumentException On an invalid key
*/
protected function normalizeKey(& $key)
{
$key = (string) $key;
if ($key === '') {
throw new Exception\InvalidArgumentException(
"An empty key isn't allowed"
);
} elseif (($p = $this->getOptions()->getKeyPattern()) && !preg_match($p, $key)) {
throw new Exception\InvalidArgumentException(
"The key '{$key}' doesn't match against pattern '{$p}'"
);
}
}
/**
* Validates and normalizes multiple keys
*
* @param array $keys
* @return void
* @throws Exception\InvalidArgumentException On an invalid key
*/
protected function normalizeKeys(array & $keys)
{
if (!$keys) {
throw new Exception\InvalidArgumentException(
"An empty list of keys isn't allowed"
);
}
array_walk($keys, array($this, 'normalizeKey'));
$keys = array_values(array_unique($keys));
}
/**
* Validates and normalizes an array of key-value pairs
*
* @param array $keyValuePairs
* @return void
* @throws Exception\InvalidArgumentException On an invalid key
*/
protected function normalizeKeyValuePairs(array & $keyValuePairs)
{
$normalizedKeyValuePairs = array();
foreach ($keyValuePairs as $key => $value) {
$this->normalizeKey($key);
$normalizedKeyValuePairs[$key] = $value;
}
$keyValuePairs = $normalizedKeyValuePairs;
}
}