From efac9230a7b52717b632517e5369a04e46226a47 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Tue, 28 Feb 2012 19:52:15 +0100 Subject: [PATCH 01/62] internal changes to cache adapters to simplify spizific adapters --- src/Storage/Adapter/AbstractAdapter.php | 655 ++++++++++++++--- src/Storage/Adapter/AbstractZendServer.php | 370 +++------- src/Storage/Adapter/Apc.php | 650 ++++++----------- src/Storage/Adapter/Filesystem.php | 703 +++++++------------ src/Storage/Adapter/Memcached.php | 343 ++++----- src/Storage/Adapter/Memory.php | 436 ++++-------- src/Storage/Adapter/WinCache.php | 492 +++---------- test/Storage/Adapter/AbstractAdapterTest.php | 283 ++++++-- test/Storage/TestAsset/MockAdapter.php | 8 +- 9 files changed, 1769 insertions(+), 2171 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index b0a046a3d..896ad11ac 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -30,8 +30,8 @@ Zend\Cache\Storage\Capabilities, Zend\Cache\Storage\Event, Zend\Cache\Storage\ExceptionEvent, - Zend\Cache\Storage\Plugin, Zend\Cache\Storage\PostEvent, + Zend\Cache\Storage\Plugin, Zend\EventManager\EventCollection, Zend\EventManager\EventManager; @@ -351,26 +351,136 @@ public function getPlugins() /* reading */ /** - * Get items + * Get an item. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item or return false + * + * @param string $key + * @param array $options + * @return mixed Data on success and false on failure + * @throws Exception + * + * @triggers getItem.pre(PreEvent) + * @triggers getItem.post(PostEvent) + * @triggers getItem.exception(ExceptionEvent) + */ + public function getItem($key, array $options = array()) + { + if (!$this->getOptions()->getReadable()) { + return false; + } + + $this->normalizeKey($key); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'key' => & $key, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetItem($key, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to get an item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item or return false + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure + * @throws Exception + */ + abstract protected function internalGetItem(& $normalizedKey, array &$normalizedOptions); + + /** + * Get multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $keys * @param array $options - * @return array + * @return array Associative array of existing keys and values + * @throws Exception + * + * @triggers getItems.pre(PreEvent) + * @triggers getItems.post(PostEvent) + * @triggers getItems.exception(ExceptionEvent) */ public function getItems(array $keys, array $options = array()) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { + if (!$this->getOptions()->getReadable()) { return array(); } + $this->normalizeKeys($keys); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetItems($keys, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to get multiple items. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing keys and values + * @throws Exception + */ + protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + { + // Ignore missing items by catching the exception + $normalizedOptions['ignore_missing_items'] = false; + $ret = array(); - foreach ($keys as $key) { + foreach ($normalizedKeys as $normalizedKey) { try { - $value = $this->getItem($key, $options); - if ($value !== false) { - $ret[$key] = $value; - } + $ret[$normalizedKey] = $this->internalGetItem($normalizedKey, $normalizedOptions); } catch (Exception\ItemNotFoundException $e) { // ignore missing items } @@ -380,11 +490,22 @@ public function getItems(array $keys, array $options = array()) } /** - * Checks if adapter has an item + * Test if an item exists. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param string $key - * @param array $options - * @return bool + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers hasItem.pre(PreEvent) + * @triggers hasItem.post(PostEvent) + * @triggers hasItem.exception(ExceptionEvent) */ public function hasItem($key, array $options = array()) { @@ -392,21 +513,67 @@ public function hasItem($key, array $options = array()) return false; } + $this->normalizeKey($key); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'key' => & $key, + 'options' => & $options, + )); + try { - $ret = ($this->getItem($key, $options) !== false); - } catch (Exception\ItemNotFoundException $e) { - $ret = false; + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalHasItem($key, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); } + } - return $ret; + /** + * Internal method to test if an item exists. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + { + try { + $this->internalGetItem($normalizedKey, $normalizedOptions); + return true; + } catch (Exception\ItemNotFoundException $e) { + return false; + } } /** - * Checks if adapter has items + * Test multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $keys * @param array $options - * @return array + * @return array Array of existing keys + * @throws Exception + * + * @triggers hasItems.pre(PreEvent) + * @triggers hasItems.post(PostEvent) + * @triggers hasItems.exception(ExceptionEvent) */ public function hasItems(array $keys, array $options = array()) { @@ -414,22 +581,141 @@ public function hasItems(array $keys, array $options = array()) return array(); } - $ret = array(); - foreach ($keys as $key) { - if ($this->hasItem($key, $options)) { - $ret[] = $key; + $this->normalizeKeys($keys); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); } + + $result = $this->internalHasItems($keys, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); } + } - return $ret; + /** + * Internal method to test multiple items. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $keys + * @param array $options + * @return array Array of existing keys + * @throws Exception + */ + protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + { + $result = array(); + foreach ($normalizedKeys as $normalizedKey) { + if ($this->internalHasItem($normalizedKey, $normalizedOptions)) { + $result[] = $normalizedKey; + } + } + return $result; + } + + /** + * Get metadata of an item. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param string $key + * @param array $options + * @return array|boolean Metadata or false on failure + * @throws Exception + * + * @triggers getMetadata.pre(PreEvent) + * @triggers getMetadata.post(PostEvent) + * @triggers getMetadata.exception(ExceptionEvent) + */ + public function getMetadata($key, array $options = array()) + { + if (!$this->getOptions()->getReadable()) { + return false; + } + + $this->normalizeKey($key); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'key' => & $key, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetMetadata($key, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to get metadata of an item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return array|boolean Metadata or false on failure + * @throws Exception + */ + protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) + { + if ($this->internalHasItem($normalizedKey, $normalizedOptions)) { + return array(); + } + + if ($normalizedOptions['ignore_missing_items']) { + return false; + } + + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found on namespace '{$normalizedOptions['namespace']}'" + ); } /** - * Get Metadatas + * Get multiple metadata + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $keys * @param array $options - * @return array + * @return array Associative array of existing cache ids and its metadata + * @throws Exception + * + * @triggers getMetadatas.pre(PreEvent) + * @triggers getMetadatas.post(PostEvent) + * @triggers getMetadatas.exception(ExceptionEvent) */ public function getMetadatas(array $keys, array $options = array()) { @@ -437,29 +723,143 @@ public function getMetadatas(array $keys, array $options = array()) return array(); } - $ret = array(); - foreach ($keys as $key) { + $this->normalizeKeys($keys); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetMetadatas($keys, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to get multiple metadata + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing cache ids and its metadata + * @throws Exception + */ + protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + { + // Ignoore missing items - don't need to throw + catch the ItemNotFoundException + // because on found metadata an array will be returns and on a missing item false + $normalizedOptions['ignore_missing_items'] = true; + + $result = array(); + foreach ($normalizedKeys as $normalizedKey) { try { - $meta = $this->getMetadata($key, $options); - if ($meta !== false) { - $ret[$key] = $meta; + $metadata = $this->internalGetMetadata($normalizedKey, $normalizedOptions); + if ($metadata !== false) { + $result[$normalizedKey] = $metadata; } } catch (Exception\ItemNotFoundException $e) { // ignore missing items } } - return $ret; + return $result; } /* writing */ + /** + * Store an item. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers setItem.pre(PreEvent) + * @triggers setItem.post(PostEvent) + * @triggers setItem.exception(ExceptionEvent) + */ + public function setItem($key, $value, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'value' => & $value, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalSetItem($key, $value, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to store an item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + abstract protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions); + /** - * Set items + * Store multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $keyValuePairs * @param array $options - * @return bool + * @return boolean + * @throws Exception + * + * @triggers setItems.pre(PreEvent) + * @triggers setItems.post(PostEvent) + * @triggers setItems.exception(ExceptionEvent) */ public function setItems(array $keyValuePairs, array $options = array()) { @@ -467,12 +867,46 @@ public function setItems(array $keyValuePairs, array $options = array()) return false; } - $ret = true; - foreach ($keyValuePairs as $key => $value) { - $ret = $this->setItem($key, $value, $options) && $ret; + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keyValuePairs' => & $keyValuePairs, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalSetItems($keyValuePairs, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); } + } - return $ret; + /** + * Internal method to store multiple items. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + { + $result = true; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $result = $this->internalSetItem($normalizedKey, $value, $normalizedOptions) && $result; + } + return $result; } /** @@ -527,6 +961,7 @@ public function replaceItem($key, $value, array $options = array()) if (!$this->hasItem($key, $options)) { throw new Exception\ItemNotFoundException("Key '{$key}' doen't exists"); } + return $this->setItem($key, $value, $options); } @@ -627,7 +1062,7 @@ public function touchItems(array $keys, array $options = array()) } /** - * Remove items + * Remove multiple items. * * @param array $keys * @param array $options @@ -731,65 +1166,67 @@ public function decrementItems(array $keyValuePairs, array $options = array()) return $ret; } - /* non-blocking */ - - /** - * Get delayed - * - * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - select optional - * - An array of the information the returned item contains - * (Default: array('key', 'value')) - * - callback optional - * - An result callback will be invoked for each item in the result set. - * - The first argument will be the item array. - * - The callback does not have to return anything. - * - * @param array $keys - * @param array $options - * @return bool - * @throws Exception\InvalidArgumentException|Exception\RuntimeException - */ - public function getDelayed(array $keys, array $options = array()) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - if (!$this->getOptions()->getReadable()) { - return false; - } elseif (!$keys) { - // empty statement - return true; - } - - $this->normalizeOptions($options); - if (!isset($options['select'])) { - $options['select'] = array('key', 'value'); - } - - $this->stmtOptions = array_merge($this->getOptions()->toArray(), $options); - $this->stmtKeys = $keys; - $this->stmtActive = true; - - if (isset($options['callback'])) { - $callback = $options['callback']; - if (!is_callable($callback, false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - - while ( ($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } - } - - return true; + /* non-blocking */ + + /** + * Get delayed + * + * Options: + * - ttl optional + * - The time-to-live (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - select optional + * - An array of the information the returned item contains + * (Default: array('key', 'value')) + * - callback optional + * - An result callback will be invoked for each item in the result set. + * - The first argument will be the item array. + * - The callback does not have to return anything. + * + * @param array $keys + * @param array $options + * @return bool + * @throws Exception\InvalidArgumentException|Exception\RuntimeException + */ + public function getDelayed(array $keys, array $options = array()) + { + if ($this->stmtActive) { + throw new Exception\RuntimeException('Statement already in use'); + } + + if (!$this->getOptions()->getReadable()) { + return false; + } elseif (!$keys) { + // empty statement + return true; + } + + $this->normalizeOptions($options); + if (!isset($options['select'])) { + $options['select'] = array('key', 'value'); + } + + $this->stmtOptions = array_merge($this->getOptions()->toArray(), $options); + $this->stmtKeys = $keys; + $this->stmtActive = true; + + if (isset($options['callback'])) { + $callback = $options['callback']; + if (!is_callable($callback, false)) { + throw new Exception\InvalidArgumentException('Invalid callback'); + } + + while ( ($item = $this->fetch()) !== false) { + call_user_func($callback, $item); + } + } + + return true; } + /* find */ + /** * Find * @@ -1088,13 +1525,36 @@ protected function normalizeKey(&$key) { $key = (string) $key; - if (($p = $this->getOptions()->getKeyPattern()) && !preg_match($p, $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 agains pattern '{$p}'" ); } } + /** + * Validates and normalizes multiple keys + * + * @param array $keys + * @return array + * @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)); + } + /** * Return registry of plugins * @@ -1107,4 +1567,5 @@ protected function getPluginRegistry() } return $this->pluginRegistry; } + } diff --git a/src/Storage/Adapter/AbstractZendServer.php b/src/Storage/Adapter/AbstractZendServer.php index 97a392b54..8253a5186 100644 --- a/src/Storage/Adapter/AbstractZendServer.php +++ b/src/Storage/Adapter/AbstractZendServer.php @@ -45,261 +45,112 @@ abstract class AbstractZendServer extends AbstractAdapter /* reading */ /** - * Get an item. + * Internal method to get an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional + * - namespace + * - The namespace to use + * - ignore_missing_items * - Throw exception on missing item or return false * - * @param string $key - * @param array $options - * @return mixed Value on success and false on failure + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure * @throws Exception - * - * @triggers getItem.pre(PreEvent) - * @triggers getItem.post(PostEvent) - * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array()) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { - if (!$this->getOptions()->getReadable()) { - return false; - } - - $this->normalizeKey($key); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - $result = $this->zdcFetch($internalKey); - if ($result === false) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - - $result = false; - } elseif (array_key_exists('token', $options)) { - $options['token'] = $result; + $internalKey = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR . $normalizedKey; + $result = $this->zdcFetch($internalKey); + if ($result === false) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + } elseif (array_key_exists('token', $normalizedOptions)) { + $normalizedOptions['token'] = $result; } + + return $result; } /** - * Get multiple items. + * Internal method to get multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param array $keys - * @param array $options - * @return array Assoziative array of existing keys and values or false on failure + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing keys and values * @throws Exception - * - * @triggers getItems.pre(PreEvent) - * @triggers getItems.post(PostEvent) - * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) { - if (!$this->getOptions()->getReadable()) { - return array(); - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } + $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; - $internalKeys = array(); - foreach ($keys as &$key) { - $this->normalizeKey($key); - $internalKeys[] = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - } - - $fetch = $this->zdcFetchMulti($internalKeys); - $prefixL = strlen($options['namespace'] . self::NAMESPACE_SEPARATOR); - $result = array(); - foreach ($fetch as $k => &$v) { - $result[ substr($k, $prefixL) ] = $v; - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; } - } - /** - * Test if an item exists. - * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param string $key - * @param array $options - * @return boolean - * @throws Exception - * - * @triggers hasItem.pre(PreEvent) - * @triggers hasItem.post(PostEvent) - * @triggers hasItem.exception(ExceptionEvent) - */ - public function hasItem($key, array $options = array()) - { - if (!$this->getOptions()->getReadable()) { - return false; + $fetch = $this->zdcFetchMulti($internalKeys); + $prefixL = strlen($prefix); + $result = array(); + foreach ($fetch as $k => & $v) { + $result[ substr($k, $prefixL) ] = $v; } - $this->normalizeKey($key); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - $result = ($this->zdcFetch($internalKey) !== false); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $result; } /** - * Test if multiple items exists. + * Internal method to test if an item exists. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers hasItems.pre(PreEvent) - * @triggers hasItems.post(PostEvent) - * @triggers hasItems.exception(ExceptionEvent) */ - public function hasItems(array $keys, array $options = array()) + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - if (!$this->getOptions()->getReadable()) { - return array(); - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeys = array(); - foreach ($keys as &$key) { - $this->normalizeKey($key); - $internalKeys[] = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - } - - $fetch = $this->zdcFetchMulti($internalKeys); - $prefixL = strlen($options['namespace'] . self::NAMESPACE_SEPARATOR); - $result = array(); - foreach ($fetch as $k => &$v) { - $result[] = substr($k, $prefixL); - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; + return ($this->zdcFetch($prefix . $normalizedKey) !== false); } /** - * Get metadata of an item. + * Internal method to test multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use * - * @param string $key + * @param array $keys * @param array $options - * @return array|boolean Metadata or false on failure + * @return array Array of existing keys * @throws Exception - * - * @triggers getMetadata.pre(PreEvent) - * @triggers getMetadata.post(PostEvent) - * @triggers getMetadata.exception(ExceptionEvent) */ - public function getMetadata($key, array $options = array()) + protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) { - if (!$this->getOptions()->getReadable()) { - return false; - } - - $this->normalizeKey($key); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } + $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; - $internalKey = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - if ($this->zdcFetch($internalKey) === false) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - $result = false; - } else { - $result = array(); - } + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; + } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $fetch = $this->zdcFetchMulti($internalKeys); + $prefixL = strlen($prefix); + $result = array(); + foreach ($fetch as $internalKey => & $value) { + $result[] = substr($internalKey, $prefixL); } + + return $result; } /** @@ -309,101 +160,54 @@ public function getMetadata($key, array $options = array()) * - namespace optional * - The namespace to use (Default: namespace of object) * - * @param array $keys - * @param array $options - * @return array - * @throws Exception\ItemNotFoundException + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array|boolean * * @triggers getMetadatas.pre(PreEvent) * @triggers getMetadatas.post(PostEvent) * @triggers getMetadatas.exception(ExceptionEvent) */ - public function getMetadatas(array $keys, array $options = array()) + protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) { - if (!$this->getOptions()->getReadable()) { - return array(); + $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeys = array(); - foreach ($keys as &$key) { - $this->normalizeKey($key); - $internalKeys[] = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - } - - $fetch = $this->zdcFetchMulti($internalKeys); - $prefixL = strlen($options['namespace'] . self::NAMESPACE_SEPARATOR); - $result = array(); - foreach ($fetch as $k => &$v) { - $result[ substr($k, $prefixL) ] = array(); - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $fetch = $this->zdcFetchMulti($internalKeys); + $prefixL = strlen($prefix); + $result = array(); + foreach ($fetch as $internalKey => $value) { + $result[ substr($internalKey, $prefixL) ] = array(); } + + return $result; } /* writing */ /** - * Store an item. + * Internal method to store an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key - * @param mixed $value - * @param array $options + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItem.pre(PreEvent) - * @triggers setItem.post(PostEvent) - * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; - } - - $this->normalizeKey($key); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - $this->zdcStore($internalKey, $value, $options['ttl']); - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $internalKey = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR . $normalizedKey; + $this->zdcStore($internalKey, $value, $normalizedOptions['ttl']); + return true; } /** diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index 08110fb73..9deccb8c3 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -144,223 +144,128 @@ public function getOptions() /* reading */ /** - * Get an item. + * Internal method to get an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional + * - namespace + * - The namespace to use + * - ignore_missing_items * - Throw exception on missing item or return false * - * @param string $key - * @param array $options - * @return mixed Value on success and false on failure + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure * @throws Exception - * - * @triggers getItem.pre(PreEvent) - * @triggers getItem.post(PostEvent) - * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array()) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $success = false; + $result = apc_fetch($internalKey, $success); + + if (!$success) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $result = apc_fetch($internalKey, $success); - if (!$success) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - $result = false; - } else { - if (array_key_exists('token', $options)) { - $options['token'] = $result; - } + $result = false; + } else { + if (array_key_exists('token', $normalizedOptions)) { + $normalizedOptions['token'] = $result; } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $result; } /** - * Get multiple items. + * Internal method to get multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param array $keys - * @param array $options - * @return array Assoziative array of existing keys and values or false on failure + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing keys and values * @throws Exception - * - * @triggers getItems.pre(PreEvent) - * @triggers getItems.post(PostEvent) - * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); - } + $namespaceSep = $this->getOptions()->getNamespaceSeparator(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $namespaceSep = $baseOptions->getNamespaceSeparator(); - $internalKeys = array(); - foreach ($keys as $key) { - $internalKeys[] = $options['namespace'] . $namespaceSep . $key; - } - - $fetch = apc_fetch($internalKeys); - if (!$options['ignore_missing_items']) { - if (count($keys) != count($fetch)) { - $missing = implode("', '", array_diff($internalKeys, array_keys($fetch))); - throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); - } - } + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; + } - // remove namespace prefix - $prefixL = strlen($options['namespace'] . $namespaceSep); - $result = array(); - foreach ($fetch as $internalKey => &$value) { - $result[ substr($internalKey, $prefixL) ] = $value; + $fetch = apc_fetch($internalKeys); + if (!$normalizedOptions['ignore_missing_items']) { + if (count($normalizedKeys) != count($fetch)) { + $missing = implode("', '", array_diff($internalKeys, array_keys($fetch))); + throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); } + } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + // remove namespace prefix + $prefixL = strlen($prefix); + $result = array(); + foreach ($fetch as $internalKey => & $value) { + $result[ substr($internalKey, $prefixL) ] = $value; } + + return $result; } /** - * Test if an item exists. + * Internal method to test if an item exists. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers hasItem.pre(PreEvent) - * @triggers hasItem.post(PostEvent) - * @triggers hasItem.exception(ExceptionEvent) */ - public function hasItem($key, array $options = array()) + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $result = apc_exists($internalKey); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + return apc_exists($prefix . $normalizedKey); } /** - * Test if multiple items exists. + * Internal method to test multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param string $key + * @param array $keys * @param array $options - * @return boolean + * @return array Array of existing keys * @throws Exception - * - * @triggers hasItems.pre(PreEvent) - * @triggers hasItems.post(PostEvent) - * @triggers hasItems.exception(ExceptionEvent) */ - public function hasItems(array $keys, array $options = array()) + protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $exists = apc_exists($internalKeys); + $result = array(); + $prefixL = strlen($prefix); + foreach ($exists as $internalKey => $bool) { + if ($bool === true) { + $result[] = substr($internalKey, $prefixL); } - - $namespaceSep = $baseOptions->getNamespaceSeparator(); - $internalKeys = array(); - foreach ($keys as $key) { - $internalKeys[] = $options['namespace'] . $namespaceSep . $key; - } - - $exists = apc_exists($internalKeys); - $result = array(); - $prefixL = strlen($options['namespace'] . $namespaceSep); - foreach ($exists as $internalKey => $bool) { - if ($bool === true) { - $result[] = substr($internalKey, $prefixL); - } - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $result; } /** @@ -372,8 +277,8 @@ public function hasItems(array $keys, array $options = array()) * - ignore_missing_items optional * - Throw exception on missing item or return false * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return array|boolean Metadata or false on failure * @throws Exception * @@ -381,50 +286,29 @@ public function hasItems(array $keys, array $options = array()) * @triggers getMetadata.post(PostEvent) * @triggers getMetadata.exception(ExceptionEvent) */ - public function getMetadata($key, array $options = array()) + protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + // @see http://pecl.php.net/bugs/bug.php?id=22564 + if (!apc_exists($internalKey)) { + $metadata = false; + } else { $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE; $regexp = '/^' . preg_quote($internalKey, '/') . '$/'; $it = new APCIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); $metadata = $it->current(); + } - // @see http://pecl.php.net/bugs/bug.php?id=22564 - if (!apc_exists($internalKey)) { - $metadata = false; - } - - if (!$metadata) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - } else { - $this->normalizeMetadata($metadata); + if (!$metadata) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - - return $this->triggerPost(__FUNCTION__, $args, $metadata); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + } else { + $this->normalizeMetadata($metadata); } + + return $metadata; } /** @@ -434,8 +318,8 @@ public function getMetadata($key, array $options = array()) * - namespace optional * - The namespace to use (Default: namespace of object) * - * @param array $keys - * @param array $options + * @param array $normalizedKeys + * @param array $normalizedOptions * @return array * @throws Exception\ItemNotFoundException * @@ -443,175 +327,95 @@ public function getMetadata($key, array $options = array()) * @triggers getMetadatas.post(PostEvent) * @triggers getMetadatas.exception(ExceptionEvent) */ - public function getMetadatas(array $keys, array $options = array()) + protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + $keysRegExp = array(); + foreach ($normalizedKeys as $normalizedKey) { + $keysRegExp[] = preg_quote($normalizedKey, '/'); } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $keysRegExp = array(); - foreach ($keys as $key) { - $keysRegExp[] = preg_quote($key, '/'); - } - $regexp = '/^' - . preg_quote($options['namespace'] . $baseOptions->getNamespaceSeparator(), '/') - . '(' . implode('|', $keysRegExp) . ')' - . '$/'; - $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE; - - $it = new APCIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); - $result = array(); - $prefixL = strlen($options['namespace'] . $baseOptions->getNamespaceSeparator()); - foreach ($it as $internalKey => $metadata) { - // @see http://pecl.php.net/bugs/bug.php?id=22564 - if (!apc_exists($internalKey)) { - continue; - } - - $this->normalizeMetadata($metadata); - $result[ substr($internalKey, $prefixL) ] = & $metadata; - } - - if (!$options['ignore_missing_items']) { - if (count($keys) != count($result)) { - $missing = implode("', '", array_diff($keys, array_keys($result))); - throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $regexp = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/'; + $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE; + + $it = new APCIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); + $result = array(); + $prefixL = strlen($prefix); + foreach ($it as $internalKey => $metadata) { + // @see http://pecl.php.net/bugs/bug.php?id=22564 + if (!apc_exists($internalKey)) { + continue; } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $this->normalizeMetadata($metadata); + $result[ substr($internalKey, $prefixL) ] = & $metadata; } + + return $result; } /* writing */ /** - * Store an item. + * Internal method to store an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key - * @param mixed $value - * @param array $options + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItem.pre(PreEvent) - * @triggers setItem.post(PostEvent) - * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!apc_store($internalKey, $value, $options['ttl'])) { - $type = is_object($value) ? get_class($value) : gettype($value); - throw new Exception\RuntimeException( - "apc_store('{$internalKey}', <{$type}>, {$options['ttl']}) failed" - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + if (!apc_store($internalKey, $value, $normalizedOptions['ttl'])) { + $type = is_object($value) ? get_class($value) : gettype($value); + throw new Exception\RuntimeException( + "apc_store('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + ); } + return true; } /** - * Store multiple items. + * Internal method to store multiple items. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItems.pre(PreEvent) - * @triggers setItems.post(PostEvent) - * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs, array $options = array()) + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeyValuePairs = array(); - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - foreach ($keyValuePairs as $key => &$value) { - $internalKey = $prefix . $key; - $internalKeyValuePairs[$internalKey] = &$value; - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $errKeys = apc_store($internalKeyValuePairs, null, $options['ttl']); - if ($errKeys) { - throw new Exception\RuntimeException( - "apc_store(, null, {$options['ttl']}) failed for keys: " - . "'" . implode("','", $errKeys) . "'" - ); - } + $internalKeyValuePairs = array(); + foreach ($normalizedKeyValuePairs as $normalizedKey => &$value) { + $internalKey = $prefix . $normalizedKey; + $internalKeyValuePairs[$internalKey] = &$value; + } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $errKeys = apc_store($internalKeyValuePairs, null, $normalizedOptions['ttl']); + if ($errKeys) { + throw new Exception\RuntimeException( + "apc_store(, null, {$normalizedOptions['ttl']}) failed for keys: " + . "'" . implode("','", $errKeys) . "'" + ); } + + return true; } /** @@ -1028,85 +832,87 @@ public function decrementItem($key, $value, array $options = array()) } } - /* non-blocking */ - - /** - * Get items that were marked to delay storage for purposes of removing blocking - * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param array $keys - * @param array $options - * @return bool - * @throws Exception - * - * @triggers getDelayed.pre(PreEvent) - * @triggers getDelayed.post(PostEvent) - * @triggers getDelayed.exception(ExceptionEvent) + /* non-blocking */ + + /** + * Get items that were marked to delay storage for purposes of removing blocking + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param array $keys + * @param array $options + * @return bool + * @throws Exception + * + * @triggers getDelayed.pre(PreEvent) + * @triggers getDelayed.post(PostEvent) + * @triggers getDelayed.exception(ExceptionEvent) */ - public function getDelayed(array $keys, array $options = array()) - { - $baseOptions = $this->getOptions(); - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } elseif (!$baseOptions->getReadable()) { - return false; - } elseif (!$keys) { - return true; - } - - $this->normalizeOptions($options); - if (isset($options['callback']) && !is_callable($options['callback'], false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - $prefix = preg_quote($prefix, '/'); - - $format = 0; - foreach ($options['select'] as $property) { - if (isset(self::$selectMap[$property])) { - $format = $format | self::$selectMap[$property]; - } - } - - $search = array(); - foreach ($keys as $key) { - $search[] = preg_quote($key, '/'); - } - $search = '/^' . $prefix . '(' . implode('|', $search) . ')$/'; - - $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); - $this->stmtActive = true; - $this->stmtOptions = &$options; - - if (isset($options['callback'])) { - $callback = $options['callback']; - while (($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + public function getDelayed(array $keys, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($this->stmtActive) { + throw new Exception\RuntimeException('Statement already in use'); + } elseif (!$baseOptions->getReadable()) { + return false; + } elseif (!$keys) { + return true; + } + + $this->normalizeOptions($options); + if (isset($options['callback']) && !is_callable($options['callback'], false)) { + throw new Exception\InvalidArgumentException('Invalid callback'); + } + + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); + $prefix = preg_quote($prefix, '/'); + + $format = 0; + foreach ($options['select'] as $property) { + if (isset(self::$selectMap[$property])) { + $format = $format | self::$selectMap[$property]; + } + } + + $search = array(); + foreach ($keys as $key) { + $search[] = preg_quote($key, '/'); + } + $search = '/^' . $prefix . '(' . implode('|', $search) . ')$/'; + + $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); + $this->stmtActive = true; + $this->stmtOptions = &$options; + + if (isset($options['callback'])) { + $callback = $options['callback']; + while (($item = $this->fetch()) !== false) { + call_user_func($callback, $item); + } + } + + $result = true; + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } } + /* find */ + /** * Find items. * diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 789f3e549..cbbf7cb64 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -105,344 +105,369 @@ public function getOptions() /* reading */ /** - * Get item + * Get an item. * - * @param $key - * @param array $options - * @return bool|mixed + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item or return false + * + * @param string $key + * @param array $options + * @return mixed Data on success and false on failure + * @throws Exception + * + * @triggers getItem.pre(PreEvent) + * @triggers getItem.post(PostEvent) + * @triggers getItem.exception(ExceptionEvent) */ public function getItem($key, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = $this->internalGetItem($key, $options); - if (array_key_exists('token', $options)) { - // use filemtime + filesize as CAS token - $keyInfo = $this->getKeyInfo($key, $options['namespace']); - $options['token'] = $keyInfo['mtime'] . filesize($keyInfo['filespec'] . '.dat'); - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::getItem($key, $options); } /** - * Get items + * Get multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $keys * @param array $options - * @return array|mixed + * @return array Associative array of existing keys and values + * @throws Exception + * + * @triggers getItems.pre(PreEvent) + * @triggers getItems.post(PostEvent) + * @triggers getItems.exception(ExceptionEvent) */ public function getItems(array $keys, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - // don't throw ItemNotFoundException on getItems - $options['ignore_missing_items'] = true; + return parent::getItems($keys, $options); + } - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); + /** + * Internal method to get an item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item or return false + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure + * @throws Exception + */ + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) + { + if ( !$this->internalHasItem($normalizedKey, $normalizedOptions) + || !($keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace'])) + ) { + if ($normalizedOptions['ignore_missing_items']) { + return false; + } else { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found within namespace '{$normalizedOptions['namespace']}'" + ); + } + } + $baseOptions = $this->getOptions(); try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } + $data = $this->getFileContent($keyInfo['filespec'] . '.dat'); - if ($baseOptions->getClearStatCache()) { - clearstatcache(); + if ($baseOptions->getReadControl()) { + if ( ($info = $this->readInfoFile($keyInfo['filespec'] . '.ifo')) + && isset($info['hash'], $info['algo']) + && Utils::generateHash($info['algo'], $data, true) != $info['hash'] + ) { + throw new Exception\UnexpectedValueException( + "ReadControl: Stored hash and computed hash don't match" + ); + } } - $result = array(); - foreach ($keys as $key) { - if ( ($rs = $this->internalGetItem($key, $options)) !== false) { - $result[$key] = $rs; - } + if (array_key_exists('token', $normalizedOptions)) { + // use filemtime + filesize as CAS token + $normalizedOptions['token'] = $keyInfo['mtime'] . filesize($keyInfo['filespec'] . '.dat'); } - return $this->triggerPost(__FUNCTION__, $args, $result); + return $data; + } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + try { + // remove cache file on exception + $this->internalRemoveItem($normalizedKey, $normalizedOptions); + } catch (Exception $tmp) { + // do not throw remove exception on this point + } + + throw $e; } } /** - * Check for an item + * Test if an item exists. * - * @param $key - * @param array $options - * @return bool|mixed + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param string $key + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers hasItem.pre(PreEvent) + * @triggers hasItem.post(PostEvent) + * @triggers hasItem.exception(ExceptionEvent) */ public function hasItem($key, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = $this->internalHasItem($key, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::hasItem($key, $options); } /** - * Check for items + * Test multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $keys * @param array $options - * @return array|mixed + * @return array Array of existing keys + * @throws Exception + * + * @triggers hasItems.pre(PreEvent) + * @triggers hasItems.post(PostEvent) + * @triggers hasItems.exception(ExceptionEvent) */ public function hasItems(array $keys, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = array(); - foreach ($keys as $key) { - if ( $this->internalHasItem($key, $options) === true ) { - $result[] = $key; - } - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::hasItems($keys, $options); } /** - * Get metadata + * Internal method to test if an item exists. * - * @param $key - * @param array $options - * @return array|bool|mixed|null + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return boolean + * @throws Exception */ - public function getMetadata($key, array $options = array()) + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; + $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); + if (!$keyInfo) { + return false; // missing or corrupted cache data } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = $this->internalGetMetadata($key, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $ttl = $normalizedOptions['ttl']; + if (!$ttl || time() < ($keyInfo['mtime'] + $ttl)) { + return true; } + + return false; } /** - * Get metadatas + * Get metadata * - * @param array $keys + * @param $key * @param array $options - * @return array|mixed + * @return array|bool|mixed|null */ - public function getMetadatas(array $keys, array $options = array()) + public function getMetadata($key, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - // don't throw ItemNotFoundException on getMetadatas - $options['ignore_missing_items'] = true; - - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = array(); - foreach ($keys as $key) { - $meta = $this->internalGetMetadata($key, $options); - if ($meta !== false ) { - $result[$key] = $meta; - } - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::getMetadata($key, $options); } - /* writing */ - /** - * Set item + * Get info by key * - * @param $key - * @param $value - * @param array $options - * @return bool|mixed + * @param string $normalizedKey + * @param array $normalizedOptions + * @return array|bool + * @throws ItemNotFoundException */ - public function setItem($key, $value, array $options = array()) + protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { + $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); + if (!$keyInfo) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found on namespace '{$normalizedOptions['namespace']}'" + ); + } return false; } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } + $baseOptions = $this->getOptions(); + if (!$baseOptions->getNoCtime()) { + $keyInfo['ctime'] = filectime($keyInfo['filespec'] . '.dat'); + } - $value = $args['value']; + if (!$baseOptions->getNoAtime()) { + $keyInfo['atime'] = fileatime($keyInfo['filespec'] . '.dat'); + } - $result = $this->internalSetItem($key, $value, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $info = $this->readInfoFile($keyInfo['filespec'] . '.ifo'); + if ($info) { + return $keyInfo + $info; } + + return $keyInfo; } /** - * Set items + * Get metadatas * - * @param array $keyValuePairs + * @param array $keys * @param array $options - * @return bool|mixed + * @return array */ - public function setItems(array $keyValuePairs, array $options = array()) + public function getMetadatas(array $keys, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } + return parent::getMetadatas($keys, $options); + } - $result = true; - foreach ($args['keyValuePairs'] as $key => $value) { - $result = $this->internalSetItem($key, $value, $options) && $result; - } + /* writing */ - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + /** + * Internal method to store an item. + * + * Options: + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + { + $baseOptions = $this->getOptions(); + $oldUmask = null; + + $lastInfoId = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() . $normalizedKey; + if ($this->lastInfoId == $lastInfoId) { + $filespec = $this->lastInfo['filespec']; + // if lastKeyInfo is available I'm sure that the cache directory exist + } else { + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions['namespace']); + if ($baseOptions->getDirLevel() > 0) { + $path = dirname($filespec); + if (!file_exists($path)) { + $oldUmask = umask($baseOptions->getDirUmask()); + ErrorHandler::start(); + $mkdir = mkdir($path, 0777, true); + $error = ErrorHandler::stop(); + if (!$mkdir) { + throw new Exception\RuntimeException( + "Error creating directory '{$path}'", 0, $error + ); + } + } + } + } + + $info = null; + if ($baseOptions->getReadControl()) { + $info['hash'] = Utils::generateHash($this->getReadControlAlgo(), $value, true); + $info['algo'] = $baseOptions->getReadControlAlgo(); + } + + if (isset($options['tags']) && $normalizedOptions['tags']) { + $tags = $normalizedOptions['tags']; + if (!is_array($tags)) { + $tags = array($tags); + } + $info['tags'] = array_values(array_unique($tags)); + } + + try { + if ($oldUmask !== null) { // $oldUmask could be defined on set directory_umask + umask($baseOptions->getFileUmask()); + } else { + $oldUmask = umask($baseOptions->getFileUmask()); + } + + $ret = $this->putFileContent($filespec . '.dat', $value); + if ($ret && $info) { + // Don't throw exception if writing of info file failed + // -> only return false + try { + $ret = $this->putFileContent($filespec . '.ifo', serialize($info)); + } catch (Exception\RuntimeException $e) { + $ret = false; + } + } + + $this->lastInfoId = null; + + // reset file_umask + umask($oldUmask); + + return $ret; + + } catch (Exception $e) { + // reset umask on exception + umask($oldUmask); + throw $e; + } } /** @@ -1121,88 +1146,6 @@ public function getCapacity(array $options = array()) /* internal */ - /** - * Set key value pair - * - * @param string $key - * @param mixed $value - * @param array $options - * @return bool - * @throws RuntimeException - */ - protected function internalSetItem($key, $value, array &$options) - { - $baseOptions = $this->getOptions(); - $oldUmask = null; - - $lastInfoId = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if ($this->lastInfoId == $lastInfoId) { - $filespec = $this->lastInfo['filespec']; - // if lastKeyInfo is available I'm sure that the cache directory exist - } else { - $filespec = $this->getFileSpec($key, $options['namespace']); - if ($baseOptions->getDirLevel() > 0) { - $path = dirname($filespec); - if (!file_exists($path)) { - $oldUmask = umask($baseOptions->getDirUmask()); - ErrorHandler::start(); - $mkdir = mkdir($path, 0777, true); - $error = ErrorHandler::stop(); - if (!$mkdir) { - throw new Exception\RuntimeException( - "Error creating directory '{$path}'", 0, $error - ); - } - } - } - } - - $info = null; - if ($baseOptions->getReadControl()) { - $info['hash'] = Utils::generateHash($this->getReadControlAlgo(), $value, true); - $info['algo'] = $baseOptions->getReadControlAlgo(); - } - - if (isset($options['tags']) && $options['tags']) { - $tags = $options['tags']; - if (!is_array($tags)) { - $tags = array($tags); - } - $info['tags'] = array_values(array_unique($tags)); - } - - try { - if ($oldUmask !== null) { // $oldUmask could be defined on set directory_umask - umask($baseOptions->getFileUmask()); - } else { - $oldUmask = umask($baseOptions->getFileUmask()); - } - - $ret = $this->putFileContent($filespec . '.dat', $value); - if ($ret && $info) { - // Don't throw exception if writing of info file failed - // -> only return false - try { - $ret = $this->putFileContent($filespec . '.ifo', serialize($info)); - } catch (Exception\RuntimeException $e) { - $ret = false; - } - } - - $this->lastInfoId = null; - - // reset file_umask - umask($oldUmask); - - return $ret; - - } catch (Exception $e) { - // reset umask on exception - umask($oldUmask); - throw $e; - } - } - /** * Remove a key * @@ -1223,114 +1166,6 @@ protected function internalRemoveItem($key, array &$options) $this->lastInfoId = null; } - /** - * Get by key - * - * @param $key - * @param array $options - * @return bool|string - * @throws Exception\ItemNotFoundException|Exception\UnexpectedValueException - */ - protected function internalGetItem($key, array &$options) - { - if ( !$this->internalHasItem($key, $options) - || !($keyInfo = $this->getKeyInfo($key, $options['namespace'])) - ) { - if ($options['ignore_missing_items']) { - return false; - } else { - throw new Exception\ItemNotFoundException( - "Key '{$key}' not found within namespace '{$options['namespace']}'" - ); - } - } - - $baseOptions = $this->getOptions(); - try { - $data = $this->getFileContent($keyInfo['filespec'] . '.dat'); - - if ($baseOptions->getReadControl()) { - if ( ($info = $this->readInfoFile($keyInfo['filespec'] . '.ifo')) - && isset($info['hash'], $info['algo']) - && Utils::generateHash($info['algo'], $data, true) != $info['hash'] - ) { - throw new Exception\UnexpectedValueException( - "ReadControl: Stored hash and computed hash don't match" - ); - } - } - - return $data; - - } catch (Exception $e) { - try { - // remove cache file on exception - $this->internalRemoveItem($key, $options); - } catch (Exception $tmp) {} // do not throw remove exception on this point - - throw $e; - } - } - - /** - * Checks for a key - * - * @param $key - * @param array $options - * @return bool - */ - protected function internalHasItem($key, array &$options) - { - $keyInfo = $this->getKeyInfo($key, $options['namespace']); - if (!$keyInfo) { - return false; // missing or corrupted cache data - } - - if ( !$options['ttl'] // infinite lifetime - || time() < ($keyInfo['mtime'] + $options['ttl']) // not expired - ) { - return true; - } - - return false; - } - - /** - * Get info by key - * - * @param $key - * @param array $options - * @return array|bool - * @throws ItemNotFoundException - */ - protected function internalGetMetadata($key, array &$options) - { - $baseOptions = $this->getOptions(); - $keyInfo = $this->getKeyInfo($key, $options['namespace']); - if (!$keyInfo) { - if ($options['ignore_missing_items']) { - return false; - } else { - throw new Exception\ItemNotFoundException("Key '{$key}' not found within namespace '{$options['namespace']}'"); - } - } - - if (!$baseOptions->getNoCtime()) { - $keyInfo['ctime'] = filectime($keyInfo['filespec'] . '.dat'); - } - - if (!$baseOptions->getNoAtime()) { - $keyInfo['atime'] = fileatime($keyInfo['filespec'] . '.dat'); - } - - $info = $this->readInfoFile($keyInfo['filespec'] . '.ifo'); - if ($info) { - return $keyInfo + $info; - } - - return $keyInfo; - } - /** * Touch a key * diff --git a/src/Storage/Adapter/Memcached.php b/src/Storage/Adapter/Memcached.php index 11f37970e..68b48221d 100644 --- a/src/Storage/Adapter/Memcached.php +++ b/src/Storage/Adapter/Memcached.php @@ -27,6 +27,8 @@ stdClass, Traversable, Zend\Cache\Exception, + Zend\Cache\Storage\Event, + Zend\Cache\Storage\CallbackEvent, Zend\Cache\Storage\Capabilities; /** @@ -79,11 +81,11 @@ public function __construct($options = null) // ext/memcached auto-connects to the server on first use $options = $this->getOptions(); - $servers = $options->getServers(); - if (!$servers) { - $options->addServer('localhost', 11211); - $servers = $options->getServers(); - } + $servers = $options->getServers(); + if (!$servers) { + $options->addServer('localhost', 11211); + $servers = $options->getServers(); + } $this->memcached->addServers($servers); } @@ -134,273 +136,208 @@ public function getOptions() /* reading */ /** - * Get an item. + * Internal method to get an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional + * - namespace + * - The namespace to use + * - ignore_missing_items * - Throw exception on missing item or return false * - * @param string $key - * @param array $options - * @return mixed Value on success and false on failure + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure * @throws Exception - * - * @triggers getItem.pre(PreEvent) - * @triggers getItem.post(PostEvent) - * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array()) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); + if (array_key_exists('token', $normalizedOptions)) { + $result = $this->memcached->get($normalizedKey, null, $normalizedOptions['token']); + } else { + $result = $this->memcached->get($normalizedKey); + } - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + if ($result === false) { + if (($rsCode = $this->memcached->getResultCode()) != 0 + && ($rsCode != MemcachedResource::RES_NOTFOUND || !$normalizedOptions['ignore_missing_items']) + ) { + throw $this->getExceptionByResultCode($rsCode); } + } - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - if (array_key_exists('token', $options)) { - $result = $this->memcached->get($key, null, $options['token']); - } else { - $result = $this->memcached->get($key); - } + return $result; + } - if ($result === false) { - if (($rsCode = $this->memcached->getResultCode()) != 0 - && ($rsCode != MemcachedResource::RES_NOTFOUND || !$options['ignore_missing_items']) - ) { - throw $this->getExceptionByResultCode($rsCode); - } - } + /** + * Internal method to get multiple items. + * + * Options: + * - namespace + * - The namespace to use + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing keys and values + * @throws Exception + */ + protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + { + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = $this->memcached->getMulti($normalizedKeys); + if ($result === false) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } + + return $result; } /** - * Get multiple items. + * Internal method to test if an item exists. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param array $keys - * @param array $options - * @return array Assoziative array of existing keys and values or false on failure + * @param string $normalizedKey + * @param array $normalizedOptions + * @return boolean * @throws Exception - * - * @triggers getItems.pre(PreEvent) - * @triggers getItems.post(PostEvent) - * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); + + $value = $this->memcached->get($normalizedKey); + if ($value === false) { + $rsCode = $this->memcached->getResultCode(); + if ($rsCode == MemcachedResource::RES_SUCCESS) { + return true; + } elseif ($rsCode == MemcachedResource::RES_NOTFOUND) { + return false; + } else { + throw $this->getExceptionByResultCode($rsCode); + } } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); + return true; + } - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } + /** + * Internal method to test multiple items. + * + * Options: + * - namespace + * - The namespace to use + * + * @param array $keys + * @param array $options + * @return array Array of existing keys + * @throws Exception + */ + protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + { + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - $result = $this->memcached->getMulti($keys); - if ($result === false) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } + $result = $this->memcached->getMulti($normalizedKeys); + if ($result === false) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + foreach ($result as $key => & $value) { + $value = true; } + + return $result; } /** - * Get metadata of an item. + * Get metadata of multiple items * * Options: * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - The namespace to use * - * @param string $key - * @param array $options - * @return array|boolean Metadata or false on failure + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array * @throws Exception * - * @triggers getMetadata.pre(PreEvent) - * @triggers getMetadata.post(PostEvent) - * @triggers getMetadata.exception(ExceptionEvent) + * @triggers getMetadatas.pre(PreEvent) + * @triggers getMetadatas.post(PostEvent) + * @triggers getMetadatas.exception(ExceptionEvent) */ - public function getMetadata($key, array $options = array()) + protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - $result = $this->memcached->get($key); - - if ($result === false) { - if (($rsCode = $this->memcached->getResultCode()) != 0 - && ($rsCode != MemcachedResource::RES_NOTFOUND || !$options['ignore_missing_items']) - ) { - throw $this->getExceptionByResultCode($rsCode); - } - } else { - $result = array(); - } + $result = $this->memcached->getMulti($normalizedKeys); + if ($result === false) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + foreach ($result as $key => & $value) { + $value = array(); } + + return $result; } /* writing */ /** - * Store an item. + * Internal method to store an item. * * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key - * @param mixed $value - * @param array $options + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItem.pre(PreEvent) - * @triggers setItem.post(PostEvent) - * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $expiration = $this->expirationTime($options['ttl']); - if (!$this->memcached->set($key, $value, $expiration)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $expiration = $this->expirationTime($normalizedOptions['ttl']); + if (!$this->memcached->set($normalizedKey, $value, $expiration)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } + + return true; } /** - * Store multiple items. + * Internal method to store multiple items. * * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItems.pre(PreEvent) - * @triggers setItems.post(PostEvent) - * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs, array $options = array()) + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $expiration = $this->expirationTime($options['ttl']); - if (!$this->memcached->setMulti($keyValuePairs, $expiration)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $expiration = $this->expirationTime($normalizedOptions['ttl']); + if (!$this->memcached->setMulti($normalizedKeyValuePairs, $expiration)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } + + return true; } /** diff --git a/src/Storage/Adapter/Memory.php b/src/Storage/Adapter/Memory.php index 9517dde6e..7a93a840a 100644 --- a/src/Storage/Adapter/Memory.php +++ b/src/Storage/Adapter/Memory.php @@ -89,176 +89,146 @@ public function getOptions() /* reading */ /** - * Get an item. + * Internal method to get an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items * - Throw exception on missing item or return false * - * @param string $key - * @param array $options - * @return mixed Value on success and false on failure + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure * @throws Exception - * - * @triggers getItem.pre(PreEvent) - * @triggers getItem.post(PostEvent) - * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array()) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $ns = $normalizedOptions['namespace']; + $exist = isset($this->data[$ns][$normalizedKey]); + if ($exist) { + $data = & $this->data[$ns][$normalizedKey]; + $ttl = $normalizedOptions['ttl']; + if ($ttl && microtime(true) >= ($data[1] + $ttl) ) { + $exist = false; } + } - $ns = $options['namespace']; - $exist = isset($this->data[$ns][$key]); - if ($exist) { - if ($options['ttl'] && microtime(true) >= ($this->data[$ns][$key][1] + $options['ttl']) ) { - $exist = false; - } + if (!$exist) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$normalizedKey}' not found on namespace '{$ns}'"); } - - if (!$exist) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$key}' not found on namespace '{$ns}'"); - } - $result = false; - } else { - $result = $this->data[$ns][$key][0]; - if (array_key_exists('token', $options)) { - $options['token'] = $this->data[$ns][$key][0]; - } + $result = false; + } else { + $result = $data[0]; + if (array_key_exists('token', $normalizedOptions)) { + $normalizedOptions['token'] = $data[0]; } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $result; } /** - * Get multiple items. + * Internal method to get multiple items. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param array $keys - * @param array $options - * @return array Assoziative array of existing keys and values or false on failure + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing keys and values * @throws Exception - * - * @triggers getItems.pre(PreEvent) - * @triggers getItems.post(PostEvent) - * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns])) { return array(); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - if (!isset($this->data[$ns])) { - $result = array(); - } else { - $data = &$this->data[$ns]; + $data = & $this->data[$ns]; + $ttl = $normalizedOptions['ttl']; - $keyValuePairs = array(); - foreach ($keys as $key) { - if (isset($data[$key])) { - if (!$options['ttl'] || microtime(true) < ($this->data[$ns][$key][1] + $options['ttl']) ) { - $keyValuePairs[$key] = $data[$key][0]; - } - } + $result = array(); + foreach ($normalizedKeys as $normalizedKey) { + if (isset($data[$normalizedKey])) { + if (!$ttl || microtime(true) < ($data[$normalizedKey][1] + $ttl) ) { + $result[$normalizedKey] = $data[$normalizedKey][0]; } - - $result = $keyValuePairs; } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $result; } /** - * Test if an item exists. + * Internal method to test if an item exists. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers hasItem.pre(PreEvent) - * @triggers hasItem.post(PostEvent) - * @triggers hasItem.exception(ExceptionEvent) */ - public function hasItem($key, array $options = array()) + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns][$normalizedKey])) { return false; } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); + // check if expired + $ttl = $normalizedOptions['ttl']; + if ($ttl && microtime(true) >= ($this->data[$ns][$normalizedKey][1] + $ttl) ) { + return false; + } - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } + return true; + } - $result = $this->checkItem($key, $options); + /** + * Internal method to test multiple items. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $keys + * @param array $options + * @return array Array of existing keys + * @throws Exception + */ + protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + { + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns])) { + return array(); + } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $data = & $this->data[$ns]; + $ttl = $normalizedOptions['ttl']; + + $result = array(); + foreach ($normalizedKeys as $normalizedKey) { + if (!$ttl || microtime(true) < ($data[$normalizedKey][1] + $ttl) ) { + $result[$normalizedKey] = true; + } } + + return $result; } /** @@ -272,8 +242,8 @@ public function hasItem($key, array $options = array()) * - ignore_missing_items optional * - Throw exception on missing item or return false * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return array|boolean Metadata or false on failure * @throws Exception * @@ -281,165 +251,88 @@ public function hasItem($key, array $options = array()) * @triggers getMetadata.post(PostEvent) * @triggers getMetadata.exception(ExceptionEvent) */ - public function getMetadata($key, array $options = array()) + protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$this->checkItem($key, $options)) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$key}' not found on namespace '{$options['namespace']}'" - ); - } - $result = false; - } else { - $ns = $options['namespace']; - $result = array( - 'mtime' => $this->data[$ns][$key][1], - 'tags' => $this->data[$ns][$key][2], + if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found on namespace '{$normalizedOptions['namespace']}'" ); } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + return false; } + + $ns = $normalizedOptions['namespace']; + return array( + 'mtime' => $this->data[$ns][$normalizedKey][1], + 'tags' => $this->data[$ns][$normalizedKey][2], + ); } /* writing */ /** - * Store an item. + * Internal method to store an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - namespace + * - The namespace to use * - * @param string $key - * @param mixed $value - * @param array $options + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItem.pre(PreEvent) - * @triggers setItem.post(PostEvent) - * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if (!$this->hasFreeCapacity()) { + $memoryLimit = $this->getOptions()->getMemoryLimit(); + throw new Exception\OutOfCapacityException( + "Memory usage exceeds limit ({$memoryLimit})." + ); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$this->hasFreeCapacity()) { - $memoryLimit = $baseOptions->getMemoryLimit(); - throw new Exception\OutOfCapacityException( - 'Memory usage exceeds limit ({$memoryLimit}).' - ); - } - - $ns = $options['namespace']; - $this->data[$ns][$key] = array($value, microtime(true), $options['tags']); + $ns = $normalizedOptions['namespace']; + $this->data[$ns][$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Store multiple items. + * Internal method to store multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItems.pre(PreEvent) - * @triggers setItems.post(PostEvent) - * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs, array $options = array()) + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if (!$this->hasFreeCapacity()) { + $memoryLimit = $this->getOptions()->getMemoryLimit(); + throw new Exception\OutOfCapacityException( + 'Memory usage exceeds limit ({$memoryLimit}).' + ); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$this->hasFreeCapacity()) { - $memoryLimit = $baseOptions->getMemoryLimit(); - throw new Exception\OutOfCapacityException( - 'Memory usage exceeds limit ({$memoryLimit}).' - ); - } - - $ns = $options['namespace']; - if (!isset($this->data[$ns])) { - $this->data[$ns] = array(); - } - - $data = & $this->data[$ns]; - foreach ($keyValuePairs as $key => $value) { - $data[$key] = array($value, microtime(true), $options['tags']); - } + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns])) { + $this->data[$ns] = array(); + } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $data = & $this->data[$ns]; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $data[$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); } + + return true; } /** @@ -1006,7 +899,7 @@ public function decrementItem($key, $value, array $options = array()) } } - /* non-blocking */ + /* find */ /** * Find items. @@ -1064,13 +957,13 @@ public function find($mode = self::MATCH_ACTIVE, array $options=array()) // if MATCH_EXPIRED -> filter active items if (($mode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { - if ($this->checkItem($key, $options)) { + if ($this->internalHasItem($key, $options)) { continue; } // if MATCH_ACTIVE -> filter expired items } else { - if (!$this->checkItem($key, $options)) { + if (!$this->internalHasItem($key, $options)) { continue; } } @@ -1145,7 +1038,7 @@ public function fetch() if ($key === null) { break; } - if (!$this->checkItem($key, $options)) { + if (!$this->internalHasItem($key, $options)) { continue; } $ref = & $this->data[ $options['namespace'] ][$key]; @@ -1407,33 +1300,6 @@ protected function hasFreeCapacity() return ($free > 0); } - /** - * Internal method to check if an key exists - * and if it isn't expired. - * - * Options: - * - namespace required - * - ttl required - * - * @param string $key - * @param array $options - */ - protected function checkItem($key, array &$options) - { - $ns = $options['namespace']; - - if (!isset($this->data[$ns][$key])) { - return false; - } - - // check if expired - if ($options['ttl'] && microtime(true) >= ($this->data[$ns][$key][1] + $options['ttl']) ) { - return false; - } - - return true; - } - /** * Internal method to run a clear command * on a given data array which doesn't contain namespaces. diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index fafbc8464..346372277 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -106,244 +106,107 @@ public function getOptions() /* reading */ /** - * Get an item. + * Internal method to get an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items * - Throw exception on missing item or return false * - * @param string $key - * @param array $options - * @return mixed Value on success and false on failure + * @param string $normalizedKey + * @param array $normalizedOptions + * @return mixed Data on success or false on failure * @throws Exception - * - * @triggers getItem.pre(PreEvent) - * @triggers getItem.post(PostEvent) - * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array()) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $success = false; + $result = wincache_ucache_get($internalKey, $success); + if (!$success) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $result = wincache_ucache_get($internalKey, $success); - if (!$success) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - } else { - if (array_key_exists('token', $options)) { - $options['token'] = $result; - } + } else { + if (array_key_exists('token', $normalizedOptions)) { + $normalizedOptions['token'] = $result; } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $result; } /** - * Get multiple items. + * Internal method to get multiple items. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param array $keys - * @param array $options - * @return array Assoziative array of existing keys and values or false on failure + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing keys and values * @throws Exception - * - * @triggers getItems.pre(PreEvent) - * @triggers getItems.post(PostEvent) - * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $namespaceSep = $baseOptions->getNamespaceSeparator(); - $internalKeys = array(); - foreach ($keys as $key) { - $internalKeys[] = $options['namespace'] . $namespaceSep . $key; + $fetch = wincache_ucache_get($internalKeys); + if (!$normalizedOptions['ignore_missing_items']) { + if (count($normalizedKeys) != count($fetch)) { + $missing = implode("', '", array_diff($internalKeys, array_keys($fetch))); + throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); } - - $fetch = wincache_ucache_get($internalKeys); - if (!$options['ignore_missing_items']) { - if (count($keys) != count($fetch)) { - $missing = implode("', '", array_diff($internalKeys, array_keys($fetch))); - throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); - } - } - - // remove namespace prefix - $prefixL = strlen($options['namespace'] . $namespaceSep); - $result = array(); - foreach ($fetch as $internalKey => &$value) { - $result[ substr($internalKey, $prefixL) ] = $value; - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } - } - /** - * Test if an item exists. - * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param string $key - * @param array $options - * @return boolean - * @throws Exception - * - * @triggers hasItem.pre(PreEvent) - * @triggers hasItem.post(PostEvent) - * @triggers hasItem.exception(ExceptionEvent) - */ - public function hasItem($key, array $options = array()) - { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; + // remove namespace prefix + $prefixL = strlen($prefix); + $result = array(); + foreach ($fetch as $internalKey => & $value) { + $result[ substr($internalKey, $prefixL) ] = $value; } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $result = wincache_ucache_exists($internalKey); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $result; } /** - * Test if an item exists. + * Internal method to test if an item exists. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param array $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers hasItems.pre(PreEvent) - * @triggers hasItems.post(PostEvent) - * @triggers hasItems.exception(ExceptionEvent) */ - public function hasItems(array $keys, array $options = array()) + protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $namespaceSep = $baseOptions->getNamespaceSeparator(); - $internalKeys = array(); - foreach ($keys as $key) { - $internalKeys[] = $options['namespace'] . $namespaceSep . $key; - } - - $prefixL = strlen($options['namespace'] . $namespaceSep); - $result = array(); - foreach ($internalKeys as $key) { - if (wincache_ucache_exists($key)) { - $result[] = substr($key, $prefixL); - } - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + return wincache_ucache_exists($prefix . $normalizedKey); } /** * Get metadata of an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) * - namespace optional * - The namespace to use (Default: namespace of object) * - ignore_missing_items optional * - Throw exception on missing item or return false * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return array|boolean Metadata or false on failure * @throws Exception * @@ -351,225 +214,89 @@ public function hasItems(array $keys, array $options = array()) * @triggers getMetadata.post(PostEvent) * @triggers getMetadata.exception(ExceptionEvent) */ - public function getMetadata($key, array $options = array()) + protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - - $info = wincache_ucache_info(true, $internalKey); - if (isset($info['ucache_entries'][1])) { - $metadata = $info['ucache_entries'][1]; - } - - if (empty($metadata)) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - $metadata= false; - } else { - $this->normalizeMetadata($metadata); - } - - return $this->triggerPost(__FUNCTION__, $args, $metadata); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $info = wincache_ucache_info(true, $internalKey); + if (isset($info['ucache_entries'][1])) { + $metadata = $info['ucache_entries'][1]; } - } - - /** - * Get all metadata for an item - * - * @param array $keys - * @param array $options - * @return array - * @throws Exception\ItemNotFoundException - * - * @triggers getMetadatas.pre(PreEvent) - * @triggers getMetadatas.post(PostEvent) - * @triggers getMetadatas.exception(ExceptionEvent) - */ - public function getMetadatas(array $keys, array $options = array()) - { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return array(); - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + if (!$metadata) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - - $result= array(); - - foreach ($keys as $key) { - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - - $info = wincache_ucache_info(true, $internalKey); - $metadata = $info['ucache_entries'][1]; - - if (empty($metadata)) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - } else { - $this->normalizeMetadata($metadata); - $prefixL = strlen($options['namespace'] . $baseOptions->getNamespaceSeparator()); - $result[ substr($internalKey, $prefixL) ] = & $metadata; - } - } - - if (!$options['ignore_missing_items']) { - if (count($keys) != count($result)) { - $missing = implode("', '", array_diff($keys, array_keys($result))); - throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); - } - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + return false; } + + $this->normalizeMetadata($metadata); + return $metadata; } /* writing */ /** - * Store an item. + * Internal method to store an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key - * @param mixed $value - * @param array $options + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItem.pre(PreEvent) - * @triggers setItem.post(PostEvent) - * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!wincache_ucache_set($internalKey, $value, $normalizedOptions['ttl'])) { + $type = is_object($value) ? get_class($value) : gettype($value); + throw new Exception\RuntimeException( + "wincache_ucache_set('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + ); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!wincache_ucache_set($internalKey, $value, $options['ttl'])) { - $type = is_object($value) ? get_class($value) : gettype($value); - throw new Exception\RuntimeException( - "wincache_ucache_set('{$internalKey}', <{$type}>, {$options['ttl']}) failed" - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Store multiple items. + * Internal method to store multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers setItems.pre(PreEvent) - * @triggers setItems.post(PostEvent) - * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs, array $options = array()) + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeyValuePairs = array(); - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - foreach ($keyValuePairs as $key => &$value) { - $internalKey = $prefix . $key; - $internalKeyValuePairs[$internalKey] = &$value; - } - - $errKeys = wincache_ucache_set($internalKeyValuePairs, null, $options['ttl']); - if ($errKeys!==array()) { - throw new Exception\RuntimeException( - "wincache_ucache_set(, null, {$options['ttl']}) failed for keys: " - . "'" . implode("','", array_keys($errKeys)) . "'" - ); - } + $internalKeyValuePairs = array(); + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $internalKey = $prefix . $normalizedKey; + $internalKeyValuePairs[$internalKey] = $value; + } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $errKeys = wincache_ucache_set($internalKeyValuePairs, null, $normalizedOptions['ttl']); + if ($errKeys) { + throw new Exception\RuntimeException( + "wincache_ucache_set(, null, {$normalizedOptions['ttl']}) failed for keys: " + . "'" . implode("','", array_keys($errKeys)) . "'" + ); } + + return true; } /** @@ -925,7 +652,7 @@ public function decrementItem($key, $value, array $options = array()) } } - /* non-blocking */ + /* find */ /* cleaning */ @@ -1096,15 +823,8 @@ protected function normalizeMetadata(array &$metadata) unset($metadata['value_size']); } - // remove namespace prefix if (isset($metadata['key_name'])) { - $pos = strpos($metadata['key_name'], $this->getOptions()->getNamespaceSeparator()); - if ($pos !== false) { - $metadata['internal_key'] = $metadata['key_name']; - } else { - $metadata['internal_key'] = $metadata['key_name']; - } - + $metadata['internal_key'] = $metadata['key_name']; unset($metadata['key_name']); } } diff --git a/test/Storage/Adapter/AbstractAdapterTest.php b/test/Storage/Adapter/AbstractAdapterTest.php index b374590cc..e1ed301c4 100644 --- a/test/Storage/Adapter/AbstractAdapterTest.php +++ b/test/Storage/Adapter/AbstractAdapterTest.php @@ -22,7 +22,7 @@ namespace ZendTest\Cache\Storage\Adapter; use Zend\Cache, - Zend\Cache\Exception\RuntimeException; + Zend\Cache\Exception; /** * @category Zend @@ -45,15 +45,12 @@ class AbstractAdapterTest extends \PHPUnit_Framework_TestCase public function setUp() { $this->_options = new Cache\Storage\Adapter\AdapterOptions(); - $this->_storage = $this->getMockForAbstractClass('Zend\Cache\Storage\Adapter\AbstractAdapter'); - $this->_storage->setOptions($this->_options); - $this->_storage->expects($this->any()) - ->method('getOptions') - ->will($this->returnValue($this->_options)); } public function testGetOptions() { + $this->_storage = $this->getMockForAbstractAdapter(); + $options = $this->_storage->getOptions(); $this->assertInstanceOf('Zend\Cache\Storage\Adapter\AdapterOptions', $options); $this->assertInternalType('boolean', $options->getWritable()); @@ -174,6 +171,8 @@ public function testSetIgnoreMissingItems() public function testPluginRegistry() { + $this->_storage = $this->getMockForAbstractAdapter(); + $plugin = new \ZendTest\Cache\Storage\TestAsset\MockPlugin(); // no plugin registered @@ -200,6 +199,8 @@ public function testPluginRegistry() public function testInternalTriggerPre() { + $this->_storage = $this->getMockForAbstractAdapter(); + $plugin = new \ZendTest\Cache\Storage\TestAsset\MockPlugin(); $this->_storage->addPlugin($plugin); @@ -227,6 +228,8 @@ public function testInternalTriggerPre() public function testInternalTriggerPost() { + $this->_storage = $this->getMockForAbstractAdapter(); + $plugin = new \ZendTest\Cache\Storage\TestAsset\MockPlugin(); $this->_storage->addPlugin($plugin); @@ -258,6 +261,8 @@ public function testInternalTriggerPost() public function testInternalTriggerExceptionThrowRuntimeException() { + $this->_storage = $this->getMockForAbstractAdapter(); + $plugin = new \ZendTest\Cache\Storage\TestAsset\MockPlugin(); $this->_storage->addPlugin($plugin); @@ -271,39 +276,179 @@ public function testInternalTriggerExceptionThrowRuntimeException() $method->setAccessible(true); $this->setExpectedException('Zend\Cache\Exception\RuntimeException', 'test'); - $method->invokeArgs($this->_storage, array('setItem', $params, new RuntimeException('test'))); + $method->invokeArgs($this->_storage, array('setItem', $params, new Exception\RuntimeException('test'))); } - public function testGetItems() + public function testGetItemCallsInternalGetItem() { - $options = array('ttl' => 123); - $items = array( - 'key1' => 'value1', - 'dKey1' => false, - 'key2' => 'value2', - ); + $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItem')); - $i = 0; + $options = array('ttl' => 123); + $key = 'key1'; + $result = 'value1'; + + $this->_storage + ->expects($this->once()) + ->method('internalGetItem') + ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue($result)); + + $rs = $this->_storage->getItem($key, $options); + $this->assertEquals($result, $rs); + } + + public function testGetItemsCallsInternalGetItems() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItems')); + + $options = array('ttl' => 123); + $keys = array('key1', 'key2'); + $result = array('key2' => 'value2'); + + $this->_storage + ->expects($this->once()) + ->method('internalGetItems') + ->with($this->equalTo($keys), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue($result)); + + $rs = $this->_storage->getItems($keys, $options); + $this->assertEquals($result, $rs); + } + + public function testInternalGetItemsCallsInternalGetItemForEachKey() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItem')); + + $options = array('ttl' => 123); + $items = array('key1' => 'value1', 'notFound' => false, 'key2' => 'value2'); + $result = array('key1' => 'value1', 'key2' => 'value2'); + + $normalizedOptions = $this->normalizeOptions($options); + $normalizedOptions['ignore_missing_items'] = false; + + $i = 0; // method call counter foreach ($items as $k => $v) { $this->_storage->expects($this->at($i++)) - ->method('getItem') - ->with($this->equalTo($k), $this->equalTo($options)) - ->will($this->returnValue($v)); + ->method('internalGetItem') + ->with($this->equalTo($k), $this->equalTo($normalizedOptions)) + // return value or throw ItemNotFoundException + ->will($v ? $this->returnValue($v) : $this->throwException(new Exception\ItemNotFoundException())); } $rs = $this->_storage->getItems(array_keys($items), $options); + $this->assertEquals($result, $rs); + } - // remove missing items from array to test - $expected = $items; - foreach ($expected as $key => $value) { - if (false === $value) { - unset($expected[$key]); - } + public function testHasItemCallsInternalHasItem() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalHasItem')); + + $options = array('ttl' => 123); + $key = 'key1'; + $result = true; + + $this->_storage + ->expects($this->once()) + ->method('internalHasItem') + ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue($result)); + + $rs = $this->_storage->hasItem($key, $options); + $this->assertSame($result, $rs); + } + + public function testInternalHasItemCallsInternalGetItemReturnsTrueOnValidFalseValue() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItem')); + + $options = array('ttl' => 123); + $key = 'key1'; + + $this->_storage + ->expects($this->once()) + ->method('internalGetItem') + ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue(false)); // return a valid false value + + $rs = $this->_storage->hasItem($key, $options); + $this->assertTrue($rs); + } + + public function testInternalHasItemCallsInternalGetItemReturnsFalseOnItemNotFoundException() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItem')); + + $options = array('ttl' => 123); + $key = 'key1'; + + $this->_storage + ->expects($this->once()) + ->method('internalGetItem') + ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->will($this->throwException(new Exception\ItemNotFoundException())); // throw ItemNotFoundException + + $rs = $this->_storage->hasItem($key, $options); + $this->assertFalse($rs); + } + + public function testHasItemsCallsInternalHasItems() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalHasItems')); + + $options = array('ttl' => 123); + $keys = array('key1', 'key2'); + $result = array('key2'); + + $this->_storage + ->expects($this->once()) + ->method('internalHasItems') + ->with($this->equalTo($keys), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue($result)); + + $rs = $this->_storage->hasItems($keys, $options); + $this->assertEquals($result, $rs); + } + + public function testInternalHasItemsCallsInternalHasItem() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalHasItem')); + + $options = array('ttl' => 123); + $items = array('key1' => true, 'key2' => false); + $result = array('key1'); + + $i = 0; // method call counter + foreach ($items as $k => $v) { + $this->_storage + ->expects($this->at($i++)) + ->method('internalHasItem') + ->with($this->equalTo($k), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue($v)); } - $this->assertEquals($expected, $rs); + $rs = $this->_storage->hasItems(array_keys($items), $options); + $this->assertEquals($result, $rs); } + public function testGetMetadataCallsInternalGetMetadata() + { + $this->_storage = $this->getMockForAbstractAdapter(array('internalGetMetadata')); + + $options = array('ttl' => 123); + $key = 'key1'; + $result = array(); + + $this->_storage + ->expects($this->once()) + ->method('internalGetMetadata') + ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->will($this->returnValue($result)); + + $rs = $this->_storage->getMetadata($key, $options); + $this->assertSame($result, $rs); + } + +/* public function testGetMetadatas() { $options = array('ttl' => 123); @@ -334,35 +479,6 @@ public function testGetMetadatas() $this->assertEquals($expected, $rs); } - public function testHasItem() - { - $this->_storage->expects($this->at(0)) - ->method('getItem') - ->with($this->equalTo('key')) - ->will($this->returnValue('value')); - - $this->assertTrue($this->_storage->hasItem('key')); - } - - public function testHasItems() - { - $keys = array('key1', 'key2', 'key3'); - - foreach ($keys as $i => $key) { - $this->_storage->expects($this->at($i)) - ->method('getItem') - ->with($this->equalTo($key)) - ->will( - ($i % 2) ? $this->returnValue('value') - : $this->returnValue(false) - ); - } - - $rs = $this->_storage->hasItems($keys); - $this->assertInternalType('array', $rs); - $this->assertEquals(floor(count($keys) / 2), count($rs)); - } - public function testSetItems() { $options = array('ttl' => 123); @@ -517,9 +633,66 @@ public function testRemoveItemsFail() $this->assertFalse($this->_storage->removeItems($items, $options)); } - +*/ // TODO: getDelayed + fatch[All] // TODO: incrementItem[s] + decrementItem[s] // TODO: touchItem[s] + /** + * Generates a mock of the abstract storage adapter by mocking all abstract and the given methods + * Also sets the adapter options + * + * @param array $methods + * @return \Zend\Cache\Storage\Adapter\AbstractAdapter + */ + protected function getMockForAbstractAdapter(array $methods = array()) + { + $class = 'Zend\Cache\Storage\Adapter\AbstractAdapter'; + + if (!$methods) { + $adapter = $this->getMockForAbstractClass($class); + } else { + $reflection = new \ReflectionClass('Zend\Cache\Storage\Adapter\AbstractAdapter'); + foreach ($reflection->getMethods() as $method) { + if ($method->isAbstract()) { + $methods[] = $method->getName(); + } + } + $adapter = $this->getMockBuilder($class)->setMethods(array_unique($methods))->getMock(); + } + + $adapter->setOptions($this->_options); + return $adapter; + } + + protected function normalizeOptions($options) + { + // ttl + if (!isset($options['ttl'])) { + $options['ttl'] = $this->_options->getTtl(); + } + + // namespace + if (!isset($options['namespace'])) { + $options['namespace'] = $this->_options->getNamespace(); + } + + // ignore_missing_items + if (!isset($options['ignore_missing_items'])) { + $options['ignore_missing_items'] = $this->_options->getIgnoreMissingItems(); + } + + // tags + if (!isset($options['tags'])) { + $options['tags'] = null; + } + + // select + if (!isset($options['select'])) { + $options['select'] = array('key', 'value'); + } + + return $options; + } + } diff --git a/test/Storage/TestAsset/MockAdapter.php b/test/Storage/TestAsset/MockAdapter.php index 8e6771228..4f3e4eadc 100644 --- a/test/Storage/TestAsset/MockAdapter.php +++ b/test/Storage/TestAsset/MockAdapter.php @@ -6,15 +6,11 @@ class MockAdapter extends AbstractAdapter { - public function getItem($key = null, array $options = array()) - { - } - - public function getMetadata($key = null, array $options = array()) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { } - public function setItem($value, $key = null, array $options = array()) + protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { } From 16a9bb592532b3dae64f09dddb6fbcb56aaad6cb Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 29 Feb 2012 22:33:12 +0100 Subject: [PATCH 02/62] small changes of Zend\Cache\StorageFactory::factory to not set adapter options after adding plugins --- src/StorageFactory.php | 68 ++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/src/StorageFactory.php b/src/StorageFactory.php index 4da4b8aff..b038d18b3 100644 --- a/src/StorageFactory.php +++ b/src/StorageFactory.php @@ -71,23 +71,23 @@ public static function factory($cfg) // instantiate the adapter if (!isset($cfg['adapter'])) { - throw new Exception\InvalidArgumentException( - 'Missing "adapter"' - ); - } elseif (is_array($cfg['adapter'])) { + throw new Exception\InvalidArgumentException('Missing "adapter"'); + } + $adapterName = $cfg['adapter']; + $adapterOptions = null; + if (is_array($cfg['adapter'])) { if (!isset($cfg['adapter']['name'])) { - throw new Exception\InvalidArgumentException( - 'Missing "adapter.name"' - ); + throw new Exception\InvalidArgumentException('Missing "adapter.name"'); } - $name = $cfg['adapter']['name']; - $options = isset($cfg['adapter']['options']) - ? $cfg['adapter']['options'] : array(); - $adapter = static::adapterFactory($name, $options); - } else { - $adapter = static::adapterFactory($cfg['adapter']); + $adapterName = $cfg['adapter']['name']; + $adapterOptions = isset($cfg['adapter']['options']) ? $cfg['adapter']['options'] : null; } + if ($adapterOptions && isset($cfg['options'])) { + $adapterOptions = array_merge($adapterOptions, $cfg['options']); + } + + $adapter = static::adapterFactory($adapterName, $adapterOptions); // add plugins if (isset($cfg['plugins'])) { @@ -99,50 +99,33 @@ public static function factory($cfg) foreach ($cfg['plugins'] as $k => $v) { if (is_string($k)) { - $name = $k; - if (!is_array($v)) { - throw new Exception\InvalidArgumentException( - "'plugins.{$k}' needs to be an array" - ); + if (!is_array($v)) { + throw new Exception\InvalidArgumentException( + "'plugins.{$k}' needs to be an array" + ); } - $options = $v; + $pluginName = $k; + $pluginOptions = $v; } elseif (is_array($v)) { if (!isset($v['name'])) { throw new Exception\InvalidArgumentException("Invalid plugins[{$k}] or missing plugins[{$k}].name"); } - $name = (string) $v['name']; + $pluginName = (string) $v['name']; if (isset($v['options'])) { - $options = $v['options']; + $pluginOptions = $v['options']; } else { - $options = array(); + $pluginOptions = array(); } } else { - $name = $v; - $options = array(); + $pluginName = $v; + $pluginOptions = array(); } - $plugin = static::pluginFactory($name, $options); + $plugin = static::pluginFactory($pluginName, $pluginOptions); $adapter->addPlugin($plugin); } } - // set adapter or plugin options - if (isset($cfg['options'])) { - if (!is_array($cfg['options']) - && !$cfg['options'] instanceof Traversable - ) { - throw new Exception\InvalidArgumentException( - 'Options needs to be an array or Traversable object' - ); - } - - // Options at the top-level should be *merged* with existing options - $options = $adapter->getOptions(); - foreach ($cfg['options'] as $key => $value) { - $options->$key = $value; - } - } - return $adapter; } @@ -227,6 +210,7 @@ public static function pluginFactory($pluginName, $options = array()) } $plugin->setOptions($options); + return $plugin; } From f471b3f586ea151fdfc3b4a66d70d22700c0ee5e Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 29 Feb 2012 22:58:55 +0100 Subject: [PATCH 03/62] Zend\Cache\StorageFactoryTest: iterator index not the same as the array index --- test/StorageFactoryTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/StorageFactoryTest.php b/test/StorageFactoryTest.php index 9e06cc596..c39cf6d56 100644 --- a/test/StorageFactoryTest.php +++ b/test/StorageFactoryTest.php @@ -114,8 +114,9 @@ public function testFactoryWithPlugins() $this->assertInstanceOf('Zend\Cache\Storage\Adapter\Memory', $cache); // test plugin structure - foreach ($cache->getPlugins() as $i => $plugin) { - $this->assertInstanceOf('Zend\Cache\Storage\Plugin\\' . $plugins[$i], $plugin); + $i = 0; + foreach ($cache->getPlugins() as $plugin) { + $this->assertInstanceOf('Zend\Cache\Storage\Plugin\\' . $plugins[$i++], $plugin); } } From 9208ac0d96391304ff860fab249c645c828a9b60 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 1 Mar 2012 07:59:53 +0100 Subject: [PATCH 04/62] Make it possible to disable memory_limit of the memory cache adapter to not set it up to 1gb on tests --- src/Storage/Adapter/Memory.php | 6 ++++++ src/Storage/Adapter/MemoryOptions.php | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Storage/Adapter/Memory.php b/src/Storage/Adapter/Memory.php index 9517dde6e..f591fedd7 100644 --- a/src/Storage/Adapter/Memory.php +++ b/src/Storage/Adapter/Memory.php @@ -1403,6 +1403,12 @@ public function getCapacity(array $options = array()) protected function hasFreeCapacity() { $total = $this->getOptions()->getMemoryLimit(); + + // check memory limit disabled + if ($total <= 0) { + return true; + } + $free = $total - (float) memory_get_usage(true); return ($free > 0); } diff --git a/src/Storage/Adapter/MemoryOptions.php b/src/Storage/Adapter/MemoryOptions.php index f9c7f81ee..f6355dcbe 100644 --- a/src/Storage/Adapter/MemoryOptions.php +++ b/src/Storage/Adapter/MemoryOptions.php @@ -45,8 +45,9 @@ class MemoryOptions extends AdapterOptions /** * Set memory limit * - * If the used memory of PHP exceeds this limit an OutOfCapacityException - * will be thrown. + * - Bytes of less or equal 0 will disable the memory limit + * - If the used memory of PHP exceeds this limit an OutOfCapacityException + * will be thrown. * * @param int $bytes * @return MemoryOptions @@ -72,8 +73,8 @@ public function getMemoryLimit() if ($memoryLimit >= 0) { $this->memoryLimit = floor($memoryLimit / 2); } else { - // use a hard memory limit of 32M if php memory limit is disabled - $this->memoryLimit = 33554432; + // disable memory limit + $this->memoryLimit = 0; } } From e397d3029d872b61c630fec6bc23398e082fbf2b Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 1 Mar 2012 22:07:34 +0100 Subject: [PATCH 05/62] cache factories have to instantiate a new object each time called + tests --- src/PatternFactory.php | 13 ++----------- src/StorageFactory.php | 6 +++--- test/PatternFactoryTest.php | 11 +++++++++++ test/StorageFactoryTest.php | 20 ++++++++++++++++---- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/PatternFactory.php b/src/PatternFactory.php index c44dfe71c..28ae2911c 100644 --- a/src/PatternFactory.php +++ b/src/PatternFactory.php @@ -82,7 +82,8 @@ public static function factory($patternName, $options = array()) public static function getBroker() { if (static::$broker === null) { - static::$broker = static::getDefaultBroker(); + static::$broker = new PatternBroker(); + static::$broker->setRegisterPluginsOnLoad(false); } return static::$broker; @@ -108,14 +109,4 @@ public static function resetBroker() { static::$broker = null; } - - /** - * Get internal pattern broker - * - * @return PatternBroker - */ - protected static function getDefaultBroker() - { - return new PatternBroker(); - } } diff --git a/src/StorageFactory.php b/src/StorageFactory.php index b038d18b3..5372ad874 100644 --- a/src/StorageFactory.php +++ b/src/StorageFactory.php @@ -87,7 +87,7 @@ public static function factory($cfg) $adapterOptions = array_merge($adapterOptions, $cfg['options']); } - $adapter = static::adapterFactory($adapterName, $adapterOptions); + $adapter = static::adapterFactory((string)$adapterName, $adapterOptions); // add plugins if (isset($cfg['plugins'])) { @@ -185,7 +185,7 @@ public static function setAdapterBroker(Broker $broker) */ public static function resetAdapterBroker() { - static::$adapterBroker = new Storage\AdapterBroker(); + static::$adapterBroker = null; } /** @@ -246,6 +246,6 @@ public static function setPluginBroker(Broker $broker) */ public static function resetPluginBroker() { - static::$pluginBroker = new Storage\PluginBroker(); + static::$pluginBroker = null; } } diff --git a/test/PatternFactoryTest.php b/test/PatternFactoryTest.php index 4009aaa0e..ee66ea314 100644 --- a/test/PatternFactoryTest.php +++ b/test/PatternFactoryTest.php @@ -57,4 +57,15 @@ public function testChangeBroker() $this->assertSame($broker, Cache\PatternFactory::getBroker()); } + public function testFactory() + { + $pattern1 = Cache\PatternFactory::factory('capture'); + $this->assertInstanceOf('Zend\Cache\Pattern\CaptureCache', $pattern1); + + $pattern2 = Cache\PatternFactory::factory('capture'); + $this->assertInstanceOf('Zend\Cache\Pattern\CaptureCache', $pattern2); + + $this->assertNotSame($pattern1, $pattern2); + } + } diff --git a/test/StorageFactoryTest.php b/test/StorageFactoryTest.php index c39cf6d56..fd62ca36d 100644 --- a/test/StorageFactoryTest.php +++ b/test/StorageFactoryTest.php @@ -42,6 +42,8 @@ public function setUp() public function tearDown() { + Cache\StorageFactory::resetAdapterBroker(); + Cache\StorageFactory::resetPluginBroker(); } public function testDefaultAdapterBroker() @@ -59,8 +61,13 @@ public function testChangeAdapterBroker() public function testAdapterFactory() { - $cache = Cache\StorageFactory::adapterFactory('Memory'); - $this->assertInstanceOf('Zend\Cache\Storage\Adapter\Memory', $cache); + $adapter1 = Cache\StorageFactory::adapterFactory('Memory'); + $this->assertInstanceOf('Zend\Cache\Storage\Adapter\Memory', $adapter1); + + $adapter2 = Cache\StorageFactory::adapterFactory('Memory'); + $this->assertInstanceOf('Zend\Cache\Storage\Adapter\Memory', $adapter2); + + $this->assertNotSame($adapter1, $adapter2); } public function testDefaultPluginBroker() @@ -78,8 +85,13 @@ public function testChangePluginBroker() public function testPluginFactory() { - $plugin = Cache\StorageFactory::pluginFactory('Serializer'); - $this->assertInstanceOf('Zend\Cache\Storage\Plugin\Serializer', $plugin); + $plugin1 = Cache\StorageFactory::pluginFactory('Serializer'); + $this->assertInstanceOf('Zend\Cache\Storage\Plugin\Serializer', $plugin1); + + $plugin2 = Cache\StorageFactory::pluginFactory('Serializer'); + $this->assertInstanceOf('Zend\Cache\Storage\Plugin\Serializer', $plugin2); + + $this->assertNotSame($plugin1, $plugin2); } public function testFactoryAdapterAsString() From 1786d34e0a80456e94cc2828bdefb15804d840f8 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 16 Mar 2012 23:03:36 +0100 Subject: [PATCH 06/62] Cache internals: Now all events will be triggered by abstract adapter and calls a protected method which can have to be implemented / overwritten within specific adapters. This also fixes problems if pre-implemented methods at abstract adapter triggering wrong events. (like getItems triggered getItem events of each item) --- src/Storage/Adapter.php | 38 +- src/Storage/Adapter/AbstractAdapter.php | 1501 +++++++++++++++++--- src/Storage/Adapter/AbstractZendServer.php | 226 +-- src/Storage/Adapter/Apc.php | 923 ++++-------- src/Storage/Adapter/Filesystem.php | 1077 +++++++------- src/Storage/Adapter/Memcached.php | 786 ++++------ src/Storage/Adapter/Memory.php | 996 ++++--------- src/Storage/Adapter/WinCache.php | 565 +++----- src/Storage/Adapter/ZendServerDisk.php | 27 +- src/Storage/Adapter/ZendServerShm.php | 38 +- 10 files changed, 2920 insertions(+), 3257 deletions(-) diff --git a/src/Storage/Adapter.php b/src/Storage/Adapter.php index 94dacc043..1b8dbd3ee 100644 --- a/src/Storage/Adapter.php +++ b/src/Storage/Adapter.php @@ -210,7 +210,7 @@ public function addItem($key, $value, array $options = array()); public function addItems(array $keyValuePairs, array $options = array()); /** - * Replace an item. + * Replace an existing item. * * @param string $key * @param mixed $value @@ -221,7 +221,7 @@ public function addItems(array $keyValuePairs, array $options = array()); public function replaceItem($key, $value, array $options = array()); /** - * Replace multiple items. + * Replace multiple existing items. * * @param array $keyValuePairs * @param array $options @@ -231,15 +231,15 @@ public function replaceItem($key, $value, array $options = array()); public function replaceItems(array $keyValuePairs, array $options = array()); /** - * Set item only if token matches + * Set an item only if token matches * - * It uses the token from received from getItem() to check if the item has + * It uses the token received from getItem() to check if the item has * changed before overwriting it. * - * @param mixed $token - * @param string|null $key - * @param mixed $value - * @param array $options + * @param mixed $token + * @param string $key + * @param mixed $value + * @param array $options * @return boolean * @throws \Zend\Cache\Exception * @see getItem() @@ -251,7 +251,7 @@ public function checkAndSetItem($token, $key, $value, array $options = array()); * Reset lifetime of an item * * @param string $key - * @param array $options + * @param array $options * @return boolean * @throws \Zend\Cache\Exception */ @@ -271,7 +271,7 @@ public function touchItems(array $keys, array $options = array()); * Remove an item. * * @param string $key - * @param array $options + * @param array $options * @return boolean * @throws \Zend\Cache\Exception */ @@ -291,9 +291,9 @@ public function removeItems(array $keys, array $options = array()); * Increment an item. * * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value of false on failure + * @param int $value + * @param array $options + * @return int|boolean The new value or false on failure * @throws \Zend\Cache\Exception */ public function incrementItem($key, $value, array $options = array()); @@ -312,9 +312,9 @@ public function incrementItems(array $keyValuePairs, array $options = array()); * Decrement an item. * * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value or false or failure + * @param int $value + * @param array $options + * @return int|boolean The new value or false on failure * @throws \Zend\Cache\Exception */ public function decrementItem($key, $value, array $options = array()); @@ -346,7 +346,7 @@ public function getDelayed(array $keys, array $options = array()); /** * Find items. * - * @param int $mode Matching mode (Value of Adapter::*) + * @param int $mode Matching mode (Value of Adapter::MATCH_*) * @param array $options * @return boolean * @throws \Zend\Cache\Exception @@ -378,7 +378,7 @@ public function fetchAll(); /** * Clear items off all namespaces. * - * @param int $mode Matching mode (Value of Adapter::MATCH_*) + * @param int $mode Matching mode (Value of Adapter::MATCH_*) * @param array $options * @return boolean * @throws \Zend\Cache\Exception @@ -389,7 +389,7 @@ public function clear($mode = self::MATCH_EXPIRED, array $options = array()); /** * Clear items by namespace. * - * @param int $mode Matching mode (Value of Adapter::MATCH_*) + * @param int $mode Matching mode (Value of Adapter::MATCH_*) * @param array $options * @return boolean * @throws \Zend\Cache\Exception diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 896ad11ac..f0317e22b 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -788,6 +788,8 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal * - The time-to-life (Default: ttl of object) * - namespace optional * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags * * @param string $key * @param mixed $value @@ -834,6 +836,8 @@ public function setItem($key, $value, array $options = array()) * - The time-to-life * - namespace * - The namespace to use + * - tags + * - An array of tags * * @param string $normalizedKey * @param mixed $value @@ -851,6 +855,8 @@ abstract protected function internalSetItem(& $normalizedKey, & $value, array & * - The time-to-life (Default: ttl of object) * - namespace optional * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags * * @param array $keyValuePairs * @param array $options @@ -867,6 +873,7 @@ public function setItems(array $keyValuePairs, array $options = array()) return false; } + $this->normalizeKeyValuePairs($keyValuePairs); $this->normalizeOptions($options); $args = new ArrayObject(array( 'keyValuePairs' => & $keyValuePairs, @@ -894,6 +901,8 @@ public function setItems(array $keyValuePairs, array $options = array()) * - The time-to-life * - namespace * - The namespace to use + * - tags + * - An array of tags * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions @@ -910,28 +919,97 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n } /** - * Add an item + * Add an item. * - * @param string|int $key - * @param mixed $value - * @param array $options - * @return bool - * @throws Exception\RuntimeException + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers addItem.pre(PreEvent) + * @triggers addItem.post(PostEvent) + * @triggers addItem.exception(ExceptionEvent) */ public function addItem($key, $value, array $options = array()) { - if ($this->hasItem($key, $options)) { - throw new Exception\RuntimeException("Key '{$key}' already exists"); + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'value' => & $value, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalAddItem($key, $value, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to add an item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) + { + if ($this->internalHasItem($normalizedKey, $normalizedOptions)) { + throw new Exception\RuntimeException("Key '{$normalizedKey}' already exists"); } - return $this->setItem($key, $value, $options); + return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); } /** - * Add items + * Add multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags * * @param array $keyValuePairs * @param array $options - * @return bool + * @return boolean + * @throws Exception + * + * @triggers addItems.pre(PreEvent) + * @triggers addItems.post(PostEvent) + * @triggers addItems.exception(ExceptionEvent) */ public function addItems(array $keyValuePairs, array $options = array()) { @@ -939,38 +1017,144 @@ public function addItems(array $keyValuePairs, array $options = array()) return false; } - $ret = true; - foreach ($keyValuePairs as $key => $value) { - $ret = $this->addItem($key, $value, $options) && $ret; + $this->normalizeKeyValuePairs($keyValuePairs); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keyValuePairs' => & $keyValuePairs, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalAddItems($keyValuePairs, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); } + } + /** + * Internal method to add multiple items. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + { + $ret = true; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $ret = $this->internalAddItem($normalizedKey, $value, $normalizedOptions) && $ret; + } return $ret; } /** - * Replace an item + * Replace an existing item. * - * @param string|int $key - * @param mixed $value - * @param array $options - * @return bool - * @throws Exception\ItemNotFoundException + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers replaceItem.pre(PreEvent) + * @triggers replaceItem.post(PostEvent) + * @triggers replaceItem.exception(ExceptionEvent) */ public function replaceItem($key, $value, array $options = array()) { - if (!$this->hasItem($key, $options)) { - throw new Exception\ItemNotFoundException("Key '{$key}' doen't exists"); + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'value' => & $value, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalReplaceItem($key, $value, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to replace an existing item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) + { + if (!$this->internalhasItem($normalizedKey, $normalizedOptions)) { + throw new Exception\ItemNotFoundException("Key '{$normalizedKey}' doesn't exists"); } - return $this->setItem($key, $value, $options); + return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); } /** - * Replace items + * Replace multiple existing items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags * * @param array $keyValuePairs * @param array $options - * @return bool + * @return boolean + * @throws Exception + * + * @triggers replaceItems.pre(PreEvent) + * @triggers replaceItems.post(PostEvent) + * @triggers replaceItems.exception(ExceptionEvent) */ public function replaceItems(array $keyValuePairs, array $options = array()) { @@ -978,190 +1162,705 @@ public function replaceItems(array $keyValuePairs, array $options = array()) return false; } - $ret = true; - foreach ($keyValuePairs as $key => $value) { - $ret = $this->replaceItem($key, $value, $options) && $ret; + $this->normalizeKeyValuePairs($keyValuePairs); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keyValuePairs' => & $keyValuePairs, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalReplaceItems($keyValuePairs, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to replace multiple existing items. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalReplaceItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + { + $ret = true; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $ret = $this->internalReplaceItem($normalizedKey, $value, $normalizedOptions) && $ret; + } + + return $ret; + } + + /** + * Set an item only if token matches + * + * It uses the token received from getItem() to check if the item has + * changed before overwriting it. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param mixed $token + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * @see getItem() + * @see setItem() + */ + public function checkAndSetItem($token, $key, $value, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'value' => & $value, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalCheckAndSetItem($token, $key, $value, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to set an item only if token matches + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param mixed $token + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see getItem() + * @see setItem() + */ + protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) + { + $oldValue = $this->internalGetItem($normalizedKey, $normalizedOptions); + if ($oldValue !== $token) { + return false; + } + + return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); + } + + /** + * Reset lifetime of an item + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param string $key + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers touchItem.pre(PreEvent) + * @triggers touchItem.post(PostEvent) + * @triggers touchItem.exception(ExceptionEvent) + */ + public function touchItem($key, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalTouchItem($key, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to reset lifetime of an item + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) + { + // do not test validity on reading + // $optsNoValidate = array('ttl' => 0) + $normalizedOptions; + + $value = $this->internalGetItem($normalizedKey, $normalizedOptions); + if ($value === false) { + // add an empty item + $value = ''; + return $this->internalAddItem($normalizedKey, $value, $normalizedOptions); + } + + // rewrite item to update mtime/ttl + if (!isset($normalizedOptions['tags'])) { + $info = $this->internalGetMetadata($normalizedKey, $normalizedOptions); + if (isset($info['tags'])) { + $normalizedOptions['tags'] = & $info['tags']; + } + } + + return $this->internalReplaceItem($normalizedKey, $value, $normalizedOptions); + } + + /** + * Reset lifetime of multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param array $keys + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers touchItems.pre(PreEvent) + * @triggers touchItems.post(PostEvent) + * @triggers touchItems.exception(ExceptionEvent) + */ + public function touchItems(array $keys, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeKeys($keys); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalTouchItems($keys, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to reset lifetime of multiple items. + * + * Options: + * - ttl + * - The namespace to us + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalTouchItems(array & $normalizedKeys, array & $normalizedOptions) + { + $ret = true; + foreach ($normalizedKeys as $normalizedKey) { + $ret = $this->internalTouchItem($normalizedKey, $normalizedOptions) && $ret; + } + return $ret; + } + + /** + * Remove an item. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item + * + * @param string $key + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers removeItem.pre(PreEvent) + * @triggers removeItem.post(PostEvent) + * @triggers removeItem.exception(ExceptionEvent) + */ + public function removeItem($key, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalRemoveItem($key, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to remove an item. + * + * Options: + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + abstract protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions); + + /** + * Remove multiple items. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item + * + * @param array $keys + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers removeItems.pre(PreEvent) + * @triggers removeItems.post(PostEvent) + * @triggers removeItems.exception(ExceptionEvent) + */ + public function removeItems(array $keys, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKeys($keys); + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalRemoveItems($keys, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to remove multiple items. + * + * Options: + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param array $keys + * @param array $options + * @return boolean + * @throws Exception + */ + protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) + { + $ret = true; + $missingKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + try { + $ret = $this->internalRemoveItem($normalizedKey, $normalizedOptions) && $ret; + } catch (Exception\ItemNotFoundException $e) { + $missingKeys[] = $normalizedKey; + } + } + + if ($missingKeys) { + throw new Exception\ItemNotFoundException( + "Keys '".implode(',', $missingKeys)."' not found within namespace '{$normalizedOptions['namespace']}'" + ); + } + + return $ret; + } + + /** + * Increment an item. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item + * + * @param string $key + * @param int $value + * @param array $options + * @return int|boolean The new value or false on failure + * @throws Exception + * + * @triggers incrementItem.pre(PreEvent) + * @triggers incrementItem.post(PostEvent) + * @triggers incrementItem.exception(ExceptionEvent) + */ + public function incrementItem($key, $value, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'value' => & $value, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalIncrementItem($key, $value, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); } - - return $ret; } /** - * Check and set item + * Internal method to increment an item. * - * @param mixed $token - * @param string $key - * @param mixed $value - * @param array $options - * @return bool + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure + * @throws Exception */ - public function checkAndSetItem($token, $key, $value, array $options = array()) + protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $oldValue = $this->getItem($key, $options); - if ($oldValue != $token) { - return false; - } - - return $this->setItem($key, $value, $options); + $value = (int) $value; + $get = (int) $this->internalGetItem($normalizedKey, $normalizedOptions); + $newValue = $get + $value; + $this->internalSetItem($normalizedKey, $newValue, $normalizedOptions); + return $newValue; } /** - * Touch an item + * Increment multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item * - * @param string|int $key + * @param array $keyValuePairs * @param array $options - * @return bool + * @return boolean + * @throws Exception + * + * @triggers incrementItems.pre(PreEvent) + * @triggers incrementItems.post(PostEvent) + * @triggers incrementItems.exception(ExceptionEvent) */ - public function touchItem($key, array $options = array()) + public function incrementItems(array $keyValuePairs, array $options = array()) { - $classOptions = $this->getOptions(); - if (!$classOptions->getWritable() || !$classOptions->getReadable()) { - return false; - } + if (!$this->getOptions()->getWritable()) { + return false; + } - // do not test validity on reading - $optsNoValidate = array('ttl' => 0) + $options; + $this->normalizeOptions($options); + $this->normalizeKeyValuePairs($keyValuePairs); + $args = new ArrayObject(array( + 'keyValuePairs' => & $keyValuePairs, + 'options' => & $options, + )); - $value = $this->getItem($key, $optsNoValidate); - if ($value === false) { - // add an empty item - return $this->addItem($key, '', $options); - } else { - // rewrite item to update mtime/ttl - if (!isset($options['tags'])) { - $info = $this->getMetadata($key, $optsNoValidate); - if (isset($info['tags'])) { - $options['tags'] = & $info['tags']; - } + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); } - // rewrite item - return $this->replaceItem($key, $value, $options); + $result = $this->internatIncrementItems($keyValuePairs, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); } } /** - * Touch items + * Internal method to increment multiple items. * - * @param array $keys - * @param array $options - * @return bool + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception */ - public function touchItems(array $keys, array $options = array()) + protected function internatIncrementItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - // Don't check readable because not all adapters needs to read the item before - if (!$this->getOptions()->getWritable()) { - return false; - } - $ret = true; - foreach ($keys as $key) { - $ret = $this->touchItem($key, $options) && $ret; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $ret = ($this->incrementItem($normalizedKey, $value, $normalizedOptions) !== false) && $ret; } return $ret; } /** - * Remove multiple items. + * Decrement an item. * - * @param array $keys - * @param array $options - * @return bool + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item + * + * @param string $key + * @param int $value + * @param array $options + * @return int|boolean The new value or false on failure + * @throws Exception + * + * @triggers decrementItem.pre(PreEvent) + * @triggers decrementItem.post(PostEvent) + * @triggers decrementItem.exception(ExceptionEvent) */ - public function removeItems(array $keys, array $options = array()) + public function decrementItem($key, $value, array $options = array()) { if (!$this->getOptions()->getWritable()) { return false; } - $ret = true; - foreach ($keys as $key) { - $ret = $this->removeItem($key, $options) && $ret; - } + $this->normalizeOptions($options); + $this->normalizeKey($key); + $args = new ArrayObject(array( + 'key' => & $key, + 'value' => & $value, + 'options' => & $options, + )); - return $ret; + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalDecrementItem($key, $value, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } } /** - * Increment an item + * Internal method to decrement an item. * - * @param string|int $key - * @param int|float $value - * @param array $options - * @return bool|int + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure + * @throws Exception */ - public function incrementItem($key, $value, array $options = array()) + protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $classOptions = $this->getOptions(); - if (!$classOptions->getWritable() || !$classOptions->getReadable()) { - return false; - } - - $value = (int) $value; - $get = (int) $this->getItem($key, $options); - $this->setItem($key, $get + $value, $options); - return $get + $value; + $value = (int) $value; + $get = (int) $this->internalGetItem($normalizedKey, $normalizedOptions); + $newValue = $get - $value; + $this->internalSetItem($normalizedKey, $newValue, $normalizedOptions); + return $newValue; } /** - * Increment items + * Decrement multiple items. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item * * @param array $keyValuePairs * @param array $options - * @return bool + * @return boolean + * @throws Exception + * + * @triggers incrementItems.pre(PreEvent) + * @triggers incrementItems.post(PostEvent) + * @triggers incrementItems.exception(ExceptionEvent) */ - public function incrementItems(array $keyValuePairs, array $options = array()) + public function decrementItems(array $keyValuePairs, array $options = array()) { - // Don't check readable because not all adapters needs read the value before if (!$this->getOptions()->getWritable()) { return false; } - $ret = true; - foreach ($keyValuePairs as $key => $value) { - $ret = $this->incrementItem($key, $value, $options) && $ret; - } - return $ret; - } + $this->normalizeOptions($options); + $this->normalizeKeyValuePairs($keyValuePairs); + $args = new ArrayObject(array( + 'keyValuePairs' => & $keyValuePairs, + 'options' => & $options, + )); - /** - * Decrement an item - * - * @param string|int $key - * @param int|float $value - * @param array $options - * @return bool|int - */ - public function decrementItem($key, $value, array $options = array()) - { - $classOptions = $this->getOptions(); - if (!$classOptions->getWritable() || !$classOptions->getReadable()) { - return false; - } + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } - $value = (int) $value; - $get = (int) $this->getItem($key, $options); - $this->setItem($key, $get - $value, $options); - return $get - $value; + $result = $this->internatDecrementItems($keyValuePairs, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } } /** - * Decrement items + * Internal method to decrement multiple items. * - * @param array $keyValuePairs - * @param array $options - * @return bool + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception */ - public function decrementItems(array $keyValuePairs, array $options = array()) + protected function internatDecrementItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - // Don't check readable because not all adapters needs read the value before - if (!$this->getOptions()->getWritable()) { - return false; - } - $ret = true; - foreach ($keyValuePairs as $key => $value) { - $ret = $this->decrementItem($key, $value, $options) && $ret; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $ret = ($this->decrementItem($normalizedKey, $value, $normalizedOptions) !== false) && $ret; } return $ret; } @@ -1169,7 +1868,7 @@ public function decrementItems(array $keyValuePairs, array $options = array()) /* non-blocking */ /** - * Get delayed + * Request multiple items. * * Options: * - ttl optional @@ -1184,67 +1883,202 @@ public function decrementItems(array $keyValuePairs, array $options = array()) * - The first argument will be the item array. * - The callback does not have to return anything. * - * @param array $keys - * @param array $options - * @return bool - * @throws Exception\InvalidArgumentException|Exception\RuntimeException + * @param array $keys + * @param array $options + * @return boolean + * @throws Exception + * @see fetch() + * @see fetchAll() + * + * @triggers getDelayed.pre(PreEvent) + * @triggers getDelayed.post(PostEvent) + * @triggers getDelayed.exception(ExceptionEvent) */ public function getDelayed(array $keys, array $options = array()) { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - if (!$this->getOptions()->getReadable()) { return false; } elseif (!$keys) { // empty statement return true; } - - $this->normalizeOptions($options); - if (!isset($options['select'])) { - $options['select'] = array('key', 'value'); - } - - $this->stmtOptions = array_merge($this->getOptions()->toArray(), $options); - $this->stmtKeys = $keys; - $this->stmtActive = true; - - if (isset($options['callback'])) { - $callback = $options['callback']; - if (!is_callable($callback, false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - - while ( ($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } - } - - return true; + + $this->normalizeKeys($keys); + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'keys' => & $keys, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetDelayed($keys, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to request multiple items. + * + * Options: + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use + * - select + * - An array of the information the returned item contains + * - callback optional + * - An result callback will be invoked for each item in the result set. + * - The first argument will be the item array. + * - The callback does not have to return anything. + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see fetch() + * @see fetchAll() + */ + protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) + { + if ($this->stmtActive) { + throw new Exception\RuntimeException('Statement already in use'); + } + + $this->stmtOptions = array_merge($this->getOptions()->toArray(), $normalizedOptions); + $this->stmtKeys = & $normalizedKeys; + $this->stmtActive = true; + + if (isset($normalizedOptions['callback'])) { + $callback = $normalizedOptions['callback']; + if (!is_callable($callback, false)) { + throw new Exception\InvalidArgumentException('Invalid callback'); + } + + while ( ($item = $this->fetch()) !== false) { + call_user_func($callback, $item); + } + } + + return true; } - /* find */ + /* find */ + + /** + * Find items. + * + * Options: + * - ttl optional + * - The time-to-live (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - Tags to search for used with matching modes of + * Adapter::MATCH_TAGS_* + * + * @param int $mode Matching mode (Value of Adapter::MATCH_*) + * @param array $options + * @return boolean + * @throws Exception + * @see fetch() + * @see fetchAll() + * + * @triggers find.pre(PreEvent) + * @triggers find.post(PostEvent) + * @triggers find.exception(ExceptionEvent) + */ + public function find($mode = self::MATCH_ACTIVE, array $options = array()) + { + if (!$this->getOptions()->getReadable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeMatchingMode($mode, self::MATCH_ACTIVE, $options); + $args = new ArrayObject(array( + 'mode' => & $mode, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalFind($mode, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } /** - * Find + * internal method to find items. * - * @param int $mode - * @param array $options - * @throws Exception\UnsupportedMethodCallException + * Options: + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use + * - tags + * - Tags to search for used with matching modes of + * Adapter::MATCH_TAGS_* + * + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see fetch() + * @see fetchAll() */ - public function find($mode = self::MATCH_ACTIVE, array $options = array()) + protected function internalFind(& $normalizedMode, array & $normalizedOptions) { throw new Exception\UnsupportedMethodCallException('find isn\'t supported by this adapter'); } /** - * Fetch + * Fetches the next item from result set * - * @return array|bool + * @return array|boolean The next item or false + * @throws Exception + * @see fetchAll() + * + * @triggers fetch.pre(PreEvent) + * @triggers fetch.post(PostEvent) + * @triggers fetch.exception(ExceptionEvent) */ public function fetch() + { + $args = new ArrayObject(); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalFetch(); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to fetch the next item from result set + * + * @return array|boolean The next item or false + * @throws Exception + */ + protected function internalFetch() { if (!$this->stmtActive) { return false; @@ -1264,7 +2098,7 @@ public function fetch() if ($select == 'key') { $item['key'] = $key; } elseif ($select == 'value') { - $value = $this->getItem($key, $options); + $value = $this->internalGetItem($key, $options); if ($value === false) { $exist = false; break; @@ -1273,7 +2107,7 @@ public function fetch() $item['value'] = $value; } else { if ($info === null) { - $info = $this->getMetadata($key, $options); + $info = $this->internalGetMetadata($key, $options); if ($info === false) { $exist = false; break; @@ -1285,9 +2119,7 @@ public function fetch() } // goto next if not exists - if ($exist === false - || ($exist === null && !$this->hasItem($key, $options)) - ) { + if ($exist === false || ($exist === null && !$this->internalHasItem($key, $options))) { continue; } @@ -1303,14 +2135,44 @@ public function fetch() } /** - * Fetch all + * Returns all items of result set. * - * @return array + * @return array The result set as array containing all items + * @throws Exception + * @see fetch() + * + * @triggers fetchAll.pre(PreEvent) + * @triggers fetchAll.post(PostEvent) + * @triggers fetchAll.exception(ExceptionEvent) */ public function fetchAll() + { + $args = new ArrayObject(); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalFetchAll(); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to return all items of result set. + * + * @return array The result set as array containing all items + * @throws Exception + * @see fetch() + */ + protected function internalFetchAll() { $rs = array(); - while (($item = $this->fetch()) !== false) { + while (($item = $this->internalFetch()) !== false) { $rs[] = $item; } return $rs; @@ -1319,13 +2181,66 @@ public function fetchAll() /* cleaning */ /** - * Clear + * Clear items off all namespaces. * - * @param int $mode + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - tags optional + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* + * + * @param int $mode Matching mode (Value of Adapter::MATCH_*) * @param array $options - * @throws Exception\RuntimeException + * @return boolean + * @throws Exception + * @see clearByNamespace() + * + * @triggers clear.pre(PreEvent) + * @triggers clear.post(PostEvent) + * @triggers clear.exception(ExceptionEvent) */ public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); + $args = new ArrayObject(array( + 'mode' => & $mode, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalClear($mode, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to clear items off all namespaces. + * + * Options: + * - ttl + * - The time-to-life + * - tags + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* + * + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see clearByNamespace() + */ + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { throw new Exception\RuntimeException( "This adapter doesn't support to clear items off all namespaces" @@ -1333,13 +2248,70 @@ public function clear($mode = self::MATCH_EXPIRED, array $options = array()) } /** - * Clear by namespace + * Clear items by namespace. + * + * Options: + * - ttl optional + * - The time-to-life (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* * - * @param int $mode + * @param int $mode Matching mode (Value of Adapter::MATCH_*) * @param array $options - * @throws Exception\RuntimeException + * @return boolean + * @throws Exception + * @see clear() + * + * @triggers clearByNamespace.pre(PreEvent) + * @triggers clearByNamespace.post(PostEvent) + * @triggers clearByNamespace.exception(ExceptionEvent) */ public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $this->normalizeOptions($options); + $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); + $args = new ArrayObject(array( + 'mode' => & $mode, + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalClearByNamespace($mode, $options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Clear items by namespace. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* + * + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see clear() + */ + protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) { throw new Exception\RuntimeException( "This adapter doesn't support to clear items by namespace" @@ -1347,12 +2319,53 @@ public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = a } /** - * Optimize + * Optimize adapter storage. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) * * @param array $options - * @return bool + * @return boolean + * @throws Exception + * + * @triggers optimize.pre(PreEvent) + * @triggers optimize.post(PostEvent) + * @triggers optimize.exception(ExceptionEvent) */ public function optimize(array $options = array()) + { + if (!$this->getOptions()->getWritable()) { + return false; + } + + $args = new ArrayObject(); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalOptimize(); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to optimize adapter storage. + * + * Options: + * - namespace + * - The namespace to use + * + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalOptimize(array & $normalizedOptions) { return true; } @@ -1363,8 +2376,33 @@ public function optimize(array $options = array()) * 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); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetCapabilities(); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to get capabilities of this adapter + * + * @return Capabilities + */ + protected function internalGetCapabilities() { if ($this->capabilities === null) { $this->capabilityMarker = new stdClass(); @@ -1373,12 +2411,53 @@ public function getCapabilities() return $this->capabilities; } + /** + * Get storage capacity. + * + * @param array $options + * @return array|boolean Capacity as array or false on failure + * @throws Exception + * + * @triggers getCapacity.pre(PreEvent) + * @triggers getCapacity.post(PostEvent) + * @triggers getCapacity.exception(ExceptionEvent) + */ + public function getCapacity(array $options = array()) + { + $this->normalizeOptions($options); + $args = new ArrayObject(array( + 'options' => & $options, + )); + + try { + $eventRs = $this->triggerPre(__FUNCTION__, $args); + if ($eventRs->stopped()) { + return $eventRs->last(); + } + + $result = $this->internalGetCapacity($options); + return $this->triggerPost(__FUNCTION__, $args, $result); + } catch (\Exception $e) { + return $this->triggerException(__FUNCTION__, $args, $e); + } + } + + /** + * Internal method to get storage capacity. + * + * @param array $normalizedOptions + * @return array|boolean Capacity as array or false on failure + * @throws Exception + */ + abstract protected function internalGetCapacity(array & $normalizedOptions); + /* internal */ /** * Validates and normalizes the $options argument * * @param array $options + * @return void */ protected function normalizeOptions(array &$options) { @@ -1424,6 +2503,7 @@ protected function normalizeOptions(array &$options) * Validates and normalize a TTL. * * @param int|float $ttl + * @return void * @throws Exception\InvalidArgumentException */ protected function normalizeTtl(&$ttl) @@ -1446,6 +2526,7 @@ protected function normalizeTtl(&$ttl) * Validates and normalize a namespace. * * @param string $namespace + * @return void * @throws Exception\InvalidArgumentException */ protected function normalizeNamespace(&$namespace) @@ -1465,6 +2546,7 @@ protected function normalizeNamespace(&$namespace) * Validates and normalize tags array * * @param array $tags + * @return void * @throws Exception\InvalidArgumentException */ protected function normalizeTags(&$tags) @@ -1487,6 +2569,7 @@ protected function normalizeTags(&$tags) * Validates and normalize select array * * @param string[]|string + * @return void */ protected function normalizeSelect(&$select) { @@ -1503,6 +2586,7 @@ protected function normalizeSelect(&$select) * @todo normalize matching mode with given tags * @param int $mode Matching mode to normalize * @param int $default Default matching mode + * @return void */ protected function normalizeMatchingMode(&$mode, $default, array &$normalizedOptions) { @@ -1518,7 +2602,7 @@ protected function normalizeMatchingMode(&$mode, $default, array &$normalizedOpt * Validates and normalizes a key * * @param string $key - * @return string + * @return void * @throws Exception\InvalidArgumentException On an invalid key */ protected function normalizeKey(&$key) @@ -1540,7 +2624,7 @@ protected function normalizeKey(&$key) * Validates and normalizes multiple keys * * @param array $keys - * @return array + * @return void * @throws Exception\InvalidArgumentException On an invalid key */ protected function normalizeKeys(array &$keys) @@ -1555,6 +2639,23 @@ protected function normalizeKeys(array &$keys) $keys = array_values(array_unique($keys)); } + /** + * Validates and normalizes an array of key-value paírs + * + * @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; + } + /** * Return registry of plugins * diff --git a/src/Storage/Adapter/AbstractZendServer.php b/src/Storage/Adapter/AbstractZendServer.php index 8253a5186..5b9b3d5f9 100644 --- a/src/Storage/Adapter/AbstractZendServer.php +++ b/src/Storage/Adapter/AbstractZendServer.php @@ -211,209 +211,119 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz } /** - * Remove an item. + * Internal method to remove an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers removeItem.pre(PreEvent) - * @triggers removeItem.post(PostEvent) - * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; + $internalKey = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR . $normalizedKey; + if (!$this->zdcDelete($internalKey) && !$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - $this->normalizeKey($key); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . self::NAMESPACE_SEPARATOR . $key; - if (!$this->zdcDelete($internalKey) && !$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /* cleaning */ /** - * Clear items off all namespaces. + * Internal method to clear items off all namespaces. * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see clearByNamespace() - * - * @triggers clear.pre(PreEvent) - * @triggers clear.post(PostEvent) - * @triggers clear.exception(ExceptionEvent) + * @see clearByNamespace() */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; + // clear all + if (($normalizedMode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { + $this->zdcClear(); } - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - // clear all - if (($mode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { - $this->zdcClear(); - } - - // expired items will be deleted automatic + // expired items will be deleted automatic - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** * Clear items by namespace. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean - * @throws Zend\Cache\Exception - * @see clear() - * - * @triggers clearByNamespace.pre(PreEvent) - * @triggers clearByNamespace.post(PostEvent) - * @triggers clearByNamespace.exception(ExceptionEvent) + * @throws Exception + * @see clear() */ - public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; + // clear all + if (($normalizedMode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { + $this->zdcClearByNamespace($normalizedOptions['namespace']); } - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - // clear all - if (($mode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { - $this->zdcClearByNamespace($options['namespace']); - } - - // expired items will be deleted automatic + // expired items will be deleted automatic - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /* status */ /** - * Get capabilities + * Internal method to get capabilities of this adapter * * @return Capabilities - * - * @triggers getCapabilities.pre(PreEvent) - * @triggers getCapabilities.post(PostEvent) - * @triggers getCapabilities.exception(ExceptionEvent) */ - public function getCapabilities() + protected function internalGetCapabilities() { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, - array( - 'supportedDatatypes' => array( - 'NULL' => true, - 'boolean' => true, - 'integer' => true, - 'double' => true, - 'string' => true, - 'array' => true, - 'object' => 'object', - 'resource' => false, - ), - 'supportedMetadata' => array(), - 'maxTtl' => 0, - 'staticTtl' => true, - 'tagging' => false, - 'ttlPrecision' => 1, - 'useRequestTime' => false, - 'expiredRead' => false, - 'maxKeyLength' => 0, - 'namespaceIsPrefix' => true, - 'namespaceSeparator' => self::NAMESPACE_SEPARATOR, - 'iterable' => false, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, - ) - ); - } - - return $this->triggerPost(__FUNCTION__, $args, $this->capabilities); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + if ($this->capabilities === null) { + $this->capabilityMarker = new stdClass(); + $this->capabilities = new Capabilities( + $this->capabilityMarker, + array( + 'supportedDatatypes' => array( + 'NULL' => true, + 'boolean' => true, + 'integer' => true, + 'double' => true, + 'string' => true, + 'array' => true, + 'object' => 'object', + 'resource' => false, + ), + 'supportedMetadata' => array(), + 'maxTtl' => 0, + 'staticTtl' => true, + 'tagging' => false, + 'ttlPrecision' => 1, + 'useRequestTime' => false, + 'expiredRead' => false, + 'maxKeyLength' => 0, + 'namespaceIsPrefix' => true, + 'namespaceSeparator' => self::NAMESPACE_SEPARATOR, + 'iterable' => false, + 'clearAllNamespaces' => true, + 'clearByNamespace' => true, + ) + ); } + + return $this->capabilities; } /* internal wrapper of zend_[disk|shm]_cache_* functions */ diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index 9deccb8c3..5c2459681 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -422,807 +422,494 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * Add an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers addItem.pre(PreEvent) - * @triggers addItem.post(PostEvent) - * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!apc_add($internalKey, $value, $options['ttl'])) { - if (apc_exists($internalKey)) { - throw new Exception\RuntimeException("Key '{$internalKey}' already exists"); - } - - $type = is_object($value) ? get_class($value) : gettype($value); - throw new Exception\RuntimeException( - "apc_add('{$internalKey}', <{$type}>, {$options['ttl']}) failed" - ); + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!apc_add($internalKey, $value, $normalizedOptions['ttl'])) { + if (apc_exists($internalKey)) { + throw new Exception\RuntimeException("Key '{$internalKey}' already exists"); } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $type = is_object($value) ? get_class($value) : gettype($value); + throw new Exception\RuntimeException( + "apc_add('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + ); } + + return true; } /** - * Add multiple items. + * Internal method to add multiple items. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers addItems.pre(PreEvent) - * @triggers addItems.post(PostEvent) - * @triggers addItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs, array $options = array()) + protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKeyValuePairs = array(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $internalKey = $prefix . $normalizedKey; + $internalKeyValuePairs[$internalKey] = $value; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeyValuePairs = array(); - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - foreach ($keyValuePairs as $key => &$value) { - $internalKey = $prefix . $key; - $internalKeyValuePairs[$internalKey] = &$value; - } - - $errKeys = apc_add($internalKeyValuePairs, null, $options['ttl']); - if ($errKeys) { - throw new Exception\RuntimeException( - "apc_add(, null, {$options['ttl']}) failed for keys: " - . "'" . implode("','", $errKeys) . "'" - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $errKeys = apc_add($internalKeyValuePairs, null, $normalizedOptions['ttl']); + if ($errKeys) { + throw new Exception\RuntimeException( + "apc_add(, null, {$normalizedOptions['ttl']}) failed for keys: " + . "'" . implode("','", $errKeys) . "'" + ); } + + return true; } /** - * Replace an item. + * Internal method to replace an existing item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers replaceItem.pre(PreEvent) - * @triggers replaceItem.post(PostEvent) - * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value, array $options = array()) + protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!apc_exists($internalKey)) { + throw new Exception\ItemNotFoundException( + "Key '{$internalKey}' doesn't exist" + ); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!apc_exists($internalKey)) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' doesn't exist" - ); - } - - if (!apc_store($internalKey, $value, $options['ttl'])) { - $type = is_object($value) ? get_class($value) : gettype($value); - throw new Exception\RuntimeException( - "apc_store('{$internalKey}', <{$type}>, {$options['ttl']}) failed" - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + if (!apc_store($internalKey, $value, $normalizedOptions['ttl'])) { + $type = is_object($value) ? get_class($value) : gettype($value); + throw new Exception\RuntimeException( + "apc_store('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + ); } + + return true; } /** - * Remove an item. + * Internal method to remove an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers removeItem.pre(PreEvent) - * @triggers removeItem.post(PostEvent) - * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!apc_delete($internalKey) && !$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!apc_delete($internalKey)) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Remove multiple items. + * Internal method to remove multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * * @param array $keys * @param array $options * @return boolean * @throws Exception - * - * @triggers removeItems.pre(PreEvent) - * @triggers removeItems.post(PostEvent) - * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItems(array $keys, array $options = array()) + protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKeys = array(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeys = array(); - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - foreach ($keys as $key) { - $internalKeys[] = $prefix . $key; - } - - $errKeys = apc_delete($internalKeys); - if ($errKeys) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Keys '" . implode("','", $errKeys) . "' not found"); - } - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $errKeys = apc_delete($internalKeys); + if ($errKeys && !$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Keys '" . implode("','", $errKeys) . "' not found"); } + + return true; } /** - * Increment an item. + * Internal method to increment an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers incrementItem.pre(PreEvent) - * @triggers incrementItem.post(PostEvent) - * @triggers incrementItem.exception(ExceptionEvent) */ - public function incrementItem($key, $value, array $options = array()) + protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $value = (int)$value; + $newValue = apc_inc($internalKey, $value); + if ($newValue === false) { + if (apc_exists($internalKey)) { + throw new Exception\RuntimeException("apc_inc('{$internalKey}', {$value}) failed"); + } elseif (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$internalKey}' not found" + ); } - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $value = (int)$value; - $newValue = apc_inc($internalKey, $value); - if ($newValue === false) { - if (apc_exists($internalKey)) { - throw new Exception\RuntimeException("apc_inc('{$internalKey}', {$value}) failed"); - } elseif (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' not found" - ); - } - - $this->addItem($key, $value, $options); - $newValue = $value; + $newValue = $value; + if (!apc_add($internalKey, $newValue, $normalizedOptions['ttl'])) { + throw new Exception\RuntimeException( + "apc_add('{$internalKey}', {$newValue}, {$normalizedOptions['ttl']}) failed" + ); } - - return $this->triggerPost(__FUNCTION__, $args, $newValue); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $newValue; } /** - * Decrement an item. + * Internal method to decrement an item. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value or false or failure + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers decrementItem.pre(PreEvent) - * @triggers decrementItem.post(PostEvent) - * @triggers decrementItem.exception(ExceptionEvent) */ - public function decrementItem($key, $value, array $options = array()) + protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $value = (int)$value; + $newValue = apc_dec($internalKey, $value); + if ($newValue === false) { + if (apc_exists($internalKey)) { + throw new Exception\RuntimeException("apc_dec('{$internalKey}', {$value}) failed"); + } elseif (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$internalKey}' not found" + ); } - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $value = (int)$value; - $newValue = apc_dec($internalKey, $value); - if ($newValue === false) { - if (apc_exists($internalKey)) { - throw new Exception\RuntimeException("apc_dec('{$internalKey}', {$value}) failed"); - } elseif (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' not found" - ); - } - - $this->addItem($key, -$value, $options); - $newValue = -$value; + $newValue = -$value; + if (!apc_add($internalKey, $newValue, $normalizedOptions['ttl'])) { + throw new Exception\RuntimeException( + "apc_add('{$internalKey}', {$newValue}, {$normalizedOptions['ttl']}) failed" + ); } - - return $this->triggerPost(__FUNCTION__, $args, $newValue); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $newValue; } /* non-blocking */ - /** - * Get items that were marked to delay storage for purposes of removing blocking - * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param array $keys - * @param array $options - * @return bool - * @throws Exception - * - * @triggers getDelayed.pre(PreEvent) - * @triggers getDelayed.post(PostEvent) - * @triggers getDelayed.exception(ExceptionEvent) + /** + * Internal method to request multiple items. + * + * Options: + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use + * - select + * - An array of the information the returned item contains + * - callback optional + * - An result callback will be invoked for each item in the result set. + * - The first argument will be the item array. + * - The callback does not have to return anything. + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see fetch() + * @see fetchAll() */ - public function getDelayed(array $keys, array $options = array()) + protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); if ($this->stmtActive) { throw new Exception\RuntimeException('Statement already in use'); - } elseif (!$baseOptions->getReadable()) { - return false; - } elseif (!$keys) { - return true; } - $this->normalizeOptions($options); - if (isset($options['callback']) && !is_callable($options['callback'], false)) { + if (isset($normalizedOptions['callback']) && !is_callable($normalizedOptions['callback'], false)) { throw new Exception\InvalidArgumentException('Invalid callback'); } - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $format = 0; + foreach ($normalizedOptions['select'] as $property) { + if (isset(self::$selectMap[$property])) { + $format = $format | self::$selectMap[$property]; } + } + + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $search = array(); + foreach ($normalizedKeys as $normalizedKey) { + $search[] = preg_quote($normalizedKey, '/'); + } + $search = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $search) . ')$/'; - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - $prefix = preg_quote($prefix, '/'); - - $format = 0; - foreach ($options['select'] as $property) { - if (isset(self::$selectMap[$property])) { - $format = $format | self::$selectMap[$property]; - } - } - - $search = array(); - foreach ($keys as $key) { - $search[] = preg_quote($key, '/'); - } - $search = '/^' . $prefix . '(' . implode('|', $search) . ')$/'; - - $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); - $this->stmtActive = true; - $this->stmtOptions = &$options; + $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); + $this->stmtActive = true; + $this->stmtOptions = & $normalizedOptions; - if (isset($options['callback'])) { - $callback = $options['callback']; - while (($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } + if (isset($normalizedOptions['callback'])) { + $callback = & $normalizedOptions['callback']; + while (($item = $this->fetch()) !== false) { + call_user_func($callback, $item); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return true; } /* find */ /** - * Find items. + * internal method to find items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see fetch() - * @see fetchAll() - * - * @triggers find.pre(PreEvent) - * @triggers find.post(PostEvent) - * @triggers find.exception(ExceptionEvent) + * @see fetch() + * @see fetchAll() */ - public function find($mode = self::MATCH_ACTIVE, array $options = array()) + protected function internalFind(& $normalizedMode, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); if ($this->stmtActive) { throw new Exception\RuntimeException('Statement already in use'); - } elseif (!$baseOptions->getReadable()) { - return false; } - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_ACTIVE, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } + // This adapter doesn't support to read expired items + if (($normalizedMode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $search = '/^' . preg_quote($prefix, '/') . '+/'; - // This adapter doesn't support to read expired items - if (($mode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - $search = '/^' . preg_quote($prefix, '/') . '+/'; - - $format = 0; - foreach ($options['select'] as $property) { - if (isset(self::$selectMap[$property])) { - $format = $format | self::$selectMap[$property]; - } + $format = 0; + foreach ($normalizedOptions['select'] as $property) { + if (isset(self::$selectMap[$property])) { + $format = $format | self::$selectMap[$property]; } - - $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); - $this->stmtActive = true; - $this->stmtOptions = &$options; } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); + $this->stmtActive = true; + $this->stmtOptions = & $normalizedOptions; } + + return true; } /** - * Fetches the next item from result set + * Internal method to fetch the next item from result set * * @return array|boolean The next item or false - * @see fetchAll() - * - * @triggers fetch.pre(PreEvent) - * @triggers fetch.post(PostEvent) - * @triggers fetch.exception(ExceptionEvent) + * @throws Exception */ - public function fetch() + protected function internalFetch() { if (!$this->stmtActive) { return false; } - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $prefixL = strlen($this->stmtOptions['namespace'] . $this->getOptions()->getNamespaceSeparator()); + $prefix = $this->stmtOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $prefixL = strlen($prefix); - do { - if (!$this->stmtIterator->valid()) { - // clear stmt - $this->stmtActive = false; - $this->stmtIterator = null; - $this->stmtOptions = null; + do { + if (!$this->stmtIterator->valid()) { + // clear stmt + $this->stmtActive = false; + $this->stmtIterator = null; + $this->stmtOptions = null; - $result = false; - break; - } + return false; + } - // @see http://pecl.php.net/bugs/bug.php?id=22564 - $exist = apc_exists($this->stmtIterator->key()); - if ($exist) { - $result = $this->stmtIterator->current(); - $this->normalizeMetadata($result); - - $select = $this->stmtOptions['select']; - if (in_array('key', $select)) { - $internalKey = $this->stmtIterator->key(); - $result['key'] = substr($internalKey, $prefixL); - } + // @see http://pecl.php.net/bugs/bug.php?id=22564 + $exist = apc_exists($this->stmtIterator->key()); + if ($exist) { + $result = $this->stmtIterator->current(); + $this->normalizeMetadata($result); + + $select = $this->stmtOptions['select']; + if (in_array('key', $select)) { + $internalKey = $this->stmtIterator->key(); + $result['key'] = substr($internalKey, $prefixL); } + } - $this->stmtIterator->next(); - } while (!$exist); + $this->stmtIterator->next(); + } while (!$exist); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $result; } /* cleaning */ /** - * Clear items off all namespaces. + * Internal method to clear items off all namespaces. * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see clearByNamespace() - * - * @triggers clear.pre(PreEvent) - * @triggers clear.post(PostEvent) - * @triggers clear.exception(ExceptionEvent) + * @see clearByNamespace() */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->clearByRegEx('/.*/', $mode, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $this->clearByRegEx('/.*/', $normalizedMode, $normalizedOptions); } /** * Clear items by namespace. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use + * - tags + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean - * @throws Zend\Cache\Exception - * @see clear() - * - * @triggers clearByNamespace.pre(PreEvent) - * @triggers clearByNamespace.post(PostEvent) - * @triggers clearByNamespace.exception(ExceptionEvent) + * @throws Exception + * @see clear() */ - public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - $regex = '/^' . preg_quote($prefix, '/') . '+/'; - $result = $this->clearByRegEx($regex, $mode, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $regex = '/^' . preg_quote($prefix, '/') . '+/'; + return $this->clearByRegEx($regex, $normalizedMode, $normalizedOptions); } /* status */ /** - * Get capabilities + * Internal method to get capabilities of this adapter * * @return Capabilities - * - * @triggers getCapabilities.pre(PreEvent) - * @triggers getCapabilities.post(PostEvent) - * @triggers getCapabilities.exception(ExceptionEvent) */ - public function getCapabilities() + protected function internalGetCapabilities() { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, - array( - 'supportedDatatypes' => array( - 'NULL' => true, - 'boolean' => true, - 'integer' => true, - 'double' => true, - 'string' => true, - 'array' => true, - 'object' => 'object', - 'resource' => false, - ), - 'supportedMetadata' => array( - 'atime', - 'ctime', - 'internal_key', - 'mem_size', - 'mtime', - 'num_hits', - 'ref_count', - 'rtime', - 'ttl', - ), - 'maxTtl' => 0, - 'staticTtl' => true, - 'tagging' => false, - 'ttlPrecision' => 1, - 'useRequestTime' => (bool) ini_get('apc.use_request_time'), - 'expiredRead' => false, - 'maxKeyLength' => 5182, - 'namespaceIsPrefix' => true, - 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), - 'iterable' => true, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, - ) - ); - } - - return $this->triggerPost(__FUNCTION__, $args, $this->capabilities); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + if ($this->capabilities === null) { + $this->capabilityMarker = new stdClass(); + $this->capabilities = new Capabilities( + $this->capabilityMarker, + array( + 'supportedDatatypes' => array( + 'NULL' => true, + 'boolean' => true, + 'integer' => true, + 'double' => true, + 'string' => true, + 'array' => true, + 'object' => 'object', + 'resource' => false, + ), + 'supportedMetadata' => array( + 'atime', + 'ctime', + 'internal_key', + 'mem_size', + 'mtime', + 'num_hits', + 'ref_count', + 'rtime', + 'ttl', + ), + 'maxTtl' => 0, + 'staticTtl' => true, + 'tagging' => false, + 'ttlPrecision' => 1, + 'useRequestTime' => (bool) ini_get('apc.use_request_time'), + 'expiredRead' => false, + 'maxKeyLength' => 5182, + 'namespaceIsPrefix' => true, + 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), + 'iterable' => true, + 'clearAllNamespaces' => true, + 'clearByNamespace' => true, + ) + ); } + + return $this->capabilities; } /** - * Get storage capacity. + * Internal method to get storage capacity. * - * @param array $options + * @param array $normalizedOptions * @return array|boolean Capacity as array or false on failure - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) + * @throws Exception */ - public function getCapacity(array $options = array()) + protected function internalGetCapacity(array & $normalizedOptions) { - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $mem = apc_sma_info(true); - $result = array( - 'free' => $mem['avail_mem'], - 'total' => $mem['num_seg'] * $mem['seg_size'], - ); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $mem = apc_sma_info(true); + return array( + 'free' => $mem['avail_mem'], + 'total' => $mem['num_seg'] * $mem['seg_size'], + ); } /* internal */ diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index cbbf7cb64..32ba9c966 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -328,6 +328,23 @@ public function getMetadata($key, array $options = array()) return parent::getMetadata($key, $options); } + /** + * Get metadatas + * + * @param array $keys + * @param array $options + * @return array + */ + public function getMetadatas(array $keys, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + clearstatcache(); + } + + return parent::getMetadatas($keys, $options); + } + /** * Get info by key * @@ -365,24 +382,178 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti return $keyInfo; } + /* writing */ + /** - * Get metadatas + * Store an item. * - * @param array $keys - * @param array $options - * @return array + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers setItem.pre(PreEvent) + * @triggers setItem.post(PostEvent) + * @triggers setItem.exception(ExceptionEvent) */ - public function getMetadatas(array $keys, array $options = array()) + public function setItem($key, $value, array $options = array()) { $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { clearstatcache(); } - return parent::getMetadatas($keys, $options); + return parent::setItem($key, $value, $options); } - /* writing */ + /** + * Store multiple items. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param array $keyValuePairs + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers setItems.pre(PreEvent) + * @triggers setItems.post(PostEvent) + * @triggers setItems.exception(ExceptionEvent) + */ + public function setItems(array $keyValuePairs, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); + } + + return parent::setItems($keyValuePairs, $options); + } + + /** + * Add an item. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers addItem.pre(PreEvent) + * @triggers addItem.post(PostEvent) + * @triggers addItem.exception(ExceptionEvent) + */ + public function addItem($key, $value, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); + } + + return parent::addItem($key, $value, $options); + } + + /** + * Add multiple items. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param array $keyValuePairs + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers addItems.pre(PreEvent) + * @triggers addItems.post(PostEvent) + * @triggers addItems.exception(ExceptionEvent) + */ + public function addItems(array $keyValuePairs, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); + } + + return parent::addItems($keyValuePairs, $options); + } + + /** + * Replace an existing item. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers replaceItem.pre(PreEvent) + * @triggers replaceItem.post(PostEvent) + * @triggers replaceItem.exception(ExceptionEvent) + */ + public function replaceItem($key, $value, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); + } + + return parent::replaceItem($key, $value, $options); + } + + /** + * Replace multiple existing items. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param array $keyValuePairs + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers replaceItems.pre(PreEvent) + * @triggers replaceItems.post(PostEvent) + * @triggers replaceItems.exception(ExceptionEvent) + */ + public function replaceItems(array $keyValuePairs, array $options = array()) + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); + } + + return parent::replaceItems($keyValuePairs, $options); + } /** * Internal method to store an item. @@ -390,6 +561,8 @@ public function getMetadatas(array $keys, array $options = array()) * Options: * - namespace * - The namespace to use + * - tags + * - An array of tags * * @param string $normalizedKey * @param mixed $value @@ -471,731 +644,451 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz } /** - * Replace an item + * Set an item only if token matches * - * @param $key - * @param $value - * @param array $options - * @return bool|mixed - * @throws ItemNotFoundException + * It uses the token received from getItem() to check if the item has + * changed before overwriting it. + * + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - tags optional + * - An array of tags + * + * @param mixed $token + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean + * @throws Exception + * @see getItem() + * @see setItem() */ - public function replaceItem($key, $value, array $options = array()) + public function checkAndSetItem($token, $key, $value, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - if ( !$this->internalHasItem($key, $options) ) { - throw new Exception\ItemNotFoundException("Key '{$key}' doesn't exist"); - } - - $result = $this->internalSetItem($key, $value, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::checkAndSetItem($token, $key, $value, $options); } /** - * Replace items + * Internal method to set an item only if token matches * - * @param array $keyValuePairs - * @param array $options - * @return bool|mixed - * @throws ItemNotFoundException + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param mixed $token + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see getItem() + * @see setItem() */ - public function replaceItems(array $keyValuePairs, array $options = array()) + protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { + $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); + if (!$keyInfo) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found within namespace '{$normalizedOptions['namespace']}'" + ); + } return false; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = true; - foreach ($keyValuePairs as $key => $value) { - if ( !$this->internalHasItem($key, $options) ) { - throw new Exception\ItemNotFoundException("Key '{$key}' doesn't exist"); - } - $result = $this->internalSetItem($key, $value, $options) && $result; - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + // use filemtime + filesize as CAS token + $check = $keyInfo['mtime'] . filesize($keyInfo['filespec'] . '.dat'); + if ($token !== $check) { + return false; } + + return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); } /** - * Add an item + * Reset lifetime of an item * - * @param $key - * @param $value - * @param array $options - * @return bool|mixed - * @throws RuntimeException + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param string $key + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers touchItem.pre(PreEvent) + * @triggers touchItem.post(PostEvent) + * @triggers touchItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + public function touchItem($key, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - if ( $this->internalHasItem($key, $options) ) { - throw new Exception\RuntimeException("Key '{$key}' already exist"); - } - - $result = $this->internalSetItem($key, $value, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::touchItem($key, $options); } /** - * Add items + * Reset lifetime of multiple items. * - * @param array $keyValuePairs - * @param array $options - * @return bool|mixed - * @throws RuntimeException + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * + * @param array $keys + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers touchItems.pre(PreEvent) + * @triggers touchItems.post(PostEvent) + * @triggers touchItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs, array $options = array()) + public function touchItems(array $keys, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - $result = true; - foreach ($keyValuePairs as $key => $value) { - if ( $this->internalHasItem($key, $options) ) { - throw new Exception\RuntimeException("Key '{$key}' already exist"); - } - - $result = $this->internalSetItem($key, $value, $options) && $result; - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::touchItems($keys, $options); } /** - * check and set item + * Internal method to reset lifetime of an item * - * @param string $token - * @param string $key - * @param mixed $value - * @param array $options - * @return bool|mixed - * @throws ItemNotFoundException - */ - public function checkAndSetItem($token, $key, $value, array $options = array()) - { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'token' => & $token, - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - if ( !($keyInfo = $this->getKeyInfo($key, $options['namespace'])) ) { - if ($options['ignore_missing_items']) { - $result = false; - } else { - throw new Exception\ItemNotFoundException("Key '{$key}' not found within namespace '{$options['namespace']}'"); - } - } else { - // use filemtime + filesize as CAS token - $check = $keyInfo['mtime'] . filesize($keyInfo['filespec'] . '.dat'); - if ($token != $check) { - $result = false; - } else { - $result = $this->internalSetItem($key, $value, $options); - } - } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } - } - - /** - * Touch an item + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param $key - * @param array $options - * @return bool|mixed + * @param string $key + * @param array $options + * @return boolean + * @throws Exception */ - public function touchItem($key, array $options = array()) + protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { + $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); + if (!$keyInfo) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found within namespace '{$normalizedOptions['namespace']}'" + ); + } return false; } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } + ErrorHandler::start(); + $touch = touch($keyInfo['filespec'] . '.dat'); + $error = ErrorHandler::stop(); + if (!$touch) { + throw new Exception\RuntimeException( + "Error touching file '{$keyInfo['filespec']}.dat'", 0, $error + ); + } - $this->internalTouchItem($key, $options); - $this->lastInfoId = null; + // remove the buffered info + $this->lastInfoId = null; - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Touch items + * Remove an item. * - * @param array $keys - * @param array $options - * @return bool|mixed + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item + * + * @param string $key + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers removeItem.pre(PreEvent) + * @triggers removeItem.post(PostEvent) + * @triggers removeItem.exception(ExceptionEvent) */ - public function touchItems(array $keys, array $options = array()) + public function removeItem($key, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - foreach ($keys as $key) { - $this->internalTouchItem($key, $options); - } - $this->lastInfoId = null; - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::removeItem($key, $options); } /** - * Remove an item + * Remove multiple items. * - * @param $key - * @param array $options - * @return bool|mixed + * Options: + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - ignore_missing_items optional + * - Throw exception on missing item + * + * @param array $keys + * @param array $options + * @return boolean + * @throws Exception + * + * @triggers removeItems.pre(PreEvent) + * @triggers removeItems.post(PostEvent) + * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + public function removeItems(array $keys, array $options = array()) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + clearstatcache(); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - // unlink is not affected by clearstatcache - $this->internalRemoveItem($key, $options); - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return parent::removeItems($keys, $options); } /** - * Remove items + * Internal method to remove an item. * - * @param array $keys - * @param array $options - * @return bool|mixed + * Options: + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return boolean + * @throws Exception */ - public function removeItems(array $keys, array $options = array()) + protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - // unlink is not affected by clearstatcache - foreach ($keys as $key) { - $this->internalRemoveItem($key, $options); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions['namespace']); + if (!file_exists($filespec . '.dat')) { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$normalizedKey}' with file '{$filespec}.dat' not found"); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + } else { + $this->unlink($filespec . '.dat'); + $this->unlink($filespec . '.ifo'); + $this->lastInfoId = null; } + return true; } /* non-blocking */ /** - * Find + * internal method to find items. * - * @param int $mode - * @param array $options - * @return bool|mixed - * @throws RuntimeException + * Options: + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use + * + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see fetch() + * @see fetchAll() */ - public function find($mode = self::MATCH_ACTIVE, array $options = array()) + protected function internalFind(& $normalizedMode, array & $normalizedOptions) { if ($this->stmtActive) { throw new Exception\RuntimeException('Statement already in use'); } - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_ACTIVE, $options); - $options = array_merge($baseOptions->toArray(), $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - try { - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - $find = $options['cache_dir'] - . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $options['dir_level']) - . \DIRECTORY_SEPARATOR . $prefix . '*.dat'; - $glob = new GlobIterator($find); - - $this->stmtActive = true; - $this->stmtGlob = $glob; - $this->stmtMatch = $mode; - $this->stmtOptions = $options; - } catch (BaseException $e) { - throw new Exception\RuntimeException('Instantiating glob iterator failed', 0, $e); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $baseOptions = $this->getOptions(); + + $prefix = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator(); + $find = $baseOptions->getCacheDir() + . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $baseOptions->getDirLevel()) + . \DIRECTORY_SEPARATOR . $prefix . '*.dat'; + $glob = new GlobIterator($find); + + $this->stmtActive = true; + $this->stmtGlob = $glob; + $this->stmtMatch = $normalizedMode; + $this->stmtOptions = $normalizedOptions; + } catch (BaseException $e) { + throw new Exception\RuntimeException("new GlobIterator({$find}) failed", 0, $e); } + + return true; } /** - * Fetch + * Internal method to fetch the next item from result set * - * @return bool|mixed + * @return array|boolean The next item or false + * @throws Exception */ - public function fetch() + protected function internalFetch() { if (!$this->stmtActive) { return false; } - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($this->stmtGlob !== null) { - $result = $this->fetchByGlob(); + if ($this->stmtGlob !== null) { + $result = $this->fetchByGlob(); - if ($result === false) { - // clear statement - $this->stmtActive = false; - $this->stmtGlob = null; - $this->stmtMatch = null; - $this->stmtOptions = null; - } - } else { - $result = parent::fetch(); + if ($result === false) { + // clear statement + $this->stmtActive = false; + $this->stmtGlob = null; + $this->stmtMatch = null; + $this->stmtOptions = null; } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + } else { + $result = parent::internalFetch(); } + + return $result; } /* cleaning */ /** - * Clear + * Internal method to clear items off all namespaces. * - * @param int $mode - * @param array $options - * @return mixed + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see clearByNamespace() */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->clearByPrefix('', $mode, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $this->clearByPrefix('', $normalizedMode, $normalizedOptions); } /** - * Clear by namespace + * Clear items by namespace. * - * @param int $mode - * @param array $options - * @return mixed + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* + * + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see clear() */ - public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) { - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $prefix = $options['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $result = $this->clearByPrefix($prefix, $mode, $options); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + return $this->clearByPrefix($prefix, $normalizedMode, $normalizedOptions); } /** - * Optimize + * Internal method to optimize adapter storage. * - * @param array $options - * @return bool|mixed + * Options: + * - namespace + * - The namespace to use + * + * @param array $normalizedOptions + * @return boolean + * @throws Exception */ - public function optimize(array $options = array()) + protected function internalOptimize(array & $normalizedOptions) { $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if ($baseOptions->getDirLevel()) { + // removes only empty directories + $this->rmDir( + $baseOptions->getCacheDir(), + $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() + ); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($baseOptions->getDirLevel()) { - // removes only empty directories - $this->rmDir( - $baseOptions->getCacheDir(), - $options['namespace'] . $baseOptions->getNamespaceSeparator() - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /* status */ /** - * Get capabilities + * Internal method to get capabilities of this adapter * - * @return mixed + * @return Capabilities */ - public function getCapabilities() + protected function internalGetCapabilities() { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, - array( - 'supportedDatatypes' => array( - 'NULL' => 'string', - 'boolean' => 'string', - 'integer' => 'string', - 'double' => 'string', - 'string' => true, - 'array' => false, - 'object' => false, - 'resource' => false, - ), - 'supportedMetadata' => array('mtime', 'filespec'), - 'maxTtl' => 0, - 'staticTtl' => false, - 'tagging' => true, - 'ttlPrecision' => 1, - 'expiredRead' => true, - 'maxKeyLength' => 251, // 255 - strlen(.dat | .ifo) - 'namespaceIsPrefix' => true, - 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), - 'iterable' => true, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, - ) - ); - - // set dynamic capibilities - $this->updateCapabilities(); - } + if ($this->capabilities === null) { + $this->capabilityMarker = new stdClass(); + $this->capabilities = new Capabilities( + $this->capabilityMarker, + array( + 'supportedDatatypes' => array( + 'NULL' => 'string', + 'boolean' => 'string', + 'integer' => 'string', + 'double' => 'string', + 'string' => true, + 'array' => false, + 'object' => false, + 'resource' => false, + ), + 'supportedMetadata' => array('mtime', 'filespec'), + 'maxTtl' => 0, + 'staticTtl' => false, + 'tagging' => true, + 'ttlPrecision' => 1, + 'expiredRead' => true, + 'maxKeyLength' => 251, // 255 - strlen(.dat | .ifo) + 'namespaceIsPrefix' => true, + 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), + 'iterable' => true, + 'clearAllNamespaces' => true, + 'clearByNamespace' => true, + ) + ); - $result = $this->capabilities; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + // set dynamic capibilities + $this->updateCapabilities(); } - } - /** - * Get capacity - * - * @param array $options - * @return mixed - */ - public function getCapacity(array $options = array()) - { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = Utils::getDiskCapacity($this->getOptions()->getCacheDir()); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $this->capabilities; } - /* internal */ - /** - * Remove a key + * Internal method to get storage capacity. * - * @param $key - * @param array $options - * @throws ItemNotFoundException + * @param array $normalizedOptions + * @return array|boolean Capacity as array or false on failure + * @throws Exception */ - protected function internalRemoveItem($key, array &$options) + protected function internalGetCapacity(array & $normalizedOptions) { - $filespec = $this->getFileSpec($key, $options['namespace']); - - if (!$options['ignore_missing_items'] && !file_exists($filespec . '.dat')) { - throw new Exception\ItemNotFoundException("Key '{$key}' with file '{$filespec}.dat' not found"); - } - - $this->unlink($filespec . '.dat'); - $this->unlink($filespec . '.ifo'); - $this->lastInfoId = null; + return Utils::getDiskCapacity($this->getOptions()->getCacheDir()); } - /** - * Touch a key - * - * @param string $key - * @param array $options - * @return bool - * @throws ItemNotFoundException|RuntimeException - */ - protected function internalTouchItem($key, array &$options) - { - $keyInfo = $this->getKeyInfo($key, $options['namespace']); - if (!$keyInfo) { - if ($options['ignore_missing_items']) { - return false; - } else { - throw new Exception\ItemNotFoundException( - "Key '{$key}' not found within namespace '{$options['namespace']}'" - ); - } - } - - ErrorHandler::start(); - $touch = touch($keyInfo['filespec'] . '.dat'); - $error = ErrorHandler::stop(); - if (!$touch) { - throw new Exception\RuntimeException( - "Error touching file '{$keyInfo['filespec']}.dat'", 0, $error - ); - } - } + /* internal */ /** * Fetch by glob diff --git a/src/Storage/Adapter/Memcached.php b/src/Storage/Adapter/Memcached.php index 53d458ac1..e833f2f16 100644 --- a/src/Storage/Adapter/Memcached.php +++ b/src/Storage/Adapter/Memcached.php @@ -344,565 +344,358 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * Add an item. * * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers addItem.pre(PreEvent) - * @triggers addItem.post(PostEvent) - * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $expiration = $this->expirationTime($options['ttl']); - if (!$this->memcached->add($key, $value, $expiration)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $expiration = $this->expirationTime($normalizedOptions['ttl']); + if (!$this->memcached->add($normalizedKey, $value, $expiration)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } + + return true; } /** - * Replace an item. + * Internal method to replace an existing item. * * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers replaceItem.pre(PreEvent) - * @triggers replaceItem.post(PostEvent) - * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value, array $options = array()) + protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $expiration = $this->expirationTime($options['ttl']); - if (!$this->memcached->replace($key, $value, $expiration)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $expiration = $this->expirationTime($normalizedOptions['ttl']); + if (!$this->memcached->replace($normalizedKey, $value, $expiration)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } + + return true; } /** - * Check and set item + * Internal method to set an item only if token matches + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - An array of tags * - * @param float $token - * @param string $key + * @param mixed $token + * @param string $normalizedKey * @param mixed $value - * @param array $options - * @return bool + * @param array $normalizedOptions + * @return boolean + * @throws Exception + * @see getItem() + * @see setItem() */ - public function checkAndSetItem($token, $key, $value, array $options = array()) + protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'token' => & $token, - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $expiration = $this->expirationTime($options['ttl']); - $result = $this->memcached->cas($token, $key, $value, $expiration); + $expiration = $this->expirationTime($normalizedOptions['ttl']); + $result = $this->memcached->cas($token, $normalizedKey, $value, $expiration); - if ($result === false) { - $rsCode = $this->memcached->getResultCode(); - if ($rsCode !== 0 && $rsCode != MemcachedResource::RES_DATA_EXISTS) { - throw $this->getExceptionByResultCode($rsCode); - } + if ($result === false) { + $rsCode = $this->memcached->getResultCode(); + if ($rsCode !== 0 && $rsCode != MemcachedResource::RES_DATA_EXISTS) { + throw $this->getExceptionByResultCode($rsCode); } + } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return $result; } /** - * Remove an item. + * Internal method to remove an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers removeItem.pre(PreEvent) - * @triggers removeItem.post(PostEvent) - * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - $result = $this->memcached->delete($key); + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); + $result = $this->memcached->delete($normalizedKey); - if ($result === false) { - if (($rsCode = $this->memcached->getResultCode()) != 0 - && ($rsCode != MemcachedResource::RES_NOTFOUND || !$options['ignore_missing_items']) - ) { - throw $this->getExceptionByResultCode($rsCode); - } + if ($result === false) { + $rsCode = $this->memcached->getResultCode(); + if ($rsCode != 0 && ($rsCode != MemcachedResource::RES_NOTFOUND || !$normalizedOptions['ignore_missing_items'])) { + throw $this->getExceptionByResultCode($rsCode); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return true; } /** - * Remove items. + * Internal method to remove multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * * @param array $keys * @param array $options * @return boolean * @throws Exception - * - * @triggers removeItems.pre(PreEvent) - * @triggers removeItems.post(PostEvent) - * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItems(array $keys, array $options = array()) + protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + // support for removing multiple items at once has been added in ext/memcached 2 + if (static::$extMemcachedMajorVersion < 2) { + return parent::internalRemoveItems($normalizedKeys, $normalizedOptions); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $rsCodes = array(); - if (static::$extMemcachedMajorVersion >= 2) { - $rsCodes = $this->memcached->deleteMulti($keys); - } else { - foreach ($keys as $key) { - $rs = $this->memcached->delete($key); - if ($rs === false) { - $rsCodes[$key] = $this->memcached->getResultCode(); - } - } - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); + $rsCodes = $this->memcached->deleteMulti($normalizedKeys); - $missingKeys = null; - foreach ($rsCodes as $key => $rsCode) { - if ($rsCode !== true && $rsCode != 0) { - if ($rsCode != MemcachedResource::RES_NOTFOUND) { - throw $this->getExceptionByResultCode($rsCode); - } elseif (!$options['ignore_missing_items']) { - $missingKeys[] = $key; - } + $missingKeys = null; + foreach ($rsCodes as $key => $rsCode) { + if ($rsCode !== true && $rsCode != 0) { + if ($rsCode != MemcachedResource::RES_NOTFOUND) { + throw $this->getExceptionByResultCode($rsCode); } + $missingKeys[] = $key; } - if ($missingKeys) { - throw new Exception\ItemNotFoundException( - "Keys '" . implode("','", $missingKeys) . "' not found" - ); - } + } - return true; - } catch (MemcachedException $e) { - throw new RuntimeException($e->getMessage(), 0, $e); + if ($missingKeys && !$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Keys '" . implode("','", $missingKeys) . "' not found within namespace '{$normalizedOptions['namespace']}'" + ); } + + return true; } /** - * Increment an item. + * Internal method to increment an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers incrementItem.pre(PreEvent) - * @triggers incrementItem.post(PostEvent) - * @triggers incrementItem.exception(ExceptionEvent) */ - public function incrementItem($key, $value, array $options = array()) + protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $value = (int)$value; - $newValue = $this->memcached->increment($key, $value); - - if ($newValue === false) { - if (($rsCode = $this->memcached->getResultCode()) != 0 - && ($rsCode != MemcachedResource::RES_NOTFOUND || !$options['ignore_missing_items']) - ) { - throw $this->getExceptionByResultCode($rsCode); - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $expiration = $this->expirationTime($options['ttl']); - if (!$this->memcached->add($key, $value, $expiration)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } + $value = (int)$value; + $newValue = $this->memcached->increment($normalizedKey, $value); - $newValue = $value; + if ($newValue === false) { + $rsCode = $this->memcached->getResultCode(); + if ($rsCode != 0 && ($rsCode != MemcachedResource::RES_NOTFOUND || !$normalizedOptions['ignore_missing_items'])) { + throw $this->getExceptionByResultCode($rsCode); } - return $this->triggerPost(__FUNCTION__, $args, $newValue); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $newValue = $value; + $expiration = $this->expirationTime($normalizedOptions['ttl']); + if (!$this->memcached->add($normalizedKey, $newValue, $expiration)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + } } + + return $newValue; } /** - * Decrement an item. + * Internal method to decrement an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value or false or failure + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers decrementItem.pre(PreEvent) - * @triggers decrementItem.post(PostEvent) - * @triggers decrementItem.exception(ExceptionEvent) */ - public function decrementItem($key, $value, array $options = array()) + protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - $value = (int)$value; - $newValue = $this->memcached->decrement($key, $value); + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - if ($newValue === false) { - if (($rsCode = $this->memcached->getResultCode()) != 0 - && ($rsCode != MemcachedResource::RES_NOTFOUND || !$options['ignore_missing_items']) - ) { - throw $this->getExceptionByResultCode($rsCode); - } + $value = (int)$value; + $newValue = $this->memcached->decrement($normalizedKey, $value); - $expiration = $this->expirationTime($options['ttl']); - if (!$this->memcached->add($key, -$value, $expiration)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - $newValue = -$value; + if ($newValue === false) { + $rsCode = $this->memcached->getResultCode(); + if ($rsCode != 0 && ($rsCode != MemcachedResource::RES_NOTFOUND || !$normalizedOptions['ignore_missing_items'])) { + throw $this->getExceptionByResultCode($rsCode); } - return $this->triggerPost(__FUNCTION__, $args, $newValue); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $newValue = -$value; + $expiration = $this->expirationTime($normalizedOptions['ttl']); + if (!$this->memcached->add($normalizedKey, $newValue, $expiration)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + } } + + return $newValue; } /* non-blocking */ /** - * Get items that were marked to delay storage for purposes of removing blocking + * Internal method to request multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - select optional + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use + * - select * - An array of the information the returned item contains - * (Default: array('key', 'value')) * - callback optional * - An result callback will be invoked for each item in the result set. * - The first argument will be the item array. * - The callback does not have to return anything. * - * @param array $keys - * @param array $options - * @return bool + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return boolean * @throws Exception - * - * @triggers getDelayed.pre(PreEvent) - * @triggers getDelayed.post(PostEvent) - * @triggers getDelayed.exception(ExceptionEvent) + * @see fetch() + * @see fetchAll() */ - public function getDelayed(array $keys, array $options = array()) + protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); if ($this->stmtActive) { throw new Exception\RuntimeException('Statement already in use'); - } elseif (!$baseOptions->getReadable()) { - return false; - } elseif (!$keys) { - return true; } - $this->normalizeOptions($options); - if (isset($options['callback']) && !is_callable($options['callback'], false)) { + if (isset($normalizedOptions['callback']) && !is_callable($normalizedOptions['callback'], false)) { throw new Exception\InvalidArgumentException('Invalid callback'); } - if (!isset($options['select'])) { - $options['select'] = array('key', 'value'); - } - - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options['namespace']); - - // redirect callback - if (isset($options['callback'])) { - $cb = function (MemcachedResource $memc, array &$item) use (&$options, $baseOptions) { - $select = & $options['select']; - // handle selected key - if (!in_array('key', $select)) { - unset($item['key']); - } - - // handle selected value - if (!in_array('value', $select)) { - unset($item['value']); - } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - call_user_func($options['callback'], $item); - }; + // redirect callback + if (isset($normalizedOptions['callback'])) { + $cb = function (MemcachedResource $memc, array & $item) use (& $normalizedOptions) { + $select = & $normalizedOptions['select']; - if (!$this->memcached->getDelayed($keys, false, $cb)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + // handle selected key + if (!in_array('key', $select)) { + unset($item['key']); } - } else { - if (!$this->memcached->getDelayed($keys)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + + // handle selected value + if (!in_array('value', $select)) { + unset($item['value']); } - $this->stmtActive = true; - $this->stmtOptions = &$options; + call_user_func($normalizedOptions['callback'], $item); + }; + + if (!$this->memcached->getDelayed($normalizedKeys, false, $cb)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + } + } else { + if (!$this->memcached->getDelayed($normalizedKeys)) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $this->stmtActive = true; + $this->stmtOptions = & $normalizedOptions; } + + return true; } /** - * Fetches the next item from result set + * Internal method to fetch the next item from result set * * @return array|boolean The next item or false - * @see fetchAll() - * - * @triggers fetch.pre(PreEvent) - * @triggers fetch.post(PostEvent) - * @triggers fetch.exception(ExceptionEvent) + * @throws Exception */ - public function fetch() + protected function internalFetch() { if (!$this->stmtActive) { return false; } - $args = new ArrayObject(); + $result = $this->memcached->fetch(); + if (!empty($result)) { + $select = & $this->stmtOptions['select']; - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + // handle selected key + if (!in_array('key', $select)) { + unset($result['key']); } - $result = $this->memcached->fetch(); - if (!empty($result)) { - $select = & $this->stmtOptions['select']; - - // handle selected key - if (!in_array('key', $select)) { - unset($result['key']); - } - - // handle selected value - if (!in_array('value', $select)) { - unset($result['value']); - } - - } else { - // clear stmt - $this->stmtActive = false; - $this->stmtOptions = null; + // handle selected value + if (!in_array('value', $select)) { + unset($result['value']); } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + } else { + // clear stmt + $this->stmtActive = false; + $this->stmtOptions = null; } + + return $result; } /** - * FetchAll + * Internal method to return all items of result set. * + * @return array The result set as array containing all items * @throws Exception - * @return array + * @see fetch() */ - public function fetchAll() + protected function internalFetchAll() { $result = $this->memcached->fetchAll(); if ($result === false) { @@ -910,8 +703,7 @@ public function fetchAll() } $select = $this->stmtOptions['select']; - - foreach ($result as &$elem) { + foreach ($result as & $elem) { if (!in_array('key', $select)) { unset($elem['key']); } @@ -923,145 +715,85 @@ public function fetchAll() /* cleaning */ /** - * Clear items off all namespaces. + * Internal method to clear items off all namespaces. * - * Options: - * - No options available for this adapter - * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see clearByNamespace() - * - * @triggers clear.pre(PreEvent) - * @triggers clear.post(PostEvent) - * @triggers clear.exception(ExceptionEvent) + * @see clearByNamespace() */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; + if (!$this->memcached->flush()) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$this->memcached->flush()) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /* status */ /** - * Get capabilities + * Internal method to get capabilities of this adapter * * @return Capabilities - * - * @triggers getCapabilities.pre(PreEvent) - * @triggers getCapabilities.post(PostEvent) - * @triggers getCapabilities.exception(ExceptionEvent) */ - public function getCapabilities() + protected function internalGetCapabilities() { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, - array( - 'supportedDatatypes' => array( - 'NULL' => true, - 'boolean' => true, - 'integer' => true, - 'double' => true, - 'string' => true, - 'array' => true, - 'object' => 'object', - 'resource' => false, - ), - 'supportedMetadata' => array(), - 'maxTtl' => 0, - 'staticTtl' => true, - 'tagging' => false, - 'ttlPrecision' => 1, - 'useRequestTime' => false, - 'expiredRead' => false, - 'maxKeyLength' => 255, - 'namespaceIsPrefix' => true, - 'iterable' => false, - 'clearAllNamespaces' => true, - 'clearByNamespace' => false, - ) - ); - } - - return $this->triggerPost(__FUNCTION__, $args, $this->capabilities); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + if ($this->capabilities === null) { + $this->capabilityMarker = new stdClass(); + $this->capabilities = new Capabilities( + $this->capabilityMarker, + array( + 'supportedDatatypes' => array( + 'NULL' => true, + 'boolean' => true, + 'integer' => true, + 'double' => true, + 'string' => true, + 'array' => true, + 'object' => 'object', + 'resource' => false, + ), + 'supportedMetadata' => array(), + 'maxTtl' => 0, + 'staticTtl' => true, + 'tagging' => false, + 'ttlPrecision' => 1, + 'useRequestTime' => false, + 'expiredRead' => false, + 'maxKeyLength' => 255, + 'namespaceIsPrefix' => true, + 'iterable' => false, + 'clearAllNamespaces' => true, + 'clearByNamespace' => false, + ) + ); } + + return $this->capabilities; } /** - * Get storage capacity. + * Internal method to get storage capacity. * - * @param array $options + * @param array $normalizedOptions * @return array|boolean Capacity as array or false on failure - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) + * @throws Exception */ - public function getCapacity(array $options = array()) + protected function internalGetCapacity(array & $normalizedOptions) { - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $stats = $this->memcached->getStats(); - if ($stats === false) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - $mem = array_pop($stats); - $result = array( - 'free' => $mem['limit_maxbytes'] - $mem['bytes'], - 'total' => $mem['limit_maxbytes'], - ); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $stats = $this->memcached->getStats(); + if ($stats === false) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } + + $mem = array_pop($stats); + return array( + 'free' => $mem['limit_maxbytes'] - $mem['bytes'], + 'total' => $mem['limit_maxbytes'], + ); } /* internal */ diff --git a/src/Storage/Adapter/Memory.php b/src/Storage/Adapter/Memory.php index 7a93a840a..944c7930d 100644 --- a/src/Storage/Adapter/Memory.php +++ b/src/Storage/Adapter/Memory.php @@ -277,6 +277,8 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti * Options: * - namespace * - The namespace to use + * - tags + * - An array of tags * * @param string $normalizedKey * @param mixed $value @@ -303,10 +305,10 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz * Internal method to store multiple items. * * Options: - * - ttl - * - The time-to-life * - namespace * - The namespace to use + * - tags + * - An array of tags * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions @@ -339,9 +341,9 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * Add an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional + * - namespace + * - The namespace to use + * - tags * - An array of tags * * @param string $key @@ -349,870 +351,473 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * @param array $options * @return boolean * @throws Exception - * - * @triggers addItem.pre(PreEvent) - * @triggers addItem.post(PostEvent) - * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if (!$this->hasFreeCapacity()) { + $memoryLimit = $this->getOptions()->getMemoryLimit(); + throw new Exception\OutOfCapacityException( + 'Memory usage exceeds limit ({$memoryLimit}).' + ); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$this->hasFreeCapacity()) { - $memoryLimit = $baseOptions->getMemoryLimit(); - throw new Exception\OutOfCapacityException( - 'Memory usage exceeds limit ({$memoryLimit}).' - ); - } - - $ns = $options['namespace']; - if (isset($this->data[$ns][$key])) { - throw new Exception\RuntimeException("Key '{$key}' already exists within namespace '$ns'"); - } - $this->data[$ns][$key] = array($value, microtime(true), $options['tags']); - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $ns = $normalizedOptions['namespace']; + if (isset($this->data[$ns][$normalizedKey])) { + throw new Exception\RuntimeException("Key '{$normalizedKey}' already exists within namespace '$ns'"); } + $this->data[$ns][$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); + + return true; } /** - * Add multiple items. + * Internal method to add multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional + * - namespace + * - The namespace to use + * - tags * - An array of tags * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers addItems.pre(PreEvent) - * @triggers addItems.post(PostEvent) - * @triggers addItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs, array $options = array()) + protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + if (!$this->hasFreeCapacity()) { + $memoryLimit = $this->getOptions()->getMemoryLimit(); + throw new Exception\OutOfCapacityException( + 'Memory usage exceeds limit ({$memoryLimit}).' + ); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$this->hasFreeCapacity()) { - $memoryLimit = $baseOptions->getMemoryLimit(); - throw new Exception\OutOfCapacityException( - 'Memory usage exceeds limit ({$memoryLimit}).' - ); - } - - $ns = $options['namespace']; - if (!isset($this->data[$ns])) { - $this->data[$ns] = array(); - } + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns])) { + $this->data[$ns] = array(); + } - $data = & $this->data[$ns]; - foreach ($keyValuePairs as $key => $value) { - if (isset($data[$key])) { - throw new Exception\RuntimeException("Key '{$key}' already exists within namespace '$ns'"); - } - $data[$key] = array($value, microtime(true), $options['tags']); + $data = & $this->data[$ns]; + $now = microtime(true); + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + if (isset($data[$normalizedKey])) { + throw new Exception\RuntimeException("Key '{$normalizedKey}' already exists within namespace '{$ns}'"); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $data[$normalizedKey] = array($value, $now, $normalizedOptions['tags']); } + + return true; } /** - * Replace an item. + * Internal method to replace an existing item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags * - An array of tags * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers replaceItem.pre(PreEvent) - * @triggers replaceItem.post(PostEvent) - * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value, array $options = array()) + protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns][$normalizedKey])) { + throw new Exception\ItemNotFoundException("Key '{$normalizedKey}' doesn't exist within namespace '{$ns}'"); } + $this->data[$ns][$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - if (!isset($this->data[$ns][$key])) { - throw new Exception\ItemNotFoundException("Key '{$key}' doen't exists within namespace '$ns'"); - } - $this->data[$ns][$key] = array($value, microtime(true), $options['tags']); - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Replace multiple items. + * Internal method to replace multiple existing items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags * - An array of tags * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers replaceItems.pre(PreEvent) - * @triggers replaceItems.post(PostEvent) - * @triggers replaceItems.exception(ExceptionEvent) */ - public function replaceItems(array $keyValuePairs, array $options = array()) + protected function internalReplaceItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $ns = $normalizedOptions['namespace']; + if (!isset($this->data[$ns])) { + throw new Exception\ItemNotFoundException("Namespace '$ns' doesn't exist"); } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - if (!isset($this->data[$ns])) { - throw new Exception\ItemNotFoundException("Namespace '$ns' doesn't exist"); - } - - $data = & $this->data[$ns]; - foreach ($keyValuePairs as $key => $value) { - if (!isset($data[$key])) { - throw new Exception\ItemNotFoundException( - "Key '{$key}' doen't exists within namespace '$ns'" - ); - } - $data[$key] = array($value, microtime(true), $options['tags']); + $data = & $this->data[$ns]; + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + if (!isset($data[$normalizedKey])) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' doesn't exist within namespace '{$ns}'" + ); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } - } - - /** - * Reset lifetime of an item - * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param string $key - * @param array $options - * @return boolean - * @throws Exception - * - * @triggers touchItem.pre(PreEvent) - * @triggers touchItem.post(PostEvent) - * @triggers touchItem.exception(ExceptionEvent) - */ - public function touchItem($key, array $options = array()) - { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $data[$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - if (isset($this->data[$ns][$key])) { - // update mtime - $this->data[$ns][$key][1] = microtime(true); - } else { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$key}' not found within namespace '{$ns}'" - ); - } - - // add an empty item - $this->data[$ns][$key] = array('', microtime(true), null); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Remove an item. + * Internal method to reset lifetime of an item * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers removeItem.pre(PreEvent) - * @triggers removeItem.post(PostEvent) - * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - if (isset($this->data[$ns][$key])) { - unset($this->data[$ns][$key]); - - // remove empty namespace - if (!$this->data[$ns]) { - unset($this->data[$ns]); - } - - } else { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$key}' not found on namespace '{$ns}'"); - } + $ns = $normalizedOptions['namespace']; + if (isset($this->data[$ns][$normalizedKey])) { + // update mtime + $this->data[$ns][$normalizedKey][1] = microtime(true); + } else { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found within namespace '{$ns}'" + ); } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + // add an empty item + $this->data[$ns][$normalizedKey] = array('', microtime(true), null); } + + return true; } /** - * Remove multiple items. + * Internal method to remove an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param array $keys - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers removeItems.pre(PreEvent) - * @triggers removeItems.post(PostEvent) - * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItems(array $keys, array $options = array()) + protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - if ($options['ignore_missing_items'] === false) { - if (!isset($this->data[$ns])) { - throw new Exception\ItemNotFoundException("Namespace '{$ns}' is empty"); - } - - $data = &$this->data[$ns]; - - $missingItems = null; - foreach ($keys as $key) { - if (isset($data[$key])) { - unset($data[$key]); - } else { - $missingItems[] = $key; - } - } - - if ($missingItems) { - throw new Exception\ItemNotFoundException( - "Keys '" . implode("','", $missingItems) . "' not found on namespace '{$ns}'" - ); - } - } elseif (isset($this->data[$ns])) { - $data = & $this->data[$ns]; - foreach ($keys as $key) { - unset($data[$key]); - } + $ns = $normalizedOptions['namespace']; + if (isset($this->data[$ns][$normalizedKey])) { + unset($this->data[$ns][$normalizedKey]); - // remove empty namespace - if (!$data) { - unset($this->data[$ns]); - } + // remove empty namespace + if (!$this->data[$ns]) { + unset($this->data[$ns]); } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + } elseif (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$normalizedKey}' not found on namespace '{$ns}'"); } + + return true; } /** - * Increment an item. + * Internal method to increment an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value of false on failure + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers incrementItem.pre(PreEvent) - * @triggers incrementItem.post(PostEvent) - * @triggers incrementItem.exception(ExceptionEvent) */ - public function incrementItem($key, $value, array $options = array()) + protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $value = (int) $value; - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - $data = & $this->data[$ns]; - if (isset($data[$key])) { - $data[$key][0]+= $value; - $data[$key][1] = microtime(true); - $result = $data[$key][0]; - } else { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$key}' not found within namespace '{$ns}'" - ); - } - - // add a new item - $data[$key] = array($value, microtime(true), null); - $result = $value; + $ns = $normalizedOptions['namespace']; + $data = & $this->data[$ns]; + if (isset($data[$normalizedKey])) { + $data[$normalizedKey][0]+= $value; + $data[$normalizedKey][1] = microtime(true); + $newValue = $data[$normalizedKey][0]; + } else { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found within namespace '{$ns}'" + ); } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + // add a new item + $newValue = $value; + $data[$normalizedKey] = array($newValue, microtime(true), null); } + + return $newValue; } /** - * Decrement an item. + * Internal method to decrement an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value or false or failure + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers decrementItem.pre(PreEvent) - * @triggers decrementItem.post(PostEvent) - * @triggers decrementItem.exception(ExceptionEvent) */ - public function decrementItem($key, $value, array $options = array()) + protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $value = (int) $value; - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $ns = $options['namespace']; - $data = & $this->data[$ns]; - if (isset($data[$key])) { - $data[$key][0]-= $value; - $data[$key][1] = microtime(true); - $result = $data[$key][0]; - } else { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$key}' not found within namespace '{$ns}'" - ); - } - - // add a new item - $data[$key] = array(-$value, microtime(true), null); - $result = -$value; + $ns = $normalizedOptions['namespace']; + $data = & $this->data[$ns]; + if (isset($data[$normalizedKey])) { + $data[$normalizedKey][0]-= $value; + $data[$normalizedKey][1] = microtime(true); + $newValue = $data[$normalizedKey][0]; + } else { + if (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$normalizedKey}' not found within namespace '{$ns}'" + ); } - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + // add a new item + $newValue = -$value; + $data[$normalizedKey] = array($newValue, microtime(true), null); } + + return $newValue; } /* find */ /** - * Find items. + * internal method to find items. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional + * - ttl + * - The time-to-live + * - namespace + * - The namespace to use + * - tags * - Tags to search for used with matching modes of - * Zend\Cache\Storage\Adapter::MATCH_TAGS_* + * Adapter::MATCH_TAGS_* * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see fetch() - * @see fetchAll() - * - * @triggers find.pre(PreEvent) - * @triggers find.post(PostEvent) - * @triggers find.exception(ExceptionEvent) + * @see fetch() + * @see fetchAll() */ - public function find($mode = self::MATCH_ACTIVE, array $options=array()) + protected function internalFind(& $normalizedMode, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getReadable()) { - return false; - } - if ($this->stmtActive) { throw new Exception\RuntimeException('Statement already in use'); } - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_ACTIVE, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $tags = & $options['tags']; - $emptyTags = $keys = array(); - foreach ($this->data[ $options['namespace'] ] as $key => &$item) { + $tags = & $normalizedOptions['tags']; + $emptyTags = $keys = array(); + foreach ($this->data[ $normalizedOptions['namespace'] ] as $key => &$item) { - // compare expired / active - if (($mode & self::MATCH_ALL) != self::MATCH_ALL) { + // compare expired / active + if (($normalizedMode & self::MATCH_ALL) != self::MATCH_ALL) { - // if MATCH_EXPIRED -> filter active items - if (($mode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { - if ($this->internalHasItem($key, $options)) { - continue; - } + // if MATCH_EXPIRED -> filter active items + if (($normalizedMode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { + if ($this->internalHasItem($key, $normalizedOptions)) { + continue; + } - // if MATCH_ACTIVE -> filter expired items - } else { - if (!$this->internalHasItem($key, $options)) { - continue; - } + // if MATCH_ACTIVE -> filter expired items + } else { + if (!$this->internalHasItem($key, $normalizedOptions)) { + continue; } } + } - // compare tags - if ($tags !== null) { - $tagsStored = isset($item[2]) ? $item[2] : $emptyTags; - - if ( ($mode & self::MATCH_TAGS_OR) == self::MATCH_TAGS_OR ) { - $matched = (count(array_diff($tags, $tagsStored)) != count($tags)); - } elseif ( ($mode & self::MATCH_TAGS_AND) == self::MATCH_TAGS_AND ) { - $matched = (count(array_diff($tags, $tagsStored)) == 0); - } + // compare tags + if ($tags !== null) { + $tagsStored = isset($item[2]) ? $item[2] : $emptyTags; - // negate - if ( ($mode & self::MATCH_TAGS_NEGATE) == self::MATCH_TAGS_NEGATE ) { - $matched = !$matched; - } + if ( ($normalizedMode & self::MATCH_TAGS_OR) == self::MATCH_TAGS_OR ) { + $matched = (count(array_diff($tags, $tagsStored)) != count($tags)); + } elseif ( ($normalizedMode & self::MATCH_TAGS_AND) == self::MATCH_TAGS_AND ) { + $matched = (count(array_diff($tags, $tagsStored)) == 0); + } - if (!$matched) { - continue; - } + // negate + if ( ($normalizedMode & self::MATCH_TAGS_NEGATE) == self::MATCH_TAGS_NEGATE ) { + $matched = !$matched; } - $keys[] = $key; + if (!$matched) { + continue; + } } - // don't check expiry on fetch - $options['ttl'] = 0; + $keys[] = $key; + } - $this->stmtKeys = $keys; - $this->stmtOptions = $options; - $this->stmtActive = true; + // don't check expiry on fetch + $normalizedOptions['ttl'] = 0; - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $this->stmtKeys = $keys; + $this->stmtOptions = $normalizedOptions; + $this->stmtActive = true; + + return true; } /** - * Fetches the next item from result set + * Internal method to fetch the next item from result set * * @return array|boolean The next item or false * @throws Exception - * @see fetchAll() - * - * @triggers fetch.pre(PreEvent) - * @triggers fetch.post(PostEvent) - * @triggers fetch.exception(ExceptionEvent) */ - public function fetch() + protected function internalFetch() { if (!$this->stmtActive) { return false; } - try { - $args = new ArrayObject(); - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); + $options = & $this->stmtOptions; + + // get the next valid item + do { + $key = array_shift($this->stmtKeys); + if ($key === null) { + break; } - $options = & $this->stmtOptions; + if (!$this->internalHasItem($key, $options)) { + continue; + } - // get the next valid item - do { - $key = array_shift($this->stmtKeys); - if ($key === null) { - break; - } - if (!$this->internalHasItem($key, $options)) { - continue; - } - $ref = & $this->data[ $options['namespace'] ][$key]; - break; - } while (true); - - // get item data - if ($key) { - $item = array(); - foreach ($options['select'] as $select) { - if ($select == 'key') { - $item['key'] = $key; - } elseif ($select == 'value') { - $item['value'] = $ref[0]; - } elseif ($select == 'mtime') { - $item['mtime'] = $ref[1]; - } elseif ($select == 'tags') { - $item['tags'] = $ref[2]; - } else { - $item[$select] = null; - } - } + break; + } while (true); - $result = $item; + // free statement after last item + if (!$key) { + $this->stmtActive = false; + $this->stmtKeys = null; + $this->stmtOptions = null; - } else { - // free statement after last item - $this->stmtActive = false; - $this->stmtKeys = null; - $this->stmtOptions = null; + return false; + } - $result = false; + $ref = & $this->data[ $options['namespace'] ][$key]; + $result = array(); + foreach ($options['select'] as $select) { + if ($select == 'key') { + $result['key'] = $key; + } elseif ($select == 'value') { + $result['value'] = $ref[0]; + } elseif ($select == 'mtime') { + $result['mtime'] = $ref[1]; + } elseif ($select == 'tags') { + $result['tags'] = $ref[2]; + } else { + $result[$select] = null; } - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return $result; } /* cleaning */ /** - * Clear items off all namespaces. - * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - tags optional - * - Tags to search for used with matching modes of - * Zend\Cache\Storage\Adapter::MATCH_TAGS_* + * Internal method to clear items off all namespaces. * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see clearByNamespace() - * - * @triggers clear.pre(PreEvent) - * @triggers clear.post(PostEvent) - * @triggers clear.exception(ExceptionEvent) + * @see clearByNamespace() */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (!$options['tags'] && ($mode & self::MATCH_ALL) == self::MATCH_ALL) { - $this->data = array(); - } else { - foreach ($this->data as &$data) { - $this->clearNamespacedDataArray($data, $mode, $options); - } + if (!$normalizedOptions['tags'] && ($normalizedMode & self::MATCH_ALL) == self::MATCH_ALL) { + $this->data = array(); + } else { + foreach ($this->data as & $data) { + $this->clearNamespacedDataArray($data, $normalizedMode, $normalizedOptions); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return true; } /** * Clear items by namespace. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - Tags to search for used with matching modes of - * Zend\Cache\Storage\Adapter::MATCH_TAGS_* + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - tags + * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean - * @throws Zend\Cache\Exception - * @see clear() - * - * @triggers clearByNamespace.pre(PreEvent) - * @triggers clearByNamespace.post(PostEvent) - * @triggers clearByNamespace.exception(ExceptionEvent) + * @throws Exception + * @see clear() */ - public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if (isset($this->data[ $options['namespace'] ])) { - if (!$options['tags'] && ($mode & self::MATCH_ALL) == self::MATCH_ALL) { - unset($this->data[ $options['namespace'] ]); - } else { - $this->clearNamespacedDataArray($this->data[ $options['namespace'] ], $mode, $options); - } + if (isset($this->data[ $normalizedOptions['namespace'] ])) { + if (!$normalizedOptions['tags'] && ($normalizedMode & self::MATCH_ALL) == self::MATCH_ALL) { + unset($this->data[ $normalizedOptions['namespace'] ]); + } else { + $this->clearNamespacedDataArray($this->data[ $normalizedOptions['namespace'] ], $normalizedMode, $normalizedOptions); } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); } + + return true; } /* status */ /** - * Get capabilities + * Internal method to get capabilities of this adapter * * @return Capabilities - * - * @triggers getCapabilities.pre(PreEvent) - * @triggers getCapabilities.post(PostEvent) - * @triggers getCapabilities.exception(ExceptionEvent) */ - public function getCapabilities() + protected function internalGetCapabilities() { - $args = new ArrayObject(); - - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - if ($this->capabilities === null) { $this->capabilityMarker = new stdClass(); $this->capabilities = new Capabilities( @@ -1247,39 +852,24 @@ public function getCapabilities() ); } - return $this->triggerPost(__FUNCTION__, $args, $this->capabilities); + return $this->capabilities; } /** - * Get storage capacity. + * Internal method to get storage capacity. * - * @param array $options + * @param array $normalizedOptions * @return array|boolean Capacity as array or false on failure * @throws Exception - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) */ - public function getCapacity(array $options = array()) + protected function internalGetCapacity(array & $normalizedOptions) { - $args = new ArrayObject(array( - 'options' => & $options, - )); - - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - $total = $this->getOptions()->getMemoryLimit(); $free = $total - (float) memory_get_usage(true); - $result = array( + return array( 'total' => $total, 'free' => ($free >= 0) ? $free : 0, ); - - return $this->triggerPost(__FUNCTION__, $args, $result); } /* internal */ diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index 346372277..e79602234 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -303,499 +303,284 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * Add an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * * @param string $key * @param mixed $value * @param array $options * @return boolean * @throws Exception - * - * @triggers addItem.pre(PreEvent) - * @triggers addItem.post(PostEvent) - * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!wincache_ucache_add($internalKey, $value, $options['ttl'])) { - if (wincache_ucache_exists($internalKey)) { - throw new Exception\RuntimeException("Key '{$internalKey}' already exists"); - } - - $type = is_object($value) ? get_class($value) : gettype($value); - throw new Exception\RuntimeException( - "wincache_ucache_add('{$internalKey}', <{$type}>, {$options['ttl']}) failed" - ); + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!wincache_ucache_add($internalKey, $value, $normalizedOptions['ttl'])) { + // TODO: check if this is really needed + if (wincache_ucache_exists($internalKey)) { + throw new Exception\RuntimeException("Key '{$internalKey}' already exists"); } - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $type = is_object($value) ? get_class($value) : gettype($value); + throw new Exception\RuntimeException( + "wincache_ucache_add('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + ); } + + return true; } /** - * Add multiple items. + * Internal method to add multiple items. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param array $keyValuePairs - * @param array $options + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers addItems.pre(PreEvent) - * @triggers addItems.post(PostEvent) - * @triggers addItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs, array $options = array()) + protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKeyValuePairs = array(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { + $internalKey = $prefix . $normalizedKey; + $internalKeyValuePairs[$internalKey] = $value; } - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKeyValuePairs = array(); - $prefix = $options['namespace'] . $baseOptions->getNamespaceSeparator(); - foreach ($keyValuePairs as $key => &$value) { - $internalKey = $prefix . $key; - $internalKeyValuePairs[$internalKey] = &$value; - } - - $errKeys = wincache_ucache_add($internalKeyValuePairs, null, $options['ttl']); - if ($errKeys!==array()) { - throw new Exception\RuntimeException( - "wincache_ucache_add(, null, {$options['ttl']}) failed for keys: " - . "'" . implode("','", array_keys($errKeys)) . "'" - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $errKeys = wincache_ucache_add($internalKeyValuePairs, null, $normalizedOptions['ttl']); + if ($errKeys !== array()) { + throw new Exception\RuntimeException( + "wincache_ucache_add(, null, {$normalizedOptions['ttl']}) failed for keys: " + . "'" . implode("','", array_keys($errKeys)) . "'" + ); } + + return true; } /** - * Replace an item. + * Internal method to replace an existing item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers replaceItem.pre(PreEvent) - * @triggers replaceItem.post(PostEvent) - * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value, array $options = array()) + protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!wincache_ucache_exists($internalKey)) { + throw new Exception\ItemNotFoundException( + "Key '{$internalKey}' doesn't exist" + ); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!wincache_ucache_exists($internalKey)) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' doesn't exist" - ); - } - - if (!wincache_ucache_set($internalKey, $value, $options['ttl'])) { - $type = is_object($value) ? get_class($value) : gettype($value); - throw new Exception\RuntimeException( - "wincache_ucache_set('{$internalKey}', <{$type}>, {$options['ttl']}) failed" - ); - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + if (!wincache_ucache_set($internalKey, $value, $normalizedOptions['ttl'])) { + $type = is_object($value) ? get_class($value) : gettype($value); + throw new Exception\RuntimeException( + "wincache_ucache_set('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + ); } + + return true; } /** - * Remove an item. + * Internal method to remove an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param array $options + * @param string $normalizedKey + * @param array $normalizedOptions * @return boolean * @throws Exception - * - * @triggers removeItem.pre(PreEvent) - * @triggers removeItem.post(PostEvent) - * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + if (!wincache_ucache_delete($internalKey) && !$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); } - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - if (!wincache_ucache_delete($internalKey)) { - if (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - } - - $result = true; - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return true; } /** - * Increment an item. + * Internal method to increment an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers incrementItem.pre(PreEvent) - * @triggers incrementItem.post(PostEvent) - * @triggers incrementItem.exception(ExceptionEvent) */ - public function incrementItem($key, $value, array $options = array()) + protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $value = (int)$value; - $newValue = wincache_ucache_inc($internalKey, $value); - if ($newValue === false) { - if (wincache_ucache_exists($internalKey)) { - throw new Exception\RuntimeException("wincache_ucache_inc('{$internalKey}', {$value}) failed"); - } elseif (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' not found" - ); - } - - $this->addItem($key, $value, $options); - $newValue = $value; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $value = (int)$value; + $newValue = wincache_ucache_inc($internalKey, $value); + if ($newValue === false) { + if (wincache_ucache_exists($internalKey)) { + throw new Exception\RuntimeException("wincache_ucache_inc('{$internalKey}', {$value}) failed"); + } elseif (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$internalKey}' not found" + ); } - return $this->triggerPost(__FUNCTION__, $args, $newValue); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $newValue = $value; + $this->addItem($normalizedKey, $newValue, $normalizedOptions); } + + return $newValue; } /** - * Decrement an item. + * Internal method to decrement an item. * * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * - ignore_missing_items + * - Throw exception on missing item * - * @param string $key - * @param int $value - * @param array $options - * @return int|boolean The new value or false or failure + * @param string $normalizedKey + * @param int $value + * @param array $normalizedOptions + * @return int|boolean The new value or false on failure * @throws Exception - * - * @triggers decrementItem.pre(PreEvent) - * @triggers decrementItem.post(PostEvent) - * @triggers decrementItem.exception(ExceptionEvent) */ - public function decrementItem($key, $value, array $options = array()) + protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeKey($key); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $internalKey = $options['namespace'] . $baseOptions->getNamespaceSeparator() . $key; - $value = (int)$value; - $newValue = wincache_ucache_dec($internalKey, $value); - if ($newValue === false) { - if (wincache_ucache_exists($internalKey)) { - throw new Exception\RuntimeException("wincache_ucache_dec('{$internalKey}', {$value}) failed"); - } elseif (!$options['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' not found" - ); - } - - $this->addItem($key, -$value, $options); - $newValue = -$value; + $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $value = (int)$value; + $newValue = wincache_ucache_dec($internalKey, $value); + if ($newValue === false) { + if (wincache_ucache_exists($internalKey)) { + throw new Exception\RuntimeException("wincache_ucache_inc('{$internalKey}', {$value}) failed"); + } elseif (!$normalizedOptions['ignore_missing_items']) { + throw new Exception\ItemNotFoundException( + "Key '{$internalKey}' not found" + ); } - return $this->triggerPost(__FUNCTION__, $args, $newValue); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $newValue = -$value; + $this->addItem($normalizedKey, $newValue, $normalizedOptions); } - } - - /* find */ + return $newValue; + } /* cleaning */ /** - * Clear items off all namespaces. + * Internal method to clear items off all namespaces. * * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - tags optional - * - Tags to search for used with matching modes of - * Zend\Cache\Storage\Adapter::MATCH_TAGS_* - * - * @param int $mode Matching mode (Value of Zend\Cache\Storage\Adapter::MATCH_*) - * @param array $options + * - ttl + * - The time-to-life + * + * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) + * @param array $normalizedOptions * @return boolean * @throws Exception - * @see clearByNamespace() - * - * @triggers clear.pre(PreEvent) - * @triggers clear.post(PostEvent) - * @triggers clear.exception(ExceptionEvent) + * @see clearByNamespace() */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) + protected function internalClear(& $normalizedMode, array & $normalizedOptions) { - if (!$this->getOptions()->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = wincache_ucache_clear(); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return wincache_ucache_clear(); } /* status */ /** - * Get capabilities + * Internal method to get capabilities of this adapter * * @return Capabilities - * - * @triggers getCapabilities.pre(PreEvent) - * @triggers getCapabilities.post(PostEvent) - * @triggers getCapabilities.exception(ExceptionEvent) */ - public function getCapabilities() + protected function internalGetCapabilities() { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, - array( - 'supportedDatatypes' => array( - 'NULL' => true, - 'boolean' => true, - 'integer' => true, - 'double' => true, - 'string' => true, - 'array' => true, - 'object' => 'object', - 'resource' => false, - ), - 'supportedMetadata' => array( - 'ttl', - 'num_hits', - 'internal_key', - 'mem_size' - ), - 'maxTtl' => 0, - 'staticTtl' => true, - 'ttlPrecision' => 1, - 'useRequestTime' => false, - 'expiredRead' => false, - 'namespaceIsPrefix' => true, - 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), - 'iterable' => false, - 'clearAllNamespaces' => true, - 'clearByNamespace' => false, - ) - ); - } - - return $this->triggerPost(__FUNCTION__, $args, $this->capabilities); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + if ($this->capabilities === null) { + $this->capabilityMarker = new stdClass(); + $this->capabilities = new Capabilities( + $this->capabilityMarker, + array( + 'supportedDatatypes' => array( + 'NULL' => true, + 'boolean' => true, + 'integer' => true, + 'double' => true, + 'string' => true, + 'array' => true, + 'object' => 'object', + 'resource' => false, + ), + 'supportedMetadata' => array( + 'ttl', + 'num_hits', + 'internal_key', + 'mem_size' + ), + 'maxTtl' => 0, + 'staticTtl' => true, + 'ttlPrecision' => 1, + 'useRequestTime' => false, + 'expiredRead' => false, + 'namespaceIsPrefix' => true, + 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), + 'iterable' => false, + 'clearAllNamespaces' => true, + 'clearByNamespace' => false, + ) + ); } + + return $this->capabilities; } /** - * Get storage capacity. + * Internal method to get storage capacity. * - * @param array $options + * @param array $normalizedOptions * @return array|boolean Capacity as array or false on failure - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) + * @throws Exception */ - public function getCapacity(array $options = array()) + protected function internalGetCapacity(array & $normalizedOptions) { - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $mem = wincache_ucache_meminfo (); - $result = array( - 'free' => $mem['memory_free'], - 'total' => $mem['memory_total'], - ); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $mem = wincache_ucache_meminfo(); + return array( + 'free' => $mem['memory_free'], + 'total' => $mem['memory_total'], + ); } /* internal */ diff --git a/src/Storage/Adapter/ZendServerDisk.php b/src/Storage/Adapter/ZendServerDisk.php index 85a930f54..f41522245 100644 --- a/src/Storage/Adapter/ZendServerDisk.php +++ b/src/Storage/Adapter/ZendServerDisk.php @@ -54,32 +54,15 @@ public function __construct($options = array()) } /** - * Get storage capacity. + * Internal method to get storage capacity. * - * @param array $options + * @param array $normalizedOptions * @return array|boolean Capacity as array or false on failure - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) + * @throws Exception */ - public function getCapacity(array $options = array()) + protected function internalGetCapacity(array & $normalizedOptions) { - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = Utils::getDiskCapacity(ini_get('zend_datacache.disk.save_path')); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + return Utils::getDiskCapacity(ini_get('zend_datacache.disk.save_path')); } /** diff --git a/src/Storage/Adapter/ZendServerShm.php b/src/Storage/Adapter/ZendServerShm.php index f04b64bf1..82c8112b7 100644 --- a/src/Storage/Adapter/ZendServerShm.php +++ b/src/Storage/Adapter/ZendServerShm.php @@ -53,38 +53,20 @@ public function __construct($options = array()) } /** - * Get storage capacity. + * Internal method to get storage capacity. * - * @param array $options + * @param array $normalizedOptions * @return array|boolean Capacity as array or false on failure - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) + * @throws Exception */ - public function getCapacity(array $options = array()) + protected function internalGetCapacity(array & $normalizedOptions) { - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $total = (int)ini_get('zend_datacache.shm.memory_cache_size'); - $total*= 1048576; // MB -> Byte - $result = array( - 'total' => $total, - // TODO: How to get free capacity status - ); - - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); - } + $total = (int)ini_get('zend_datacache.shm.memory_cache_size'); + $total*= 1048576; // MB -> Byte + return array( + 'total' => $total, + // TODO: How to get free capacity status + ); } /** From 4d2ee5f52c8efa986850eb9314677f6726956da6 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 18 Mar 2012 06:26:04 +0100 Subject: [PATCH 07/62] fixed testDisabledFileBlocking on windows --- src/Storage/Adapter/FilesystemOptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Adapter/FilesystemOptions.php b/src/Storage/Adapter/FilesystemOptions.php index 0d983fd3b..33e5d5fde 100644 --- a/src/Storage/Adapter/FilesystemOptions.php +++ b/src/Storage/Adapter/FilesystemOptions.php @@ -329,7 +329,7 @@ public function getDirUmask() public function setFileBlocking($flag) { $flag = (bool) $flag; - if ($flag && substr(\PHP_OS, 0, 3) == 'WIN') { + if (!$flag && substr(\PHP_OS, 0, 3) == 'WIN') { throw new Exception\InvalidArgumentException( "This option can't be disabled on windows" ); From 3dc87fd07834a0c99c6a3efaf3ad1e7eeef145b1 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 18 Mar 2012 20:46:01 +0100 Subject: [PATCH 08/62] dos2unix --- src/Storage/Adapter/AbstractAdapter.php | 162 ++++++++++---------- src/Storage/Adapter/Apc.php | 70 ++++----- src/StorageFactory.php | 8 +- test/PatternFactoryTest.php | 10 +- test/Storage/Adapter/WinCacheTest.php | 4 +- test/Storage/Adapter/ZendServerDiskTest.php | 4 +- test/Storage/Adapter/ZendServerShmTest.php | 4 +- test/StorageFactoryTest.php | 6 +- 8 files changed, 134 insertions(+), 134 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index f0317e22b..0734a8dce 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -670,19 +670,19 @@ public function getMetadata($key, array $options = array()) } } - /** - * Internal method to get metadata of an item. - * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - * @param string $normalizedKey - * @param array $normalizedOptions - * @return array|boolean Metadata or false on failure - * @throws Exception + /** + * Internal method to get metadata of an item. + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param string $normalizedKey + * @param array $normalizedOptions + * @return array|boolean Metadata or false on failure + * @throws Exception */ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { @@ -743,19 +743,19 @@ public function getMetadatas(array $keys, array $options = array()) } } - /** - * Internal method to get multiple metadata - * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - * @param array $normalizedKeys - * @param array $normalizedOptions - * @return array Associative array of existing cache ids and its metadata - * @throws Exception + /** + * Internal method to get multiple metadata + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing cache ids and its metadata + * @throws Exception */ protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) { @@ -780,8 +780,8 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal /* writing */ - /** - * Store an item. + /** + * Store an item. * * Options: * - ttl optional @@ -790,17 +790,17 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal * - The namespace to use (Default: namespace of object) * - tags optional * - An array of tags - * - * @param string $key - * @param mixed $value - * @param array $options - * @return boolean + * + * @param string $key + * @param mixed $value + * @param array $options + * @return boolean * @throws Exception * * @triggers setItem.pre(PreEvent) * @triggers setItem.post(PostEvent) - * @triggers setItem.exception(ExceptionEvent) - */ + * @triggers setItem.exception(ExceptionEvent) + */ public function setItem($key, $value, array $options = array()) { if (!$this->getOptions()->getWritable()) { @@ -828,8 +828,8 @@ public function setItem($key, $value, array $options = array()) } } - /** - * Internal method to store an item. + /** + * Internal method to store an item. * * Options: * - ttl @@ -838,13 +838,13 @@ public function setItem($key, $value, array $options = array()) * - The namespace to use * - tags * - An array of tags - * - * @param string $normalizedKey - * @param mixed $value - * @param array $normalizedOptions - * @return boolean - * @throws Exception - */ + * + * @param string $normalizedKey + * @param mixed $value + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ abstract protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions); /** @@ -893,8 +893,8 @@ public function setItems(array $keyValuePairs, array $options = array()) } } - /** - * Internal method to store multiple items. + /** + * Internal method to store multiple items. * * Options: * - ttl @@ -903,19 +903,19 @@ public function setItems(array $keyValuePairs, array $options = array()) * - The namespace to use * - tags * - An array of tags - * - * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions - * @return boolean - * @throws Exception - */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { $result = true; foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { $result = $this->internalSetItem($normalizedKey, $value, $normalizedOptions) && $result; } - return $result; + return $result; } /** @@ -1865,24 +1865,24 @@ protected function internatDecrementItems(array & $normalizedKeyValuePairs, arra return $ret; } - /* non-blocking */ - - /** - * Request multiple items. - * - * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - select optional - * - An array of the information the returned item contains - * (Default: array('key', 'value')) - * - callback optional - * - An result callback will be invoked for each item in the result set. - * - The first argument will be the item array. - * - The callback does not have to return anything. - * + /* non-blocking */ + + /** + * Request multiple items. + * + * Options: + * - ttl optional + * - The time-to-live (Default: ttl of object) + * - namespace optional + * - The namespace to use (Default: namespace of object) + * - select optional + * - An array of the information the returned item contains + * (Default: array('key', 'value')) + * - callback optional + * - An result callback will be invoked for each item in the result set. + * - The first argument will be the item array. + * - The callback does not have to return anything. + * * @param array $keys * @param array $options * @return boolean @@ -1893,15 +1893,15 @@ protected function internatDecrementItems(array & $normalizedKeyValuePairs, arra * @triggers getDelayed.pre(PreEvent) * @triggers getDelayed.post(PostEvent) * @triggers getDelayed.exception(ExceptionEvent) - */ - public function getDelayed(array $keys, array $options = array()) - { - if (!$this->getOptions()->getReadable()) { - return false; - } elseif (!$keys) { - // empty statement - return true; - } + */ + public function getDelayed(array $keys, array $options = array()) + { + if (!$this->getOptions()->getReadable()) { + return false; + } elseif (!$keys) { + // empty statement + return true; + } $this->normalizeKeys($keys); $this->normalizeOptions($options); diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index 5c2459681..9968410b3 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -656,8 +656,8 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no return $newValue; } - /* non-blocking */ - + /* non-blocking */ + /** * Internal method to request multiple items. * @@ -680,42 +680,42 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no * @see fetch() * @see fetchAll() */ - protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - if (isset($normalizedOptions['callback']) && !is_callable($normalizedOptions['callback'], false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - + protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) + { + if ($this->stmtActive) { + throw new Exception\RuntimeException('Statement already in use'); + } + + if (isset($normalizedOptions['callback']) && !is_callable($normalizedOptions['callback'], false)) { + throw new Exception\InvalidArgumentException('Invalid callback'); + } + $format = 0; - foreach ($normalizedOptions['select'] as $property) { - if (isset(self::$selectMap[$property])) { - $format = $format | self::$selectMap[$property]; - } - } + foreach ($normalizedOptions['select'] as $property) { + if (isset(self::$selectMap[$property])) { + $format = $format | self::$selectMap[$property]; + } + } $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $search = array(); - foreach ($normalizedKeys as $normalizedKey) { - $search[] = preg_quote($normalizedKey, '/'); - } - $search = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $search) . ')$/'; - - $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); - $this->stmtActive = true; - $this->stmtOptions = & $normalizedOptions; - - if (isset($normalizedOptions['callback'])) { - $callback = & $normalizedOptions['callback']; - while (($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } - } - - return true; + $search = array(); + foreach ($normalizedKeys as $normalizedKey) { + $search[] = preg_quote($normalizedKey, '/'); + } + $search = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $search) . ')$/'; + + $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); + $this->stmtActive = true; + $this->stmtOptions = & $normalizedOptions; + + if (isset($normalizedOptions['callback'])) { + $callback = & $normalizedOptions['callback']; + while (($item = $this->fetch()) !== false) { + call_user_func($callback, $item); + } + } + + return true; } /* find */ diff --git a/src/StorageFactory.php b/src/StorageFactory.php index 5372ad874..ef39a5cb2 100644 --- a/src/StorageFactory.php +++ b/src/StorageFactory.php @@ -99,10 +99,10 @@ public static function factory($cfg) foreach ($cfg['plugins'] as $k => $v) { if (is_string($k)) { - if (!is_array($v)) { - throw new Exception\InvalidArgumentException( - "'plugins.{$k}' needs to be an array" - ); + if (!is_array($v)) { + throw new Exception\InvalidArgumentException( + "'plugins.{$k}' needs to be an array" + ); } $pluginName = $k; $pluginOptions = $v; diff --git a/test/PatternFactoryTest.php b/test/PatternFactoryTest.php index ee66ea314..93b5cfddf 100644 --- a/test/PatternFactoryTest.php +++ b/test/PatternFactoryTest.php @@ -57,15 +57,15 @@ public function testChangeBroker() $this->assertSame($broker, Cache\PatternFactory::getBroker()); } - public function testFactory() - { + public function testFactory() + { $pattern1 = Cache\PatternFactory::factory('capture'); $this->assertInstanceOf('Zend\Cache\Pattern\CaptureCache', $pattern1); - + $pattern2 = Cache\PatternFactory::factory('capture'); $this->assertInstanceOf('Zend\Cache\Pattern\CaptureCache', $pattern2); - - $this->assertNotSame($pattern1, $pattern2); + + $this->assertNotSame($pattern1, $pattern2); } } diff --git a/test/Storage/Adapter/WinCacheTest.php b/test/Storage/Adapter/WinCacheTest.php index 35264936a..c414fc7e9 100644 --- a/test/Storage/Adapter/WinCacheTest.php +++ b/test/Storage/Adapter/WinCacheTest.php @@ -36,8 +36,8 @@ class WinCacheTest extends CommonAdapterTest public function setUp() { - if (!defined('TESTS_ZEND_CACHE_WINCACHE_ENABLED') || !TESTS_ZEND_CACHE_WINCACHE_ENABLED) { - $this->markTestSkipped("Skipped by TestConfiguration (TESTS_ZEND_CACHE_WINCACHE_ENABLED)"); + if (!defined('TESTS_ZEND_CACHE_WINCACHE_ENABLED') || !TESTS_ZEND_CACHE_WINCACHE_ENABLED) { + $this->markTestSkipped("Skipped by TestConfiguration (TESTS_ZEND_CACHE_WINCACHE_ENABLED)"); } if (!extension_loaded('wincache')) { diff --git a/test/Storage/Adapter/ZendServerDiskTest.php b/test/Storage/Adapter/ZendServerDiskTest.php index 2fefd40af..22f8e3b71 100644 --- a/test/Storage/Adapter/ZendServerDiskTest.php +++ b/test/Storage/Adapter/ZendServerDiskTest.php @@ -37,8 +37,8 @@ class ZendServerDiskTest extends CommonAdapterTest public function setUp() { - if (!defined('TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED') || !TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED) { - $this->markTestSkipped("Skipped by TestConfiguration (TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED)"); + if (!defined('TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED') || !TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED) { + $this->markTestSkipped("Skipped by TestConfiguration (TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED)"); } if (!function_exists('zend_disk_cache_store') || PHP_SAPI == 'cli') { diff --git a/test/Storage/Adapter/ZendServerShmTest.php b/test/Storage/Adapter/ZendServerShmTest.php index b2c3142fa..965f65695 100644 --- a/test/Storage/Adapter/ZendServerShmTest.php +++ b/test/Storage/Adapter/ZendServerShmTest.php @@ -37,8 +37,8 @@ class ZendServerShmTest extends CommonAdapterTest public function setUp() { - if (!defined('TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED') || !TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED) { - $this->markTestSkipped("Skipped by TestConfiguration (TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED)"); + if (!defined('TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED') || !TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED) { + $this->markTestSkipped("Skipped by TestConfiguration (TESTS_ZEND_CACHE_ZEND_SERVER_ENABLED)"); } if (strtolower(PHP_SAPI) == 'cli') { diff --git a/test/StorageFactoryTest.php b/test/StorageFactoryTest.php index fd62ca36d..8940e04ad 100644 --- a/test/StorageFactoryTest.php +++ b/test/StorageFactoryTest.php @@ -42,7 +42,7 @@ public function setUp() public function tearDown() { - Cache\StorageFactory::resetAdapterBroker(); + Cache\StorageFactory::resetAdapterBroker(); Cache\StorageFactory::resetPluginBroker(); } @@ -64,7 +64,7 @@ public function testAdapterFactory() $adapter1 = Cache\StorageFactory::adapterFactory('Memory'); $this->assertInstanceOf('Zend\Cache\Storage\Adapter\Memory', $adapter1); - $adapter2 = Cache\StorageFactory::adapterFactory('Memory'); + $adapter2 = Cache\StorageFactory::adapterFactory('Memory'); $this->assertInstanceOf('Zend\Cache\Storage\Adapter\Memory', $adapter2); $this->assertNotSame($adapter1, $adapter2); @@ -88,7 +88,7 @@ public function testPluginFactory() $plugin1 = Cache\StorageFactory::pluginFactory('Serializer'); $this->assertInstanceOf('Zend\Cache\Storage\Plugin\Serializer', $plugin1); - $plugin2 = Cache\StorageFactory::pluginFactory('Serializer'); + $plugin2 = Cache\StorageFactory::pluginFactory('Serializer'); $this->assertInstanceOf('Zend\Cache\Storage\Plugin\Serializer', $plugin2); $this->assertNotSame($plugin1, $plugin2); From b1cb0435d183a31aca76eb061e10adcac346532f Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 22 Mar 2012 22:29:00 +0100 Subject: [PATCH 09/62] Cache: now storage adapter options triggers 'option' event on change option(s), the adapter can listen to it to update capabilities and to update internal instances --- src/Storage/Adapter/AbstractAdapter.php | 30 ++++- src/Storage/Adapter/AdapterOptions.php | 148 ++++++++++++++++------ src/Storage/Adapter/Apc.php | 18 ++- src/Storage/Adapter/ApcOptions.php | 4 +- src/Storage/Adapter/Filesystem.php | 90 ++++++------- src/Storage/Adapter/FilesystemOptions.php | 73 ++++------- src/Storage/Adapter/Memcached.php | 2 +- src/Storage/Adapter/MemcachedOptions.php | 16 ++- src/Storage/Adapter/MemoryOptions.php | 4 +- src/Storage/Adapter/WinCache.php | 18 ++- src/Storage/Adapter/WinCacheOptions.php | 4 +- 11 files changed, 259 insertions(+), 148 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 0734a8dce..31ad92f76 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -51,6 +51,12 @@ abstract class AbstractAdapter implements Adapter */ protected $events = null; + /** + * Event handles of this adapter + * @var array + */ + protected $eventHandles = array(); + /** * The plugin registry * @@ -128,6 +134,13 @@ public function __destruct() foreach ($this->getPlugins() as $plugin) { $this->removePlugin($plugin); } + + if ($this->eventHandles) { + $events = $this->events(); + foreach ($this->eventHandles as $handle) { + $events->detach($handle); + } + } } /* configuration */ @@ -141,11 +154,20 @@ public function __destruct() */ public function setOptions($options) { - if (!$options instanceof AdapterOptions) { - $options = new AdapterOptions($options); - } + if ($this->options !== $options) { + if (!$options instanceof AdapterOptions) { + $options = new AdapterOptions($options); + } - $this->options = $options; + if ($this->options) { + $this->options->setAdapter(null); + } + $options->setAdapter($this); + $this->options = $options; + + $event = new Event('option', $this, new ArrayObject($options->toArray())); + $this->events()->trigger($event); + } return $this; } diff --git a/src/Storage/Adapter/AdapterOptions.php b/src/Storage/Adapter/AdapterOptions.php index 46daef1d2..508ed1be7 100644 --- a/src/Storage/Adapter/AdapterOptions.php +++ b/src/Storage/Adapter/AdapterOptions.php @@ -21,7 +21,10 @@ namespace Zend\Cache\Storage\Adapter; -use Zend\Cache\Exception, +use ArrayObject, + Zend\Cache\Exception, + Zend\Cache\Storage\Adapter, + Zend\Cache\Storage\Event, Zend\Stdlib\Options; /** @@ -35,6 +38,14 @@ */ class AdapterOptions extends Options { + + /** + * The adapter using these options + * + * @var null|Filesystem + */ + protected $adapter; + /** * Ignore missing items * @@ -103,6 +114,18 @@ public function toArray() return $array; } + /** + * Adapter using this instance + * + * @param Adapter|null $adapter + * @return AdapterOptions + */ + public function setAdapter(Adapter $adapter = null) + { + $this->adapter = $adapter; + return $this; + } + /** * Enables or disables ignoring of missing items. * @@ -121,7 +144,11 @@ public function toArray() */ public function setIgnoreMissingItems($flag) { - $this->ignoreMissingItems = (bool) $flag; + $flag = (bool) $flag; + if ($this->ignoreMissingItems !== $flag) { + $this->triggerOptionEvent('ignore_missing_items', $flag); + $this->ignoreMissingItems = $flag; + } return $this; } @@ -144,19 +171,20 @@ public function getIgnoreMissingItems() */ public function setKeyPattern($pattern) { - if (($pattern = (string) $pattern) === '') { - $this->keyPattern = ''; - return $this; - } + $pattern = (string) $pattern; + if ($this->keyPattern !== $pattern) { + // validate pattern + if ($pattern !== '') { + if (@preg_match($pattern, '') === false) { + $err = error_get_last(); + throw new Exception\InvalidArgumentException("Invalid pattern '{$pattern}': {$err['message']}"); + } + } - // validate pattern - if (@preg_match($pattern, '') === false) { - $err = error_get_last(); - throw new Exception\InvalidArgumentException("Invalid pattern '{$pattern}': {$err['message']}"); + $this->triggerOptionEvent('key_pattern', $pattern); + $this->keyPattern = $pattern; } - $this->keyPattern = $pattern; - return $this; } @@ -179,18 +207,23 @@ public function getKeyPattern() public function setNamespace($namespace) { $namespace = (string)$namespace; - if ($namespace === '') { - throw new Exception\InvalidArgumentException('No namespace given'); - } + if ($this->namespace !== $namespace) { + if ($namespace === '') { + // TODO: allow empty namespaces + throw new Exception\InvalidArgumentException('No namespace given'); + } + + $pattern = $this->getNamespacePattern(); + if ($pattern && !preg_match($pattern, $namespace)) { + throw new Exception\InvalidArgumentException( + "The namespace '{$namespace}' doesn't match agains pattern '{$pattern}'" + ); + } - if (($pattern = $this->getNamespacePattern()) - && !preg_match($pattern, $namespace) - ) { - throw new Exception\InvalidArgumentException( - "The namespace '{$namespace}' doesn't match agains pattern '{$pattern}'" - ); + $this->triggerOptionEvent('namespace', $namespace); + $this->namespace = $namespace; } - $this->namespace = (string) $namespace; + return $this; } @@ -212,26 +245,27 @@ public function getNamespace() */ public function setNamespacePattern($pattern) { - if (($pattern = (string) $pattern) === '') { - $this->namespacePattern = ''; - return $this; - } + $pattern = (string) $pattern; + if ($this->namespacePattern !== $pattern) { + if ($pattern !== '') { + // validate pattern + if (@preg_match($pattern, '') === false) { + $err = error_get_last(); + throw new Exception\InvalidArgumentException("Invalid pattern '{$pattern}': {$err['message']}"); + + // validate current namespace + } elseif (($ns = $this->getNamespace()) && !preg_match($pattern, $ns)) { + throw new Exception\RuntimeException( + "The current namespace '{$ns}' doesn't match agains pattern '{$pattern}'" + . " - please change the namespace first" + ); + } + } - // validate pattern - if (@preg_match($pattern, '') === false) { - $err = error_get_last(); - throw new Exception\InvalidArgumentException("Invalid pattern '{$pattern}': {$err['message']}"); - - // validate current namespace - } elseif (($ns = $this->getNamespace()) && !preg_match($pattern, $ns)) { - throw new Exception\RuntimeException( - "The current namespace '{$ns}' doesn't match agains pattern '{$pattern}'" - . " - please change the namespace first" - ); + $this->triggerOptionEvent('namespace_pattern', $pattern); + $this->namespacePattern = $pattern; } - $this->namespacePattern = $pattern; - return $this; } @@ -253,7 +287,11 @@ public function getNamespacePattern() */ public function setReadable($flag) { - $this->readable = (bool) $flag; + $flag = (bool) $flag; + if ($this->readable !== $flag) { + $this->triggerOptionEvent('readable', $flag); + $this->readable = $flag; + } return $this; } @@ -276,7 +314,10 @@ public function getReadable() public function setTtl($ttl) { $this->normalizeTtl($ttl); - $this->ttl = $ttl; + if ($this->ttl !== $ttl) { + $this->triggerOptionEvent('ttl', $ttl); + $this->ttl = $ttl; + } return $this; } @@ -298,7 +339,11 @@ public function getTtl() */ public function setWritable($flag) { - $this->writable = (bool) $flag; + $flag = (bool) $flag; + if ($this->writable !== $flag) { + $this->triggerOptionEvent('writable', $flag); + $this->writable = $flag; + } return $this; } @@ -312,11 +357,30 @@ public function getWritable() return $this->writable; } + /** + * Triggers an option.change event + * if the this options instance has a connection too an adapter instance + * + * @param string $optionName + * @param mixed $optionValue + * @return void + */ + protected function triggerOptionEvent($optionName, $optionValue) + { + if (!$this->adapter) { + return; + } + + $event = new Event('option', $this->adapter, new ArrayObject(array($optionName => $optionValue))); + $this->adapter->events()->trigger($event); + } + /** * Validates and normalize a TTL. * * @param int|float $ttl * @throws Exception\InvalidArgumentException + * @return void */ protected function normalizeTtl(&$ttl) { diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index 9968410b3..bb9748091 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -852,9 +852,9 @@ protected function internalClearByNamespace(& $normalizedMode, array & $normaliz protected function internalGetCapabilities() { if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, + $marker = new stdClass(); + $capabilities = new Capabilities( + $marker, array( 'supportedDatatypes' => array( 'NULL' => true, @@ -891,6 +891,18 @@ protected function internalGetCapabilities() 'clearByNamespace' => true, ) ); + + // update namespace separator on change option + $this->events()->attach('option', function ($event) use ($capabilities, $marker) { + $params = $event->getParams(); + + if (isset($params['namespace_separator'])) { + $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']); + } + }); + + $this->capabilities = $capabilities; + $this->capabilityMarker = $marker; } return $this->capabilities; diff --git a/src/Storage/Adapter/ApcOptions.php b/src/Storage/Adapter/ApcOptions.php index adf39b5f5..e14b6f0e6 100644 --- a/src/Storage/Adapter/ApcOptions.php +++ b/src/Storage/Adapter/ApcOptions.php @@ -47,7 +47,9 @@ class ApcOptions extends AdapterOptions */ public function setNamespaceSeparator($separator) { - $this->namespaceSeparator = (string) $separator; + $separator = (string) $separator; + $this->triggerOptionEvent('namespace_separator', $separator); + $this->namespaceSeparator = $separator; return $this; } diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index c8eec183f..b2bf10ad5 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -83,9 +83,7 @@ public function setOptions($options) $options = new FilesystemOptions($options); } - $this->options = $options; - $options->setAdapter($this); - return $this; + return parent::setOptions($options); } /** @@ -1040,9 +1038,20 @@ protected function internalOptimize(array & $normalizedOptions) protected function internalGetCapabilities() { if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, + $marker = new stdClass(); + $options = $this->getOptions(); + + // detect metadata + $metadata = array('mtime', 'filespec'); + if (!$options->getNoAtime()) { + $metadata[] = 'atime'; + } + if (!$options->getNoCtime()) { + $metadata[] = 'ctime'; + } + + $capabilities = new Capabilities( + $marker, array( 'supportedDatatypes' => array( 'NULL' => 'string', @@ -1054,7 +1063,7 @@ protected function internalGetCapabilities() 'object' => false, 'resource' => false, ), - 'supportedMetadata' => array('mtime', 'filespec'), + 'supportedMetadata' => $metadata, 'maxTtl' => 0, 'staticTtl' => false, 'tagging' => true, @@ -1062,15 +1071,42 @@ protected function internalGetCapabilities() 'expiredRead' => true, 'maxKeyLength' => 251, // 255 - strlen(.dat | .ifo) 'namespaceIsPrefix' => true, - 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), + 'namespaceSeparator' => $options->getNamespaceSeparator(), 'iterable' => true, 'clearAllNamespaces' => true, 'clearByNamespace' => true, ) ); - // set dynamic capibilities - $this->updateCapabilities(); + // update capabilities on change options + $this->events()->attach('option', function ($event) use ($capabilities, $marker) { + $params = $event->getParams(); + + if (isset($params['namespace_separator'])) { + $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']); + } + + if (isset($params['no_atime']) || isset($params['no_ctime'])) { + $metadata = $capabilities->getSupportedMetadata(); + + if (isset($params['no_atime']) && !$params['no_atime']) { + $metadata[] = 'atime'; + } elseif (isset($params['no_atime']) && ($index = array_search('atime', $metadata)) !== false) { + unset($metadata[$index]); + } + + if (isset($params['no_ctime']) && !$params['no_ctime']) { + $metadata[] = 'ctime'; + } elseif (isset($params['no_ctime']) && ($index = array_search('ctime', $metadata)) !== false) { + unset($metadata[$index]); + } + + $capabilities->setSupportedMetadata($marker, $metadata); + } + }); + + $this->capabilityMarker = $marker; + $this->capabilities = $capabilities; } return $this->capabilities; @@ -1578,38 +1614,4 @@ protected function unlink($file) ); } } - - /** - * Update dynamic capabilities only if already created - * - * @return void - */ - public function updateCapabilities() - { - if ($this->capabilities) { - $options = $this->getOptions(); - - // update namespace separator - $this->capabilities->setNamespaceSeparator( - $this->capabilityMarker, - $options->getNamespaceSeparator() - ); - - // update metadata capabilities - $metadata = array('mtime', 'filespec'); - - if (!$options->getNoCtime()) { - $metadata[] = 'ctime'; - } - - if (!$options->getNoAtime()) { - $metadata[] = 'atime'; - } - - $this->capabilities->setSupportedMetadata( - $this->capabilityMarker, - $metadata - ); - } - } } diff --git a/src/Storage/Adapter/FilesystemOptions.php b/src/Storage/Adapter/FilesystemOptions.php index 33e5d5fde..ce20ad9c7 100644 --- a/src/Storage/Adapter/FilesystemOptions.php +++ b/src/Storage/Adapter/FilesystemOptions.php @@ -35,12 +35,6 @@ */ class FilesystemOptions extends AdapterOptions { - /** - * The adapter using these options - * - * @var null|Filesystem - */ - protected $adapter; /** * Directory to store cache files @@ -151,19 +145,6 @@ class FilesystemOptions extends AdapterOptions */ protected $readControlAlgo = 'crc32'; - /** - * Filesystem adapter using this instance - * - * @param Filesystem $filesystem - * @return FilesystemOptions - */ - public function setAdapter(Filesystem $filesystem) - { - $this->adapter = $filesystem; - $this->updateCapabilities(); - return $this; - } - /** * Set cache dir * @@ -189,8 +170,11 @@ public function setCacheDir($dir) } $dir = rtrim(realpath($dir), \DIRECTORY_SEPARATOR); + } else { + $dir = sys_get_temp_dir(); } + $this->triggerOptionEvent('cache_dir', $dir); $this->cacheDir = $dir; return $this; } @@ -203,7 +187,7 @@ public function setCacheDir($dir) public function getCacheDir() { if ($this->cacheDir === null) { - $this->setCacheDir(sys_get_temp_dir()); + $this->setCacheDir(null); } return $this->cacheDir; @@ -217,7 +201,9 @@ public function getCacheDir() */ public function setClearStatCache($flag) { - $this->clearStatCache = (bool) $flag; + $flag = (bool) $flag; + $this->triggerOptionEvent('clear_stat_cache', $flag); + $this->clearStatCache = $flag; return $this; } @@ -246,6 +232,7 @@ public function setDirLevel($level) "Directory level '{$level}' must be between 0 and 16" ); } + $this->triggerOptionEvent('dir_level', $level); $this->dirLevel = $level; return $this; } @@ -302,6 +289,7 @@ public function setDirUmask($umask) } }); + $this->triggerOptionEvent('dir_umask', $umask); $this->dirUmask = $umask; return $this; } @@ -335,7 +323,8 @@ public function setFileBlocking($flag) ); } - $this->fileBlocking = (bool) $flag; + $this->triggerOptionEvent('file_blocking', $flag); + $this->fileBlocking = $flag; return $this; } @@ -361,7 +350,9 @@ public function getFileBlocking() */ public function setFileLocking($flag) { - $this->fileLocking = (bool)$flag; + $flag = (bool) $flag; + $this->triggerOptionEvent('file_locking', $flag); + $this->fileLocking = $flag; return $this; } @@ -422,6 +413,7 @@ public function setFileUmask($umask) } }); + $this->triggerOptionEvent('file_umask', $umask); $this->fileUmask = $umask; return $this; } @@ -444,8 +436,9 @@ public function getFileUmask() */ public function setNamespaceSeparator($separator) { - $this->namespaceSeparator = (string) $separator; - $this->updateCapabilities(); + $separator = (string) $separator; + $this->triggerOptionEvent('namespace_separator', $separator); + $this->namespaceSeparator = $separator; return $this; } @@ -467,8 +460,9 @@ public function getNamespaceSeparator() */ public function setNoAtime($flag) { - $this->noAtime = (bool) $flag; - $this->updateCapabilities(); + $flag = (bool) $flag; + $this->triggerOptionEvent('no_atime', $flag); + $this->noAtime = $flag; return $this; } @@ -490,8 +484,9 @@ public function getNoAtime() */ public function setNoCtime($flag) { - $this->noCtime = (bool) $flag; - $this->updateCapabilities(); + $flag = (bool) $flag; + $this->triggerOptionEvent('no_ctime', $flag); + $this->noCtime = $flag; return $this; } @@ -513,7 +508,9 @@ public function getNoCtime() */ public function setReadControl($flag) { - $this->readControl = (bool) $flag; + $flag = (bool) $flag; + $this->triggerOptionEvent('read_control', $flag); + $this->readControl = $flag; return $this; } @@ -542,6 +539,7 @@ public function setReadControlAlgo($algo) throw new Exception\InvalidArgumentException("Unsupported hash algorithm '{$algo}"); } + $this->triggerOptionEvent('read_control_algo', $algo); $this->readControlAlgo = $algo; return $this; } @@ -577,19 +575,4 @@ protected function normalizeUmask($umask, $callback = null) return $umask; } - - /** - * Update target capabilities - * - * Returns immediately if no adapter is present. - * - * @return void - */ - protected function updateCapabilities() - { - if (!$this->adapter) { - return; - } - $this->adapter->updateCapabilities(); - } } diff --git a/src/Storage/Adapter/Memcached.php b/src/Storage/Adapter/Memcached.php index e833f2f16..bdfbfc431 100644 --- a/src/Storage/Adapter/Memcached.php +++ b/src/Storage/Adapter/Memcached.php @@ -477,7 +477,7 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio */ protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) { - // support for removing multiple items at once has been added in ext/memcached 2 + // support for removing multiple items at once has been added in ext/memcached-2.0.0 if (static::$extMemcachedMajorVersion < 2) { return parent::internalRemoveItems($normalizedKeys, $normalizedOptions); } diff --git a/src/Storage/Adapter/MemcachedOptions.php b/src/Storage/Adapter/MemcachedOptions.php index ba4eaa37e..266d7d990 100644 --- a/src/Storage/Adapter/MemcachedOptions.php +++ b/src/Storage/Adapter/MemcachedOptions.php @@ -45,7 +45,7 @@ class MemcachedOptions extends AdapterOptions private $optionsMap = array( 'binary_protocol' => MemcachedResource::OPT_BINARY_PROTOCOL, 'buffer_writes' => MemcachedResource::OPT_BUFFER_WRITES, - 'cache_lookups' => MemcachedResource::OPT_CACHE_LOOKUPS, + //'cache_lookups' => MemcachedResource::OPT_CACHE_LOOKUPS, 'compression' => MemcachedResource::OPT_COMPRESSION, 'connect_timeout' => MemcachedResource::OPT_CONNECT_TIMEOUT, 'distribution' => MemcachedResource::OPT_DISTRIBUTION, @@ -54,10 +54,10 @@ class MemcachedOptions extends AdapterOptions 'no_block' => MemcachedResource::OPT_NO_BLOCK, 'poll_timeout' => MemcachedResource::OPT_POLL_TIMEOUT, 'recv_timeout' => MemcachedResource::OPT_RECV_TIMEOUT, - 'retry_timeout' => MemcachedResource::OPT_RETRY_TIMEOUT, + //'retry_timeout' => MemcachedResource::OPT_RETRY_TIMEOUT, 'send_timeout' => MemcachedResource::OPT_SEND_TIMEOUT, 'serializer' => MemcachedResource::OPT_SERIALIZER, - 'server_failure_limit' => MemcachedResource::OPT_SERVER_FAILURE_LIMIT, + //'server_failure_limit' => MemcachedResource::OPT_SERVER_FAILURE_LIMIT, 'socket_recv_size' => MemcachedResource::OPT_SOCKET_RECV_SIZE, 'socket_send_size' => MemcachedResource::OPT_SOCKET_SEND_SIZE, 'tcp_nodelay' => MemcachedResource::OPT_TCP_NODELAY, @@ -287,6 +287,16 @@ public function getServers() return $this->servers; } + /** + * Get overwrittern libmemcached options + * + * @return array + */ + public function getLibOptions() + { + return $this->libOptions; + } + /** * Set flag indicating whether or not to enable binary protocol for * communication with server diff --git a/src/Storage/Adapter/MemoryOptions.php b/src/Storage/Adapter/MemoryOptions.php index f6355dcbe..777ba2b04 100644 --- a/src/Storage/Adapter/MemoryOptions.php +++ b/src/Storage/Adapter/MemoryOptions.php @@ -54,7 +54,9 @@ class MemoryOptions extends AdapterOptions */ public function setMemoryLimit($bytes) { - $this->memoryLimit = (int) $bytes; + $bytes = (int) $bytes; + $this->triggerOptionEvent('memory_limit', $bytes); + $this->memoryLimit = $bytes; return $this; } diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index e79602234..a92bb637a 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -530,9 +530,9 @@ protected function internalClear(& $normalizedMode, array & $normalizedOptions) protected function internalGetCapabilities() { if ($this->capabilities === null) { - $this->capabilityMarker = new stdClass(); - $this->capabilities = new Capabilities( - $this->capabilityMarker, + $marker = new stdClass(); + $capabilities = new Capabilities( + $marker, array( 'supportedDatatypes' => array( 'NULL' => true, @@ -562,6 +562,18 @@ protected function internalGetCapabilities() 'clearByNamespace' => false, ) ); + + // update namespace separator on change option + $this->events()->attach('option', function ($event) use ($capabilities, $marker) { + $params = $event->getParams(); + + if (isset($params['namespace_separator'])) { + $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']); + } + }); + + $this->capabilities = $capabilities; + $this->capabilityMarker = $marker; } return $this->capabilities; diff --git a/src/Storage/Adapter/WinCacheOptions.php b/src/Storage/Adapter/WinCacheOptions.php index e2256e953..09db0fadd 100644 --- a/src/Storage/Adapter/WinCacheOptions.php +++ b/src/Storage/Adapter/WinCacheOptions.php @@ -49,7 +49,9 @@ class WinCacheOptions extends AdapterOptions */ public function setNamespaceSeparator($separator) { - $this->namespaceSeparator = (string) $separator; + $separator = (string) $separator; + $this->triggerOptionEvent('namespace_separator', $separator); + $this->namespaceSeparator = $separator; return $this; } From d4aeeeddb682a6503b072f2e5864179798796f8d Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 22 Mar 2012 23:21:33 +0100 Subject: [PATCH 10/62] memcached adapter: be more free to set libmemcached options and update options after passing it to the adapter instance --- src/Storage/Adapter/Memcached.php | 47 +- src/Storage/Adapter/MemcachedOptions.php | 740 ++--------------------- 2 files changed, 79 insertions(+), 708 deletions(-) diff --git a/src/Storage/Adapter/Memcached.php b/src/Storage/Adapter/Memcached.php index bdfbfc431..5ac6373e8 100644 --- a/src/Storage/Adapter/Memcached.php +++ b/src/Storage/Adapter/Memcached.php @@ -73,20 +73,47 @@ public function __construct($options = null) throw new Exception\ExtensionNotLoadedException('Need ext/memcached version >= 1.0.0'); } - $this->memcached = new MemcachedResource(); - parent::__construct($options); - // It's ok to add server as soon as possible because + // It's ok to init the memcached instance as soon as possible because // ext/memcached auto-connects to the server on first use + $this->memcached = new MemcachedResource(); $options = $this->getOptions(); + // set lib options + if (static::$extMemcachedMajorVersion > 1) { + $this->memcached->setOptions($options->getLibOptions()); + } else { + foreach ($options->getLibOptions() as $k => $v) { + $this->memcached->setOption($k, $v); + } + } + $servers = $options->getServers(); if (!$servers) { $options->addServer('127.0.0.1', 11211); $servers = $options->getServers(); } $this->memcached->addServers($servers); + + // get notified on change options + $memc = $this->memcached; + $memcMV = static::$extMemcachedMajorVersion; + $this->events()->attach('option', function ($event) use ($memc, $memcMV) { + $params = $event->getParams(); + + if (isset($params['lib_options'])) { + if ($memcMV > 1) { + $memc->setOptions($params['lib_options']); + } else { + foreach ($params['lib_options'] as $k => $v) { + $memc->setOption($k, $v); + } + } + } + + // TODO: update on change/add server(s) + }); } /* options */ @@ -104,19 +131,7 @@ public function setOptions($options) $options = new MemcachedOptions($options); } - $this->options = $options; - - // Set memcached options, using options map to map to Memcached constants - $map = $options->getOptionsMap(); - foreach ($options->toArray() as $key => $value) { - if (!array_key_exists($key, $map)) { - // skip keys for which there are not equivalent options - continue; - } - $this->memcached->setOption($map[$key], $value); - } - - return $this; + return parent::setOptions($options); } /** diff --git a/src/Storage/Adapter/MemcachedOptions.php b/src/Storage/Adapter/MemcachedOptions.php index 266d7d990..a9f91cdcc 100644 --- a/src/Storage/Adapter/MemcachedOptions.php +++ b/src/Storage/Adapter/MemcachedOptions.php @@ -37,35 +37,6 @@ class MemcachedOptions extends AdapterOptions { - /** - * Map of option keys to \Memcached options - * - * @var array - */ - private $optionsMap = array( - 'binary_protocol' => MemcachedResource::OPT_BINARY_PROTOCOL, - 'buffer_writes' => MemcachedResource::OPT_BUFFER_WRITES, - //'cache_lookups' => MemcachedResource::OPT_CACHE_LOOKUPS, - 'compression' => MemcachedResource::OPT_COMPRESSION, - 'connect_timeout' => MemcachedResource::OPT_CONNECT_TIMEOUT, - 'distribution' => MemcachedResource::OPT_DISTRIBUTION, - 'hash' => MemcachedResource::OPT_HASH, - 'libketama_compatible' => MemcachedResource::OPT_LIBKETAMA_COMPATIBLE, - 'no_block' => MemcachedResource::OPT_NO_BLOCK, - 'poll_timeout' => MemcachedResource::OPT_POLL_TIMEOUT, - 'recv_timeout' => MemcachedResource::OPT_RECV_TIMEOUT, - //'retry_timeout' => MemcachedResource::OPT_RETRY_TIMEOUT, - 'send_timeout' => MemcachedResource::OPT_SEND_TIMEOUT, - 'serializer' => MemcachedResource::OPT_SERIALIZER, - //'server_failure_limit' => MemcachedResource::OPT_SERVER_FAILURE_LIMIT, - 'socket_recv_size' => MemcachedResource::OPT_SOCKET_RECV_SIZE, - 'socket_send_size' => MemcachedResource::OPT_SOCKET_SEND_SIZE, - 'tcp_nodelay' => MemcachedResource::OPT_TCP_NODELAY, - - // The prefix_key act as namespace an will be set directly - // 'prefix_key' => MemcachedResource::OPT_PREFIX_KEY, - ); - /** * Memcached server address * @@ -74,130 +45,11 @@ class MemcachedOptions extends AdapterOptions protected $servers = array(); /** - * Whether or not to enable binary protocol for communication with server + * Libmemcached options * - * @var bool - */ - protected $binaryProtocol = false; - - /** - * Enable or disable buffered I/O - * - * @var bool - */ - protected $bufferWrites = false; - - /** - * Whether or not to cache DNS lookups - * - * @var bool - */ - protected $cacheLookups = false; - - /** - * Whether or not to use compression - * - * @var bool - */ - protected $compression = true; - - /** - * Time at which to issue connection timeout, in ms - * - * @var int - */ - protected $connectTimeout = 1000; - - /** - * Server distribution algorithm - * - * @var int - */ - protected $distribution = MemcachedResource::DISTRIBUTION_MODULA; - - /** - * Hashing algorithm to use - * - * @var int - */ - protected $hash = MemcachedResource::HASH_DEFAULT; - - /** - * Whether or not to enable compatibility with libketama-like behavior. - * - * @var bool - */ - protected $libketamaCompatible = false; - - /** - * Whether or not to enable asynchronous I/O - * - * @var bool - */ - protected $noBlock = false; - - /** - * Timeout for connection polling, in ms - * - * @var int - */ - protected $pollTimeout = 1000; - - /** - * Maximum allowed time for a recv operation, in ms - * - * @var int - */ - protected $recvTimeout = 0; - - /** - * Time to wait before retrying a connection, in seconds - * - * @var int - */ - protected $retryTimeout = 0; - - /** - * Maximum allowed time for a send operation, in ms - * - * @var int - */ - protected $sendTimeout = 0; - - /** - * Serializer to use - * - * @var int - */ - protected $serializer = MemcachedResource::SERIALIZER_PHP; - - /** - * Maximum number of server connection errors - * - * @var int - */ - protected $serverFailureLimit = 0; - - /** - * Maximum socket send buffer in bytes - * - * @var int - */ - protected $socketSendSize; - - /** - * Maximum socket recv buffer in bytes - * - * @var int - */ - protected $socketRecvSize; - - /** - * Whether or not to enable no-delay feature for connecting sockets - * - * @var bool + * @var array */ - protected $tcpNodelay = false; + protected $libOptions = array(); /** * Set namespace. @@ -241,12 +93,9 @@ public function addServer($host, $port = 11211) )); } - if ((!is_int($port) && !is_numeric($port)) - || 0 > $port - ) { + if (!is_numeric($port) || $port <= 0) { throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ + '%s expects a positive integer', __METHOD__ )); } @@ -274,6 +123,7 @@ public function setServers(array $servers) $this->addServer($server[0], $server[1]); } } + return $this; } @@ -288,580 +138,86 @@ public function getServers() } /** - * Get overwrittern libmemcached options - * - * @return array - */ - public function getLibOptions() - { - return $this->libOptions; - } - - /** - * Set flag indicating whether or not to enable binary protocol for - * communication with server - * - * @param bool $binaryProtocol - * @return MemcachedOptions - */ - public function setBinaryProtocol($binaryProtocol) - { - $this->binaryProtocol = (bool) $binaryProtocol; - return $this; - } - - /** - * Whether or not to enable binary protocol for communication with server - * - * @return bool - */ - public function getBinaryProtocol() - { - return $this->binaryProtocol; - } - - /** - * Set flag indicating whether or not buffered I/O is enabled + * Set libmemcached options * - * @param bool $bufferWrites + * @param array $libOptions * @return MemcachedOptions + * @link http://php.net/manual/memcached.constants.php */ - public function setBufferWrites($bufferWrites) + public function setLibOptions(array $libOptions) { - $this->bufferWrites = (bool) $bufferWrites; - return $this; - } - - /** - * Whether or not buffered I/O is enabled - * - * @return bool - */ - public function getBufferWrites() - { - return $this->bufferWrites; - } - - /** - * Set flag indicating whether or not to cache DNS lookups - * - * @param bool $cacheLookups - * @return MemcachedOptions - */ - public function setCacheLookups($cacheLookups) - { - $this->cacheLookups = (bool) $cacheLookups; - return $this; - } - - /** - * Whether or not to cache DNS lookups - * - * @return bool - */ - public function getCacheLookups() - { - return $this->cacheLookups; - } - - /** - * Set flag indicating whether or not to use compression - * - * @param bool $compression - * @return MemcachedOptions - */ - public function setCompression($compression) - { - $this->compression = (bool) $compression; - return $this; - } - - /** - * Whether or not compression is enabled - * - * @return bool - */ - public function getCompression() - { - return $this->compression; - } - - /** - * Set interval for connection timeouts, in ms - * - * @param int $connectTimeout - * @return MemcachedOptions - */ - public function setConnectTimeout($connectTimeout) - { - if ((!is_int($connectTimeout) && !is_numeric($connectTimeout)) - || 0 > $connectTimeout - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); + $normalizedOptions = array(); + foreach ($libOptions as $key => $value) { + $this->normalizeLibOptionKey($key); + $normalizedOptions[$key] = $value; } - $this->connectTimeout = (int) $connectTimeout; - return $this; - } - - /** - * Get connection timeout value - * - * @return int - */ - public function getConnectTimeout() - { - return $this->connectTimeout; - } - - /** - * Set server distribution algorithm - * - * @param int $distribution - * @return MemcachedOptions - */ - public function setDistribution($distribution) - { - if (!in_array($distribution, array( - MemcachedResource::DISTRIBUTION_MODULA, - MemcachedResource::DISTRIBUTION_CONSISTENT, - ))) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects either Memcached::DISTRIBUTION_MODULA or Memcached::DISTRIBUTION_CONSISTENT', - __METHOD__ - )); - } + $this->triggerOptionEvent('lib_options', $normalizedOptions); + $this->libOptions = array_merge($this->libOptions, $normalizedOptions); - $this->distribution = $distribution; return $this; } /** - * Get server distribution algorithm - * - * @return int - */ - public function getDistribution() - { - return $this->distribution; - } - - /** - * Set hashing algorithm + * Set libmemcached option * - * @param int $hash + * @param string|int $key + * @param mixed $value * @return MemcachedOptions + * @link http://php.net/manual/memcached.constants.php */ - public function setHash($hash) - { - if (!in_array($hash, array( - MemcachedResource::HASH_DEFAULT, - MemcachedResource::HASH_MD5, - MemcachedResource::HASH_CRC, - MemcachedResource::HASH_FNV1_64, - MemcachedResource::HASH_FNV1A_64, - MemcachedResource::HASH_FNV1_32, - MemcachedResource::HASH_FNV1A_32, - MemcachedResource::HASH_HSIEH, - MemcachedResource::HASH_MURMUR, - ))) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects one of the Memcached::HASH_* constants', - __METHOD__ - )); - } - - $this->hash = $hash; - return $this; - } - - /** - * Get hash algorithm - * - * @return int - */ - public function getHash() + public function setLibOption($key, $value) { - return $this->hash; - } + $this->normalizeLibOptionKey($key); + $this->triggerOptionEvent('lib_options', array($key, $value)); + $this->libOptions[$key] = $value; - /** - * Set flag indicating whether or not to enable libketama compatibility - * - * @param bool $libketamaCompatible - * @return MemcachedOptions - */ - public function setLibketamaCompatible($libketamaCompatible) - { - $this->libketamaCompatible = (bool) $libketamaCompatible; return $this; } /** - * Whether or not to enable libketama compatibility - * - * @return bool - */ - public function getLibketamaCompatible() - { - return $this->libketamaCompatible; - } - - /** - * Set flag indicating whether or not to enable asynchronous I/O + * Get libmemcached options * - * @param bool $noBlock - * @return MemcachedOptions - */ - public function setNoBlock($noBlock) - { - $this->noBlock = (bool) $noBlock; - return $this; - } - - /** - * Whether or not to enable asynchronous I/O - * - * @return bool - */ - public function getNoBlock() - { - return $this->noBlock; - } - - /** - * Set interval for connection polling timeout, in ms - * - * @param int $pollTimeout - * @return MemcachedOptions - */ - public function setPollTimeout($pollTimeout) - { - if ((!is_int($pollTimeout) && !is_numeric($pollTimeout)) - || 0 > $pollTimeout - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); - } - - $this->pollTimeout = (int) $pollTimeout; - return $this; - } - - /** - * Get connection polling timeout value - * - * @return int - */ - public function getPollTimeout() - { - return $this->pollTimeout; - } - - /** - * Set prefix for keys - * - * The prefix key act as namespace. - * - * @param string $prefixKey - * @return MemcachedOptions - */ - public function setPrefixKey($prefixKey) - { - return $this->setNamespace($prefixKey); - } - - /** - * Get prefix key - * - * The prefix key act as namespace. - * - * @return string - */ - public function getPrefixKey() - { - return $this->getNamespace(); - } - - /** - * Set interval for recv timeout, in ms - * - * @param int $recvTimeout - * @return MemcachedOptions - */ - public function setRecvTimeout($recvTimeout) - { - if ((!is_int($recvTimeout) && !is_numeric($recvTimeout)) - || 0 > $recvTimeout - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); - } - - $this->recvTimeout = (int) $recvTimeout; - return $this; - } - - /** - * Get recv timeout value - * - * @return int - */ - public function getRecvTimeout() - { - return $this->recvTimeout; - } - - /** - * Set retry interval, in seconds - * - * @param int $retryTimeout - * @return MemcachedOptions - */ - public function setRetryTimeout($retryTimeout) - { - if ((!is_int($retryTimeout) && !is_numeric($retryTimeout)) - || 0 > $retryTimeout - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); - } - - $this->retryTimeout = (int) $retryTimeout; - return $this; - } - - /** - * Get retry timeout value, in seconds - * - * @return int + * @return array + * @link http://php.net/manual/memcached.constants.php */ - public function getRetryTimeout() + public function getLibOptions() { - return $this->retryTimeout; + return $this->libOptions; } /** - * Set interval for send timeout, in ms + * Get libmemcached option * - * @param int $sendTimeout - * @return MemcachedOptions + * @return mixed + * @link http://php.net/manual/memcached.constants.php */ - public function setSendTimeout($sendTimeout) + public function getLibOption($key) { - if ((!is_int($sendTimeout) && !is_numeric($sendTimeout)) - || 0 > $sendTimeout - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); + $this->normalizeLibOptionKey($key); + if (isset($this->libOptions[$key])) { + return $this->libOptions[$key]; } - - $this->sendTimeout = (int) $sendTimeout; - return $this; - } - - /** - * Get send timeout value - * - * @return int - */ - public function getSendTimeout() - { - return $this->sendTimeout; + return null; } /** - * Set serializer + * Normalize libmemcached option name into it's constant value * - * @param int $serializer - * @return MemcachedOptions + * @param string|int $key + * @throws Exception\InvalidArgumentException */ - public function setSerializer($serializer) + protected function normalizeLibOptionKey(& $key) { - if (!in_array($serializer, array( - MemcachedResource::SERIALIZER_PHP, - MemcachedResource::SERIALIZER_IGBINARY, - MemcachedResource::SERIALIZER_JSON, - ))) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects one of the Memcached::SERIALIZER_* constants', - __METHOD__ - )); - } - - if ($serializer == MemcachedResource::SERIALIZER_IGBINARY) { - if (!MemcachedResource::HAVE_IGBINARY) { - throw new Exception\RuntimeException(sprintf( - '%s: cannot set to igbinary; not available', - __METHOD__ - )); - } - } - - if ($serializer == MemcachedResource::SERIALIZER_JSON) { - if (!MemcachedResource::HAVE_JSON) { - throw new Exception\RuntimeException(sprintf( - '%s: cannot set to json; not available', - __METHOD__ - )); + if (is_string($key)) { + $const = 'Memcached::OPT_' . str_replace(array(' ', '-'), '_', strtoupper($key)); + if (!defined($const)) { + throw new Exception\InvalidArgumentException("Unknown libmemcached option '{$key}' ({$const})"); } + $key = constant($const); + } else { + $key = (int) $key; } - - $this->serializer = $serializer; - return $this; - } - - /** - * Get serializer - * - * @return int - */ - public function getSerializer() - { - return $this->serializer; - } - - /** - * Set maximum number of server connection failures - * - * @param int $serverFailureLimit - * @return MemcachedOptions - */ - public function setServerFailureLimit($serverFailureLimit) - { - if ((!is_int($serverFailureLimit) && !is_numeric($serverFailureLimit)) - || 0 > $serverFailureLimit - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); - } - - $this->serverFailureLimit = (int) $serverFailureLimit; - return $this; - } - - /** - * Get maximum server failures allowed - * - * @return int - */ - public function getServerFailureLimit() - { - return $this->serverFailureLimit; - } - - /** - * Set maximum socket send buffer in bytes - * - * @param int $socketSendSize - * @return MemcachedOptions - */ - public function setSocketSendSize($socketSendSize) - { - if ($socketSendSize === null) { - return $this; - } - - if ((!is_int($socketSendSize) && !is_numeric($socketSendSize)) - || 0 > $socketSendSize - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); - } - - $this->socketSendSize = (int) $socketSendSize; - return $this; - } - - /** - * Get maximum socket send buffer in bytes - * - * @return int - */ - public function getSocketSendSize() - { - return $this->socketSendSize; - } - - /** - * Set maximum socket recv buffer in bytes - * - * @param int $socketRecvSize - * @return MemcachedOptions - */ - public function setSocketRecvSize($socketRecvSize) - { - if ($socketRecvSize === null) { - return $this; - } - - if ((!is_int($socketRecvSize) && !is_numeric($socketRecvSize)) - || 0 > $socketRecvSize - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a positive integer', - __METHOD__ - )); - } - - $this->socketRecvSize = (int) $socketRecvSize; - return $this; - } - - /** - * Get maximum socket recv buffer in bytes - * - * @return int - */ - public function getSocketRecvSize() - { - return $this->socketRecvSize; - } - - /** - * Set whether or not to enable no-delay feature when connecting sockets - * - * @param bool $tcpNodelay - * @return MemcachedOptions - */ - public function setTcpNodelay($tcpNodelay) - { - $this->tcpNodelay = (bool) $tcpNodelay; - return $this; } - /** - * Whether or not to enable no-delay feature when connecting sockets - * - * @return bool - */ - public function getTcpNodelay() - { - return $this->tcpNodelay; - } - - /** - * Get map of option keys to \Memcached constants - * - * @return array - */ - public function getOptionsMap() - { - return $this->optionsMap; - } } From 227a0ed641d87d2ce486ecd46262e186eee56024 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 22 Mar 2012 23:34:05 +0100 Subject: [PATCH 11/62] make sure the 'option' event will be triggered on setOptions --- src/Storage/Adapter/Apc.php | 3 +-- src/Storage/Adapter/Memory.php | 3 +-- src/Storage/Adapter/WinCache.php | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index bb9748091..463749706 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -122,8 +122,7 @@ public function setOptions($options) $options = new ApcOptions($options); } - $this->options = $options; - return $this; + return parent::setOptions($options); } /** diff --git a/src/Storage/Adapter/Memory.php b/src/Storage/Adapter/Memory.php index 38a4983a1..9a6fd2f71 100644 --- a/src/Storage/Adapter/Memory.php +++ b/src/Storage/Adapter/Memory.php @@ -68,8 +68,7 @@ public function setOptions($options) $options = new MemoryOptions($options); } - $this->options = $options; - return $this; + return parent::setOptions($options); } /** diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index a92bb637a..1f88d78b9 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -85,8 +85,7 @@ public function setOptions($options) $options = new WinCacheOptions($options); } - $this->options = $options; - return $this; + return parent::setOptions($options); } /** From 21327efe5b6aa6cf6309fdea13b99315fab5e25c Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 22 Mar 2012 23:41:37 +0100 Subject: [PATCH 12/62] Cache adapter: allow empty namespaces --- src/Storage/Adapter/AbstractAdapter.php | 8 +++----- src/Storage/Adapter/AdapterOptions.php | 5 ----- src/Storage/Adapter/MemcachedOptions.php | 2 +- test/Storage/Adapter/AbstractAdapterTest.php | 6 ------ 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 31ad92f76..b1d0eefd9 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -2554,12 +2554,10 @@ protected function normalizeTtl(&$ttl) protected function normalizeNamespace(&$namespace) { $namespace = (string) $namespace; - - if ($namespace === '') { - throw new Exception\InvalidArgumentException('Empty namespaces are not allowed'); - } elseif (($p = $this->getOptions()->getNamespacePattern()) && !preg_match($p, $namespace)) { + $pattern = $this->getOptions()->getNamespacePattern(); + if ($pattern && !preg_match($pattern, $namespace)) { throw new Exception\InvalidArgumentException( - "The namespace '{$namespace}' doesn't match against pattern '{$p}'" + "The namespace '{$namespace}' doesn't match against pattern '{$pattern}'" ); } } diff --git a/src/Storage/Adapter/AdapterOptions.php b/src/Storage/Adapter/AdapterOptions.php index 508ed1be7..9eb49f184 100644 --- a/src/Storage/Adapter/AdapterOptions.php +++ b/src/Storage/Adapter/AdapterOptions.php @@ -208,11 +208,6 @@ public function setNamespace($namespace) { $namespace = (string)$namespace; if ($this->namespace !== $namespace) { - if ($namespace === '') { - // TODO: allow empty namespaces - throw new Exception\InvalidArgumentException('No namespace given'); - } - $pattern = $this->getNamespacePattern(); if ($pattern && !preg_match($pattern, $namespace)) { throw new Exception\InvalidArgumentException( diff --git a/src/Storage/Adapter/MemcachedOptions.php b/src/Storage/Adapter/MemcachedOptions.php index a9f91cdcc..e04271ede 100644 --- a/src/Storage/Adapter/MemcachedOptions.php +++ b/src/Storage/Adapter/MemcachedOptions.php @@ -62,7 +62,7 @@ class MemcachedOptions extends AdapterOptions */ public function setNamespace($namespace) { - $namespace = (string)$namespace; + $namespace = (string) $namespace; if (128 < strlen($namespace)) { throw new Exception\InvalidArgumentException(sprintf( diff --git a/test/Storage/Adapter/AbstractAdapterTest.php b/test/Storage/Adapter/AbstractAdapterTest.php index e1ed301c4..722719324 100644 --- a/test/Storage/Adapter/AbstractAdapterTest.php +++ b/test/Storage/Adapter/AbstractAdapterTest.php @@ -123,12 +123,6 @@ public function testSetNamespace0() $this->assertSame('0', $this->_options->getNamespace()); } - public function testSetEmptyNamespaceThrowsException() - { - $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException'); - $this->_options->setNamespace(''); - } - public function testSetNamespacePatternThrowsExceptionOnInvalidPattern() { $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException'); From 277bf167a9469def65e22af55c7e9e55e6fc5afe Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Mar 2012 21:01:40 +0200 Subject: [PATCH 13/62] fixed missing reset of umask --- src/Storage/Adapter/Filesystem.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index d7d253a09..1957feea1 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -650,6 +650,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz $mkdir = mkdir($path, 0777, true); $error = ErrorHandler::stop(); if (!$mkdir) { + umask($oldUmask); throw new Exception\RuntimeException( "Error creating directory '{$path}'", 0, $error ); @@ -673,7 +674,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz } try { - if ($oldUmask !== null) { // $oldUmask could be defined on set directory_umask + if ($oldUmask !== null) { // $oldUmask could be defined on create directory umask($baseOptions->getFileUmask()); } else { $oldUmask = umask($baseOptions->getFileUmask()); From 6828829faf918566bfb161611a98b3f04a2bb7e7 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Mar 2012 21:52:06 +0200 Subject: [PATCH 14/62] removed internal method getKeyInfo: now getFilespec will be buffered and please use internalHasItem instead --- src/Storage/Adapter/Filesystem.php | 199 +++++++++++++---------------- 1 file changed, 88 insertions(+), 111 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 1957feea1..883fb2ad5 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -55,20 +55,18 @@ class Filesystem extends AbstractAdapter protected $stmtMatch = null; /** - * Last buffered identified of internal method getKeyInfo() + * Key (namespace + separator + key) of buffered information * * @var string|null */ - protected $lastInfoId = null; + protected $bufferKey = null; /** - * Buffered result of internal method getKeyInfo() + * The buffered filespec * - * @var array|null + * @var string|null */ - protected $lastInfo = null; - - /* configuration */ + protected $bufferedFilespec = null; /** * Set options. @@ -178,24 +176,23 @@ public function getItems(array $keys, array $options = array()) */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) { - if ( !$this->internalHasItem($normalizedKey, $normalizedOptions) - || !($keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace'])) - ) { - if ($normalizedOptions['ignore_missing_items']) { - return false; - } else { + if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$normalizedOptions['ignore_missing_items']) { throw new Exception\ItemNotFoundException( "Key '{$normalizedKey}' not found within namespace '{$normalizedOptions['namespace']}'" ); } + + return false; } - $baseOptions = $this->getOptions(); try { - $data = $this->getFileContent($keyInfo['filespec'] . '.dat'); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $baseOptions = $this->getOptions(); + $data = $this->getFileContent($filespec . '.dat'); if ($baseOptions->getReadControl()) { - if ( ($info = $this->readInfoFile($keyInfo['filespec'] . '.ifo')) + if ( ($info = $this->readInfoFile($filespec . '.ifo')) && isset($info['hash'], $info['algo']) && Utils::generateHash($info['algo'], $data, true) != $info['hash'] ) { @@ -207,7 +204,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) if (array_key_exists('token', $normalizedOptions)) { // use filemtime + filesize as CAS token - $normalizedOptions['token'] = $keyInfo['mtime'] . filesize($keyInfo['filespec'] . '.dat'); + $normalizedOptions['token'] = filemtime($filespec . '.dat') . filesize($filespec . '.dat'); } return $data; @@ -250,14 +247,13 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized // read items foreach ($normalizedKeys as $i => $normalizedKey) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions) - || !($keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace'])) - ) { + if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { unset($normalizedKeys[$i]); continue; } - $data = $this->getFileContent($keyInfo['filespec'] . '.dat', $wouldblock); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $data = $this->getFileContent($filespec . '.dat', $wouldblock); if ($data === false) { continue; } else { @@ -265,7 +261,7 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized } if ($baseOptions->getReadControl()) { - $info = $this->readInfoFile($keyInfo['filespec'] . '.ifo'); + $info = $this->readInfoFile($filespec . '.ifo'); if (isset($info['hash'], $info['algo']) && Utils::generateHash($info['algo'], $data, true) != $info['hash'] ) { @@ -359,17 +355,29 @@ public function hasItems(array $keys, array $options = array()) */ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) { - $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); - if (!$keyInfo) { - return false; // missing or corrupted cache data + $ttl = $normalizedOptions['ttl']; + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + + if (!file_exists($filespec . '.dat')) { + return false; } - $ttl = $normalizedOptions['ttl']; - if (!$ttl || time() < ($keyInfo['mtime'] + $ttl)) { - return true; + if ($ttl) { + ErrorHandler::start(); + $mtime = filemtime($filespec . '.dat'); + $error = ErrorHandler::stop(); + if (!$mtime) { + throw new Exception\RuntimeException( + "Error getting mtime of file '{$filespec}.dat'", 0, $error + ); + } + + if (time() >= ($mtime + $ttl)) { + return false; + } } - return false; + return true; } /** @@ -416,31 +424,36 @@ public function getMetadatas(array $keys, array $options = array()) */ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { - $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); - if (!$keyInfo) { + if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { if (!$normalizedOptions['ignore_missing_items']) { throw new Exception\ItemNotFoundException( "Key '{$normalizedKey}' not found on namespace '{$normalizedOptions['namespace']}'" ); } + return false; } $baseOptions = $this->getOptions(); - if (!$baseOptions->getNoCtime()) { - $keyInfo['ctime'] = filectime($keyInfo['filespec'] . '.dat'); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + + $metadata = $this->readInfoFile($filespec . '.ifo'); + if (!$metadata) { + $metadata = array(); } - if (!$baseOptions->getNoAtime()) { - $keyInfo['atime'] = fileatime($keyInfo['filespec'] . '.dat'); + $metadata['filespec'] = $filespec; + $metadata['mtime'] = filemtime($filespec . '.dat'); + + if (!$baseOptions->getNoCtime()) { + $metadata['ctime'] = filectime($filespec . '.dat'); } - $info = $this->readInfoFile($keyInfo['filespec'] . '.ifo'); - if ($info) { - return $keyInfo + $info; + if (!$baseOptions->getNoAtime()) { + $metadata['atime'] = fileatime($filespec . '.dat'); } - return $keyInfo; + return $metadata; } /* writing */ @@ -636,12 +649,12 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz $baseOptions = $this->getOptions(); $oldUmask = null; - $lastInfoId = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() . $normalizedKey; - if ($this->lastInfoId == $lastInfoId) { + $bufferKey = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() . $normalizedKey; + if ($this->bufferKey == $bufferKey) { $filespec = $this->lastInfo['filespec']; // if lastKeyInfo is available I'm sure that the cache directory exist } else { - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions['namespace']); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); if ($baseOptions->getDirLevel() > 0) { $path = dirname($filespec); if (!file_exists($path)) { @@ -691,7 +704,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz } } - $this->lastInfoId = null; + $this->bufferKey = null; // reset file_umask umask($oldUmask); @@ -758,18 +771,19 @@ public function checkAndSetItem($token, $key, $value, array $options = array()) */ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) { - $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); - if (!$keyInfo) { + if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { if (!$normalizedOptions['ignore_missing_items']) { throw new Exception\ItemNotFoundException( "Key '{$normalizedKey}' not found within namespace '{$normalizedOptions['namespace']}'" ); } + return false; } // use filemtime + filesize as CAS token - $check = $keyInfo['mtime'] . filesize($keyInfo['filespec'] . '.dat'); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $check = filemtime($filespec . '.dat') . filesize($filespec . '.dat'); if ($token !== $check) { return false; } @@ -845,27 +859,29 @@ public function touchItems(array $keys, array $options = array()) */ protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) { - $keyInfo = $this->getKeyInfo($normalizedKey, $normalizedOptions['namespace']); - if (!$keyInfo) { + if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { if (!$normalizedOptions['ignore_missing_items']) { throw new Exception\ItemNotFoundException( "Key '{$normalizedKey}' not found within namespace '{$normalizedOptions['namespace']}'" ); } + return false; } + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + ErrorHandler::start(); - $touch = touch($keyInfo['filespec'] . '.dat'); + $touch = touch($filespec . '.dat'); $error = ErrorHandler::stop(); if (!$touch) { throw new Exception\RuntimeException( - "Error touching file '{$keyInfo['filespec']}.dat'", 0, $error + "Error touching file '{$filespec}.dat'", 0, $error ); } // remove the buffered info - $this->lastInfoId = null; + $this->bufferKey = null; return true; } @@ -942,7 +958,7 @@ public function removeItems(array $keys, array $options = array()) */ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions['namespace']); + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); if (!file_exists($filespec . '.dat')) { if (!$normalizedOptions['ignore_missing_items']) { throw new Exception\ItemNotFoundException("Key '{$normalizedKey}' with file '{$filespec}.dat' not found"); @@ -950,7 +966,7 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio } else { $this->unlink($filespec . '.dat'); $this->unlink($filespec . '.ifo'); - $this->lastInfoId = null; + $this->bufferKey = null; } return true; } @@ -1431,73 +1447,34 @@ protected function rmDir($dir, $prefix) return $ret; } - /** - * Get an array of information about the cache key. - * NOTE: returns false if cache doesn't hit. - * - * @param string $key - * @param string $ns - * @return array|boolean - */ - protected function getKeyInfo($key, $ns) - { - $lastInfoId = $ns . $this->getOptions()->getNamespaceSeparator() . $key; - if ($this->lastInfoId == $lastInfoId) { - return $this->lastInfo; - } - - $filespec = $this->getFileSpec($key, $ns); - $file = $filespec . '.dat'; - - if (!file_exists($file)) { - return false; - } - - ErrorHandler::start(); - $mtime = filemtime($file); - $error = ErrorHandler::stop(); - if (!$mtime) { - throw new Exception\RuntimeException( - "Error getting mtime of file '{$file}'", 0, $error - ); - } - - $this->lastInfoId = $lastInfoId; - $this->lastInfo = array( - 'filespec' => $filespec, - 'mtime' => $mtime, - ); - - return $this->lastInfo; - } - /** * Get file spec of the given key and namespace * - * @param string $key - * @param string $ns + * @param string $normalizedKey + * @param array $normalizedOptions * @return string */ - protected function getFileSpec($key, $ns) + protected function getFileSpec($normalizedKey, array & $normalizedOptions) { - $options = $this->getOptions(); - $prefix = $ns . $options->getNamespaceSeparator(); - $lastInfoId = $prefix . $key; - if ($this->lastInfoId == $lastInfoId) { - return $this->lastInfo['filespec']; - } - - $path = $options->getCacheDir(); - $level = $options->getDirLevel(); - if ( $level > 0 ) { - // create up to 256 directories per directory level - $hash = md5($key); - for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) { - $path .= \DIRECTORY_SEPARATOR . $prefix . $hash[$i] . $hash[$i+1]; + $baseOptions = $this->getOptions(); + $prefix = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator(); + $bufferKey = $prefix . $normalizedKey; + + if ($this->bufferKey !== $bufferKey) { + $path = $baseOptions->getCacheDir(); + $level = $baseOptions->getDirLevel(); + if ( $level > 0 ) { + // create up to 256 directories per directory level + $hash = md5($normalizedKey); + for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) { + $path .= \DIRECTORY_SEPARATOR . $prefix . $hash[$i] . $hash[$i+1]; + } } + + $this->bufferedFilespec = $path . \DIRECTORY_SEPARATOR . $prefix . $normalizedKey; } - return $path . \DIRECTORY_SEPARATOR . $prefix . $key; + return $this->bufferedFilespec; } /** From deb3fe27044f4fa75679f0442f0ef1eaadc2fa3d Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Mar 2012 23:08:41 +0200 Subject: [PATCH 15/62] It's not sure that a cache directory exists after getting filespec --- src/Storage/Adapter/Filesystem.php | 34 ++++++++++++------------------ 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 883fb2ad5..7fd1e6faf 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -647,27 +647,21 @@ public function replaceItems(array $keyValuePairs, array $options = array()) protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { $baseOptions = $this->getOptions(); - $oldUmask = null; + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $oldUmask = null; - $bufferKey = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() . $normalizedKey; - if ($this->bufferKey == $bufferKey) { - $filespec = $this->lastInfo['filespec']; - // if lastKeyInfo is available I'm sure that the cache directory exist - } else { - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - if ($baseOptions->getDirLevel() > 0) { - $path = dirname($filespec); - if (!file_exists($path)) { - $oldUmask = umask($baseOptions->getDirUmask()); - ErrorHandler::start(); - $mkdir = mkdir($path, 0777, true); - $error = ErrorHandler::stop(); - if (!$mkdir) { - umask($oldUmask); - throw new Exception\RuntimeException( - "Error creating directory '{$path}'", 0, $error - ); - } + if ($baseOptions->getDirLevel() > 0) { + $path = dirname($filespec); + if (!file_exists($path)) { + $oldUmask = umask($baseOptions->getDirUmask()); + ErrorHandler::start(); + $mkdir = mkdir($path, 0777, true); + $error = ErrorHandler::stop(); + if (!$mkdir) { + umask($oldUmask); + throw new Exception\RuntimeException( + "Error creating directory '{$path}'", 0, $error + ); } } } From f462b4aab8216cdc32e117fa0585849d8079ba23 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Mar 2012 23:12:28 +0200 Subject: [PATCH 16/62] added missing flock(LOCK_UN) & fclose on error --- src/Storage/Adapter/Filesystem.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 7fd1e6faf..afdf6c8e1 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -1606,12 +1606,15 @@ protected function putFileContent($file, $data) } if (!fwrite($fp, $data)) { + flock($fp, \LOCK_UN); fclose($fp); $err = ErrorHandler::stop(); throw new Exception\RuntimeException("Error writing file '{$file}'", 0, $err); } if (!ftruncate($fp, strlen($data))) { + flock($fp, \LOCK_UN); + fclose($fp); $err = ErrorHandler::stop(); throw new Exception\RuntimeException("Error truncating file '{$file}'", 0, $err); } From d4b75e85e6e172f36fc9aafecd1858286dd4c656 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Mar 2012 23:33:48 +0200 Subject: [PATCH 17/62] removed option 'file_blocking' because skipping writing data if the file is locked would only make sense if the file is blocked by another process writing the file (LOCK_EX) but it is also blocked on readers (LOCK_SH) --- src/Storage/Adapter/Filesystem.php | 22 +++++--- src/Storage/Adapter/FilesystemOptions.php | 49 ---------------- test/Storage/Adapter/FilesystemTest.php | 69 ----------------------- 3 files changed, 13 insertions(+), 127 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index afdf6c8e1..5962b7170 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -1573,20 +1573,21 @@ protected function getFileContent($file, $wouldblock = false) /** * Write content to a file * - * @param string $file File complete path - * @param string $data Data to write - * @return bool + * @param string $file File complete path + * @param string $data Data to write + * @param boolean $wouldblock Return FALSE if the lock would block + * @return boolean TRUE on success, FALSE if lock would block * @throws Exception\RuntimeException */ - protected function putFileContent($file, $data) + protected function putFileContent($file, $data, $wouldblock = false) { - $options = $this->getOptions(); - $locking = $options->getFileLocking(); - $blocking = $locking ? $options->getFileBlocking() : false; + $locking = $this->getOptions()->getFileLocking(); + $wouldblock = $locking && $wouldblock; ErrorHandler::start(); - if ($locking && !$blocking) { + // file_put_contents can't used + if ($locking && $wouldblock) { $fp = fopen($file, 'cb'); if (!$fp) { $err = ErrorHandler::stop(); @@ -1595,11 +1596,12 @@ protected function putFileContent($file, $data) ); } + $wouldblock = null; if(!flock($fp, \LOCK_EX | \LOCK_NB, $wouldblock)) { fclose($fp); $err = ErrorHandler::stop(); if ($wouldblock) { - throw new Exception\LockedException("File '{$file}' locked", 0, $err); + return false; } else { throw new Exception\RuntimeException("Error locking file '{$file}'", 0, $err); } @@ -1621,6 +1623,8 @@ protected function putFileContent($file, $data) flock($fp, \LOCK_UN); fclose($fp); + + // file_put_contents can be used } else { $flags = 0; if ($locking) { diff --git a/src/Storage/Adapter/FilesystemOptions.php b/src/Storage/Adapter/FilesystemOptions.php index ce20ad9c7..d69ca3bc1 100644 --- a/src/Storage/Adapter/FilesystemOptions.php +++ b/src/Storage/Adapter/FilesystemOptions.php @@ -65,17 +65,6 @@ class FilesystemOptions extends AdapterOptions */ protected $dirUmask = 0007; - /** - * Block writing files until writing by another process finished. - * - * NOTE: this only attempts if fileLocking is enabled - * NOTE: if disabled writing operations can throw a LockedException - * NOTE: This option can't be disabled on windows - * - * @var boolean - */ - protected $fileBlocking = true; - /** * Lock files on writing * @@ -304,44 +293,6 @@ public function getDirUmask() return $this->dirUmask; } - /** - * Set block writing files until writing by another process finished. - * - * NOTE: this only attempts if fileLocking is enabled - * NOTE: if disabled writing operations can throw a LockedException - * NOTE: This option can't be disabled on windows - * - * @param bool $flag - * @return FilesystemOptions - */ - public function setFileBlocking($flag) - { - $flag = (bool) $flag; - if (!$flag && substr(\PHP_OS, 0, 3) == 'WIN') { - throw new Exception\InvalidArgumentException( - "This option can't be disabled on windows" - ); - } - - $this->triggerOptionEvent('file_blocking', $flag); - $this->fileBlocking = $flag; - return $this; - } - - /** - * Get block writing files until writing by another process finished. - * - * NOTE: this only attempts if fileLocking is enabled - * NOTE: if disabled writing operations can throw a LockedException - * NOTE: This option can't be disabled on windows - * - * @return bool - */ - public function getFileBlocking() - { - return $this->fileBlocking; - } - /** * Set file locking * diff --git a/test/Storage/Adapter/FilesystemTest.php b/test/Storage/Adapter/FilesystemTest.php index 2c96244bf..879f8b82b 100644 --- a/test/Storage/Adapter/FilesystemTest.php +++ b/test/Storage/Adapter/FilesystemTest.php @@ -262,75 +262,6 @@ public function testSetReadControlAlgoInvalidException() $this->_options->setReadControlAlgo('unknown'); } - public function testDisabledFileBlocking() - { - if (substr(\PHP_OS, 0, 3) == 'WIN') { - $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException'); - } - - $this->_options->setFileLocking(true); - $this->_options->setFileBlocking(false); - - // create cache item and get data file - $this->assertTrue($this->_storage->setItem('key', 'value')); - $meta = $this->_storage->getMetadata('key'); - $this->assertInternalType('array', $meta); - $this->assertArrayHasKey('filespec', $meta); - $file = $meta['filespec'] . '.dat'; - - /****************** - * first test with exclusive lock - */ - - // open file and create a lock - $fp = @fopen($file, 'cb'); - $this->assertInternalType('resource', $fp); - flock($fp, LOCK_EX); - - // rewriting file should fail in part of open lock - try { - $this->_storage->setItem('key', 'lock'); - - // close - flock($fp, LOCK_UN); - fclose($fp); - - $this->fail('Missing expected exception Zend\Cache\Exception\LockedException'); - } catch (\Zend\Cache\Exception\LockedException $e) { - // expected exception was thrown - - // close - flock($fp, LOCK_UN); - fclose($fp); - } - - /****************** - * second test with shared lock - */ - - // open file and create a lock - $fp = @fopen($file, 'rb'); - $this->assertInternalType('resource', $fp); - flock($fp, LOCK_SH); - - // rewriting file should fail in part of open lock - try { - $this->_storage->setItem('key', 'lock'); - - // close - flock($fp, LOCK_UN); - fclose($fp); - - $this->fail('Missing expected exception Zend\Cache\Exception\LockedException'); - } catch (\Zend\Cache\Exception\LockedException $e) { - // expected exception was thrown - - // close - flock($fp, LOCK_UN); - fclose($fp); - } - } - public function testGetMetadataWithCtime() { $this->_options->setNoCtime(false); From af2a849cb33fb78bb2e14bab87199495151ea2ef Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Mar 2012 23:37:13 +0200 Subject: [PATCH 18/62] The method unlink don't need to check if the file exists because it's already checked before and on error it will also be checked before throwing an exception --- src/Storage/Adapter/Filesystem.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 5962b7170..45c1041ca 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -1653,11 +1653,6 @@ protected function putFileContent($file, $data, $wouldblock = false) */ protected function unlink($file) { - // If file does not exist, nothing to do - if (!file_exists($file)) { - return; - } - ErrorHandler::start(); $res = unlink($file); $err = ErrorHandler::stop(); From 0eab73b76b8ee2f1f32aec7d6146d2a8f50840f3 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Mar 2012 08:16:24 +0200 Subject: [PATCH 19/62] Cache filesystem adapter: - no need to buffer filespec generation - implement $wouldblock argument by reference - optimized internalGetMetadatas with non blocking - optimized single writes with non blocking if *.dat AND *.ifo file have to be written --- src/Storage/Adapter/Filesystem.php | 225 ++++++++++++++++++----------- 1 file changed, 141 insertions(+), 84 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 45c1041ca..213dae8fc 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -54,20 +54,6 @@ class Filesystem extends AbstractAdapter */ protected $stmtMatch = null; - /** - * Key (namespace + separator + key) of buffered information - * - * @var string|null - */ - protected $bufferKey = null; - - /** - * The buffered filespec - * - * @var string|null - */ - protected $bufferedFilespec = null; - /** * Set options. * @@ -239,25 +225,30 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized { $baseOptions = $this->getOptions(); + // Don't change arguments passed by reference + $keys = $normalizedKeys; + $options = $normalizedOptions; + $result = array(); - while (true) { + while ($keys) { // LOCK_NB if more than one items have to read - $wouldblock = count($normalizedKeys) > 1; + $nonBlocking = count($keys) > 1; + $wouldblock = null; // read items - foreach ($normalizedKeys as $i => $normalizedKey) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { - unset($normalizedKeys[$i]); + foreach ($keys as $i => $key) { + if (!$this->internalHasItem($key, $options)) { + unset($keys[$i]); continue; } - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - $data = $this->getFileContent($filespec . '.dat', $wouldblock); - if ($data === false) { + $filespec = $this->getFileSpec($key, $options); + $data = $this->getFileContent($filespec . '.dat', $nonBlocking, $wouldblock); + if ($nonBlocking && $wouldblock) { continue; } else { - unset($normalizedKeys[$i]); + unset($keys[$i]); } if ($baseOptions->getReadControl()) { @@ -271,13 +262,11 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized } } - $result[$normalizedKey] = $data; + $result[$key] = $data; } - // no more items to read - if (!$normalizedKeys) { - break; - } + // Don't check ttl after first iteration + $options['ttl'] = 0; } return $result; @@ -456,6 +445,72 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti return $metadata; } + /** + * Internal method to get multiple metadata + * + * Options: + * - ttl + * - The time-to-life + * - namespace + * - The namespace to use + * + * @param array $normalizedKeys + * @param array $normalizedOptions + * @return array Associative array of existing cache ids and its metadata + * @throws Exception + */ + protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + { + $baseOptions = $this->getOptions(); + $result = array(); + + // Don't change arguments passed by reference + $keys = $normalizedKeys; + $options = $normalizedOptions; + + while ($keys) { + + // LOCK_NB if more than one items have to read + $nonBlocking = count($keys) > 1; + $wouldblock = null; + + foreach ($keys as $i => $key) { + if (!$this->internalHasItem($key, $options)) { + unset($keys[$i]); + continue; + } + + $filespec = $this->getFileSpec($key, $options); + + $metadata = $this->readInfoFile($filespec . '.ifo', $nonBlocking, $wouldblock); + if ($nonBlocking && $wouldblock) { + continue; + } elseif (!$metadata) { + $metadata = array(); + } + + $metadata['filespec'] = $filespec; + $metadata['mtime'] = filemtime($filespec . '.dat'); + + if (!$baseOptions->getNoCtime()) { + $metadata['ctime'] = filectime($filespec . '.dat'); + } + + if (!$baseOptions->getNoAtime()) { + $metadata['atime'] = fileatime($filespec . '.dat'); + } + + $result[$key] = $metadata; + unset($keys[$i]); + } + + // Don't check ttl after first iteration + $options['ttl'] = 0; + } + + return $result; + } + /* writing */ /** @@ -687,23 +742,29 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz $oldUmask = umask($baseOptions->getFileUmask()); } - $ret = $this->putFileContent($filespec . '.dat', $value); - if ($ret && $info) { - // Don't throw exception if writing of info file failed - // -> only return false - try { - $ret = $this->putFileContent($filespec . '.ifo', serialize($info)); - } catch (Exception\RuntimeException $e) { - $ret = false; - } + $contents = array($filespec . '.dat' => $value); + if ($info) { + $contents[$filespec . '.ifo'] = serialize($info); + } else { + $this->unlink($filespec . '.ifo'); } - $this->bufferKey = null; + while ($contents) { + $nonBlocking = count($contents) > 1; + $wouldblock = null; + + foreach ($contents as $file => $content) { + $this->putFileContent($file, $content, $nonBlocking, $wouldblock); + if (!$nonBlocking || !$wouldblock) { + unset($contents[$file]); + } + } + } // reset file_umask umask($oldUmask); - return $ret; + return true; } catch (Exception $e) { // reset umask on exception @@ -874,9 +935,6 @@ protected function internalTouchItem(& $normalizedKey, array & $normalizedOption ); } - // remove the buffered info - $this->bufferKey = null; - return true; } @@ -960,7 +1018,6 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio } else { $this->unlink($filespec . '.dat'); $this->unlink($filespec . '.ifo'); - $this->bufferKey = null; } return true; } @@ -1452,39 +1509,39 @@ protected function getFileSpec($normalizedKey, array & $normalizedOptions) { $baseOptions = $this->getOptions(); $prefix = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator(); - $bufferKey = $prefix . $normalizedKey; - - if ($this->bufferKey !== $bufferKey) { - $path = $baseOptions->getCacheDir(); - $level = $baseOptions->getDirLevel(); - if ( $level > 0 ) { - // create up to 256 directories per directory level - $hash = md5($normalizedKey); - for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) { - $path .= \DIRECTORY_SEPARATOR . $prefix . $hash[$i] . $hash[$i+1]; - } - } - $this->bufferedFilespec = $path . \DIRECTORY_SEPARATOR . $prefix . $normalizedKey; + $path = $baseOptions->getCacheDir(); + $level = $baseOptions->getDirLevel(); + if ( $level > 0 ) { + // create up to 256 directories per directory level + $hash = md5($normalizedKey); + for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) { + $path .= \DIRECTORY_SEPARATOR . $prefix . $hash[$i] . $hash[$i+1]; + } } - return $this->bufferedFilespec; + return $path . \DIRECTORY_SEPARATOR . $prefix . $normalizedKey; } /** * Read info file * - * @param string $file + * @param string $file + * @param boolean $nonBlocking Don't block script if file is locked + * @param boolean $wouldblock The optional argument is set to TRUE if the lock would block * @return array|boolean The info array or false if file wasn't found * @throws Exception\RuntimeException */ - protected function readInfoFile($file) + protected function readInfoFile($file, $nonBlocking = false, & $wouldblock = null) { if (!file_exists($file)) { return false; } - $content = $this->getFileContent($file); + $content = $this->getFileContent($file, $nonBlocking, $wouldblock); + if ($nonBlocking && $wouldblock) { + return false; + } ErrorHandler::start(); $ifo = unserialize($content); @@ -1501,14 +1558,16 @@ protected function readInfoFile($file) /** * Read a complete file * - * @param string $file File complete path - * @param boolean $wouldblock Return FALSE if the lock would block - * @return string|boolean + * @param string $file File complete path + * @param boolean $nonBlocking Don't block script if file is locked + * @param boolean $wouldblock The optional argument is set to TRUE if the lock would block + * @return string * @throws Exception\RuntimeException */ - protected function getFileContent($file, $wouldblock = false) + protected function getFileContent($file, $nonBlocking = false, & $wouldblock = null) { - $locking = $this->getOptions()->getFileLocking(); + $locking = $this->getOptions()->getFileLocking(); + $wouldblock = null; ErrorHandler::start(); @@ -1522,13 +1581,12 @@ protected function getFileContent($file, $wouldblock = false) ); } - if ($wouldblock) { - $wouldblock = null; + if ($nonBlocking) { $lock = flock($fp, \LOCK_SH | \LOCK_NB, $wouldblock); if ($wouldblock) { fclose($fp); ErrorHandler::stop(); - return false; + return; } } else { $lock = flock($fp, \LOCK_SH); @@ -1573,21 +1631,23 @@ protected function getFileContent($file, $wouldblock = false) /** * Write content to a file * - * @param string $file File complete path - * @param string $data Data to write - * @param boolean $wouldblock Return FALSE if the lock would block - * @return boolean TRUE on success, FALSE if lock would block + * @param string $file File complete path + * @param string $data Data to write + * @param boolean $nonBlocking Don't block script if file is locked + * @param boolean $wouldblock The optional argument is set to TRUE if the lock would block + * @return void * @throws Exception\RuntimeException */ - protected function putFileContent($file, $data, $wouldblock = false) + protected function putFileContent($file, $data, $nonBlocking = false, & $wouldblock = null) { - $locking = $this->getOptions()->getFileLocking(); - $wouldblock = $locking && $wouldblock; + $locking = $this->getOptions()->getFileLocking(); + $nonBlocking = $locking && $nonBlocking; + $wouldblock = null; ErrorHandler::start(); - // file_put_contents can't used - if ($locking && $wouldblock) { + // if locking and non blocking is enabled -> file_put_contents can't used + if ($locking && $nonBlocking) { $fp = fopen($file, 'cb'); if (!$fp) { $err = ErrorHandler::stop(); @@ -1596,12 +1656,11 @@ protected function putFileContent($file, $data, $wouldblock = false) ); } - $wouldblock = null; if(!flock($fp, \LOCK_EX | \LOCK_NB, $wouldblock)) { fclose($fp); $err = ErrorHandler::stop(); if ($wouldblock) { - return false; + return; } else { throw new Exception\RuntimeException("Error locking file '{$file}'", 0, $err); } @@ -1624,24 +1683,22 @@ protected function putFileContent($file, $data, $wouldblock = false) flock($fp, \LOCK_UN); fclose($fp); - // file_put_contents can be used + // else -> file_put_contents can be used } else { $flags = 0; if ($locking) { $flags = $flags | \LOCK_EX; } - $bytes = strlen($data); - if (file_put_contents($file, $data, $flags) !== $bytes) { + if (file_put_contents($file, $data, $flags) === false) { $err = ErrorHandler::stop(); throw new Exception\RuntimeException( - "Error putting {$bytes} bytes to file '{$file}'", 0, $err + "Error writing file '{$file}'", 0, $err ); } } ErrorHandler::stop(); - return true; } /** From 0f8bfc4e91b8f2c736f4fa662ad73f18b2793277 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Mar 2012 21:12:57 +0200 Subject: [PATCH 20/62] optimized writing multiple items of filesystem adapter using non blocking locks --- src/Storage/Adapter/Filesystem.php | 108 ++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 9 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 213dae8fc..294139c63 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -702,8 +702,8 @@ public function replaceItems(array $keyValuePairs, array $options = array()) protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { $baseOptions = $this->getOptions(); - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); $oldUmask = null; + $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); if ($baseOptions->getDirLevel() > 0) { $path = dirname($filespec); @@ -726,23 +726,20 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); $info['algo'] = $baseOptions->getReadControlAlgo(); } - - if (isset($options['tags']) && $normalizedOptions['tags']) { - $tags = $normalizedOptions['tags']; - if (!is_array($tags)) { - $tags = array($tags); - } - $info['tags'] = array_values(array_unique($tags)); + if (isset($options['tags'])) { + $info['tags'] = $normalizedOptions['tags']; } + // write files try { + // set umask for files if ($oldUmask !== null) { // $oldUmask could be defined on create directory umask($baseOptions->getFileUmask()); } else { $oldUmask = umask($baseOptions->getFileUmask()); } - $contents = array($filespec . '.dat' => $value); + $contents = array($filespec . '.dat' => & $value); if ($info) { $contents[$filespec . '.ifo'] = serialize($info); } else { @@ -773,6 +770,99 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz } } + /** + * Internal method to store multiple items. + * + * Options: + * - namespace + * - The namespace to use + * - tags + * - An array of tags + * + * @param array $normalizedKeyValuePairs + * @param array $normalizedOptions + * @return boolean + * @throws Exception + */ + protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + { + $baseOptions = $this->getOptions(); + $oldUmask = null; + + // create an associated array of files and contents to write + $contents = array(); + foreach ($normalizedKeyValuePairs as $key => & $value) { + $filespec = $this->getFileSpec($key, $normalizedOptions); + + // init directory level + if ($baseOptions->getDirLevel() > 0) { + $path = dirname($filespec); + if (!file_exists($path)) { + $oldUmask = ($oldUmask === null) ? umask($baseOptions->getDirUmask()) : $oldUmask; + ErrorHandler::start(); + $mkdir = mkdir($path, 0777, true); + $error = ErrorHandler::stop(); + if (!$mkdir) { + umask($oldUmask); + throw new Exception\RuntimeException( + "Error creating directory '{$path}'", 0, $error + ); + } + } + } + + // *.dat file + $contents[$filespec . '.dat'] = & $value; + + // *.ifo file + $info = null; + if ($baseOptions->getReadControl()) { + $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); + $info['algo'] = $baseOptions->getReadControlAlgo(); + } + if (isset($normalizedOptions['tags'])) { + $info['tags'] = & $normalizedOptions['tags']; + } + if ($info) { + $contents[$filespec . '.ifo'] = serialize($info); + } else { + $this->unlink($filespec . '.ifo'); + } + } + + // write to disk + try { + // set umask for files + if ($oldUmask !== null) { // $oldUmask could be defined on create directory + umask($baseOptions->getFileUmask()); + } else { + $oldUmask = umask($baseOptions->getFileUmask()); + } + + while ($contents) { + $nonBlocking = count($contents) > 1; + $wouldblock = null; + + foreach ($contents as $file => & $content) { + $this->putFileContent($file, $content, $nonBlocking, $wouldblock); + if (!$nonBlocking || !$wouldblock) { + unset($contents[$file]); + } + } + } + + // reset umask + umask($oldUmask); + + return true; + + } catch (Exception $e) { + // reset umask on exception + umask($oldUmask); + throw $e; + } + } + /** * Set an item only if token matches * From 46afe3b5e09fc27647e8b85b16f4343e917f39ff Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 6 Apr 2012 21:15:08 +0200 Subject: [PATCH 21/62] re-implemented a buffer of the last used filespec --- src/Storage/Adapter/Filesystem.php | 36 ++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 294139c63..fe8448c59 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -54,6 +54,21 @@ class Filesystem extends AbstractAdapter */ protected $stmtMatch = null; + /** + * An identity for the last filespec + * (cache directory + namespace prefix + key + directory level) + * + * @var string + */ + protected $lastFileSpecId = ''; + + /** + * The last used filespec + * + * @var string + */ + protected $lastFileSpec = ''; + /** * Set options. * @@ -1600,17 +1615,24 @@ protected function getFileSpec($normalizedKey, array & $normalizedOptions) $baseOptions = $this->getOptions(); $prefix = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator(); - $path = $baseOptions->getCacheDir(); + $path = $baseOptions->getCacheDir() . \DIRECTORY_SEPARATOR; $level = $baseOptions->getDirLevel(); - if ( $level > 0 ) { - // create up to 256 directories per directory level - $hash = md5($normalizedKey); - for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) { - $path .= \DIRECTORY_SEPARATOR . $prefix . $hash[$i] . $hash[$i+1]; + + $fileSpecId = $path . $prefix . $normalizedKey . '/' . $level; + if ($this->lastFileSpecId !== $fileSpecId) { + if ($level > 0) { + // create up to 256 directories per directory level + $hash = md5($normalizedKey); + for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) { + $path .= $prefix . $hash[$i] . $hash[$i+1] . \DIRECTORY_SEPARATOR; + } } + + $this->lastFileSpecId = $fileSpecId; + $this->lastFileSpec = $path . $prefix . $normalizedKey; } - return $path . \DIRECTORY_SEPARATOR . $prefix . $normalizedKey; + return $this->lastFileSpec; } /** From 4dad11ee4cdbf3a6ea890494aab506bc79fd2981 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 4 Apr 2012 00:27:17 +0200 Subject: [PATCH 22/62] Adding shell script to run tests It iterates over tested components and runs phpunit for each of them --- .travis/run-tests.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .travis/run-tests.sh diff --git a/.travis/run-tests.sh b/.travis/run-tests.sh new file mode 100644 index 000000000..47d0c4a07 --- /dev/null +++ b/.travis/run-tests.sh @@ -0,0 +1,8 @@ +#!/bin/bash +travisdir=$(dirname $(readlink /proc/$$/fd/255)) +testdir="$travisdir/../tests" +testedcomponents=(`cat "$travisdir/tested-components"`) + +for tested in "${testedcomponents[@]}" + do phpunit -c $testdir/phpunit.xml $testdir/$tested +done From 775902341fd11e313983f4c630a3be796c19bbf9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 4 Apr 2012 00:29:10 +0200 Subject: [PATCH 23/62] Adding script used to configure the test suite --- .travis/TestConfiguration.php | 825 ++++++++++++++++++++++++++++++++++ 1 file changed, 825 insertions(+) create mode 100644 .travis/TestConfiguration.php diff --git a/.travis/TestConfiguration.php b/.travis/TestConfiguration.php new file mode 100644 index 000000000..fd8947049 --- /dev/null +++ b/.travis/TestConfiguration.php @@ -0,0 +1,825 @@ + test disabling output buffering in + * dispatcher + */ +defined('TESTS_ZEND_CONTROLLER_DISPATCHER_OB') || define('TESTS_ZEND_CONTROLLER_DISPATCHER_OB', false); + +/** + * Zend_Crypt related constantes + * + * TESTS_ZEND_CRYPT_OPENSSL_CONF => location of an openssl.cnf file for use + * with RSA encryption + */ +defined('TESTS_ZEND_CRYPT_OPENSSL_CONF') || define('TESTS_ZEND_CRYPT_OPENSSL_CONF', false); + +/** + * Zend_Db_Adapter_Pdo_Mysql and Zend_Db_Adapter_Mysqli + * + * There are separate properties to enable tests for the PDO_MYSQL adapter and + * the native Mysqli adapters, but the other properties are shared between the + * two MySQL-related Zend_Db adapters. + */ +defined('TESTS_ZEND_DB_ADAPTER_PDO_MYSQL_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_MYSQL_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_MYSQLI_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_MYSQLI_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_MYSQL_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_HOSTNAME', '127.0.0.1'); +defined('TESTS_ZEND_DB_ADAPTER_MYSQL_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_USERNAME', null); +defined('TESTS_ZEND_DB_ADAPTER_MYSQL_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_PASSWORD', null); +defined('TESTS_ZEND_DB_ADAPTER_MYSQL_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_DATABASE', 'test'); +defined('TESTS_ZEND_DB_ADAPTER_MYSQL_PORT') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_PORT', 3306); + +/** + * Zend_Db_Adapter_Pdo_Sqlite + * + * Username and password are irrelevant for SQLite. + */ +defined('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_DATABASE', ':memory:'); + +/** + * Zend_Db_Adapter_Pdo_Mssql + * + * Note that you need to patch your ntwdblib.dll, the one that + * comes with PHP does not work. See user comments at + * http://us2.php.net/manual/en/ref.mssql.php + */ +defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_HOSTNAME', '127.0.0.1'); +defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_USERNAME', null); +defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_PASSWORD', null); +defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_DATABASE', 'test'); + +/** + * Zend_Db_Adapter_Pdo_Pgsql + */ +defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_HOSTNAME', '127.0.0.1'); +defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_USERNAME', null); +defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_PASSWORD', null); +defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_DATABASE', 'postgres'); + +/** + * Zend_Db_Adapter_Oracle and Zend_Db_Adapter_Pdo_Oci + * + * There are separate properties to enable tests for the PDO_OCI adapter and + * the native Oracle adapter, but the other properties are shared between the + * two Oracle-related Zend_Db adapters. + */ +defined('TESTS_ZEND_DB_ADAPTER_PDO_OCI_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_OCI_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_ORACLE_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_ORACLE_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_HOSTNAME', '127.0.0.1'); +defined('TESTS_ZEND_DB_ADAPTER_ORACLE_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_USERNAME', null); +defined('TESTS_ZEND_DB_ADAPTER_ORACLE_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_PASSWORD', null); +defined('TESTS_ZEND_DB_ADAPTER_ORACLE_SID') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_SID', 'xe'); + +/** + * Zend_Db_Adapter_Db2 and Zend_Db_Adapter_Pdo_Ibm + * There are separate properties to enable tests for the PDO_IBM adapter and + * the native DB2 adapter, but the other properties are shared between the + * two related Zend_Db adapters. + */ +defined('TESTS_ZEND_DB_ADAPTER_PDO_IBM_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_IBM_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_DB2_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_DB2_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_DB2_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_DB2_HOSTNAME', '127.0.0.1'); +defined('TESTS_ZEND_DB_ADAPTER_DB2_PORT') || define('TESTS_ZEND_DB_ADAPTER_DB2_PORT', 50000); +defined('TESTS_ZEND_DB_ADAPTER_DB2_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_DB2_USERNAME', null); +defined('TESTS_ZEND_DB_ADAPTER_DB2_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_DB2_PASSWORD', null); +defined('TESTS_ZEND_DB_ADAPTER_DB2_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_DB2_DATABASE', 'sample'); + +/** + * Zend_Db_Adapter_Sqlsrv + * Note: Make sure that you create the "test" database and set a + * username and password + * + */ +defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_ENABLED', false); +defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_HOSTNAME', 'localhost\SQLEXPRESS'); +defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_USERNAME', null); +defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_PASSWORD', null); +defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_DATABASE', 'test'); + +/** + * Zend_Feed_Reader tests + * + * If the ONLINE_ENABLED property is false, only tests that can be executed + * without network connectivity are run; when enabled, all tests will run. + */ +defined('TESTS_ZEND_FEED_READER_ONLINE_ENABLED') || define('TESTS_ZEND_FEED_READER_ONLINE_ENABLED', false); + +/** + * Zend_Gdata tests + * + * If the ONLINE_ENABLED property is false, only tests that can be executed with + * a mock HTTP client are run. No request is sent to the Google Gdata servers. + * If ONLINE_ENABLED is true, some tests may make requests to the remote + * servers. This does not work if you are running tests on a disconnected + * client host. Also, the tests may show as failures if the Google servers + * cannot be reached or if they do not respond for another reason. + * + * If the CLIENTLOGIN_ENABLED property below is false, the authenticated + * tests are reported Skipped in the test run. Set this property to true + * to enable tests that require ClientLogin authentication. Enter your + * Google login credentials in the EMAIL and PASSWORD properties below. + * + * Edit TestConfiguration.php, not TestConfiguration.php.dist. + * Never commit plaintext passwords to the source code repository. + * + * Note: the GData tests currently require that the TZID env variable + * be set or the timezone otherwise configured. You'll see errors from the + * tests if this is not the case. + */ +defined('TESTS_ZEND_GDATA_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_ONLINE_ENABLED', false); +defined('TESTS_ZEND_GDATA_CLIENTLOGIN_ENABLED') || define('TESTS_ZEND_GDATA_CLIENTLOGIN_ENABLED', false); + +/* + * The credentials provided here should be only for a TEST account. + * Data for various services in this account may be added to, updated, + * or deleted based upon the actions of these test accounts. + */ +defined('TESTS_ZEND_GDATA_CLIENTLOGIN_EMAIL') || define('TESTS_ZEND_GDATA_CLIENTLOGIN_EMAIL', 'example@example.com'); +defined('TESTS_ZEND_GDATA_CLIENTLOGIN_PASSWORD') || define('TESTS_ZEND_GDATA_CLIENTLOGIN_PASSWORD', 'password'); + +/* + * This is the ID of a blank blog. There is no need to have + * any content in this blog. Also, blogs can only be used + * several times for the purpose of these test cases before + * they must be deleted and recreated. Otherwise, the tests + * will start failing, as posts to Blogger will return a 201 Created + * response even though the entry was not posted to the blog. + * This problem is being investigated. + */ +defined('TESTS_ZEND_GDATA_BLOGGER_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_BLOGGER_ONLINE_ENABLED', false); +defined('TESTS_ZEND_GDATA_BLOG_ID') || define('TESTS_ZEND_GDATA_BLOG_ID', '1111111111111111111'); + +/* + * This is the key for a spreadsheet with data only in the first row of + * the spreadsheet. The strings 'a1', 'b1', 'c1', 'd1' should be in the + * corresponding cell locations. + */ +defined('TESTS_ZEND_GDATA_SPREADSHEETS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_SPREADSHEETS_ONLINE_ENABLED', false); +defined('TESTS_ZEND_GDATA_SPREADSHEETS_SPREADSHEETKEY') || define('TESTS_ZEND_GDATA_SPREADSHEETS_SPREADSHEETKEY', 'o01111111111111111111.1111111111111111111'); +defined('TESTS_ZEND_GDATA_SPREADSHEETS_WORKSHEETID') || define('TESTS_ZEND_GDATA_SPREADSHEETS_WORKSHEETID', 'default'); + +/* + * This indicates that online tests for the Google Calendar API should + * be performed. The default calendar will be used. + */ +defined('TESTS_ZEND_GDATA_CALENDAR_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_CALENDAR_ONLINE_ENABLED', false); + +/* + * This is the fully-qualified domain name for a domiain hosted using + * Google Apps. This domain must be registered with Google Apps and + * have API access enabled. This should be a TEST domain only. + */ +defined('TESTS_ZEND_GDATA_GAPPS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_GAPPS_ONLINE_ENABLED', false); +defined('TESTS_ZEND_GDATA_GAPPS_DOMAIN') || define('TESTS_ZEND_GDATA_GAPPS_DOMAIN', 'example.com.invalid'); +defined('TESTS_ZEND_GDATA_GAPPS_EMAIL') || define('TESTS_ZEND_GDATA_GAPPS_EMAIL', 'example@example.com'); +defined('TESTS_ZEND_GDATA_GAPPS_PASSWORD') || define('TESTS_ZEND_GDATA_GAPPS_PASSWORD', 'password'); + +/* + * This is the ONLINE_ENABLED property for Google Base. + */ +defined('TESTS_ZEND_GDATA_GBASE_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_GBASE_ONLINE_ENABLED', false); + +/* + * This indicates that online tests for the Books Search data API + * should be performed. + */ +defined('TESTS_ZEND_GDATA_BOOKS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_BOOKS_ONLINE_ENABLED', false); + +/* + * This indicates that online tests for the YouTube data API should + * be performed. + */ +defined('TESTS_ZEND_GDATA_YOUTUBE_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_YOUTUBE_ONLINE_ENABLED', false); + +/* + * This is the username to use for retrieving subscriptions, etc + */ +defined('TESTS_ZEND_GDATA_YOUTUBE_ACCOUNT') || define('TESTS_ZEND_GDATA_YOUTUBE_ACCOUNT', 'zfgdata'); + +/* + * This is the developer key to access the YouTube API + */ +defined('TESTS_ZEND_GDATA_YOUTUBE_DEVELOPER_KEY') || define('TESTS_ZEND_GDATA_YOUTUBE_DEVELOPER_KEY', 'your_developer_key_here'); + +/* + * This is the client ID to access the YouTube API + */ +defined('TESTS_ZEND_GDATA_YOUTUBE_CLIENT_ID') || define('TESTS_ZEND_GDATA_YOUTUBE_CLIENT_ID', 'ZF_UnitTests_unknown'); + +/* + * This indicates that online tests for the Google Documents API should + * be performed. + */ +defined('TESTS_ZEND_GDATA_DOCS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_DOCS_ONLINE_ENABLED', false); + +/* + * This indicates that online tests for the GData Photos API should + * be performed. + */ +defined('TESTS_ZEND_GDATA_PHOTOS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_PHOTOS_ONLINE_ENABLED', false); + +/* + * This indicates that online tests for the Google Health API should + * be performed. + */ +defined('TESTS_ZEND_GDATA_HEALTH_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_HEALTH_ONLINE_ENABLED', false); + +/** + * Zend_Http_Client tests + * + * To enable the dynamic Zend_Http_Client tests, you will need to symbolically + * link or copy the files in tests/Zend/Http/Client/_files to a directory + * under your web server(s) document root and set this constant to point to the + * URL of this directory. + */ +defined('TESTS_ZEND_HTTP_CLIENT_BASEURI') || define('TESTS_ZEND_HTTP_CLIENT_BASEURI', false); + +/** + * Zend_Http_Client_Proxy tests + * + * HTTP proxy to be used for testing the Proxy adapter. Set to a string of + * the form 'host:port'. Set to null to skip HTTP proxy tests. + */ +defined('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY') || define('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY', false); +defined('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_USER') || define('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_USER', ''); +defined('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_PASS') || define('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_PASS', ''); + +/** + * Zend_Loader_Autoloader multi-version support tests + * + * ENABLED: whether or not to run the multi-version tests + * PATH: path to a directory containing multiple ZF version installs + * LATEST: most recent ZF version in the PATH + * e.g., "1.9.2" + * LATEST_MAJOR: most recent ZF major version in the PATH to test against + * e.g., "1.9.2" + * LATEST_MINOR: most recent ZF minor version in the PATH to test against + * e.g., "1.8.4PL1" + * SPECIFIC: specific ZF version in the PATH to test against + * e.g., "1.7.6" + * As an example, consider the following tree: + * ZendFramework/ + * |-- 1.9.2 + * |-- ZendFramework-1.9.1-minimal + * |-- 1.8.4PL1 + * |-- 1.8.4 + * |-- ZendFramework-1.8.3 + * |-- 1.7.8 + * |-- 1.7.7 + * |-- 1.7.6 + * You would then set the value of "LATEST" and "LATEST_MAJOR" to "1.9.2", and + * could choose between "1.9.2", "1.8.4PL1", and "1.7.8" for "LATEST_MINOR", + * and any version number for "SPECIFIC". "PATH" would point to the parent + * "ZendFramework" directory. + */ +defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_ENABLED') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_ENABLED', false); +defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_PATH') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_PATH', false); +defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST', false); +defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MAJOR') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MAJOR', false); +defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MINOR') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MINOR', false); +defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_SPECIFIC') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_SPECIFIC', false); + +/** + * Zend_Ldap online tests + */ +defined('TESTS_ZEND_LDAP_ONLINE_ENABLED') || define('TESTS_ZEND_LDAP_ONLINE_ENABLED', false); + +/* These largely map to the options described in the Zend_Ldap and + * Zend_Auth_Adapter_Ldap documentation. + * + * Example Configuration for Active Directory: + * HOST: dc1.w.net + * USE_START_TLS: true + * USE_SSL: false + * USERNAME: CN=User 1,CN=Users,DC=w,DC=net + * PRINCIPAL_NAME: user1@w.net + * LDAP_PASSWORD: pass1 + * BASE_DN: CN=Users,DC=w,DC=net + * DOMAIN_NAME: w.net + * ACCOUNT_DOMAIN_NAME_SHORT: W + * ALT_USERNAME: user2 + * ALT_DN: CN=User 2,CN=Users,DC=w,DC=net + * ALT_PASSWORD: pass2 + * + * Example Configuration for OpenLDAP + * HOST: s0.foo.net + * USERNAME: CN=user1,DC=foo,DC=net + * PRINCIPAL_NAME: user1@foo.net + * LDAP_PASSWORD: pass1 + * BIND_REQUIRES_DN: true + * BASE_DN: OU=Sales,DC=w,DC=net + * DOMAIN_NAME: foo.net + * ACCOUNT_DOMAIN_NAME_SHORT: FOO + * ALT_USERNAME: abaker + * ALT_DN: CN=Alice Baker,OU=Sales,DC=foo,DC=net + * ALT_PASSWORD: apass + */ +defined('TESTS_ZEND_LDAP_HOST') || define('TESTS_ZEND_LDAP_HOST', 'localhost'); +//defined('TESTS_ZEND_LDAP_PORT') || define('TESTS_ZEND_LDAP_PORT', 389); +defined('TESTS_ZEND_LDAP_USE_START_TLS') || define('TESTS_ZEND_LDAP_USE_START_TLS', true); +//defined('TESTS_ZEND_LDAP_USE_SSL') || define('TESTS_ZEND_LDAP_USE_SSL', false); +defined('TESTS_ZEND_LDAP_USERNAME') || define('TESTS_ZEND_LDAP_USERNAME', 'CN=someUser,DC=example,DC=com'); +defined('TESTS_ZEND_LDAP_PRINCIPAL_NAME') || define('TESTS_ZEND_LDAP_PRINCIPAL_NAME', 'someUser@example.com'); +defined('TESTS_ZEND_LDAP_PASSWORD') || define('TESTS_ZEND_LDAP_PASSWORD', null); +defined('TESTS_ZEND_LDAP_BIND_REQUIRES_DN') || define('TESTS_ZEND_LDAP_BIND_REQUIRES_DN', true); +defined('TESTS_ZEND_LDAP_BASE_DN') || define('TESTS_ZEND_LDAP_BASE_DN', 'OU=Sales,DC=example,DC=com'); +//defined('TESTS_ZEND_LDAP_ACCOUNT_FILTER_FORMAT') || define('TESTS_ZEND_LDAP_ACCOUNT_FILTER_FORMAT', '(&(objectClass=posixAccount)(uid=%s))'); +defined('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME') || define('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME', 'example.com'); +defined('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME_SHORT') || define('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME_SHORT', 'EXAMPLE'); +defined('TESTS_ZEND_LDAP_ALT_USERNAME') || define('TESTS_ZEND_LDAP_ALT_USERNAME', 'anotherUser'); +defined('TESTS_ZEND_LDAP_ALT_DN') || define('TESTS_ZEND_LDAP_ALT_DN', 'CN=Another User,OU=Sales,DC=example,DC=com'); +defined('TESTS_ZEND_LDAP_ALT_PASSWORD') || define('TESTS_ZEND_LDAP_ALT_PASSWORD', null); // Used in Zend_Auth_Adapter_Ldap tests +//(defined('TESTS_ZEND_LDAP_WRITEABLE_SUBTREE') || define('TESTS_ZEND_LDAP_WRITEABLE_SUBTREE', 'OU=Test,OU=Sales,DC=example,DC=com'); + +/** + * Zend_Locale tests + * + * If the TESTS_ZEND_LOCALE_FORMAT_SETLOCALE property below is a valid, + * locally recognized locale (try "locale -a"), then all tests in + * tests/Zend/Locale/ test suites will execute *after* + * setlocale(LC_ALL, TESTS_ZEND_LOCALE_FORMAT_SETLOCALE); + * Primarily, this switches certain PHP functions to emit "localized" output, + * including the built-in "to string" for integer and float conversions. + * Thus, a locale of 'fr_FR' yields number-to-string conversions in a + * localized form with the decimal place separator chosen via: + * setlocale(LC_ALL, 'fr_FR@euro'); + */ +//define('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE', 'fr'); +//define('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE', 'fr_FR@euro'); +defined('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE') || define('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE', false); + +/** + * Zend_Date tests + * + * If the BCMATH_ENABLED property below is false, all arithmetic + * operations will use ordinary PHP math operators and functions. + * Otherwise, the bcmath functions will be used for unlimited precision. + * + * If the EXTENDED_COVERAGE property below is false, most of the I18N + * unit tests will not be computed... this speeds tests up to 80 minutes + * when doing reports. * + * Edit TestConfiguration.php, not TestConfiguration.php.dist. + */ +defined('TESTS_ZEND_LOCALE_BCMATH_ENABLED') || define('TESTS_ZEND_LOCALE_BCMATH_ENABLED', true); +defined('TESTS_ZEND_I18N_EXTENDED_COVERAGE') || define('TESTS_ZEND_I18N_EXTENDED_COVERAGE', true); + +/** + * Zend_Mail_Storage tests + * + * TESTS_ZEND_MAIL_SERVER_TESTDIR and TESTS_ZEND_MAIL_SERVER_FORMAT are used for POP3 and IMAP tests. + * TESTS_ZEND_MAIL_SERVER_FORMAT is the format your test mail server uses: 'mbox' or 'maildir'. The mail + * storage for the user specified in your POP3 or IMAP tests should be TESTS_ZEND_MAIL_SERVER_TESTDIR. Be + * careful: it's cleared before copying the files. If you want to copy the files manually set the dir + * to null (or anything == null). + * + * TESTS_ZEND_MAIL_TEMPDIR is used for testing write operations in local storages. If not set (== null) + * tempnam() is used. + */ +defined('TESTS_ZEND_MAIL_SERVER_TESTDIR') || define('TESTS_ZEND_MAIL_SERVER_TESTDIR', null); +defined('TESTS_ZEND_MAIL_SERVER_FORMAT') || define('TESTS_ZEND_MAIL_SERVER_FORMAT', 'mbox'); +defined('TESTS_ZEND_MAIL_TEMPDIR') || define('TESTS_ZEND_MAIL_TEMPDIR', null); + +/** + * Zend_Mail_Storage_Pop3 / Zend_Mail_Transport_Pop3 + * + * IMPORTANT: you need to copy tests/Zend/Mail/_files/test.mbox to your mail + * if you haven't set TESTS_ZEND_MAIL_SERVER_TESTDIR + */ +defined('TESTS_ZEND_MAIL_POP3_ENABLED') || define('TESTS_ZEND_MAIL_POP3_ENABLED', false); +defined('TESTS_ZEND_MAIL_POP3_HOST') || define('TESTS_ZEND_MAIL_POP3_HOST', 'localhost'); +defined('TESTS_ZEND_MAIL_POP3_USER') || define('TESTS_ZEND_MAIL_POP3_USER', 'test'); +defined('TESTS_ZEND_MAIL_POP3_PASSWORD') || define('TESTS_ZEND_MAIL_POP3_PASSWORD', ''); +// test SSL connections if enabled in your test server +defined('TESTS_ZEND_MAIL_POP3_SSL') || define('TESTS_ZEND_MAIL_POP3_SSL', true); +defined('TESTS_ZEND_MAIL_POP3_TLS') || define('TESTS_ZEND_MAIL_POP3_TLS', true); +// WRONG_PORT should be an existing server port, +// INVALID_PORT should be a non existing (each on defined host) +defined('TESTS_ZEND_MAIL_POP3_WRONG_PORT') || define('TESTS_ZEND_MAIL_POP3_WRONG_PORT', 80); +defined('TESTS_ZEND_MAIL_POP3_INVALID_PORT') || define('TESTS_ZEND_MAIL_POP3_INVALID_PORT', 3141); + +/** + * Zend_Mail_Storage_Imap / Zend_Mail_Transport_Imap + * + * IMPORTANT: you need to copy tests/Zend/Mail/_files/test.mbox to your mail + * if you haven't set TESTS_ZEND_MAIL_SERVER_TESTDIR + */ +defined('TESTS_ZEND_MAIL_IMAP_ENABLED') || define('TESTS_ZEND_MAIL_IMAP_ENABLED', false); +defined('TESTS_ZEND_MAIL_IMAP_HOST') || define('TESTS_ZEND_MAIL_IMAP_HOST', 'localhost'); +defined('TESTS_ZEND_MAIL_IMAP_USER') || define('TESTS_ZEND_MAIL_IMAP_USER', 'test'); +defined('TESTS_ZEND_MAIL_IMAP_PASSWORD') || define('TESTS_ZEND_MAIL_IMAP_PASSWORD', ''); +// test SSL connections if enabled in your test server +defined('TESTS_ZEND_MAIL_IMAP_SSL') || define('TESTS_ZEND_MAIL_IMAP_SSL', true); +defined('TESTS_ZEND_MAIL_IMAP_TLS') || define('TESTS_ZEND_MAIL_IMAP_TLS', true); +// WRONG_PORT should be an existing server port, +// INVALID_PORT should be a non-existing (each on defined host) +defined('TESTS_ZEND_MAIL_IMAP_WRONG_PORT') || define('TESTS_ZEND_MAIL_IMAP_WRONG_PORT', 80); +defined('TESTS_ZEND_MAIL_IMAP_INVALID_PORT') || define('TESTS_ZEND_MAIL_IMAP_INVALID_PORT', 3141); + + +/** + * Zend_Mail_Storage_Maildir test + * + * Before enabling this test you have to unpack messages.tar in + * Zend/Mail/_files/test.maildir/cur/ and remove the tar for this test to work. + * That's because the messages files have a colon in the filename and that's a + * forbidden character on Windows. + */ +defined('TESTS_ZEND_MAIL_MAILDIR_ENABLED') || define('TESTS_ZEND_MAIL_MAILDIR_ENABLED', false); + +/** + * Zend_Mail_Transport_Smtp + * + * @todo TO be implemented + */ +defined('TESTS_ZEND_MAIL_SMTP_ENABLED') || define('TESTS_ZEND_MAIL_SMTP_ENABLED', false); +defined('TESTS_ZEND_MAIL_SMTP_HOST') || define('TESTS_ZEND_MAIL_SMTP_HOST', 'localhost'); +defined('TESTS_ZEND_MAIL_SMTP_PORT') || define('TESTS_ZEND_MAIL_SMTP_PORT', 25); +defined('TESTS_ZEND_MAIL_SMTP_USER') || define('TESTS_ZEND_MAIL_SMTP_USER', 'testuser'); +defined('TESTS_ZEND_MAIL_SMTP_PASSWORD') || define('TESTS_ZEND_MAIL_SMTP_PASSWORD', 'testpassword'); +defined('TESTS_ZEND_MAIL_SMTP_AUTH') || define('TESTS_ZEND_MAIL_SMTP_AUTH', false); +// AUTH can be set to false or a string of AUTH method (e.g. LOGIN, PLAIN, CRAMMD5 or DIGESTMD5) + +/** + * Zend_Queue Test Configuration constants + * + * The Zend_Queue_Adapter_Db constant should be a JSON-encoded string + * representing a configuration object for Zend_Db::factory(). For example: + * { + * type: "pdo_mysql", + * host: "127.0.0.1", + * port: 3306, + * username: "queue", + * password: "queue", + * dbname: "queue" + * } + * + * The PlatformJobQueue adapter expects two parameters, the host and password. + * The HOST string should include both the host and port (typically 10003): + * 127.0.0.1:10003 + * When running tests against PlatformJobQueue, it's best to do so where + * Platform is installed on localhost and has maximum workers set to 20 + * (default is 5); do so with this zend.ini setting: + * zend_jq.max_num_of_request_workers=20 + * + * Selectively define the below in order to run tests for them. + */ +defined('TESTS_ZEND_QUEUE_ACTIVEMQ_ENABLED') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_ENABLED', false); +defined('TESTS_ZEND_QUEUE_ACTIVEMQ_SCHEME') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_SCHEME', false); +defined('TESTS_ZEND_QUEUE_ACTIVEMQ_HOST') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_HOST', false); +defined('TESTS_ZEND_QUEUE_ACTIVEMQ_PORT') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_PORT', false); +defined('TESTS_ZEND_QUEUE_DB_ENABLED') || define('TESTS_ZEND_QUEUE_DB_ENABLED', false); +defined('TESTS_ZEND_QUEUE_DB') || define('TESTS_ZEND_QUEUE_DB', false); +defined('TESTS_ZEND_QUEUE_MEMCACHEQ_ENABLED') || define('TESTS_ZEND_QUEUE_MEMCACHEQ_ENABLED', false); +defined('TESTS_ZEND_QUEUE_MEMCACHEQ_HOST') || define('TESTS_ZEND_QUEUE_MEMCACHEQ_HOST', false); +defined('TESTS_ZEND_QUEUE_MEMCACHEQ_PORT') || define('TESTS_ZEND_QUEUE_MEMCACHEQ_PORT', false); +defined('TESTS_ZEND_QUEUE_PLATFORMJQ_ENABLED') || define('TESTS_ZEND_QUEUE_PLATFORMJQ_ENABLED', false); +defined('TESTS_ZEND_QUEUE_PLATFORMJQ_HOST') || define('TESTS_ZEND_QUEUE_PLATFORMJQ_HOST', false); +defined('TESTS_ZEND_QUEUE_PLATFORMJQ_PASS') || define('TESTS_ZEND_QUEUE_PLATFORMJQ_PASS', false); + + +/** + * Zend\Service\AgileZen online tests + */ +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_ENABLED',false); +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_APIKEY','insert the API key'); +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_PROJECT_ID','insert the project id'); +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_STORY_ID','insert the story id'); +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_INVITE_EMAIL','insert email for invitation'); +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_INVITE_ROLE_ID','insert role id for invitation'); +define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_MEMBER_NAME','insert the member name to add to the project'); + + +/** + * Zend_Service_Amazon online tests + */ +defined('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ACCESSKEYID') || define('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ACCESSKEYID', 'Enter AWSAccessKeyId here'); +defined('TESTS_ZEND_SERVICE_AMAZON_ONLINE_SECRETKEY') || define('TESTS_ZEND_SERVICE_AMAZON_ONLINE_SECRETKEY', 'Enter AWSSecretKey here'); +defined('TESTS_ZEND_SERVICE_AMAZON_EC2_IMAGE_ID') || define('TESTS_ZEND_SERVICE_AMAZON_EC2_IMAGE_ID', 'zftestamazonimageid'); +defined('TESTS_ZEND_SERVICE_AMAZON_EC2_ZONE') || define('TESTS_ZEND_SERVICE_AMAZON_EC2_ZONE', 'us-east-1'); +defined('TESTS_ZEND_SERVICE_AMAZON_EC2_SECURITY_GROUP') || define('TESTS_ZEND_SERVICE_AMAZON_EC2_SECURITY_GROUP', 'default'); +defined('TESTS_ZEND_SERVICE_AMAZON_S3_BUCKET') || define('TESTS_ZEND_SERVICE_AMAZON_S3_BUCKET', 'zftestamazons3bucket'); +defined('TESTS_ZEND_SERVICE_AMAZON_SQS_QUEUE') || define('TESTS_ZEND_SERVICE_AMAZON_SQS_QUEUE', 'zftestamazonsqsqueuename'); + +/** + * Zend_Service_Delicious tests + */ +defined('TESTS_ZEND_SERVICE_DELICIOUS_ENABLED') || define('TESTS_ZEND_SERVICE_DELICIOUS_ENABLED', false); + +/** + * Zend_Service_DeveloperGarden tests + * Setup your Username and Password to test this Service + */ +defined('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_LOGIN') || define('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_LOGIN', 'ZF_Username'); +defined('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_PASSWORD') || define('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_PASSWORD', 'ZF_Password'); + +/** + * Zend_Service_Flickr online tests + */ +defined('TESTS_ZEND_SERVICE_FLICKR_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_FLICKR_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_FLICKR_ONLINE_APIKEY') || define('TESTS_ZEND_SERVICE_FLICKR_ONLINE_APIKEY', 'Enter API key here'); + +/** + * Zend_Service_GoGrid offline tests + */ + +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_KEY') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_KEY','insert key here'); +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SECRET') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SECRET','insert secret here'); +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_NAME') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_NAME','test-zf'); +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IMAGE') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IMAGE','insert image name here'); +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_RAM') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_RAM','insert ram name here'); +defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IP') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IP','insert ip here'); + +/** + * Zend\Service\LiveDocx configuration + * + * Define username and password in order to run unit tests for LiveDocx web services. + * + * phpunit/phpunit will typically work. + */ +defined('TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME') || define('TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME', false); +defined('TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD', false); + +/** + * Zend\Service\LiveDocx premium configuration + * + * Define username, password, WSDL in order to run unit tests for premium LiveDocx web services. + */ +defined('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_USERNAME') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_USERNAME', false); +defined('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_PASSWORD') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_PASSWORD', false); +defined('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_WSDL') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_WSDL', false); + +/** + * Zend_Service_Rackspace tests + */ +defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_USER') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_USER', 'Enter key here'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_KEY') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_KEY', 'Enter secret here'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_REGION') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_REGION', 'USA'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_CONTAINER_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_CONTAINER_NAME', 'zf-unit-test'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_OBJECT_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_OBJECT_NAME','zf-object-test'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NAME', 'zf-unit-test'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGEID') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGEID', '49'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NEW_IMAGEID') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NEW_IMAGEID', '49'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_FLAVORID') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_FLAVORID', '1'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGE_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGE_NAME', 'ZFunitTestImage'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_SHARED_IP_GROUP_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_SHARED_IP_GROUP_NAME', 'ZFgroupIP'); +defined('TESTS_ZEND_SERVICE_RACKSPACE_TIMEOUT') || define('TESTS_ZEND_SERVICE_RACKSPACE_TIMEOUT', 60); + +/** + * Zend_Service_ReCaptcha tests + */ +defined('TESTS_ZEND_SERVICE_RECAPTCHA_ENABLED') || define('TESTS_ZEND_SERVICE_RECAPTCHA_ENABLED', false); +defined('TESTS_ZEND_SERVICE_RECAPTCHA_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_RECAPTCHA_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_RECAPTCHA_PUBLIC_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_PUBLIC_KEY', 'public key'); +defined('TESTS_ZEND_SERVICE_RECAPTCHA_PRIVATE_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_PRIVATE_KEY', 'private key'); +defined('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PUBLIC_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PUBLIC_KEY', 'public mailhide key'); +defined('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PRIVATE_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PRIVATE_KEY', 'private mailhide key'); + +/** + * Zend_Service_Simpy tests + */ +defined('TESTS_ZEND_SERVICE_SIMPY_ENABLED') || define('TESTS_ZEND_SERVICE_SIMPY_ENABLED', false); +defined('TESTS_ZEND_SERVICE_SIMPY_USERNAME') || define('TESTS_ZEND_SERVICE_SIMPY_USERNAME', 'syapizend'); +defined('TESTS_ZEND_SERVICE_SIMPY_PASSWORD') || define('TESTS_ZEND_SERVICE_SIMPY_PASSWORD', 'mgt37ge'); + +/** + * Zend_Service_SlideShare tests + */ +defined('TESTS_ZEND_SERVICE_SLIDESHARE_USERNAME') || define('TESTS_ZEND_SERVICE_SLIDESHARE_USERNAME', ''); +defined('TESTS_ZEND_SERVICE_SLIDESHARE_PASSWORD') || define('TESTS_ZEND_SERVICE_SLIDESHARE_PASSWORD', ''); +defined('TESTS_ZEND_SERVICE_SLIDESHARE_SHAREDSECRET') || define('TESTS_ZEND_SERVICE_SLIDESHARE_SHAREDSECRET', ''); +defined('TESTS_ZEND_SERVICE_SLIDESHARE_APIKEY') || define('TESTS_ZEND_SERVICE_SLIDESHARE_APIKEY', ''); + +// The slide show ID to retrieve during tests +defined('TESTS_ZEND_SERVICE_SLIDESHARE_SLIDESHOWID') || define('TESTS_ZEND_SERVICE_SLIDESHARE_SLIDESHOWID', 0); + +// The tag to retrieve during tests +defined('TESTS_ZEND_SERVICE_SLIDESHARE_TAG') || define('TESTS_ZEND_SERVICE_SLIDESHARE_TAG', 'zend'); + +// The group to retrieve during tests +defined('TESTS_ZEND_SERVICE_SLIDESHARE_GROUP') || define('TESTS_ZEND_SERVICE_SLIDESHARE_GROUP', ''); + +/** + * Zend_Service_Twitter tests + * + * ONLINE_ENABLED indicates whether or not to run tests requiring a network + * connection. + * + * TWITTER_USER and TWITTER_PASS are valid Twitter credentials you wish to use + * when testing. + */ +defined('TESTS_ZEND_SERVICE_TWITTER_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_TWITTER_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_TWITTER_USER') || define('TESTS_ZEND_SERVICE_TWITTER_USER', 'zftestuser'); +defined('TESTS_ZEND_SERVICE_TWITTER_PASS') || define('TESTS_ZEND_SERVICE_TWITTER_PASS', 'zftestuser'); + +/** + * Zend_Service_WindowsAzure tests + */ + +/** + * Online + */ + +define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_ACCOUNTNAME',''); +define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_ACCOUNTKEY',''); +define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_TABLE_HOST',''); +define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_STORAGE_PROXY_HOST',''); +define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_STORAGE_PROXY_PORT',''); +define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_STORAGE_PROXY_CREDENTIALS',''); + +/** + * Proxy settings + */ +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_USEPROXY') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_USEPROXY', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY', ''); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_PORT') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_PORT', '8080'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_CREDENTIALS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_CREDENTIALS', ''); + +/** + * Azure hosts + */ +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_DEV', '127.0.0.1:10000'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_DEV', '127.0.0.1:10001'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_DEV', '127.0.0.1:10002'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_PROD', 'blob.core.windows.net'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_PROD', 'queue.core.windows.net'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_PROD', 'table.core.windows.net'); + +/** + * Credentials + */ +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_DEV', 'devstoreaccount1'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_DEV', 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=='); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_PROD', 'phpazure'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_PROD', 'I+ebYPcIDB6BsmfAe6pJSpOw8oXA6jMBZv1BEZcSPRqTpldt44refCl65YpKJqcBOiD21Lxsj8d6Ah8Oc2/gKA=='); + +/** + * Blob storage tests + */ +// Enable this tests only when you have a working account +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNTESTS', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNONPROD', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNLARGEBLOB') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNLARGEBLOB', true); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_CONTAINER_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_CONTAINER_PREFIX', 'phpazuretestblob'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSTREAM_CONTAINER_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSTREAM_CONTAINER_PREFIX', 'phpazureteststream'); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSA_CONTAINER_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSA_CONTAINER_PREFIX', 'phpazuretestshared'); + +/** + * Table storage tests + */ +// Enable this tests only when you have a working account +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNTESTS', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNONPROD', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_TABLENAME_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_TABLENAME_PREFIX', 'phpazuretesttable'); + +/** + * Queue storage tests + */ +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNTESTS', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNONPROD', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_PREFIX', 'phpazuretestqueue'); + +/** + * SessionHandler tests + */ +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNTESTS', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNONPROD', false); +defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_TABLENAME_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_TABLENAME_PREFIX', 'phpazuretestsession'); + +/** + * Zend_Service_Yahoo online tests + */ +defined('TESTS_ZEND_SERVICE_YAHOO_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_YAHOO_ONLINE_ENABLED', false); +defined('TESTS_ZEND_SERVICE_YAHOO_ONLINE_APPID') || define('TESTS_ZEND_SERVICE_YAHOO_ONLINE_APPID', 'Enter APPID here'); + +/** + * Zend_Soap_AutoDiscover scenario tests for complex objects and wsdl generation + * + * Copy all the files of zf/tests/Zend/Soap/_files/fulltests into a directory + * that can be reached by webserver and enter the base uri to this directory + * into the variable. The test "Zend_Soap_AutoDiscover_OnlineTest" makes use + * of the servers and AutoDiscover feature. + * + * NOTE: Make sure the servers are using the correct Zend Framework copy, + * when having more than one version installed and include paths are changing. + */ +defined('TESTS_ZEND_SOAP_AUTODISCOVER_ONLINE_SERVER_BASEURI') || define('TESTS_ZEND_SOAP_AUTODISCOVER_ONLINE_SERVER_BASEURI', false); + +/** + * Zend_Uri tests + * + * Setting CRASH_TEST_ENABLED to true will enable some tests that may + * potentially crash PHP on some systems, due to very deep-nesting regular + * expressions. + * + * Only do this if you know what you are doing! + */ +defined('TESTS_ZEND_URI_CRASH_TEST_ENABLED') || define('TESTS_ZEND_URI_CRASH_TEST_ENABLED', false); + +/** + * Zend_Validate tests + * + * Set ONLINE_ENABLED if you wish to run validators that require network + * connectivity. + */ +defined('TESTS_ZEND_VALIDATE_ONLINE_ENABLED') || define('TESTS_ZEND_VALIDATE_ONLINE_ENABLED', false); + +/** + * PHPUnit Code Coverage / Test Report + */ +defined('TESTS_GENERATE_REPORT') || define('TESTS_GENERATE_REPORT', false); +defined('TESTS_GENERATE_REPORT_TARGET') || define('TESTS_GENERATE_REPORT_TARGET', '/path/to/target'); + From 2b52673c96ad568fc47e9d78fbae2c8cbf252bed Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 4 Apr 2012 00:32:21 +0200 Subject: [PATCH 24/62] Making the run-tests.sh script executable --- .travis/run-tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .travis/run-tests.sh diff --git a/.travis/run-tests.sh b/.travis/run-tests.sh old mode 100644 new mode 100755 From e07e12e5060e6f92081034c0f95ed9b7381cecc9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 4 Apr 2012 20:56:26 +0200 Subject: [PATCH 25/62] Moving travis test configuration This way it is more obvious to the committer changing test configuration that also travis config should be changed --- .travis/TestConfiguration.php | 825 ---------------------------------- 1 file changed, 825 deletions(-) delete mode 100644 .travis/TestConfiguration.php diff --git a/.travis/TestConfiguration.php b/.travis/TestConfiguration.php deleted file mode 100644 index fd8947049..000000000 --- a/.travis/TestConfiguration.php +++ /dev/null @@ -1,825 +0,0 @@ - test disabling output buffering in - * dispatcher - */ -defined('TESTS_ZEND_CONTROLLER_DISPATCHER_OB') || define('TESTS_ZEND_CONTROLLER_DISPATCHER_OB', false); - -/** - * Zend_Crypt related constantes - * - * TESTS_ZEND_CRYPT_OPENSSL_CONF => location of an openssl.cnf file for use - * with RSA encryption - */ -defined('TESTS_ZEND_CRYPT_OPENSSL_CONF') || define('TESTS_ZEND_CRYPT_OPENSSL_CONF', false); - -/** - * Zend_Db_Adapter_Pdo_Mysql and Zend_Db_Adapter_Mysqli - * - * There are separate properties to enable tests for the PDO_MYSQL adapter and - * the native Mysqli adapters, but the other properties are shared between the - * two MySQL-related Zend_Db adapters. - */ -defined('TESTS_ZEND_DB_ADAPTER_PDO_MYSQL_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_MYSQL_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_MYSQLI_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_MYSQLI_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_MYSQL_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_HOSTNAME', '127.0.0.1'); -defined('TESTS_ZEND_DB_ADAPTER_MYSQL_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_USERNAME', null); -defined('TESTS_ZEND_DB_ADAPTER_MYSQL_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_PASSWORD', null); -defined('TESTS_ZEND_DB_ADAPTER_MYSQL_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_DATABASE', 'test'); -defined('TESTS_ZEND_DB_ADAPTER_MYSQL_PORT') || define('TESTS_ZEND_DB_ADAPTER_MYSQL_PORT', 3306); - -/** - * Zend_Db_Adapter_Pdo_Sqlite - * - * Username and password are irrelevant for SQLite. - */ -defined('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_PDO_SQLITE_DATABASE', ':memory:'); - -/** - * Zend_Db_Adapter_Pdo_Mssql - * - * Note that you need to patch your ntwdblib.dll, the one that - * comes with PHP does not work. See user comments at - * http://us2.php.net/manual/en/ref.mssql.php - */ -defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_HOSTNAME', '127.0.0.1'); -defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_USERNAME', null); -defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_PASSWORD', null); -defined('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_PDO_MSSQL_DATABASE', 'test'); - -/** - * Zend_Db_Adapter_Pdo_Pgsql - */ -defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_HOSTNAME', '127.0.0.1'); -defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_USERNAME', null); -defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_PASSWORD', null); -defined('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_PDO_PGSQL_DATABASE', 'postgres'); - -/** - * Zend_Db_Adapter_Oracle and Zend_Db_Adapter_Pdo_Oci - * - * There are separate properties to enable tests for the PDO_OCI adapter and - * the native Oracle adapter, but the other properties are shared between the - * two Oracle-related Zend_Db adapters. - */ -defined('TESTS_ZEND_DB_ADAPTER_PDO_OCI_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_OCI_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_ORACLE_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_ORACLE_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_HOSTNAME', '127.0.0.1'); -defined('TESTS_ZEND_DB_ADAPTER_ORACLE_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_USERNAME', null); -defined('TESTS_ZEND_DB_ADAPTER_ORACLE_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_PASSWORD', null); -defined('TESTS_ZEND_DB_ADAPTER_ORACLE_SID') || define('TESTS_ZEND_DB_ADAPTER_ORACLE_SID', 'xe'); - -/** - * Zend_Db_Adapter_Db2 and Zend_Db_Adapter_Pdo_Ibm - * There are separate properties to enable tests for the PDO_IBM adapter and - * the native DB2 adapter, but the other properties are shared between the - * two related Zend_Db adapters. - */ -defined('TESTS_ZEND_DB_ADAPTER_PDO_IBM_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_PDO_IBM_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_DB2_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_DB2_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_DB2_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_DB2_HOSTNAME', '127.0.0.1'); -defined('TESTS_ZEND_DB_ADAPTER_DB2_PORT') || define('TESTS_ZEND_DB_ADAPTER_DB2_PORT', 50000); -defined('TESTS_ZEND_DB_ADAPTER_DB2_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_DB2_USERNAME', null); -defined('TESTS_ZEND_DB_ADAPTER_DB2_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_DB2_PASSWORD', null); -defined('TESTS_ZEND_DB_ADAPTER_DB2_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_DB2_DATABASE', 'sample'); - -/** - * Zend_Db_Adapter_Sqlsrv - * Note: Make sure that you create the "test" database and set a - * username and password - * - */ -defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_ENABLED') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_ENABLED', false); -defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_HOSTNAME') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_HOSTNAME', 'localhost\SQLEXPRESS'); -defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_USERNAME') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_USERNAME', null); -defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_PASSWORD') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_PASSWORD', null); -defined('TESTS_ZEND_DB_ADAPTER_SQLSRV_DATABASE') || define('TESTS_ZEND_DB_ADAPTER_SQLSRV_DATABASE', 'test'); - -/** - * Zend_Feed_Reader tests - * - * If the ONLINE_ENABLED property is false, only tests that can be executed - * without network connectivity are run; when enabled, all tests will run. - */ -defined('TESTS_ZEND_FEED_READER_ONLINE_ENABLED') || define('TESTS_ZEND_FEED_READER_ONLINE_ENABLED', false); - -/** - * Zend_Gdata tests - * - * If the ONLINE_ENABLED property is false, only tests that can be executed with - * a mock HTTP client are run. No request is sent to the Google Gdata servers. - * If ONLINE_ENABLED is true, some tests may make requests to the remote - * servers. This does not work if you are running tests on a disconnected - * client host. Also, the tests may show as failures if the Google servers - * cannot be reached or if they do not respond for another reason. - * - * If the CLIENTLOGIN_ENABLED property below is false, the authenticated - * tests are reported Skipped in the test run. Set this property to true - * to enable tests that require ClientLogin authentication. Enter your - * Google login credentials in the EMAIL and PASSWORD properties below. - * - * Edit TestConfiguration.php, not TestConfiguration.php.dist. - * Never commit plaintext passwords to the source code repository. - * - * Note: the GData tests currently require that the TZID env variable - * be set or the timezone otherwise configured. You'll see errors from the - * tests if this is not the case. - */ -defined('TESTS_ZEND_GDATA_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_ONLINE_ENABLED', false); -defined('TESTS_ZEND_GDATA_CLIENTLOGIN_ENABLED') || define('TESTS_ZEND_GDATA_CLIENTLOGIN_ENABLED', false); - -/* - * The credentials provided here should be only for a TEST account. - * Data for various services in this account may be added to, updated, - * or deleted based upon the actions of these test accounts. - */ -defined('TESTS_ZEND_GDATA_CLIENTLOGIN_EMAIL') || define('TESTS_ZEND_GDATA_CLIENTLOGIN_EMAIL', 'example@example.com'); -defined('TESTS_ZEND_GDATA_CLIENTLOGIN_PASSWORD') || define('TESTS_ZEND_GDATA_CLIENTLOGIN_PASSWORD', 'password'); - -/* - * This is the ID of a blank blog. There is no need to have - * any content in this blog. Also, blogs can only be used - * several times for the purpose of these test cases before - * they must be deleted and recreated. Otherwise, the tests - * will start failing, as posts to Blogger will return a 201 Created - * response even though the entry was not posted to the blog. - * This problem is being investigated. - */ -defined('TESTS_ZEND_GDATA_BLOGGER_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_BLOGGER_ONLINE_ENABLED', false); -defined('TESTS_ZEND_GDATA_BLOG_ID') || define('TESTS_ZEND_GDATA_BLOG_ID', '1111111111111111111'); - -/* - * This is the key for a spreadsheet with data only in the first row of - * the spreadsheet. The strings 'a1', 'b1', 'c1', 'd1' should be in the - * corresponding cell locations. - */ -defined('TESTS_ZEND_GDATA_SPREADSHEETS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_SPREADSHEETS_ONLINE_ENABLED', false); -defined('TESTS_ZEND_GDATA_SPREADSHEETS_SPREADSHEETKEY') || define('TESTS_ZEND_GDATA_SPREADSHEETS_SPREADSHEETKEY', 'o01111111111111111111.1111111111111111111'); -defined('TESTS_ZEND_GDATA_SPREADSHEETS_WORKSHEETID') || define('TESTS_ZEND_GDATA_SPREADSHEETS_WORKSHEETID', 'default'); - -/* - * This indicates that online tests for the Google Calendar API should - * be performed. The default calendar will be used. - */ -defined('TESTS_ZEND_GDATA_CALENDAR_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_CALENDAR_ONLINE_ENABLED', false); - -/* - * This is the fully-qualified domain name for a domiain hosted using - * Google Apps. This domain must be registered with Google Apps and - * have API access enabled. This should be a TEST domain only. - */ -defined('TESTS_ZEND_GDATA_GAPPS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_GAPPS_ONLINE_ENABLED', false); -defined('TESTS_ZEND_GDATA_GAPPS_DOMAIN') || define('TESTS_ZEND_GDATA_GAPPS_DOMAIN', 'example.com.invalid'); -defined('TESTS_ZEND_GDATA_GAPPS_EMAIL') || define('TESTS_ZEND_GDATA_GAPPS_EMAIL', 'example@example.com'); -defined('TESTS_ZEND_GDATA_GAPPS_PASSWORD') || define('TESTS_ZEND_GDATA_GAPPS_PASSWORD', 'password'); - -/* - * This is the ONLINE_ENABLED property for Google Base. - */ -defined('TESTS_ZEND_GDATA_GBASE_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_GBASE_ONLINE_ENABLED', false); - -/* - * This indicates that online tests for the Books Search data API - * should be performed. - */ -defined('TESTS_ZEND_GDATA_BOOKS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_BOOKS_ONLINE_ENABLED', false); - -/* - * This indicates that online tests for the YouTube data API should - * be performed. - */ -defined('TESTS_ZEND_GDATA_YOUTUBE_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_YOUTUBE_ONLINE_ENABLED', false); - -/* - * This is the username to use for retrieving subscriptions, etc - */ -defined('TESTS_ZEND_GDATA_YOUTUBE_ACCOUNT') || define('TESTS_ZEND_GDATA_YOUTUBE_ACCOUNT', 'zfgdata'); - -/* - * This is the developer key to access the YouTube API - */ -defined('TESTS_ZEND_GDATA_YOUTUBE_DEVELOPER_KEY') || define('TESTS_ZEND_GDATA_YOUTUBE_DEVELOPER_KEY', 'your_developer_key_here'); - -/* - * This is the client ID to access the YouTube API - */ -defined('TESTS_ZEND_GDATA_YOUTUBE_CLIENT_ID') || define('TESTS_ZEND_GDATA_YOUTUBE_CLIENT_ID', 'ZF_UnitTests_unknown'); - -/* - * This indicates that online tests for the Google Documents API should - * be performed. - */ -defined('TESTS_ZEND_GDATA_DOCS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_DOCS_ONLINE_ENABLED', false); - -/* - * This indicates that online tests for the GData Photos API should - * be performed. - */ -defined('TESTS_ZEND_GDATA_PHOTOS_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_PHOTOS_ONLINE_ENABLED', false); - -/* - * This indicates that online tests for the Google Health API should - * be performed. - */ -defined('TESTS_ZEND_GDATA_HEALTH_ONLINE_ENABLED') || define('TESTS_ZEND_GDATA_HEALTH_ONLINE_ENABLED', false); - -/** - * Zend_Http_Client tests - * - * To enable the dynamic Zend_Http_Client tests, you will need to symbolically - * link or copy the files in tests/Zend/Http/Client/_files to a directory - * under your web server(s) document root and set this constant to point to the - * URL of this directory. - */ -defined('TESTS_ZEND_HTTP_CLIENT_BASEURI') || define('TESTS_ZEND_HTTP_CLIENT_BASEURI', false); - -/** - * Zend_Http_Client_Proxy tests - * - * HTTP proxy to be used for testing the Proxy adapter. Set to a string of - * the form 'host:port'. Set to null to skip HTTP proxy tests. - */ -defined('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY') || define('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY', false); -defined('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_USER') || define('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_USER', ''); -defined('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_PASS') || define('TESTS_ZEND_HTTP_CLIENT_HTTP_PROXY_PASS', ''); - -/** - * Zend_Loader_Autoloader multi-version support tests - * - * ENABLED: whether or not to run the multi-version tests - * PATH: path to a directory containing multiple ZF version installs - * LATEST: most recent ZF version in the PATH - * e.g., "1.9.2" - * LATEST_MAJOR: most recent ZF major version in the PATH to test against - * e.g., "1.9.2" - * LATEST_MINOR: most recent ZF minor version in the PATH to test against - * e.g., "1.8.4PL1" - * SPECIFIC: specific ZF version in the PATH to test against - * e.g., "1.7.6" - * As an example, consider the following tree: - * ZendFramework/ - * |-- 1.9.2 - * |-- ZendFramework-1.9.1-minimal - * |-- 1.8.4PL1 - * |-- 1.8.4 - * |-- ZendFramework-1.8.3 - * |-- 1.7.8 - * |-- 1.7.7 - * |-- 1.7.6 - * You would then set the value of "LATEST" and "LATEST_MAJOR" to "1.9.2", and - * could choose between "1.9.2", "1.8.4PL1", and "1.7.8" for "LATEST_MINOR", - * and any version number for "SPECIFIC". "PATH" would point to the parent - * "ZendFramework" directory. - */ -defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_ENABLED') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_ENABLED', false); -defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_PATH') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_PATH', false); -defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST', false); -defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MAJOR') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MAJOR', false); -defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MINOR') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_LATEST_MINOR', false); -defined('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_SPECIFIC') || define('TESTS_ZEND_LOADER_AUTOLOADER_MULTIVERSION_SPECIFIC', false); - -/** - * Zend_Ldap online tests - */ -defined('TESTS_ZEND_LDAP_ONLINE_ENABLED') || define('TESTS_ZEND_LDAP_ONLINE_ENABLED', false); - -/* These largely map to the options described in the Zend_Ldap and - * Zend_Auth_Adapter_Ldap documentation. - * - * Example Configuration for Active Directory: - * HOST: dc1.w.net - * USE_START_TLS: true - * USE_SSL: false - * USERNAME: CN=User 1,CN=Users,DC=w,DC=net - * PRINCIPAL_NAME: user1@w.net - * LDAP_PASSWORD: pass1 - * BASE_DN: CN=Users,DC=w,DC=net - * DOMAIN_NAME: w.net - * ACCOUNT_DOMAIN_NAME_SHORT: W - * ALT_USERNAME: user2 - * ALT_DN: CN=User 2,CN=Users,DC=w,DC=net - * ALT_PASSWORD: pass2 - * - * Example Configuration for OpenLDAP - * HOST: s0.foo.net - * USERNAME: CN=user1,DC=foo,DC=net - * PRINCIPAL_NAME: user1@foo.net - * LDAP_PASSWORD: pass1 - * BIND_REQUIRES_DN: true - * BASE_DN: OU=Sales,DC=w,DC=net - * DOMAIN_NAME: foo.net - * ACCOUNT_DOMAIN_NAME_SHORT: FOO - * ALT_USERNAME: abaker - * ALT_DN: CN=Alice Baker,OU=Sales,DC=foo,DC=net - * ALT_PASSWORD: apass - */ -defined('TESTS_ZEND_LDAP_HOST') || define('TESTS_ZEND_LDAP_HOST', 'localhost'); -//defined('TESTS_ZEND_LDAP_PORT') || define('TESTS_ZEND_LDAP_PORT', 389); -defined('TESTS_ZEND_LDAP_USE_START_TLS') || define('TESTS_ZEND_LDAP_USE_START_TLS', true); -//defined('TESTS_ZEND_LDAP_USE_SSL') || define('TESTS_ZEND_LDAP_USE_SSL', false); -defined('TESTS_ZEND_LDAP_USERNAME') || define('TESTS_ZEND_LDAP_USERNAME', 'CN=someUser,DC=example,DC=com'); -defined('TESTS_ZEND_LDAP_PRINCIPAL_NAME') || define('TESTS_ZEND_LDAP_PRINCIPAL_NAME', 'someUser@example.com'); -defined('TESTS_ZEND_LDAP_PASSWORD') || define('TESTS_ZEND_LDAP_PASSWORD', null); -defined('TESTS_ZEND_LDAP_BIND_REQUIRES_DN') || define('TESTS_ZEND_LDAP_BIND_REQUIRES_DN', true); -defined('TESTS_ZEND_LDAP_BASE_DN') || define('TESTS_ZEND_LDAP_BASE_DN', 'OU=Sales,DC=example,DC=com'); -//defined('TESTS_ZEND_LDAP_ACCOUNT_FILTER_FORMAT') || define('TESTS_ZEND_LDAP_ACCOUNT_FILTER_FORMAT', '(&(objectClass=posixAccount)(uid=%s))'); -defined('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME') || define('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME', 'example.com'); -defined('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME_SHORT') || define('TESTS_ZEND_LDAP_ACCOUNT_DOMAIN_NAME_SHORT', 'EXAMPLE'); -defined('TESTS_ZEND_LDAP_ALT_USERNAME') || define('TESTS_ZEND_LDAP_ALT_USERNAME', 'anotherUser'); -defined('TESTS_ZEND_LDAP_ALT_DN') || define('TESTS_ZEND_LDAP_ALT_DN', 'CN=Another User,OU=Sales,DC=example,DC=com'); -defined('TESTS_ZEND_LDAP_ALT_PASSWORD') || define('TESTS_ZEND_LDAP_ALT_PASSWORD', null); // Used in Zend_Auth_Adapter_Ldap tests -//(defined('TESTS_ZEND_LDAP_WRITEABLE_SUBTREE') || define('TESTS_ZEND_LDAP_WRITEABLE_SUBTREE', 'OU=Test,OU=Sales,DC=example,DC=com'); - -/** - * Zend_Locale tests - * - * If the TESTS_ZEND_LOCALE_FORMAT_SETLOCALE property below is a valid, - * locally recognized locale (try "locale -a"), then all tests in - * tests/Zend/Locale/ test suites will execute *after* - * setlocale(LC_ALL, TESTS_ZEND_LOCALE_FORMAT_SETLOCALE); - * Primarily, this switches certain PHP functions to emit "localized" output, - * including the built-in "to string" for integer and float conversions. - * Thus, a locale of 'fr_FR' yields number-to-string conversions in a - * localized form with the decimal place separator chosen via: - * setlocale(LC_ALL, 'fr_FR@euro'); - */ -//define('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE', 'fr'); -//define('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE', 'fr_FR@euro'); -defined('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE') || define('TESTS_ZEND_LOCALE_FORMAT_SETLOCALE', false); - -/** - * Zend_Date tests - * - * If the BCMATH_ENABLED property below is false, all arithmetic - * operations will use ordinary PHP math operators and functions. - * Otherwise, the bcmath functions will be used for unlimited precision. - * - * If the EXTENDED_COVERAGE property below is false, most of the I18N - * unit tests will not be computed... this speeds tests up to 80 minutes - * when doing reports. * - * Edit TestConfiguration.php, not TestConfiguration.php.dist. - */ -defined('TESTS_ZEND_LOCALE_BCMATH_ENABLED') || define('TESTS_ZEND_LOCALE_BCMATH_ENABLED', true); -defined('TESTS_ZEND_I18N_EXTENDED_COVERAGE') || define('TESTS_ZEND_I18N_EXTENDED_COVERAGE', true); - -/** - * Zend_Mail_Storage tests - * - * TESTS_ZEND_MAIL_SERVER_TESTDIR and TESTS_ZEND_MAIL_SERVER_FORMAT are used for POP3 and IMAP tests. - * TESTS_ZEND_MAIL_SERVER_FORMAT is the format your test mail server uses: 'mbox' or 'maildir'. The mail - * storage for the user specified in your POP3 or IMAP tests should be TESTS_ZEND_MAIL_SERVER_TESTDIR. Be - * careful: it's cleared before copying the files. If you want to copy the files manually set the dir - * to null (or anything == null). - * - * TESTS_ZEND_MAIL_TEMPDIR is used for testing write operations in local storages. If not set (== null) - * tempnam() is used. - */ -defined('TESTS_ZEND_MAIL_SERVER_TESTDIR') || define('TESTS_ZEND_MAIL_SERVER_TESTDIR', null); -defined('TESTS_ZEND_MAIL_SERVER_FORMAT') || define('TESTS_ZEND_MAIL_SERVER_FORMAT', 'mbox'); -defined('TESTS_ZEND_MAIL_TEMPDIR') || define('TESTS_ZEND_MAIL_TEMPDIR', null); - -/** - * Zend_Mail_Storage_Pop3 / Zend_Mail_Transport_Pop3 - * - * IMPORTANT: you need to copy tests/Zend/Mail/_files/test.mbox to your mail - * if you haven't set TESTS_ZEND_MAIL_SERVER_TESTDIR - */ -defined('TESTS_ZEND_MAIL_POP3_ENABLED') || define('TESTS_ZEND_MAIL_POP3_ENABLED', false); -defined('TESTS_ZEND_MAIL_POP3_HOST') || define('TESTS_ZEND_MAIL_POP3_HOST', 'localhost'); -defined('TESTS_ZEND_MAIL_POP3_USER') || define('TESTS_ZEND_MAIL_POP3_USER', 'test'); -defined('TESTS_ZEND_MAIL_POP3_PASSWORD') || define('TESTS_ZEND_MAIL_POP3_PASSWORD', ''); -// test SSL connections if enabled in your test server -defined('TESTS_ZEND_MAIL_POP3_SSL') || define('TESTS_ZEND_MAIL_POP3_SSL', true); -defined('TESTS_ZEND_MAIL_POP3_TLS') || define('TESTS_ZEND_MAIL_POP3_TLS', true); -// WRONG_PORT should be an existing server port, -// INVALID_PORT should be a non existing (each on defined host) -defined('TESTS_ZEND_MAIL_POP3_WRONG_PORT') || define('TESTS_ZEND_MAIL_POP3_WRONG_PORT', 80); -defined('TESTS_ZEND_MAIL_POP3_INVALID_PORT') || define('TESTS_ZEND_MAIL_POP3_INVALID_PORT', 3141); - -/** - * Zend_Mail_Storage_Imap / Zend_Mail_Transport_Imap - * - * IMPORTANT: you need to copy tests/Zend/Mail/_files/test.mbox to your mail - * if you haven't set TESTS_ZEND_MAIL_SERVER_TESTDIR - */ -defined('TESTS_ZEND_MAIL_IMAP_ENABLED') || define('TESTS_ZEND_MAIL_IMAP_ENABLED', false); -defined('TESTS_ZEND_MAIL_IMAP_HOST') || define('TESTS_ZEND_MAIL_IMAP_HOST', 'localhost'); -defined('TESTS_ZEND_MAIL_IMAP_USER') || define('TESTS_ZEND_MAIL_IMAP_USER', 'test'); -defined('TESTS_ZEND_MAIL_IMAP_PASSWORD') || define('TESTS_ZEND_MAIL_IMAP_PASSWORD', ''); -// test SSL connections if enabled in your test server -defined('TESTS_ZEND_MAIL_IMAP_SSL') || define('TESTS_ZEND_MAIL_IMAP_SSL', true); -defined('TESTS_ZEND_MAIL_IMAP_TLS') || define('TESTS_ZEND_MAIL_IMAP_TLS', true); -// WRONG_PORT should be an existing server port, -// INVALID_PORT should be a non-existing (each on defined host) -defined('TESTS_ZEND_MAIL_IMAP_WRONG_PORT') || define('TESTS_ZEND_MAIL_IMAP_WRONG_PORT', 80); -defined('TESTS_ZEND_MAIL_IMAP_INVALID_PORT') || define('TESTS_ZEND_MAIL_IMAP_INVALID_PORT', 3141); - - -/** - * Zend_Mail_Storage_Maildir test - * - * Before enabling this test you have to unpack messages.tar in - * Zend/Mail/_files/test.maildir/cur/ and remove the tar for this test to work. - * That's because the messages files have a colon in the filename and that's a - * forbidden character on Windows. - */ -defined('TESTS_ZEND_MAIL_MAILDIR_ENABLED') || define('TESTS_ZEND_MAIL_MAILDIR_ENABLED', false); - -/** - * Zend_Mail_Transport_Smtp - * - * @todo TO be implemented - */ -defined('TESTS_ZEND_MAIL_SMTP_ENABLED') || define('TESTS_ZEND_MAIL_SMTP_ENABLED', false); -defined('TESTS_ZEND_MAIL_SMTP_HOST') || define('TESTS_ZEND_MAIL_SMTP_HOST', 'localhost'); -defined('TESTS_ZEND_MAIL_SMTP_PORT') || define('TESTS_ZEND_MAIL_SMTP_PORT', 25); -defined('TESTS_ZEND_MAIL_SMTP_USER') || define('TESTS_ZEND_MAIL_SMTP_USER', 'testuser'); -defined('TESTS_ZEND_MAIL_SMTP_PASSWORD') || define('TESTS_ZEND_MAIL_SMTP_PASSWORD', 'testpassword'); -defined('TESTS_ZEND_MAIL_SMTP_AUTH') || define('TESTS_ZEND_MAIL_SMTP_AUTH', false); -// AUTH can be set to false or a string of AUTH method (e.g. LOGIN, PLAIN, CRAMMD5 or DIGESTMD5) - -/** - * Zend_Queue Test Configuration constants - * - * The Zend_Queue_Adapter_Db constant should be a JSON-encoded string - * representing a configuration object for Zend_Db::factory(). For example: - * { - * type: "pdo_mysql", - * host: "127.0.0.1", - * port: 3306, - * username: "queue", - * password: "queue", - * dbname: "queue" - * } - * - * The PlatformJobQueue adapter expects two parameters, the host and password. - * The HOST string should include both the host and port (typically 10003): - * 127.0.0.1:10003 - * When running tests against PlatformJobQueue, it's best to do so where - * Platform is installed on localhost and has maximum workers set to 20 - * (default is 5); do so with this zend.ini setting: - * zend_jq.max_num_of_request_workers=20 - * - * Selectively define the below in order to run tests for them. - */ -defined('TESTS_ZEND_QUEUE_ACTIVEMQ_ENABLED') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_ENABLED', false); -defined('TESTS_ZEND_QUEUE_ACTIVEMQ_SCHEME') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_SCHEME', false); -defined('TESTS_ZEND_QUEUE_ACTIVEMQ_HOST') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_HOST', false); -defined('TESTS_ZEND_QUEUE_ACTIVEMQ_PORT') || define('TESTS_ZEND_QUEUE_ACTIVEMQ_PORT', false); -defined('TESTS_ZEND_QUEUE_DB_ENABLED') || define('TESTS_ZEND_QUEUE_DB_ENABLED', false); -defined('TESTS_ZEND_QUEUE_DB') || define('TESTS_ZEND_QUEUE_DB', false); -defined('TESTS_ZEND_QUEUE_MEMCACHEQ_ENABLED') || define('TESTS_ZEND_QUEUE_MEMCACHEQ_ENABLED', false); -defined('TESTS_ZEND_QUEUE_MEMCACHEQ_HOST') || define('TESTS_ZEND_QUEUE_MEMCACHEQ_HOST', false); -defined('TESTS_ZEND_QUEUE_MEMCACHEQ_PORT') || define('TESTS_ZEND_QUEUE_MEMCACHEQ_PORT', false); -defined('TESTS_ZEND_QUEUE_PLATFORMJQ_ENABLED') || define('TESTS_ZEND_QUEUE_PLATFORMJQ_ENABLED', false); -defined('TESTS_ZEND_QUEUE_PLATFORMJQ_HOST') || define('TESTS_ZEND_QUEUE_PLATFORMJQ_HOST', false); -defined('TESTS_ZEND_QUEUE_PLATFORMJQ_PASS') || define('TESTS_ZEND_QUEUE_PLATFORMJQ_PASS', false); - - -/** - * Zend\Service\AgileZen online tests - */ -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_ENABLED',false); -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_APIKEY','insert the API key'); -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_PROJECT_ID','insert the project id'); -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_STORY_ID','insert the story id'); -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_INVITE_EMAIL','insert email for invitation'); -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_INVITE_ROLE_ID','insert role id for invitation'); -define('TESTS_ZEND_SERVICE_AGILEZEN_ONLINE_MEMBER_NAME','insert the member name to add to the project'); - - -/** - * Zend_Service_Amazon online tests - */ -defined('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ACCESSKEYID') || define('TESTS_ZEND_SERVICE_AMAZON_ONLINE_ACCESSKEYID', 'Enter AWSAccessKeyId here'); -defined('TESTS_ZEND_SERVICE_AMAZON_ONLINE_SECRETKEY') || define('TESTS_ZEND_SERVICE_AMAZON_ONLINE_SECRETKEY', 'Enter AWSSecretKey here'); -defined('TESTS_ZEND_SERVICE_AMAZON_EC2_IMAGE_ID') || define('TESTS_ZEND_SERVICE_AMAZON_EC2_IMAGE_ID', 'zftestamazonimageid'); -defined('TESTS_ZEND_SERVICE_AMAZON_EC2_ZONE') || define('TESTS_ZEND_SERVICE_AMAZON_EC2_ZONE', 'us-east-1'); -defined('TESTS_ZEND_SERVICE_AMAZON_EC2_SECURITY_GROUP') || define('TESTS_ZEND_SERVICE_AMAZON_EC2_SECURITY_GROUP', 'default'); -defined('TESTS_ZEND_SERVICE_AMAZON_S3_BUCKET') || define('TESTS_ZEND_SERVICE_AMAZON_S3_BUCKET', 'zftestamazons3bucket'); -defined('TESTS_ZEND_SERVICE_AMAZON_SQS_QUEUE') || define('TESTS_ZEND_SERVICE_AMAZON_SQS_QUEUE', 'zftestamazonsqsqueuename'); - -/** - * Zend_Service_Delicious tests - */ -defined('TESTS_ZEND_SERVICE_DELICIOUS_ENABLED') || define('TESTS_ZEND_SERVICE_DELICIOUS_ENABLED', false); - -/** - * Zend_Service_DeveloperGarden tests - * Setup your Username and Password to test this Service - */ -defined('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_LOGIN') || define('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_LOGIN', 'ZF_Username'); -defined('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_PASSWORD') || define('TESTS_ZEND_SERVICE_DEVELOPERGARDEN_ONLINE_PASSWORD', 'ZF_Password'); - -/** - * Zend_Service_Flickr online tests - */ -defined('TESTS_ZEND_SERVICE_FLICKR_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_FLICKR_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_FLICKR_ONLINE_APIKEY') || define('TESTS_ZEND_SERVICE_FLICKR_ONLINE_APIKEY', 'Enter API key here'); - -/** - * Zend_Service_GoGrid offline tests - */ - -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_KEY') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_KEY','insert key here'); -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SECRET') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SECRET','insert secret here'); -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_NAME') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_NAME','test-zf'); -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IMAGE') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IMAGE','insert image name here'); -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_RAM') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_RAM','insert ram name here'); -defined('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IP') || define('TESTS_ZEND_SERVICE_GOGRID_ONLINE_SERVER_IP','insert ip here'); - -/** - * Zend\Service\LiveDocx configuration - * - * Define username and password in order to run unit tests for LiveDocx web services. - * - * phpunit/phpunit will typically work. - */ -defined('TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME') || define('TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME', false); -defined('TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD', false); - -/** - * Zend\Service\LiveDocx premium configuration - * - * Define username, password, WSDL in order to run unit tests for premium LiveDocx web services. - */ -defined('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_USERNAME') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_USERNAME', false); -defined('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_PASSWORD') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_PASSWORD', false); -defined('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_WSDL') || define('TESTS_ZEND_SERVICE_LIVEDOCX_PREMIUM_WSDL', false); - -/** - * Zend_Service_Rackspace tests - */ -defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_USER') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_USER', 'Enter key here'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_KEY') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_KEY', 'Enter secret here'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_REGION') || define('TESTS_ZEND_SERVICE_RACKSPACE_ONLINE_REGION', 'USA'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_CONTAINER_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_CONTAINER_NAME', 'zf-unit-test'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_OBJECT_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_OBJECT_NAME','zf-object-test'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NAME', 'zf-unit-test'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGEID') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGEID', '49'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NEW_IMAGEID') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_NEW_IMAGEID', '49'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_FLAVORID') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_FLAVORID', '1'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGE_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_IMAGE_NAME', 'ZFunitTestImage'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_SHARED_IP_GROUP_NAME') || define('TESTS_ZEND_SERVICE_RACKSPACE_SERVER_SHARED_IP_GROUP_NAME', 'ZFgroupIP'); -defined('TESTS_ZEND_SERVICE_RACKSPACE_TIMEOUT') || define('TESTS_ZEND_SERVICE_RACKSPACE_TIMEOUT', 60); - -/** - * Zend_Service_ReCaptcha tests - */ -defined('TESTS_ZEND_SERVICE_RECAPTCHA_ENABLED') || define('TESTS_ZEND_SERVICE_RECAPTCHA_ENABLED', false); -defined('TESTS_ZEND_SERVICE_RECAPTCHA_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_RECAPTCHA_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_RECAPTCHA_PUBLIC_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_PUBLIC_KEY', 'public key'); -defined('TESTS_ZEND_SERVICE_RECAPTCHA_PRIVATE_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_PRIVATE_KEY', 'private key'); -defined('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PUBLIC_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PUBLIC_KEY', 'public mailhide key'); -defined('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PRIVATE_KEY') || define('TESTS_ZEND_SERVICE_RECAPTCHA_MAILHIDE_PRIVATE_KEY', 'private mailhide key'); - -/** - * Zend_Service_Simpy tests - */ -defined('TESTS_ZEND_SERVICE_SIMPY_ENABLED') || define('TESTS_ZEND_SERVICE_SIMPY_ENABLED', false); -defined('TESTS_ZEND_SERVICE_SIMPY_USERNAME') || define('TESTS_ZEND_SERVICE_SIMPY_USERNAME', 'syapizend'); -defined('TESTS_ZEND_SERVICE_SIMPY_PASSWORD') || define('TESTS_ZEND_SERVICE_SIMPY_PASSWORD', 'mgt37ge'); - -/** - * Zend_Service_SlideShare tests - */ -defined('TESTS_ZEND_SERVICE_SLIDESHARE_USERNAME') || define('TESTS_ZEND_SERVICE_SLIDESHARE_USERNAME', ''); -defined('TESTS_ZEND_SERVICE_SLIDESHARE_PASSWORD') || define('TESTS_ZEND_SERVICE_SLIDESHARE_PASSWORD', ''); -defined('TESTS_ZEND_SERVICE_SLIDESHARE_SHAREDSECRET') || define('TESTS_ZEND_SERVICE_SLIDESHARE_SHAREDSECRET', ''); -defined('TESTS_ZEND_SERVICE_SLIDESHARE_APIKEY') || define('TESTS_ZEND_SERVICE_SLIDESHARE_APIKEY', ''); - -// The slide show ID to retrieve during tests -defined('TESTS_ZEND_SERVICE_SLIDESHARE_SLIDESHOWID') || define('TESTS_ZEND_SERVICE_SLIDESHARE_SLIDESHOWID', 0); - -// The tag to retrieve during tests -defined('TESTS_ZEND_SERVICE_SLIDESHARE_TAG') || define('TESTS_ZEND_SERVICE_SLIDESHARE_TAG', 'zend'); - -// The group to retrieve during tests -defined('TESTS_ZEND_SERVICE_SLIDESHARE_GROUP') || define('TESTS_ZEND_SERVICE_SLIDESHARE_GROUP', ''); - -/** - * Zend_Service_Twitter tests - * - * ONLINE_ENABLED indicates whether or not to run tests requiring a network - * connection. - * - * TWITTER_USER and TWITTER_PASS are valid Twitter credentials you wish to use - * when testing. - */ -defined('TESTS_ZEND_SERVICE_TWITTER_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_TWITTER_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_TWITTER_USER') || define('TESTS_ZEND_SERVICE_TWITTER_USER', 'zftestuser'); -defined('TESTS_ZEND_SERVICE_TWITTER_PASS') || define('TESTS_ZEND_SERVICE_TWITTER_PASS', 'zftestuser'); - -/** - * Zend_Service_WindowsAzure tests - */ - -/** - * Online - */ - -define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_ACCOUNTNAME',''); -define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_ACCOUNTKEY',''); -define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_TABLE_HOST',''); -define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_STORAGE_PROXY_HOST',''); -define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_STORAGE_PROXY_PORT',''); -define('TESTS_ZEND_SERVICE_WINDOWSAZURE_ONLINE_STORAGE_PROXY_CREDENTIALS',''); - -/** - * Proxy settings - */ -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_USEPROXY') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_USEPROXY', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY', ''); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_PORT') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_PORT', '8080'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_CREDENTIALS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_PROXY_CREDENTIALS', ''); - -/** - * Azure hosts - */ -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_DEV', '127.0.0.1:10000'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_DEV', '127.0.0.1:10001'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_DEV', '127.0.0.1:10002'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_HOST_PROD', 'blob.core.windows.net'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_HOST_PROD', 'queue.core.windows.net'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_HOST_PROD', 'table.core.windows.net'); - -/** - * Credentials - */ -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_DEV', 'devstoreaccount1'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_DEV') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_DEV', 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=='); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_ACCOUNT_PROD', 'phpazure'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_PROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_STORAGE_KEY_PROD', 'I+ebYPcIDB6BsmfAe6pJSpOw8oXA6jMBZv1BEZcSPRqTpldt44refCl65YpKJqcBOiD21Lxsj8d6Ah8Oc2/gKA=='); - -/** - * Blob storage tests - */ -// Enable this tests only when you have a working account -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNTESTS', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNONPROD', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNLARGEBLOB') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_RUNLARGEBLOB', true); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_CONTAINER_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOB_CONTAINER_PREFIX', 'phpazuretestblob'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSTREAM_CONTAINER_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSTREAM_CONTAINER_PREFIX', 'phpazureteststream'); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSA_CONTAINER_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_BLOBSA_CONTAINER_PREFIX', 'phpazuretestshared'); - -/** - * Table storage tests - */ -// Enable this tests only when you have a working account -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNTESTS', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_RUNONPROD', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_TABLENAME_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_TABLE_TABLENAME_PREFIX', 'phpazuretesttable'); - -/** - * Queue storage tests - */ -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNTESTS', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_RUNONPROD', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_QUEUE_PREFIX', 'phpazuretestqueue'); - -/** - * SessionHandler tests - */ -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNTESTS') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNTESTS', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNONPROD') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_RUNONPROD', false); -defined('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_TABLENAME_PREFIX') || define('TESTS_ZEND_SERVICE_WINDOWSAZURE_SESSIONHANDLER_TABLENAME_PREFIX', 'phpazuretestsession'); - -/** - * Zend_Service_Yahoo online tests - */ -defined('TESTS_ZEND_SERVICE_YAHOO_ONLINE_ENABLED') || define('TESTS_ZEND_SERVICE_YAHOO_ONLINE_ENABLED', false); -defined('TESTS_ZEND_SERVICE_YAHOO_ONLINE_APPID') || define('TESTS_ZEND_SERVICE_YAHOO_ONLINE_APPID', 'Enter APPID here'); - -/** - * Zend_Soap_AutoDiscover scenario tests for complex objects and wsdl generation - * - * Copy all the files of zf/tests/Zend/Soap/_files/fulltests into a directory - * that can be reached by webserver and enter the base uri to this directory - * into the variable. The test "Zend_Soap_AutoDiscover_OnlineTest" makes use - * of the servers and AutoDiscover feature. - * - * NOTE: Make sure the servers are using the correct Zend Framework copy, - * when having more than one version installed and include paths are changing. - */ -defined('TESTS_ZEND_SOAP_AUTODISCOVER_ONLINE_SERVER_BASEURI') || define('TESTS_ZEND_SOAP_AUTODISCOVER_ONLINE_SERVER_BASEURI', false); - -/** - * Zend_Uri tests - * - * Setting CRASH_TEST_ENABLED to true will enable some tests that may - * potentially crash PHP on some systems, due to very deep-nesting regular - * expressions. - * - * Only do this if you know what you are doing! - */ -defined('TESTS_ZEND_URI_CRASH_TEST_ENABLED') || define('TESTS_ZEND_URI_CRASH_TEST_ENABLED', false); - -/** - * Zend_Validate tests - * - * Set ONLINE_ENABLED if you wish to run validators that require network - * connectivity. - */ -defined('TESTS_ZEND_VALIDATE_ONLINE_ENABLED') || define('TESTS_ZEND_VALIDATE_ONLINE_ENABLED', false); - -/** - * PHPUnit Code Coverage / Test Report - */ -defined('TESTS_GENERATE_REPORT') || define('TESTS_GENERATE_REPORT', false); -defined('TESTS_GENERATE_REPORT_TARGET') || define('TESTS_GENERATE_REPORT_TARGET', '/path/to/target'); - From 9d47a65a3432246796cc8f82bac70883f5847193 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 4 Apr 2012 21:28:23 +0200 Subject: [PATCH 26/62] Re-enabling components as of @weierophinney suggestions --- .travis/skipped-components | 16 ---------------- .travis/tested-components | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/.travis/skipped-components b/.travis/skipped-components index 7d38e2de2..6ccd1be13 100644 --- a/.travis/skipped-components +++ b/.travis/skipped-components @@ -1,27 +1,11 @@ Zend/Amf Zend/Barcode -Zend/Cache -Zend/Code Zend/Date -Zend/Docbook Zend/Feed -Zend/File -Zend/Filter -Zend/GData -Zend/Json -Zend/Locale -Zend/Mail -Zend/Mime -Zend/Navigation -Zend/OpenId Zend/Paginator Zend/Queue -Zend/RegistryTest.php Zend/Service Zend/Session -Zend/Soap Zend/Test Zend/Translator -Zend/Validator Zend/Wildfire -Zend/XmlRpc diff --git a/.travis/tested-components b/.travis/tested-components index 34047abc0..da5b101b4 100644 --- a/.travis/tested-components +++ b/.travis/tested-components @@ -1,40 +1,54 @@ -Zend/Mvc -Zend/View Zend/Acl Zend/Authentication +Zend/Cache Zend/Captcha Zend/Cloud +Zend/Code Zend/Config Zend/Console Zend/Crypt Zend/Currency Zend/Db Zend/Di +Zend/Docbook Zend/Dojo Zend/Dom Zend/EventManager +Zend/File +Zend/Filter Zend/Form +Zend/GData Zend/Http Zend/InfoCard +Zend/Json Zend/Ldap Zend/Loader +Zend/Locale Zend/Log +Zend/Mail Zend/Markup Zend/Measure Zend/Memory +Zend/Mime Zend/Module Zend/Mvc +Zend/Navigation Zend/OAuth +Zend/OpenId Zend/Pdf Zend/ProgressBar +Zend/RegistryTest.php Zend/Rest Zend/Search Zend/Serializer Zend/Server +Zend/Soap Zend/Stdlib Zend/Tag Zend/Text Zend/TimeSync Zend/Uri +Zend/Validator Zend/VersionTest.php Zend/View +Zend/XmlRpc From 49c983cbb443e692e54b185edf02b673fde8b570 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 4 Apr 2012 22:16:58 +0200 Subject: [PATCH 27/62] Fixing exit code and output of test runner The test-runner will run all test suites and display their names anyway, then use an appropriate exit code in case of failures. Using the list of components to be tested (was using the skipped components list to be sure that the exit code of the test runner were correct). --- .travis/run-tests.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis/run-tests.sh b/.travis/run-tests.sh index 47d0c4a07..11d98cd6a 100755 --- a/.travis/run-tests.sh +++ b/.travis/run-tests.sh @@ -2,7 +2,13 @@ travisdir=$(dirname $(readlink /proc/$$/fd/255)) testdir="$travisdir/../tests" testedcomponents=(`cat "$travisdir/tested-components"`) +result=0 for tested in "${testedcomponents[@]}" - do phpunit -c $testdir/phpunit.xml $testdir/$tested + do + echo "$tested:" + phpunit -c $testdir/phpunit.xml $testdir/$tested + let "result = $result || $?" done + +exit $result \ No newline at end of file From b27fc250cea6794ba744776e247c1585734882bc Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 9 Apr 2012 11:28:58 -0500 Subject: [PATCH 28/62] [zendframework/zf2#1008] Updated test lists - Moved Session, Paginator to tested-components - Added Zend/Feed/Reader, Writer to tested-components --- .travis/skipped-components | 2 -- .travis/tested-components | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis/skipped-components b/.travis/skipped-components index 6ccd1be13..6847359d1 100644 --- a/.travis/skipped-components +++ b/.travis/skipped-components @@ -2,10 +2,8 @@ Zend/Amf Zend/Barcode Zend/Date Zend/Feed -Zend/Paginator Zend/Queue Zend/Service -Zend/Session Zend/Test Zend/Translator Zend/Wildfire diff --git a/.travis/tested-components b/.travis/tested-components index da5b101b4..330e5f196 100644 --- a/.travis/tested-components +++ b/.travis/tested-components @@ -14,6 +14,8 @@ Zend/Docbook Zend/Dojo Zend/Dom Zend/EventManager +Zend/Feed/Reader +Zend/Feed/Writer Zend/File Zend/Filter Zend/Form @@ -35,6 +37,7 @@ Zend/Mvc Zend/Navigation Zend/OAuth Zend/OpenId +Zend/Paginator Zend/Pdf Zend/ProgressBar Zend/RegistryTest.php @@ -42,6 +45,7 @@ Zend/Rest Zend/Search Zend/Serializer Zend/Server +Zend/Session Zend/Soap Zend/Stdlib Zend/Tag From 5a92a779591519f3a6451e3d3b98411aff2defed Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Tue, 17 Apr 2012 00:59:16 +0200 Subject: [PATCH 29/62] format --- src/Storage/Plugin.php | 1 - src/Storage/Plugin/AbstractPlugin.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Storage/Plugin.php b/src/Storage/Plugin.php index b4c4bf8f9..00ce3a46c 100644 --- a/src/Storage/Plugin.php +++ b/src/Storage/Plugin.php @@ -57,5 +57,4 @@ public function setOptions(Plugin\PluginOptions $options); * @return PluginOptions */ public function getOptions(); - } diff --git a/src/Storage/Plugin/AbstractPlugin.php b/src/Storage/Plugin/AbstractPlugin.php index 2850a4c59..b833144c0 100644 --- a/src/Storage/Plugin/AbstractPlugin.php +++ b/src/Storage/Plugin/AbstractPlugin.php @@ -61,5 +61,4 @@ public function getOptions() } return $this->options; } - } From e9ecc1a18a34eadf1494d4862d2d481e5b26846a Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Tue, 17 Apr 2012 01:14:33 +0200 Subject: [PATCH 30/62] added missing @param --- src/Storage/Adapter/AbstractAdapter.php | 1 + src/Storage/Plugin/ClearByFactor.php | 1 + src/Storage/Plugin/ExceptionHandler.php | 1 + src/Storage/Plugin/IgnoreUserAbort.php | 1 + src/Storage/Plugin/OptimizeByFactor.php | 1 + src/Storage/Plugin/Serializer.php | 1 + 6 files changed, 6 insertions(+) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index da9832668..e492fb0e6 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -324,6 +324,7 @@ public function hasPlugin(Plugin $plugin) * Register a plugin * * @param Plugin $plugin + * @param int $priority * @return AbstractAdapter Fluent interface * @throws Exception\LogicException */ diff --git a/src/Storage/Plugin/ClearByFactor.php b/src/Storage/Plugin/ClearByFactor.php index 05b0f75c8..836cfa12f 100644 --- a/src/Storage/Plugin/ClearByFactor.php +++ b/src/Storage/Plugin/ClearByFactor.php @@ -47,6 +47,7 @@ class ClearByFactor extends AbstractPlugin * Attach * * @param EventCollection $eventCollection + * @param int $priority * @return ClearByFactor * @throws Exception\LogicException */ diff --git a/src/Storage/Plugin/ExceptionHandler.php b/src/Storage/Plugin/ExceptionHandler.php index 44e3d7f41..5c5f31c21 100644 --- a/src/Storage/Plugin/ExceptionHandler.php +++ b/src/Storage/Plugin/ExceptionHandler.php @@ -45,6 +45,7 @@ class ExceptionHandler extends AbstractPlugin * Attach * * @param EventCollection $eventCollection + * @param int $priority * @return ExceptionHandler * @throws Exception\LogicException */ diff --git a/src/Storage/Plugin/IgnoreUserAbort.php b/src/Storage/Plugin/IgnoreUserAbort.php index 9819513d5..2324296f3 100644 --- a/src/Storage/Plugin/IgnoreUserAbort.php +++ b/src/Storage/Plugin/IgnoreUserAbort.php @@ -53,6 +53,7 @@ class IgnoreUserAbort extends AbstractPlugin * Attach * * @param EventCollection $eventCollection + * @param int $priority * @return Serializer * @throws Exception\LogicException */ diff --git a/src/Storage/Plugin/OptimizeByFactor.php b/src/Storage/Plugin/OptimizeByFactor.php index 772ec1754..851b7846f 100644 --- a/src/Storage/Plugin/OptimizeByFactor.php +++ b/src/Storage/Plugin/OptimizeByFactor.php @@ -46,6 +46,7 @@ class OptimizeByFactor extends AbstractPlugin * Attach * * @param EventCollection $eventCollection + * @param int $priority * @return OptimizeByFactor * @throws Exception\LogicException */ diff --git a/src/Storage/Plugin/Serializer.php b/src/Storage/Plugin/Serializer.php index 9dffcd11c..4345abbaa 100644 --- a/src/Storage/Plugin/Serializer.php +++ b/src/Storage/Plugin/Serializer.php @@ -54,6 +54,7 @@ class Serializer extends AbstractPlugin * Attach * * @param EventCollection $eventCollection + * @param int $priority * @return Serializer * @throws Exception\LogicException */ From f08355791f96663082724ea14f1e210c21e577ae Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Mon, 23 Apr 2012 20:30:10 +0100 Subject: [PATCH 31/62] Typo fix: messagae => message --- src/Utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils.php b/src/Utils.php index 8c3aca561..4ab240f40 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -93,7 +93,7 @@ public static function getSystemMemoryCapacity() // *nix if (false === ($meminfo = @file_get_contents('/proc/meminfo'))) { $lastErr = error_get_last(); - throw new Exception\RuntimeException("Can't read '/proc/meminfo': {$lastErr['messagae']}"); + throw new Exception\RuntimeException("Can't read '/proc/meminfo': {$lastErr['message']}"); } elseif (!preg_match_all('/(\w+):\s*(\d+\s*\w*)[\r|\n]/i', $meminfo, $matches, PREG_PATTERN_ORDER)) { throw new Exception\RuntimeException("Can't parse '/proc/meminfo'"); } From 53599fc508239cc11f4c3ca6a22a8dcfe407e68f Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Mon, 23 Apr 2012 20:31:19 +0100 Subject: [PATCH 32/62] use realpath() to ensure that test passes on Max OS X where sys_get_temp_dir() and realpath(sys_get_temp_dir()) are two different things. --- test/Storage/Adapter/FilesystemTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Storage/Adapter/FilesystemTest.php b/test/Storage/Adapter/FilesystemTest.php index f1de88c6f..19f661b3f 100644 --- a/test/Storage/Adapter/FilesystemTest.php +++ b/test/Storage/Adapter/FilesystemTest.php @@ -89,7 +89,7 @@ protected function _removeRecursive($dir) public function testNormalizeCacheDir() { - $cacheDir = $cacheDirExpected = sys_get_temp_dir(); + $cacheDir = $cacheDirExpected = realpath(sys_get_temp_dir()); if (DIRECTORY_SEPARATOR != '/') { $cacheDir = str_replace(DIRECTORY_SEPARATOR, '/', $cacheDir); From 203f6bbb240db0ce876e3ba0ffa2c2bd0237273b Mon Sep 17 00:00:00 2001 From: Gabriel Baker Date: Sat, 21 Apr 2012 22:28:24 +0100 Subject: [PATCH 33/62] Fixed un-needed use statements --- src/Exception/BadMethodCallException.php | 2 -- src/Exception/ExtensionNotLoadedException.php | 2 -- src/Exception/InvalidArgumentException.php | 2 -- src/Exception/LogicException.php | 2 -- src/Exception/OutOfCapacityException.php | 2 -- src/Exception/RuntimeException.php | 2 -- src/Exception/UnexpectedValueException.php | 2 -- src/Exception/UnsupportedMethodCallException.php | 2 -- 8 files changed, 16 deletions(-) diff --git a/src/Exception/BadMethodCallException.php b/src/Exception/BadMethodCallException.php index f36d3a306..9eab64712 100644 --- a/src/Exception/BadMethodCallException.php +++ b/src/Exception/BadMethodCallException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/ExtensionNotLoadedException.php b/src/Exception/ExtensionNotLoadedException.php index 7d2b975ef..330f773a2 100644 --- a/src/Exception/ExtensionNotLoadedException.php +++ b/src/Exception/ExtensionNotLoadedException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index f61f4c9a0..b59446342 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/LogicException.php b/src/Exception/LogicException.php index b5da1a017..6d4f4b5f3 100644 --- a/src/Exception/LogicException.php +++ b/src/Exception/LogicException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/OutOfCapacityException.php b/src/Exception/OutOfCapacityException.php index 017f14092..2dfaef98a 100644 --- a/src/Exception/OutOfCapacityException.php +++ b/src/Exception/OutOfCapacityException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index 6cb3c1fd0..432113373 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/UnexpectedValueException.php b/src/Exception/UnexpectedValueException.php index b89b01629..17d4c86dc 100644 --- a/src/Exception/UnexpectedValueException.php +++ b/src/Exception/UnexpectedValueException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache diff --git a/src/Exception/UnsupportedMethodCallException.php b/src/Exception/UnsupportedMethodCallException.php index 5337978f8..0cdf67848 100644 --- a/src/Exception/UnsupportedMethodCallException.php +++ b/src/Exception/UnsupportedMethodCallException.php @@ -20,8 +20,6 @@ namespace Zend\Cache\Exception; -use Zend\Cache\Exception\ExceptionInterface; - /** * @category Zend * @package Zend_Cache From e53dc2974894a55b8faa2f5241bddad1f06c3130 Mon Sep 17 00:00:00 2001 From: Gabriel Baker Date: Tue, 24 Apr 2012 21:42:34 +0100 Subject: [PATCH 34/62] Fixed CS issues --- src/Storage/Adapter/AdapterOptions.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Storage/Adapter/AdapterOptions.php b/src/Storage/Adapter/AdapterOptions.php index 0e31756a7..629dc87de 100644 --- a/src/Storage/Adapter/AdapterOptions.php +++ b/src/Storage/Adapter/AdapterOptions.php @@ -23,7 +23,6 @@ use ArrayObject, Zend\Cache\Exception, - Zend\Cache\Storage\Adapter, Zend\Cache\Storage\Event, Zend\Stdlib\Options; @@ -117,10 +116,10 @@ public function toArray() /** * Adapter using this instance * - * @param Adapter\AdapterInterface|null $adapter + * @param AdapterInterface|null $adapter * @return AdapterOptions */ - public function setAdapter(Adapter\AdapterInterface $adapter = null) + public function setAdapter(AdapterInterface $adapter = null) { $this->adapter = $adapter; return $this; From 8e91278e8a76be4e677ec97cd2efd516b271f87c Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 25 Apr 2012 23:09:32 +0200 Subject: [PATCH 35/62] added Zend\EventManager\EventsAware and use it instead of EventManagerAware, removed AbstractAdapter::setEventManager to not allow overwriting it --- src/Storage/Adapter/AbstractAdapter.php | 21 +++------------------ src/Storage/Adapter/AdapterOptions.php | 6 +++--- src/Storage/Capabilities.php | 4 ++-- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index d0cc0f498..1c30af08c 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -34,7 +34,7 @@ Zend\Cache\Storage\Plugin, Zend\EventManager\EventCollection, Zend\EventManager\EventManager, - Zend\EventManager\EventManagerAware; + Zend\EventManager\EventsAware; /** * @category Zend @@ -43,7 +43,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -abstract class AbstractAdapter implements Adapter, EventManagerAware +abstract class AbstractAdapter implements Adapter, EventsAware { /** * The used EventManager if any @@ -222,18 +222,6 @@ public function getCaching() /* Event/Plugin handling */ - /** - * Set event manager instance - * - * @param EventCollection $events - * @return AbstractAdapter - */ - public function setEventManager(EventCollection $events) - { - $this->events = $events; - return $this; - } - /** * Get the event manager * @@ -242,10 +230,7 @@ public function setEventManager(EventCollection $events) public function events() { if ($this->events === null) { - $this->setEventManager(new EventManager(array( - __CLASS__, - get_called_class(), - ))); + $this->events = new EventManager(array(__CLASS__, get_called_class())); } return $this->events; } diff --git a/src/Storage/Adapter/AdapterOptions.php b/src/Storage/Adapter/AdapterOptions.php index a8655a6e4..dcaa0a790 100644 --- a/src/Storage/Adapter/AdapterOptions.php +++ b/src/Storage/Adapter/AdapterOptions.php @@ -25,7 +25,7 @@ Zend\Cache\Exception, Zend\Cache\Storage\Adapter, Zend\Cache\Storage\Event, - Zend\EventManager\EventManagerAware, + Zend\EventManager\EventsAware, Zend\Stdlib\Options; /** @@ -355,7 +355,7 @@ public function getWritable() /** * Triggers an option event if this options instance has a connection to - * an adapter implements EventManagerAware. + * an adapter implements EventsAware. * * @param string $optionName * @param mixed $optionValue @@ -363,7 +363,7 @@ public function getWritable() */ protected function triggerOptionEvent($optionName, $optionValue) { - if ($this->adapter instanceof EventManagerAware) { + if ($this->adapter instanceof EventsAware) { $event = new Event('option', $this->adapter, new ArrayObject(array($optionName => $optionValue))); $this->adapter->events()->trigger($event); } diff --git a/src/Storage/Capabilities.php b/src/Storage/Capabilities.php index 95a4dd562..11a8c7c47 100644 --- a/src/Storage/Capabilities.php +++ b/src/Storage/Capabilities.php @@ -24,7 +24,7 @@ use ArrayObject, stdClass, Zend\Cache\Exception, - Zend\EventManager\EventManagerAware; + Zend\EventManager\EventsAware; /** * @category Zend @@ -572,7 +572,7 @@ protected function setCapability(stdClass $marker, $name, $value) $this->$property = $value; // trigger event - if ($this->adapter instanceof EventManagerAware) { + if ($this->adapter instanceof EventsAware) { $this->adapter->events()->trigger('capability', $this->adapter, new ArrayObject(array( $name => $value ))); From 96eae5662c7ddf01298b2a5bd18cf23d255cbebd Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Tue, 1 May 2012 06:31:33 +0100 Subject: [PATCH 36/62] Ensure that we're checking for the correct path as realpath(sys_get_temp_dir()) is different on OS X to sys_get_temp_dir() --- test/Storage/Adapter/FilesystemTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Storage/Adapter/FilesystemTest.php b/test/Storage/Adapter/FilesystemTest.php index f1de88c6f..19f661b3f 100644 --- a/test/Storage/Adapter/FilesystemTest.php +++ b/test/Storage/Adapter/FilesystemTest.php @@ -89,7 +89,7 @@ protected function _removeRecursive($dir) public function testNormalizeCacheDir() { - $cacheDir = $cacheDirExpected = sys_get_temp_dir(); + $cacheDir = $cacheDirExpected = realpath(sys_get_temp_dir()); if (DIRECTORY_SEPARATOR != '/') { $cacheDir = str_replace(DIRECTORY_SEPARATOR, '/', $cacheDir); From 51800af3e4a7fcb76b3fbf681b54f29073b30eec Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Tue, 1 May 2012 07:28:56 +0100 Subject: [PATCH 37/62] add getSystemMemoryCapacityOSX() --- src/Utils.php | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/Utils.php b/src/Utils.php index 8c3aca561..7f7eb5d1b 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -90,10 +90,15 @@ public static function getSystemMemoryCapacity() return self::getSystemMemoryCapacityWin(); } + // Darwin + if (substr(\PHP_OS, 0, 6) == 'Darwin') { + return self::getSystemMemoryCapacityOSX(); + } + // *nix if (false === ($meminfo = @file_get_contents('/proc/meminfo'))) { $lastErr = error_get_last(); - throw new Exception\RuntimeException("Can't read '/proc/meminfo': {$lastErr['messagae']}"); + throw new Exception\RuntimeException("Can't read '/proc/meminfo': {$lastErr['message']}"); } elseif (!preg_match_all('/(\w+):\s*(\d+\s*\w*)[\r|\n]/i', $meminfo, $matches, PREG_PATTERN_ORDER)) { throw new Exception\RuntimeException("Can't parse '/proc/meminfo'"); } @@ -174,6 +179,62 @@ static protected function getSystemMemoryCapacityWin() ); } + /** + * Get system memory capacity on windows systems + * + * @return array + * @throws Exception\RuntimeException + */ + static protected function getSystemMemoryCapacityOSX() + { + $total = 0; + $free = 0; + + if (!function_exists('exec')) { + throw new Exception\RuntimeException( + "Built-in function 'exec' is disabled" + ); + } else { + // sysctl will tell us the total amount of memory + $cmd = 'sysctl -n hw.memsize'; + $out = $ret = null; + $line = exec($cmd, $out, $ret); + + if ($ret) { + $out = implode("\n", $out); + throw new Exception\RuntimeException( + "Command '{$cmd}' failed" + . ", return: '{$ret}'" + . ", output: '{$out}'" + ); + } + $total = $line; + + // now work out amount used using vm_stat + $cmd = 'vm_stat | grep free'; + $out = $ret = null; + $line = exec($cmd, $out, $ret); + + if ($ret) { + $out = implode("\n", $out); + throw new Exception\RuntimeException( + "Command '{$cmd}' failed" + . ", return: '{$ret}'" + . ", output: '{$out}'" + ); + } + preg_match('/([\d]+)/', $line, $matches); + if (isset($matches[1])) { + $free = $matches[1] * 4096; + } + } + + return array( + 'total' => $total, + 'free' => $free, + ); + } + /** * Generate a hash value. * From 8a1e2d2a9ef321af69ded7e46decdb8969928d70 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 7 May 2012 12:20:17 -0500 Subject: [PATCH 38/62] [zen-27] Cache -- EM typehinting - Typehint on EventManagerInterface, not EventCollection --- src/Storage/Adapter/AbstractAdapter.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 386e86cbf..721f9fb2c 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -31,8 +31,8 @@ Zend\Cache\Storage\ExceptionEvent, Zend\Cache\Storage\PostEvent, Zend\Cache\Storage\Plugin, - Zend\EventManager\EventCollection, Zend\EventManager\EventManager, + Zend\EventManager\EventManagerInterface, Zend\EventManager\EventManagerAware; /** @@ -224,11 +224,15 @@ public function getCaching() /** * Set event manager instance * - * @param EventCollection $events + * @param EventManagerInterface $events * @return AbstractAdapter */ - public function setEventManager(EventCollection $events) + public function setEventManager(EventManagerInterface $events) { + $events->setIdentifiers(array( + __CLASS__, + get_called_class(), + )); $this->events = $events; return $this; } @@ -241,10 +245,7 @@ public function setEventManager(EventCollection $events) public function events() { if ($this->events === null) { - $this->setEventManager(new EventManager(array( - __CLASS__, - get_called_class(), - ))); + $this->setEventManager(new EventManager()); } return $this->events; } From 03facac393fa2ce280f13024a4f05fd7fc730689 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 7 May 2012 12:40:22 -0500 Subject: [PATCH 39/62] [zen-27] Update all classes that were EventManagerAware - to use EventManagerAwareInterface - also fixed some test cases that were still using setSharedCollections() to use setSharedManager() --- src/Storage/Adapter/AbstractAdapter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 721f9fb2c..277c5ca51 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -32,8 +32,8 @@ Zend\Cache\Storage\PostEvent, Zend\Cache\Storage\Plugin, Zend\EventManager\EventManager, - Zend\EventManager\EventManagerInterface, - Zend\EventManager\EventManagerAware; + Zend\EventManager\EventManagerAwareInterface, + Zend\EventManager\EventManagerInterface; /** * @category Zend @@ -42,7 +42,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -abstract class AbstractAdapter implements AdapterInterface, EventManagerAware +abstract class AbstractAdapter implements AdapterInterface, EventManagerAwareInterface { /** * The used EventManager if any From 613e32b818848708b3efed4b31607a9811445210 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 7 May 2012 13:34:18 -0500 Subject: [PATCH 40/62] [zen-27] use correct typehint in constructor - s/Adapter/Adapter\AdapterInterface/ --- src/Storage/Capabilities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Capabilities.php b/src/Storage/Capabilities.php index b477a2a0e..e7dbb17d1 100644 --- a/src/Storage/Capabilities.php +++ b/src/Storage/Capabilities.php @@ -142,7 +142,7 @@ class Capabilities * @param null|Capabilities $baseCapabilities */ public function __construct( - Adapter $adapter, + Adapter\AdapterInterface $adapter, stdClass $marker, array $capabilities = array(), Capabilities $baseCapabilities = null From 8648880b9b75837ca51fecc5c7c8bc1b82bde502 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 May 2012 21:15:12 +0200 Subject: [PATCH 41/62] renamed $eventCollection to $events --- src/Storage/Plugin/ClearByFactor.php | 22 ++++---- src/Storage/Plugin/ExceptionHandler.php | 72 ++++++++++++------------- src/Storage/Plugin/IgnoreUserAbort.php | 2 +- src/Storage/Plugin/OptimizeByFactor.php | 22 ++++---- src/Storage/Plugin/Serializer.php | 2 +- 5 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/Storage/Plugin/ClearByFactor.php b/src/Storage/Plugin/ClearByFactor.php index 78b726baa..51f3b7d0a 100644 --- a/src/Storage/Plugin/ClearByFactor.php +++ b/src/Storage/Plugin/ClearByFactor.php @@ -46,14 +46,14 @@ class ClearByFactor extends AbstractPlugin /** * Attach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @param int $priority * @return ClearByFactor * @throws Exception\LogicException */ - public function attach(EventManagerInterface $eventCollection, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1) { - $index = spl_object_hash($eventCollection); + $index = spl_object_hash($events); if (isset($this->handles[$index])) { throw new Exception\LogicException('Plugin already attached'); } @@ -62,10 +62,10 @@ public function attach(EventManagerInterface $eventCollection, $priority = 1) $this->handles[$index] = & $handles; $callback = array($this, 'clearByFactor'); - $handles[] = $eventCollection->attach('setItem.post', $callback, $priority); - $handles[] = $eventCollection->attach('setItems.post', $callback, $priority); - $handles[] = $eventCollection->attach('addItem.post', $callback, $priority); - $handles[] = $eventCollection->attach('addItems.post', $callback, $priority); + $handles[] = $events->attach('setItem.post', $callback, $priority); + $handles[] = $events->attach('setItems.post', $callback, $priority); + $handles[] = $events->attach('addItem.post', $callback, $priority); + $handles[] = $events->attach('addItems.post', $callback, $priority); return $this; } @@ -73,20 +73,20 @@ public function attach(EventManagerInterface $eventCollection, $priority = 1) /** * Detach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @return ClearByFactor * @throws Exception\LogicException */ - public function detach(EventManagerInterface $eventCollection) + public function detach(EventManagerInterface $events) { - $index = spl_object_hash($eventCollection); + $index = spl_object_hash($events); if (!isset($this->handles[$index])) { throw new Exception\LogicException('Plugin not attached'); } // detach all handles of this index foreach ($this->handles[$index] as $handle) { - $eventCollection->detach($handle); + $events->detach($handle); } // remove all detached handles diff --git a/src/Storage/Plugin/ExceptionHandler.php b/src/Storage/Plugin/ExceptionHandler.php index cc1b8af10..4e8bc202b 100644 --- a/src/Storage/Plugin/ExceptionHandler.php +++ b/src/Storage/Plugin/ExceptionHandler.php @@ -44,14 +44,14 @@ class ExceptionHandler extends AbstractPlugin /** * Attach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @param int $priority * @return ExceptionHandler * @throws Exception\LogicException */ - public function attach(EventManagerInterface $eventCollection, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1) { - $index = spl_object_hash($eventCollection); + $index = spl_object_hash($events); if (isset($this->handles[$index])) { throw new Exception\LogicException('Plugin already attached'); } @@ -61,54 +61,54 @@ public function attach(EventManagerInterface $eventCollection, $priority = 1) $this->handles[$index] = & $handles; // read - $handles[] = $eventCollection->attach('getItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('getItems.exception', $callback, $priority); + $handles[] = $events->attach('getItem.exception', $callback, $priority); + $handles[] = $events->attach('getItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('hasItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('hasItems.exception', $callback, $priority); + $handles[] = $events->attach('hasItem.exception', $callback, $priority); + $handles[] = $events->attach('hasItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('getMetadata.exception', $callback, $priority); - $handles[] = $eventCollection->attach('getMetadatas.exception', $callback, $priority); + $handles[] = $events->attach('getMetadata.exception', $callback, $priority); + $handles[] = $events->attach('getMetadatas.exception', $callback, $priority); // non-blocking - $handles[] = $eventCollection->attach('getDelayed.exception', $callback, $priority); - $handles[] = $eventCollection->attach('find.exception', $callback, $priority); + $handles[] = $events->attach('getDelayed.exception', $callback, $priority); + $handles[] = $events->attach('find.exception', $callback, $priority); - $handles[] = $eventCollection->attach('fetch.exception', $callback, $priority); - $handles[] = $eventCollection->attach('fetchAll.exception', $callback, $priority); + $handles[] = $events->attach('fetch.exception', $callback, $priority); + $handles[] = $events->attach('fetchAll.exception', $callback, $priority); // write - $handles[] = $eventCollection->attach('setItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('setItems.exception', $callback, $priority); + $handles[] = $events->attach('setItem.exception', $callback, $priority); + $handles[] = $events->attach('setItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('addItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('addItems.exception', $callback, $priority); + $handles[] = $events->attach('addItem.exception', $callback, $priority); + $handles[] = $events->attach('addItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('replaceItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('replaceItems.exception', $callback, $priority); + $handles[] = $events->attach('replaceItem.exception', $callback, $priority); + $handles[] = $events->attach('replaceItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('touchItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('touchItems.exception', $callback, $priority); + $handles[] = $events->attach('touchItem.exception', $callback, $priority); + $handles[] = $events->attach('touchItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('removeItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('removeItems.exception', $callback, $priority); + $handles[] = $events->attach('removeItem.exception', $callback, $priority); + $handles[] = $events->attach('removeItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('checkAndSetItem.exception', $callback, $priority); + $handles[] = $events->attach('checkAndSetItem.exception', $callback, $priority); // increment / decrement item(s) - $handles[] = $eventCollection->attach('incrementItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('incrementItems.exception', $callback, $priority); + $handles[] = $events->attach('incrementItem.exception', $callback, $priority); + $handles[] = $events->attach('incrementItems.exception', $callback, $priority); - $handles[] = $eventCollection->attach('decrementItem.exception', $callback, $priority); - $handles[] = $eventCollection->attach('decrementItems.exception', $callback, $priority); + $handles[] = $events->attach('decrementItem.exception', $callback, $priority); + $handles[] = $events->attach('decrementItems.exception', $callback, $priority); // clear - $handles[] = $eventCollection->attach('clear.exception', $callback, $priority); - $handles[] = $eventCollection->attach('clearByNamespace.exception', $callback, $priority); + $handles[] = $events->attach('clear.exception', $callback, $priority); + $handles[] = $events->attach('clearByNamespace.exception', $callback, $priority); // additional - $handles[] = $eventCollection->attach('optimize.exception', $callback, $priority); - $handles[] = $eventCollection->attach('getCapacity.exception', $callback, $priority); + $handles[] = $events->attach('optimize.exception', $callback, $priority); + $handles[] = $events->attach('getCapacity.exception', $callback, $priority); return $this; } @@ -116,20 +116,20 @@ public function attach(EventManagerInterface $eventCollection, $priority = 1) /** * Detach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @return ExceptionHandler * @throws Exception\LogicException */ - public function detach(EventManagerInterface $eventCollection) + public function detach(EventManagerInterface $events) { - $index = spl_object_hash($eventCollection); + $index = spl_object_hash($events); if (!isset($this->handles[$index])) { throw new Exception\LogicException('Plugin not attached'); } // detach all handles of this index foreach ($this->handles[$index] as $handle) { - $eventCollection->detach($handle); + $events->detach($handle); } // remove all detached handles diff --git a/src/Storage/Plugin/IgnoreUserAbort.php b/src/Storage/Plugin/IgnoreUserAbort.php index f3c3f4ec2..4c8703b4d 100644 --- a/src/Storage/Plugin/IgnoreUserAbort.php +++ b/src/Storage/Plugin/IgnoreUserAbort.php @@ -51,7 +51,7 @@ class IgnoreUserAbort extends AbstractPlugin /** * Attach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @param int $priority * @return Serializer * @throws Exception\LogicException diff --git a/src/Storage/Plugin/OptimizeByFactor.php b/src/Storage/Plugin/OptimizeByFactor.php index 57d967f3b..a72f24096 100644 --- a/src/Storage/Plugin/OptimizeByFactor.php +++ b/src/Storage/Plugin/OptimizeByFactor.php @@ -45,14 +45,14 @@ class OptimizeByFactor extends AbstractPlugin /** * Attach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @param int $priority * @return OptimizeByFactor * @throws Exception\LogicException */ - public function attach(EventManagerInterface $eventCollection, $priority = 1) + public function attach(EventManagerInterface $events, $priority = 1) { - $index = spl_object_hash($eventCollection); + $index = spl_object_hash($events); if (isset($this->handles[$index])) { throw new Exception\LogicException('Plugin already attached'); } @@ -61,10 +61,10 @@ public function attach(EventManagerInterface $eventCollection, $priority = 1) $this->handles[$index] = & $handles; $callback = array($this, 'optimizeByFactor'); - $handles[] = $eventCollection->attach('removeItem.post', $callback, $priority); - $handles[] = $eventCollection->attach('removeItems.post', $callback, $priority); - $handles[] = $eventCollection->attach('clear.post', $callback, $priority); - $handles[] = $eventCollection->attach('clearByNamespace.post', $callback, $priority); + $handles[] = $events->attach('removeItem.post', $callback, $priority); + $handles[] = $events->attach('removeItems.post', $callback, $priority); + $handles[] = $events->attach('clear.post', $callback, $priority); + $handles[] = $events->attach('clearByNamespace.post', $callback, $priority); return $this; } @@ -72,20 +72,20 @@ public function attach(EventManagerInterface $eventCollection, $priority = 1) /** * Detach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @return OptimizeByFactor * @throws Exception\LogicException */ - public function detach(EventManagerInterface $eventCollection) + public function detach(EventManagerInterface $events) { - $index = spl_object_hash($eventCollection); + $index = spl_object_hash($events); if (!isset($this->handles[$index])) { throw new Exception\LogicException('Plugin not attached'); } // detach all handles of this index foreach ($this->handles[$index] as $handle) { - $eventCollection->detach($handle); + $events->detach($handle); } // remove all detached handles diff --git a/src/Storage/Plugin/Serializer.php b/src/Storage/Plugin/Serializer.php index 982ff359c..3916e5eee 100644 --- a/src/Storage/Plugin/Serializer.php +++ b/src/Storage/Plugin/Serializer.php @@ -53,7 +53,7 @@ class Serializer extends AbstractPlugin /** * Attach * - * @param EventManagerInterface $eventCollection + * @param EventManagerInterface $events * @param int $priority * @return Serializer * @throws Exception\LogicException From 9515dc7ddc38d03180dec110a5a0212fdcb9747f Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 May 2012 23:43:41 +0200 Subject: [PATCH 42/62] Cache: added umask test and small code format --- src/Storage/Adapter/AbstractAdapter.php | 6 +++--- test/Storage/Adapter/FilesystemTest.php | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 9b2434678..c5987136d 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -899,13 +899,13 @@ public function setItems(array $keyValuePairs, array $options = array()) */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $result = array(); + $failedKeys = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { if (!$this->internalSetItem($normalizedKey, $value, $normalizedOptions)) { - $result[] = $normalizedKey; + $failedKeys[] = $normalizedKey; } } - return $result; + return $failedKeys; } /** diff --git a/test/Storage/Adapter/FilesystemTest.php b/test/Storage/Adapter/FilesystemTest.php index 19f661b3f..3f3d3f452 100644 --- a/test/Storage/Adapter/FilesystemTest.php +++ b/test/Storage/Adapter/FilesystemTest.php @@ -35,9 +35,12 @@ class FilesystemTest extends CommonAdapterTest { protected $_tmpCacheDir; + protected $_umask; public function setUp() { + $this->_umask = umask(); + $this->_tmpCacheDir = @tempnam(sys_get_temp_dir(), 'zend_cache_test_'); if (!$this->_tmpCacheDir) { $err = error_get_last(); @@ -47,7 +50,7 @@ public function setUp() $this->fail("Can't remove temporary cache directory-file: {$err['message']}"); } elseif (!@mkdir($this->_tmpCacheDir, 0777)) { $err = error_get_last(); - $this->fail("Can't create temporaty cache directory: {$err['message']}"); + $this->fail("Can't create temporary cache directory: {$err['message']}"); } $this->_options = new Cache\Storage\Adapter\FilesystemOptions(array( @@ -63,6 +66,11 @@ public function tearDown() { $this->_removeRecursive($this->_tmpCacheDir); + if ($this->_umask != umask()) { + umask($this->_umask); + $this->fail("Umask wasn't reset"); + } + parent::tearDown(); } From e6c72a9843bb2f8440da99b73228f7adac453476 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Tue, 8 May 2012 00:12:05 +0200 Subject: [PATCH 43/62] filesystem adapter: split logic to create the directory structure into an own method --- src/Storage/Adapter/Filesystem.php | 76 +++++++++++++----------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 1bdb76942..11f094782 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -705,24 +705,8 @@ public function replaceItems(array $keyValuePairs, array $options = array()) protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) { $baseOptions = $this->getOptions(); - $oldUmask = null; $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - - if ($baseOptions->getDirLevel() > 0) { - $path = dirname($filespec); - if (!file_exists($path)) { - $oldUmask = umask($baseOptions->getDirUmask()); - ErrorHandler::start(); - $mkdir = mkdir($path, 0777, true); - $error = ErrorHandler::stop(); - if (!$mkdir) { - umask($oldUmask); - throw new Exception\RuntimeException( - "Error creating directory '{$path}'", 0, $error - ); - } - } - } + $this->prepareDirectoryStructure($filespec); $info = null; if ($baseOptions->getReadControl()) { @@ -736,11 +720,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz // write files try { // set umask for files - if ($oldUmask !== null) { // $oldUmask could be defined on create directory - umask($baseOptions->getFileUmask()); - } else { - $oldUmask = umask($baseOptions->getFileUmask()); - } + $oldUmask = umask($baseOptions->getFileUmask()); $contents = array($filespec . '.dat' => & $value); if ($info) { @@ -796,23 +776,7 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n $contents = array(); foreach ($normalizedKeyValuePairs as $key => & $value) { $filespec = $this->getFileSpec($key, $normalizedOptions); - - // init directory level - if ($baseOptions->getDirLevel() > 0) { - $path = dirname($filespec); - if (!file_exists($path)) { - $oldUmask = ($oldUmask === null) ? umask($baseOptions->getDirUmask()) : $oldUmask; - ErrorHandler::start(); - $mkdir = mkdir($path, 0777, true); - $error = ErrorHandler::stop(); - if (!$mkdir) { - umask($oldUmask); - throw new Exception\RuntimeException( - "Error creating directory '{$path}'", 0, $error - ); - } - } - } + $this->prepareDirectoryStructure($filespec); // *.dat file $contents[$filespec . '.dat'] = & $value; @@ -836,11 +800,7 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n // write to disk try { // set umask for files - if ($oldUmask !== null) { // $oldUmask could be defined on create directory - umask($baseOptions->getFileUmask()); - } else { - $oldUmask = umask($baseOptions->getFileUmask()); - } + $oldUmask = umask($baseOptions->getFileUmask()); while ($contents) { $nonBlocking = count($contents) > 1; @@ -1710,6 +1670,34 @@ protected function getFileContent($file, $nonBlocking = false, & $wouldblock = n return $res; } + /** + * Prepares a directory structure for the given file(spec) + * using the configured directory level. + * + * @param string $file + * @return void + * @throws Exception\RuntimeException + */ + protected function prepareDirectoryStructure($file) + { + $options = $this->getOptions(); + if ($options->getDirLevel() > 0) { + $path = dirname($file); + if (!file_exists($path)) { + $oldUmask = umask($options->getDirUmask()); + ErrorHandler::start(); + $mkdir = mkdir($path, 0777, true); + $error = ErrorHandler::stop(); + umask($oldUmask); + if (!$mkdir) { + throw new Exception\RuntimeException( + "Error creating directory '{$path}'", 0, $error + ); + } + } + } + } + /** * Write content to a file * From 65aacbac3a102f45a9eee97fdd52db4b5577285b Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 9 May 2012 11:28:05 -0500 Subject: [PATCH 44/62] Remove --stderr switch from Travis test runner - Appears that it may not be necessary --- .travis/run-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/run-tests.sh b/.travis/run-tests.sh index 1ba31be7e..9334e9597 100755 --- a/.travis/run-tests.sh +++ b/.travis/run-tests.sh @@ -7,7 +7,7 @@ result=0 for tested in "${testedcomponents[@]}" do echo "$tested:" - phpunit -c $testdir/phpunit.xml --stderr $testdir/$tested + phpunit -c $testdir/phpunit.xml $testdir/$tested result=$(($result || $?)) done From c8463a3aa146996f640edd03395452e71c8b3104 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 May 2012 23:48:58 +0200 Subject: [PATCH 45/62] Updated result values in cases of catched exceptions --- src/Storage/Adapter/AbstractAdapter.php | 103 ++++++++++++------- src/Storage/ExceptionEvent.php | 43 ++------ src/Storage/PostEvent.php | 10 +- test/Storage/Adapter/AbstractAdapterTest.php | 3 +- test/Storage/Plugin/ExceptionHandlerTest.php | 8 +- 5 files changed, 85 insertions(+), 82 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 3dc823414..74a48690d 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -248,12 +248,12 @@ protected function triggerPre($eventName, ArrayObject $args) /** * Triggers the PostEvent and return the result value. * - * @param string $eventName + * @param string $eventName * @param ArrayObject $args - * @param mixed $result + * @param mixed $result * @return mixed */ - protected function triggerPost($eventName, ArrayObject $args, &$result) + protected function triggerPost($eventName, ArrayObject $args, & $result) { $postEvent = new PostEvent($eventName . '.post', $this, $args, $result); $eventRs = $this->events()->trigger($postEvent); @@ -270,15 +270,16 @@ protected function triggerPost($eventName, ArrayObject $args, &$result) * If the ExceptionEvent has the flag "throwException" enabled throw the * exception after trigger else return the result. * - * @param string $eventName + * @param string $eventName * @param ArrayObject $args - * @param \Exception $exception + * @param mixed $result + * @param \Exception $exception * @throws Exception\ExceptionInterface * @return mixed */ - protected function triggerException($eventName, ArrayObject $args, \Exception $exception) + protected function triggerException($eventName, ArrayObject $args, & $result, \Exception $exception) { - $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $exception); + $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $exception); $eventRs = $this->events()->trigger($exceptionEvent); if ($exceptionEvent->getThrowException()) { @@ -402,7 +403,8 @@ public function getItem($key, array $options = array(), & $success = null, & $ca $result = $this->internalGetItem($args['key'], $args['options'], $args['success'], $args['casToken']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -464,7 +466,8 @@ public function getItems(array $keys, array $options = array()) $result = $this->internalGetItems($args['keys'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array(); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -536,7 +539,8 @@ public function hasItem($key, array $options = array()) $result = $this->internalHasItem($args['key'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -601,7 +605,8 @@ public function hasItems(array $keys, array $options = array()) $result = $this->internalHasItems($args['keys'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array(); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -670,7 +675,8 @@ public function getMetadata($key, array $options = array()) $result = $this->internalGetMetadata($args['key'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -737,7 +743,8 @@ public function getMetadatas(array $keys, array $options = array()) $result = $this->internalGetMetadatas($args['keys'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array(); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -813,7 +820,8 @@ public function setItem($key, $value, array $options = array()) $result = $this->internalSetItem($args['key'], $args['value'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -878,7 +886,8 @@ public function setItems(array $keyValuePairs, array $options = array()) $result = $this->internalSetItems($args['keyValuePairs'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array_keys($keyValuePairs); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -953,7 +962,8 @@ public function addItem($key, $value, array $options = array()) $result = $this->internalAddItem($args['key'], $args['value'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1024,7 +1034,8 @@ public function addItems(array $keyValuePairs, array $options = array()) $result = $this->internalAddItems($args['keyValuePairs'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array_keys($keyValuePairs); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1099,7 +1110,8 @@ public function replaceItem($key, $value, array $options = array()) $result = $this->internalReplaceItem($args['key'], $args['value'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1171,7 +1183,8 @@ public function replaceItems(array $keyValuePairs, array $options = array()) $result = $this->internalReplaceItems($args['keyValuePairs'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array_keys($keyValuePairs); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1249,7 +1262,8 @@ public function checkAndSetItem($token, $key, $value, array $options = array()) $result = $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1323,7 +1337,8 @@ public function touchItem($key, array $options = array()) $result = $this->internalTouchItem($args['key'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1400,7 +1415,7 @@ public function touchItems(array $keys, array $options = array()) $result = $this->internalTouchItems($args['keys'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + return $this->triggerException(__FUNCTION__, $args, $keys, $e); } } @@ -1467,7 +1482,8 @@ public function removeItem($key, array $options = array()) $result = $this->internalRemoveItem($args['key'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1523,7 +1539,7 @@ public function removeItems(array $keys, array $options = array()) $result = $this->internalRemoveItems($args['keys'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + return $this->triggerException(__FUNCTION__, $args, $keys, $e); } } @@ -1592,7 +1608,8 @@ public function incrementItem($key, $value, array $options = array()) $result = $this->internalIncrementItem($args['key'], $args['value'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1667,7 +1684,8 @@ public function incrementItems(array $keyValuePairs, array $options = array()) $result = $this->internalIncrementItems($args['keyValuePairs'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array(); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1739,7 +1757,8 @@ public function decrementItem($key, $value, array $options = array()) $result = $this->internalDecrementItem($args['key'], $args['value'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1814,7 +1833,8 @@ public function decrementItems(array $keyValuePairs, array $options = array()) $result = $this->internalDecrementItems($args['keyValuePairs'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array(); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1898,7 +1918,8 @@ public function getDelayed(array $keys, array $options = array()) $result = $this->internalGetDelayed($args['keys'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -1995,7 +2016,8 @@ public function find($mode = self::MATCH_ACTIVE, array $options = array()) $result = $this->internalFind($args['mode'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2047,7 +2069,8 @@ public function fetch() $result = $this->internalFetch(); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2138,7 +2161,8 @@ public function fetchAll() $result = $this->internalFetchAll(); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = array(); + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2201,7 +2225,8 @@ public function clear($mode = self::MATCH_EXPIRED, array $options = array()) $result = $this->internalClear($args['mode'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2270,7 +2295,8 @@ public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = a $result = $this->internalClearByNamespace($args['mode'], $args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2332,7 +2358,8 @@ public function optimize(array $options = array()) $result = $this->internalOptimize($args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2375,7 +2402,8 @@ public function getCapabilities() $result = $this->internalGetCapabilities(); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } @@ -2420,7 +2448,8 @@ public function getCapacity(array $options = array()) $result = $this->internalGetCapacity($args['options']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { - return $this->triggerException(__FUNCTION__, $args, $e); + $result = false; + return $this->triggerException(__FUNCTION__, $args, $result, $e); } } diff --git a/src/Storage/ExceptionEvent.php b/src/Storage/ExceptionEvent.php index 6865f9490..145c0c265 100644 --- a/src/Storage/ExceptionEvent.php +++ b/src/Storage/ExceptionEvent.php @@ -31,7 +31,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class ExceptionEvent extends Event +class ExceptionEvent extends PostEvent { /** * The exception to be thrown @@ -47,28 +47,21 @@ class ExceptionEvent extends Event */ protected $throwException = true; - /** - * The result/return value - * if the exception shouldn't throw - * - * @var mixed - */ - protected $result = false; - /** * Constructor * * Accept a target and its parameters. * - * @param string $name Event name - * @param Adapter $storage + * @param string $name + * @param Adapter $storage * @param ArrayObject $params - * @param Exception $exception + * @param mixed $result + * @param Exception $exception * @return void */ - public function __construct($name, Adapter\AdapterInterface $storage, ArrayObject $params, Exception $exception) + public function __construct($name, Adapter\AdapterInterface $storage, ArrayObject $params, & $result, Exception $exception) { - parent::__construct($name, $storage, $params); + parent::__construct($name, $storage, $params, $result); $this->setException($exception); } @@ -115,26 +108,4 @@ public function getThrowException() { return $this->throwException; } - - /** - * Set the result/return value - * - * @param mixed $value - * @return ExceptionEvent - */ - public function setResult(&$value) - { - $this->result = & $value; - return $this; - } - - /** - * Get the result/return value - * - * @return mixed - */ - public function & getResult() - { - return $this->result; - } } diff --git a/src/Storage/PostEvent.php b/src/Storage/PostEvent.php index 870f1f50a..497c20bbb 100644 --- a/src/Storage/PostEvent.php +++ b/src/Storage/PostEvent.php @@ -44,13 +44,13 @@ class PostEvent extends Event * * Accept a target and its parameters. * - * @param string $name Event name - * @param Adapter $storage + * @param string $name + * @param Adapter $storage * @param ArrayObject $params - * @param mixed $result + * @param mixed $result * @return void */ - public function __construct($name, Adapter\AdapterInterface $storage, ArrayObject $params, &$result) + public function __construct($name, Adapter\AdapterInterface $storage, ArrayObject $params, & $result) { parent::__construct($name, $storage, $params); $this->setResult($result); @@ -62,7 +62,7 @@ public function __construct($name, Adapter\AdapterInterface $storage, ArrayObjec * @param mixed $value * @return PostEvent */ - public function setResult(&$value) + public function setResult(& $value) { $this->result = & $value; return $this; diff --git a/test/Storage/Adapter/AbstractAdapterTest.php b/test/Storage/Adapter/AbstractAdapterTest.php index 4cbad10cf..9d14cc996 100644 --- a/test/Storage/Adapter/AbstractAdapterTest.php +++ b/test/Storage/Adapter/AbstractAdapterTest.php @@ -250,6 +250,7 @@ public function testInternalTriggerExceptionThrowRuntimeException() $plugin = new \ZendTest\Cache\Storage\TestAsset\MockPlugin(); $this->_storage->addPlugin($plugin); + $result = null; $params = new \ArrayObject(array( 'key' => 'key1', 'value' => 'value1' @@ -260,7 +261,7 @@ public function testInternalTriggerExceptionThrowRuntimeException() $method->setAccessible(true); $this->setExpectedException('Zend\Cache\Exception\RuntimeException', 'test'); - $method->invokeArgs($this->_storage, array('setItem', $params, new Exception\RuntimeException('test'))); + $method->invokeArgs($this->_storage, array('setItem', $params, & $result, new Exception\RuntimeException('test'))); } public function testGetItemCallsInternalGetItem() diff --git a/test/Storage/Plugin/ExceptionHandlerTest.php b/test/Storage/Plugin/ExceptionHandlerTest.php index 0bfb700d9..efac4fcff 100644 --- a/test/Storage/Plugin/ExceptionHandlerTest.php +++ b/test/Storage/Plugin/ExceptionHandlerTest.php @@ -110,10 +110,11 @@ public function testOnExceptionCallCallback() }); // run onException + $result = null; $event = new ExceptionEvent('getItem.exception', $this->_adapter, new ArrayObject(array( 'key' => 'key', 'options' => array() - )), $expectedException); + )), $result, $expectedException); $this->_plugin->onException($event); $this->assertTrue( @@ -127,14 +128,15 @@ public function testDontThrowException() $this->_options->setThrowExceptions(false); // run onException + $result = 'test'; $event = new ExceptionEvent('getItem.exception', $this->_adapter, new ArrayObject(array( 'key' => 'key', 'options' => array() - )), new \Exception()); + )), $result, new \Exception()); $this->_plugin->onException($event); $this->assertFalse($event->getThrowException()); - $this->assertFalse($event->getResult()); + $this->assertSame('test', $event->getResult()); } } From 7d3cc3c46efe4573d3739a3ad370a02cfa8cb04f Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 11 May 2012 00:46:10 +0200 Subject: [PATCH 46/62] updated docblocks --- src/Storage/Adapter/AbstractAdapter.php | 60 +++++++++++----------- src/Storage/Adapter/AbstractZendServer.php | 8 +-- src/Storage/Adapter/AdapterInterface.php | 36 ++++++------- src/Storage/Adapter/Apc.php | 22 ++++---- src/Storage/Adapter/Filesystem.php | 32 ++++++------ src/Storage/Adapter/Memcached.php | 18 +++---- src/Storage/Adapter/Memory.php | 20 ++++---- src/Storage/Adapter/WinCache.php | 26 +++------- src/Storage/Adapter/ZendServerDisk.php | 2 +- src/Storage/Adapter/ZendServerShm.php | 2 +- 10 files changed, 108 insertions(+), 118 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 74a48690d..21ecea584 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -371,7 +371,7 @@ public function getPlugins() * @param array $options * @param boolean $success * @param mixed $casToken - * @return mixed Data on success and null on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface * * @triggers getItem.pre(PreEvent) @@ -421,7 +421,7 @@ public function getItem($key, array $options = array(), & $success = null, & $ca * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken - * @return mixed Data on success or null on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ abstract protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null); @@ -437,7 +437,7 @@ abstract protected function internalGetItem(& $normalizedKey, array & $normalize * * @param array $keys * @param array $options - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface * * @triggers getItems.pre(PreEvent) @@ -482,7 +482,7 @@ public function getItems(array $keys, array $options = array()) * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -576,7 +576,7 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface * * @triggers hasItems.pre(PreEvent) @@ -621,7 +621,7 @@ public function hasItems(array $keys, array $options = array()) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface */ protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) @@ -646,7 +646,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * * @param string $key * @param array $options - * @return array|boolean Metadata or false on failure + * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * * @triggers getMetadata.pre(PreEvent) @@ -691,7 +691,7 @@ public function getMetadata($key, array $options = array()) * * @param string $normalizedKey * @param array $normalizedOptions - * @return array|boolean Metadata or false on failure + * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) @@ -714,7 +714,7 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti * * @param array $keys * @param array $options - * @return array Associative array of existing cache ids and its metadata + * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface * * @triggers getMetadatas.pre(PreEvent) @@ -759,7 +759,7 @@ public function getMetadatas(array $keys, array $options = array()) * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing cache ids and its metadata + * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface */ protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) @@ -857,7 +857,7 @@ abstract protected function internalSetItem(& $normalizedKey, & $value, array & * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface * * @triggers setItems.pre(PreEvent) @@ -904,7 +904,7 @@ public function setItems(array $keyValuePairs, array $options = array()) * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -1005,7 +1005,7 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface * * @triggers addItems.pre(PreEvent) @@ -1052,7 +1052,7 @@ public function addItems(array $keyValuePairs, array $options = array()) * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -1154,7 +1154,7 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface * * @triggers replaceItems.pre(PreEvent) @@ -1201,7 +1201,7 @@ public function replaceItems(array $keyValuePairs, array $options = array()) * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalReplaceItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -1386,7 +1386,7 @@ protected function internalTouchItem(& $normalizedKey, array & $normalizedOption * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not updated keys * @throws Exception\ExceptionInterface * * @triggers touchItems.pre(PreEvent) @@ -1430,7 +1430,7 @@ public function touchItems(array $keys, array $options = array()) * * @param array $normalizedKeys * @param array $normalizedOptions - * @return boolean + * @return array Array of not updated keys * @throws Exception\ExceptionInterface */ protected function internalTouchItems(array & $normalizedKeys, array & $normalizedOptions) @@ -1510,7 +1510,7 @@ abstract protected function internalRemoveItem(& $normalizedKey, array & $normal * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not removed keys * @throws Exception\ExceptionInterface * * @triggers removeItems.pre(PreEvent) @@ -1552,7 +1552,7 @@ public function removeItems(array $keys, array $options = array()) * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) @@ -1578,7 +1578,7 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali * @param string $key * @param int $value * @param array $options - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface * * @triggers incrementItem.pre(PreEvent) @@ -1625,7 +1625,7 @@ public function incrementItem($key, $value, array $options = array()) * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -1655,7 +1655,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface * * @triggers incrementItems.pre(PreEvent) @@ -1700,7 +1700,7 @@ public function incrementItems(array $keyValuePairs, array $options = array()) * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface */ protected function internalIncrementItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -1727,7 +1727,7 @@ protected function internalIncrementItems(array & $normalizedKeyValuePairs, arra * @param string $key * @param int $value * @param array $options - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface * * @triggers decrementItem.pre(PreEvent) @@ -1774,7 +1774,7 @@ public function decrementItem($key, $value, array $options = array()) * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -1804,7 +1804,7 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface * * @triggers incrementItems.pre(PreEvent) @@ -1849,7 +1849,7 @@ public function decrementItems(array $keyValuePairs, array $options = array()) * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface */ protected function internalDecrementItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -2425,7 +2425,7 @@ protected function internalGetCapabilities() * Get storage capacity. * * @param array $options - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface * * @triggers getCapacity.pre(PreEvent) @@ -2457,7 +2457,7 @@ public function getCapacity(array $options = array()) * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ abstract protected function internalGetCapacity(array & $normalizedOptions); diff --git a/src/Storage/Adapter/AbstractZendServer.php b/src/Storage/Adapter/AbstractZendServer.php index 879d506d8..349cdb1cf 100644 --- a/src/Storage/Adapter/AbstractZendServer.php +++ b/src/Storage/Adapter/AbstractZendServer.php @@ -55,7 +55,7 @@ abstract class AbstractZendServer extends AbstractAdapter * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken - * @return mixed Data on success or false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) @@ -82,7 +82,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -131,7 +131,7 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface */ protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) @@ -162,7 +162,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array|boolean + * @return array Associative array of keys and metadata * * @triggers getMetadatas.pre(PreEvent) * @triggers getMetadatas.post(PostEvent) diff --git a/src/Storage/Adapter/AdapterInterface.php b/src/Storage/Adapter/AdapterInterface.php index e8211068a..d89071c2e 100644 --- a/src/Storage/Adapter/AdapterInterface.php +++ b/src/Storage/Adapter/AdapterInterface.php @@ -110,9 +110,9 @@ public function getOptions(); * * @param string $key * @param array $options - * @param boolesn $success + * @param boolean $success * @param mixed $casToken - * @return mixed Data on success and false on failure + * @return mixed Data on success, null on failure * @throws \Zend\Cache\Exception\ExceptionInterface */ public function getItem($key, array $options = array(), & $success = null, & $casToken = null); @@ -122,7 +122,7 @@ public function getItem($key, array $options = array(), & $success = null, & $ca * * @param array $keys * @param array $options - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws \Zend\Cache\Exception\ExceptionInterface */ public function getItems(array $keys, array $options = array()); @@ -142,7 +142,7 @@ public function hasItem($key, array $options = array()); * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws \Zend\Cache\Exception\ExceptionInterface */ public function hasItems(array $keys, array $options = array()); @@ -152,7 +152,7 @@ public function hasItems(array $keys, array $options = array()); * * @param string $key * @param array $options - * @return array|boolean Metadata or false on failure + * @return array|boolean Metadata on success, false on failure * @throws \Zend\Cache\Exception\ExceptionInterface */ public function getMetadata($key, array $options = array()); @@ -162,7 +162,7 @@ public function getMetadata($key, array $options = array()); * * @param array $keys * @param array $options - * @return array Associative array of existing cache ids and its metadata + * @return array Associative array of keys and metadata * @throws \Zend\Cache\Exception\ExceptionInterface */ public function getMetadatas(array $keys, array $options = array()); @@ -173,8 +173,8 @@ public function getMetadatas(array $keys, array $options = array()); * Store an item. * * @param string $key - * @param mixed $value - * @param array $options + * @param mixed $value + * @param array $options * @return boolean * @throws \Zend\Cache\Exception\ExceptionInterface */ @@ -185,7 +185,7 @@ public function setItem($key, $value, array $options = array()); * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws \Zend\Cache\Exception\ExceptionInterface */ public function setItems(array $keyValuePairs, array $options = array()); @@ -206,7 +206,7 @@ public function addItem($key, $value, array $options = array()); * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws \Zend\Cache\Exception\ExceptionInterface */ public function addItems(array $keyValuePairs, array $options = array()); @@ -227,7 +227,7 @@ public function replaceItem($key, $value, array $options = array()); * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws \Zend\Cache\Exception\ExceptionInterface */ public function replaceItems(array $keyValuePairs, array $options = array()); @@ -264,7 +264,7 @@ public function touchItem($key, array $options = array()); * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not updated keys * @throws \Zend\Cache\Exception\ExceptionInterface */ public function touchItems(array $keys, array $options = array()); @@ -284,7 +284,7 @@ public function removeItem($key, array $options = array()); * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not removed keys * @throws \Zend\Cache\Exception\ExceptionInterface */ public function removeItems(array $keys, array $options = array()); @@ -295,7 +295,7 @@ public function removeItems(array $keys, array $options = array()); * @param string $key * @param int $value * @param array $options - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws \Zend\Cache\Exception\ExceptionInterface */ public function incrementItem($key, $value, array $options = array()); @@ -305,7 +305,7 @@ public function incrementItem($key, $value, array $options = array()); * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Associative array of keys and new values * @throws \Zend\Cache\Exception\ExceptionInterface */ public function incrementItems(array $keyValuePairs, array $options = array()); @@ -316,7 +316,7 @@ public function incrementItems(array $keyValuePairs, array $options = array()); * @param string $key * @param int $value * @param array $options - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws \Zend\Cache\Exception\ExceptionInterface */ public function decrementItem($key, $value, array $options = array()); @@ -326,7 +326,7 @@ public function decrementItem($key, $value, array $options = array()); * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Associative array of keys and new values * @throws \Zend\Cache\Exception\ExceptionInterface */ public function decrementItems(array $keyValuePairs, array $options = array()); @@ -421,7 +421,7 @@ public function getCapabilities(); * Get storage capacity. * * @param array $options - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws \Zend\Cache\Exception\ExceptionInterface */ public function getCapacity(array $options = array()); diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index 13441fd3e..3eb71e1c0 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -153,7 +153,7 @@ public function getOptions() * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken - * @return mixed Data on success or false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) @@ -179,7 +179,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -231,7 +231,7 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface */ protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) @@ -263,7 +263,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * * @param string $normalizedKey * @param array $normalizedOptions - * @return array|boolean Metadata or false on failure + * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * * @triggers getMetadata.pre(PreEvent) @@ -301,7 +301,7 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array + * @return array Associative array of keys and metadata * * @triggers getMetadatas.pre(PreEvent) * @triggers getMetadatas.post(PostEvent) @@ -374,7 +374,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -442,7 +442,7 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -525,7 +525,7 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) @@ -559,7 +559,7 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -593,7 +593,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -873,7 +873,7 @@ protected function internalGetCapabilities() * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index 11f094782..b97d9856f 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -114,7 +114,7 @@ public function getOptions() * @param array $options * @param boolean $success * @param mixed $casToken - * @return mixed Data on success and false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface * * @triggers getItem.pre(PreEvent) @@ -142,7 +142,7 @@ public function getItem($key, array $options = array(), & $success = null, & $ca * * @param array $keys * @param array $options - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface * * @triggers getItems.pre(PreEvent) @@ -172,7 +172,7 @@ public function getItems(array $keys, array $options = array()) * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken - * @return mixed Data on success or false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) @@ -228,7 +228,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -321,7 +321,7 @@ public function hasItem($key, array $options = array()) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface * * @triggers hasItems.pre(PreEvent) @@ -382,9 +382,9 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) /** * Get metadata * - * @param $key - * @param array $options - * @return array|bool|mixed|null + * @param string $key + * @param array $options + * @return array|boolean Metadata on success, false on failure */ public function getMetadata($key, array $options = array()) { @@ -401,7 +401,7 @@ public function getMetadata($key, array $options = array()) * * @param array $keys * @param array $options - * @return array + * @return array Associative array of keys and metadata */ public function getMetadatas(array $keys, array $options = array()) { @@ -418,7 +418,7 @@ public function getMetadatas(array $keys, array $options = array()) * * @param string $normalizedKey * @param array $normalizedOptions - * @return array|bool + * @return array|boolean Metadata on success, false on failure */ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) { @@ -459,7 +459,7 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing cache ids and its metadata + * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface */ protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) @@ -556,7 +556,7 @@ public function setItem($key, $value, array $options = array()) * * @param array $keyValuePairs * @param array $options - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface * * @triggers setItems.pre(PreEvent) @@ -764,7 +764,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -929,7 +929,7 @@ public function touchItem($key, array $options = array()) * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not updated keys * @throws Exception\ExceptionInterface * * @triggers touchItems.pre(PreEvent) @@ -1015,7 +1015,7 @@ public function removeItem($key, array $options = array()) * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not removed keys * @throws Exception\ExceptionInterface * * @triggers removeItems.pre(PreEvent) @@ -1282,7 +1282,7 @@ protected function internalGetCapabilities() * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) diff --git a/src/Storage/Adapter/Memcached.php b/src/Storage/Adapter/Memcached.php index 4a4dcdb79..94076c336 100644 --- a/src/Storage/Adapter/Memcached.php +++ b/src/Storage/Adapter/Memcached.php @@ -161,7 +161,7 @@ public function getOptions() * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken - * @return mixed Data on success or false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) @@ -199,7 +199,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -254,7 +254,7 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface */ protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) @@ -278,7 +278,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array + * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface * * @triggers getMetadatas.pre(PreEvent) @@ -341,7 +341,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -492,7 +492,7 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio * * @param array $keys * @param array $options - * @return boolean + * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) @@ -530,7 +530,7 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -571,7 +571,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -796,7 +796,7 @@ protected function internalGetCapabilities() * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) diff --git a/src/Storage/Adapter/Memory.php b/src/Storage/Adapter/Memory.php index d3dffe0a8..f3d718893 100644 --- a/src/Storage/Adapter/Memory.php +++ b/src/Storage/Adapter/Memory.php @@ -100,7 +100,7 @@ public function getOptions() * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken - * @return mixed Data on success or false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) @@ -134,7 +134,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -200,7 +200,7 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * * @param array $keys * @param array $options - * @return array Array of existing keys + * @return array Array of found keys * @throws Exception\ExceptionInterface */ protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) @@ -236,7 +236,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * * @param string $normalizedKey * @param array $normalizedOptions - * @return array|boolean Metadata or false on failure + * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * * @triggers getMetadata.pre(PreEvent) @@ -299,7 +299,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -368,7 +368,7 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -440,7 +440,7 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalReplaceItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -528,7 +528,7 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -560,7 +560,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -822,7 +822,7 @@ protected function internalGetCapabilities() * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index 06b25095b..ab6e646de 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -112,12 +112,10 @@ public function getOptions() * - The time-to-life * - namespace * - The namespace to use - * - ignore_missing_items - * - Throw exception on missing item or return false * * @param string $normalizedKey * @param array $normalizedOptions - * @return mixed Data on success or false on failure + * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) @@ -148,7 +146,7 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) * * @param array $normalizedKeys * @param array $normalizedOptions - * @return array Associative array of existing keys and values + * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) @@ -201,12 +199,10 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * Options: * - namespace optional * - The namespace to use (Default: namespace of object) - * - ignore_missing_items optional - * - Throw exception on missing item or return false * * @param string $normalizedKey * @param array $normalizedOptions - * @return array|boolean Metadata or false on failure + * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * * @triggers getMetadata.pre(PreEvent) @@ -274,7 +270,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -342,7 +338,7 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions - * @return boolean + * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) @@ -405,8 +401,6 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm * Options: * - namespace * - The namespace to use - * - ignore_missing_items - * - Throw exception on missing item * * @param string $normalizedKey * @param array $normalizedOptions @@ -431,13 +425,11 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio * - The time-to-life * - namespace * - The namespace to use - * - ignore_missing_items - * - Throw exception on missing item * * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -469,13 +461,11 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no * - The time-to-life * - namespace * - The namespace to use - * - ignore_missing_items - * - Throw exception on missing item * * @param string $normalizedKey * @param int $value * @param array $normalizedOptions - * @return int|boolean The new value or false on failure + * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) @@ -583,7 +573,7 @@ protected function internalGetCapabilities() * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) diff --git a/src/Storage/Adapter/ZendServerDisk.php b/src/Storage/Adapter/ZendServerDisk.php index d350cb96e..e16191ae1 100644 --- a/src/Storage/Adapter/ZendServerDisk.php +++ b/src/Storage/Adapter/ZendServerDisk.php @@ -57,7 +57,7 @@ public function __construct($options = array()) * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) diff --git a/src/Storage/Adapter/ZendServerShm.php b/src/Storage/Adapter/ZendServerShm.php index 7aa025ab0..95fd0aaa9 100644 --- a/src/Storage/Adapter/ZendServerShm.php +++ b/src/Storage/Adapter/ZendServerShm.php @@ -56,7 +56,7 @@ public function __construct($options = array()) * Internal method to get storage capacity. * * @param array $normalizedOptions - * @return array|boolean Capacity as array or false on failure + * @return array|boolean Associative array of capacity, false on failure * @throws Exception\ExceptionInterface */ protected function internalGetCapacity(array & $normalizedOptions) From f904d3c4f81e8fbd75577d6928ffeb2a4b61e9e5 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 11 May 2012 01:02:16 +0200 Subject: [PATCH 47/62] Now the WinCache adapter follows the new API --- src/Storage/Adapter/WinCache.php | 145 +++++++++++++------------------ 1 file changed, 62 insertions(+), 83 deletions(-) diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index ab6e646de..f3960dde7 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -113,25 +113,21 @@ public function getOptions() * - namespace * - The namespace to use * - * @param string $normalizedKey - * @param array $normalizedOptions + * @param string $normalizedKey + * @param array $normalizedOptions + * @param boolean $success + * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions) + protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) { $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); $internalKey = $prefix . $normalizedKey; - $success = false; $result = wincache_ucache_get($internalKey, $success); - if (!$success) { - if (!$normalizedOptions['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } - } else { - if (array_key_exists('token', $normalizedOptions)) { - $normalizedOptions['token'] = $result; - } + + if ($success) { + $casToken = $result; } return $result; @@ -158,12 +154,6 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized } $fetch = wincache_ucache_get($internalKeys); - if (!$normalizedOptions['ignore_missing_items']) { - if (count($normalizedKeys) != count($fetch)) { - $missing = implode("', '", array_diff($internalKeys, array_keys($fetch))); - throw new Exception\ItemNotFoundException('Keys not found: ' . $missing); - } - } // remove namespace prefix $prefixL = strlen($prefix); @@ -216,17 +206,11 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti $info = wincache_ucache_info(true, $internalKey); if (isset($info['ucache_entries'][1])) { $metadata = $info['ucache_entries'][1]; - } - - if (!$metadata) { - if (!$normalizedOptions['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); - } + $this->normalizeMetadata($metadata); + return $metadata; + } else { return false; } - - $this->normalizeMetadata($metadata); - return $metadata; } /* writing */ @@ -275,7 +259,8 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz */ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $prefixL = strlen($prefix); $internalKeyValuePairs = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { @@ -283,15 +268,14 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n $internalKeyValuePairs[$internalKey] = $value; } - $errKeys = wincache_ucache_set($internalKeyValuePairs, null, $normalizedOptions['ttl']); - if ($errKeys) { - throw new Exception\RuntimeException( - "wincache_ucache_set(, null, {$normalizedOptions['ttl']}) failed for keys: " - . "'" . implode("','", array_keys($errKeys)) . "'" - ); + $result = wincache_ucache_set($internalKeyValuePairs, null, $normalizedOptions['ttl']); + + // remove key prefic + foreach ($result as & $key) { + $key = substr($key, $prefixL); } - return true; + return $result; } /** @@ -313,11 +297,6 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz { $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; if (!wincache_ucache_add($internalKey, $value, $normalizedOptions['ttl'])) { - // TODO: check if this is really needed - if (wincache_ucache_exists($internalKey)) { - throw new Exception\RuntimeException("Key '{$internalKey}' already exists"); - } - $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( "wincache_ucache_add('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" @@ -350,15 +329,14 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n $internalKeyValuePairs[$internalKey] = $value; } - $errKeys = wincache_ucache_add($internalKeyValuePairs, null, $normalizedOptions['ttl']); - if ($errKeys !== array()) { - throw new Exception\RuntimeException( - "wincache_ucache_add(, null, {$normalizedOptions['ttl']}) failed for keys: " - . "'" . implode("','", array_keys($errKeys)) . "'" - ); + $result = wincache_ucache_add($internalKeyValuePairs, null, $normalizedOptions['ttl']); + + // remove key prefic + foreach ($result as & $key) { + $key = substr($key, $prefixL); } - return true; + return $result; } /** @@ -410,11 +388,42 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) { $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - if (!wincache_ucache_delete($internalKey) && !$normalizedOptions['ignore_missing_items']) { - throw new Exception\ItemNotFoundException("Key '{$internalKey}' not found"); + return wincache_ucache_delete($internalKey); + } + + /** + * Internal method to remove multiple items. + * + * Options: + * - namespace + * - The namespace to use + * + * @param array $keys + * @param array $options + * @return array Array of not removed keys + * @throws Exception\ExceptionInterface + */ + protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) + { + $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + + $internalKeys = array(); + foreach ($normalizedKeys as $normalizedKey) { + $internalKeys[] = $prefix . $normalizedKey; } - return true; + $result = wincache_ucache_delete($internalKeys); + if ($result === false) { + return $normalizedKeys; + } elseif ($result) { + // remove key prefix + $prefixL = strlen($prefix); + foreach ($result as & $key) { + $key = substr($key, $prefixL); + } + } + + return $result; } /** @@ -435,22 +444,7 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - $value = (int)$value; - $newValue = wincache_ucache_inc($internalKey, $value); - if ($newValue === false) { - if (wincache_ucache_exists($internalKey)) { - throw new Exception\RuntimeException("wincache_ucache_inc('{$internalKey}', {$value}) failed"); - } elseif (!$normalizedOptions['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' not found" - ); - } - - $newValue = $value; - $this->addItem($normalizedKey, $newValue, $normalizedOptions); - } - - return $newValue; + return wincache_ucache_inc($internalKey, (int)$value); } /** @@ -471,22 +465,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) { $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - $value = (int)$value; - $newValue = wincache_ucache_dec($internalKey, $value); - if ($newValue === false) { - if (wincache_ucache_exists($internalKey)) { - throw new Exception\RuntimeException("wincache_ucache_inc('{$internalKey}', {$value}) failed"); - } elseif (!$normalizedOptions['ignore_missing_items']) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' not found" - ); - } - - $newValue = -$value; - $this->addItem($normalizedKey, $newValue, $normalizedOptions); - } - - return $newValue; + return wincache_ucache_dec($internalKey, (int)$value); } /* cleaning */ @@ -593,7 +572,7 @@ protected function internalGetCapacity(array & $normalizedOptions) * @param array $metadata * @return void */ - protected function normalizeMetadata(array &$metadata) + protected function normalizeMetadata(array & $metadata) { if (isset($metadata['hitcount'])) { $metadata['num_hits'] = $metadata['hitcount']; From 93b2609f55998da0d76b951002479df979e7f9ad Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 11 May 2012 01:05:18 +0200 Subject: [PATCH 48/62] removed no longer needed ItemNotFoundException --- src/Storage/Adapter/WinCache.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index f3960dde7..dec09b410 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -358,9 +358,7 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm { $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; if (!wincache_ucache_exists($internalKey)) { - throw new Exception\ItemNotFoundException( - "Key '{$internalKey}' doesn't exist" - ); + return false; } if (!wincache_ucache_set($internalKey, $value, $normalizedOptions['ttl'])) { From cff9ea342789b9a25a083913a36de51ce298f842 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 11 May 2012 01:07:58 +0200 Subject: [PATCH 49/62] removed no longer needed option 'ignore_missing_items' --- src/Exception/ItemNotFoundException.php | 31 ------------- src/Storage/Adapter/AdapterOptions.php | 44 ------------------- .../Adapter/AbstractZendServerTest.php | 1 - 3 files changed, 76 deletions(-) delete mode 100644 src/Exception/ItemNotFoundException.php diff --git a/src/Exception/ItemNotFoundException.php b/src/Exception/ItemNotFoundException.php deleted file mode 100644 index 0ba6d2e75..000000000 --- a/src/Exception/ItemNotFoundException.php +++ /dev/null @@ -1,31 +0,0 @@ -ignoreMissingItems !== $flag) { - $this->triggerOptionEvent('ignore_missing_items', $flag); - $this->ignoreMissingItems = $flag; - } - return $this; - } - - /** - * Ignore missing items - * - * @return boolean - * @see setIgnoreMissingItems() - */ - public function getIgnoreMissingItems() - { - return $this->ignoreMissingItems; - } - /** * Set key pattern * diff --git a/test/Storage/Adapter/AbstractZendServerTest.php b/test/Storage/Adapter/AbstractZendServerTest.php index 4640e76b7..dc552d9b5 100644 --- a/test/Storage/Adapter/AbstractZendServerTest.php +++ b/test/Storage/Adapter/AbstractZendServerTest.php @@ -56,7 +56,6 @@ public function testGetOptions() $this->assertInternalType('string', $options->getNamespace()); $this->assertInternalType('string', $options->getNamespacePattern()); $this->assertInternalType('string', $options->getKeyPattern()); - $this->assertInternalType('boolean', $options->getIgnoreMissingItems()); } public function testGetWithDefaultNamespace() From 58466b3c48b87bdb673f4f9d8a4b057514281945 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 11 May 2012 01:09:18 +0200 Subject: [PATCH 50/62] removed no longer needed LockedException --- src/Exception/LockedException.php | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 src/Exception/LockedException.php diff --git a/src/Exception/LockedException.php b/src/Exception/LockedException.php deleted file mode 100644 index 5c2101286..000000000 --- a/src/Exception/LockedException.php +++ /dev/null @@ -1,31 +0,0 @@ - Date: Fri, 11 May 2012 11:57:50 -0500 Subject: [PATCH 51/62] [zendframework/zf2#1199] Allow testing barcode - also changed tested-components to merely list "Zend\Feed", so all of feed is executed --- .travis/skipped-components | 1 - .travis/tested-components | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis/skipped-components b/.travis/skipped-components index 0790ed22c..c4cd70659 100644 --- a/.travis/skipped-components +++ b/.travis/skipped-components @@ -1,5 +1,4 @@ Zend/Amf -Zend/Barcode Zend/Date Zend/Queue Zend/Service diff --git a/.travis/tested-components b/.travis/tested-components index c0fe64778..d1d71333e 100644 --- a/.travis/tested-components +++ b/.travis/tested-components @@ -1,5 +1,6 @@ Zend/Acl Zend/Authentication +Zend/Barcode Zend/Cache Zend/Captcha Zend/Cloud @@ -14,8 +15,7 @@ Zend/DocBook Zend/Dojo Zend/Dom Zend/EventManager -Zend/Feed/Reader -Zend/Feed/Writer +Zend/Feed Zend/File Zend/Filter Zend/Form From 679c783dd5fe905177cfa4e7005f4fd515bd70e2 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 11 May 2012 12:18:48 -0500 Subject: [PATCH 52/62] [zen-27][zendframework/zf2#1199] Fix Translator tests - Fixes log setup and usage in tests and code for Translator - Re-enabled Translator tests, as they now appear to work --- .travis/skipped-components | 1 - .travis/tested-components | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/skipped-components b/.travis/skipped-components index c4cd70659..31bcaa87f 100644 --- a/.travis/skipped-components +++ b/.travis/skipped-components @@ -3,5 +3,4 @@ Zend/Date Zend/Queue Zend/Service Zend/Test -Zend/Translator Zend/Wildfire diff --git a/.travis/tested-components b/.travis/tested-components index d1d71333e..b1f4a794d 100644 --- a/.travis/tested-components +++ b/.travis/tested-components @@ -51,6 +51,7 @@ Zend/Stdlib Zend/Tag Zend/Text Zend/TimeSync +Zend/Translator Zend/Uri Zend/Validator Zend/VersionTest.php From 97a43920fb5d21a804c164feeb8c38330d6f3463 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 11 May 2012 08:17:31 -0500 Subject: [PATCH 53/62] [zen-12] Removed Dojo from test suite - Dojo integration largely relied on integration with Zend\Form; removing from testing for now, as it has not been refactored to work with the new Zend\Form code. --- .travis/skipped-components | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/skipped-components b/.travis/skipped-components index 31bcaa87f..171dfe9d7 100644 --- a/.travis/skipped-components +++ b/.travis/skipped-components @@ -1,5 +1,6 @@ Zend/Amf Zend/Date +Zend/Dojo Zend/Queue Zend/Service Zend/Test From ae9228a8d08e442243bd1c8e16e86d722d83d20d Mon Sep 17 00:00:00 2001 From: Maks3w Date: Fri, 18 May 2012 00:22:37 +0200 Subject: [PATCH 54/62] [Travis] Enable Zend\Math tests --- .travis/tested-components | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/tested-components b/.travis/tested-components index b1f4a794d..9b338206b 100644 --- a/.travis/tested-components +++ b/.travis/tested-components @@ -29,6 +29,7 @@ Zend/Locale Zend/Log Zend/Mail Zend/Markup +Zend/Math Zend/Measure Zend/Memory Zend/Mime From c7f2938d551f25fd07b99c392a2e0cdff150a1ad Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 28 May 2012 21:06:33 +0200 Subject: [PATCH 55/62] Simplyfied cache API and added modified interfaces: - renamed Zend\Cache\Storage\AdapterInterface -> Zend\Cache\Storage\StorageInterface -> because it's the interface of the storage and the adapters are an implementation detail - renamed Zend\Cache\Exception\OutOfCapacityException -> Zend\Cache\Exception\OutOfSpaceException - removed options argument array -> this simplifies things a lot and speed-op internal operations -> please only use the option instance instead - moved some spezial methods into own interfaces and implement it only if the adapters supports it - AvailableSpaceCapableInterface::getAvailableSpace() - TotalSpaceCapableInterface::getTotalSpace() - ClearByNamespaceInterface::clearByNamespace($namespace) - ClearByPrefixInterface::clearByPrefix($prefix) - ClearExpiredInterface::clearExpired() - FlushableInterface::flush() - IterableInterface::getIterator() (extends IteratorAggregate) - OptimizableInterface::optimize() - TagableInterface::setTags($key, array $tags) - TagableInterface::getTags($key) - TagableInterface::clearByTags(array $tags, $disjunction = false) - removed capability properties now handled by interfaces - iterable - clearByNamespace - clearAllNamespaces --- ...yException.php => OutOfSpaceException.php} | 2 +- src/Pattern/CallbackCache.php | 141 +- src/Pattern/CaptureCache.php | 3 +- src/Pattern/ClassCache.php | 61 +- src/Pattern/ObjectCache.php | 115 +- src/Pattern/OutputCache.php | 7 +- src/Pattern/PatternOptions.php | 29 +- src/Storage/Adapter/AbstractAdapter.php | 1353 ++--------------- src/Storage/Adapter/AbstractZendServer.php | 160 +- src/Storage/Adapter/AdapterInterface.php | 428 ------ src/Storage/Adapter/AdapterOptions.php | 63 +- src/Storage/Adapter/Apc.php | 650 +++----- src/Storage/Adapter/ApcIterator.php | 179 +++ src/Storage/Adapter/Filesystem.php | 1245 +++++++-------- src/Storage/Adapter/FilesystemIterator.php | 194 +++ src/Storage/Adapter/FilesystemOptions.php | 9 - src/Storage/Adapter/KeyListIterator.php | 191 +++ src/Storage/Adapter/Memcached.php | 424 ++---- src/Storage/Adapter/Memory.php | 737 ++++----- src/Storage/Adapter/MemoryOptions.php | 14 +- src/Storage/Adapter/WinCache.php | 314 ++-- src/Storage/Adapter/ZendServerDisk.php | 121 +- src/Storage/Adapter/ZendServerShm.php | 84 +- src/Storage/AdapterBroker.php | 4 +- .../AvailableSpaceCapableInterface.php | 39 + src/Storage/Capabilities.php | 125 +- src/Storage/ClearByNamespaceInterface.php | 40 + src/Storage/ClearByPrefixInterface.php | 40 + src/Storage/ClearExpiredInterface.php | 39 + src/Storage/Event.php | 22 +- src/Storage/ExceptionEvent.php | 2 +- src/Storage/FlushableInterface.php | 39 + src/Storage/IterableInterface.php | 39 + src/Storage/IteratorInterface.php | 60 + src/Storage/OptimizableInterface.php | 39 + ...rByFactor.php => ClearExpiredByFactor.php} | 28 +- src/Storage/Plugin/ExceptionHandler.php | 15 - src/Storage/Plugin/IgnoreUserAbort.php | 4 +- src/Storage/Plugin/OptimizeByFactor.php | 17 +- src/Storage/Plugin/PluginOptions.php | 39 +- src/Storage/Plugin/Serializer.php | 145 +- src/Storage/PluginBroker.php | 5 +- src/Storage/PluginLoader.php | 17 +- src/Storage/PostEvent.php | 10 +- src/Storage/StorageInterface.php | 263 ++++ src/Storage/TagableInterface.php | 62 + src/Storage/TotalSpaceCapableInterface.php | 39 + src/StorageFactory.php | 20 +- src/Utils.php | 31 +- test/Pattern/CallbackCacheTest.php | 40 +- test/Pattern/CaptureCacheTest.php | 1 - test/Pattern/ClassCacheTest.php | 9 +- test/Pattern/ObjectCacheTest.php | 81 +- test/Pattern/OutputCacheTest.php | 3 +- test/PatternFactoryTest.php | 1 - test/Storage/Adapter/AbstractAdapterTest.php | 230 +-- .../Adapter/AbstractZendServerTest.php | 140 +- test/Storage/Adapter/ApcTest.php | 1 - test/Storage/Adapter/CommonAdapterTest.php | 611 ++------ test/Storage/Adapter/MemcachedTest.php | 4 +- test/Storage/Adapter/MemoryTest.php | 5 +- test/Storage/Adapter/WinCacheTest.php | 1 - test/Storage/Adapter/ZendServerDiskTest.php | 1 - test/Storage/Adapter/ZendServerShmTest.php | 1 - ...rTest.php => ClearExpiredByFactorTest.php} | 54 +- test/Storage/Plugin/ExceptionHandlerTest.php | 13 - test/Storage/Plugin/IgnoreUserAbortTest.php | 1 - test/Storage/Plugin/OptimizeByFactorTest.php | 11 +- test/Storage/Plugin/SerializerTest.php | 4 - .../TestAsset/ClearExpiredMockAdapter.php | 12 + test/Storage/TestAsset/MockAdapter.php | 11 +- test/Storage/TestAsset/MockPlugin.php | 1 - .../TestAsset/OptimizableMockAdapter.php | 12 + test/StorageFactoryTest.php | 13 +- test/TestAsset/DummyPattern.php | 1 - test/TestAsset/DummyStoragePlugin.php | 1 - test/UtilsTest.php | 6 - 77 files changed, 3366 insertions(+), 5610 deletions(-) rename src/Exception/{OutOfCapacityException.php => OutOfSpaceException.php} (91%) delete mode 100644 src/Storage/Adapter/AdapterInterface.php create mode 100644 src/Storage/Adapter/ApcIterator.php create mode 100644 src/Storage/Adapter/FilesystemIterator.php create mode 100644 src/Storage/Adapter/KeyListIterator.php create mode 100644 src/Storage/AvailableSpaceCapableInterface.php create mode 100644 src/Storage/ClearByNamespaceInterface.php create mode 100644 src/Storage/ClearByPrefixInterface.php create mode 100644 src/Storage/ClearExpiredInterface.php create mode 100644 src/Storage/FlushableInterface.php create mode 100644 src/Storage/IterableInterface.php create mode 100644 src/Storage/IteratorInterface.php create mode 100644 src/Storage/OptimizableInterface.php rename src/Storage/Plugin/{ClearByFactor.php => ClearExpiredByFactor.php} (79%) create mode 100644 src/Storage/StorageInterface.php create mode 100644 src/Storage/TagableInterface.php create mode 100644 src/Storage/TotalSpaceCapableInterface.php rename test/Storage/Plugin/{ClearByFactorTest.php => ClearExpiredByFactorTest.php} (57%) create mode 100644 test/Storage/TestAsset/ClearExpiredMockAdapter.php create mode 100644 test/Storage/TestAsset/OptimizableMockAdapter.php diff --git a/src/Exception/OutOfCapacityException.php b/src/Exception/OutOfSpaceException.php similarity index 91% rename from src/Exception/OutOfCapacityException.php rename to src/Exception/OutOfSpaceException.php index 2dfaef98a..290592c8d 100644 --- a/src/Exception/OutOfCapacityException.php +++ b/src/Exception/OutOfSpaceException.php @@ -26,6 +26,6 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class OutOfCapacityException extends \OverflowException implements ExceptionInterface +class OutOfSpaceException extends \OverflowException implements ExceptionInterface { } diff --git a/src/Pattern/CallbackCache.php b/src/Pattern/CallbackCache.php index 736be227c..566039c93 100644 --- a/src/Pattern/CallbackCache.php +++ b/src/Pattern/CallbackCache.php @@ -22,8 +22,7 @@ namespace Zend\Cache\Pattern; use Zend\Cache\Exception, - Zend\Cache\StorageFactory, - Zend\Cache\Storage\Adapter\AdapterInterface as StorageAdapter; + Zend\Cache\StorageFactory; /** * @category Zend @@ -56,17 +55,16 @@ public function setOptions(PatternOptions $options) * * @param callback $callback A valid callback * @param array $args Callback arguments - * @param array $options Options * @return mixed Result * @throws Exception */ - public function call($callback, array $args = array(), array $options = array()) + public function call($callback, array $args = array()) { - $classOptions = $this->getOptions(); - + $options = $this->getOptions(); + $storage = $options->getStorage(); $success = null; - $key = $this->_generateKey($callback, $args, $options); - $result = $classOptions->getStorage()->getItem($key, $options, $success); + $key = $this->generateCallbackKey($callback, $args); + $result = $storage->getItem($key, $success); if ($success) { if (!isset($result[0])) { throw new Exception\RuntimeException("Invalid cached data for key '{$key}'"); @@ -76,7 +74,7 @@ public function call($callback, array $args = array(), array $options = array()) return $result[0]; } - $cacheOutput = $classOptions->getCacheOutput(); + $cacheOutput = $options->getCacheOutput(); if ($cacheOutput) { ob_start(); ob_implicit_flush(false); @@ -103,7 +101,7 @@ public function call($callback, array $args = array(), array $options = array()) $data = array($ret); } - $classOptions->getStorage()->setItem($key, $data, $options); + $storage->setItem($key, $data); return $ret; } @@ -123,106 +121,91 @@ public function __call($function, array $args) /** * Generate a unique key in base of a key representing the callback part - * and a key representing the arguments part merged using md5($callbackKey.$argumentsKey). - * - * Options: - * callback_key A string representing the callback part of the key - * or NULL to autogenerate the callback key part - * argument_key A string representing the arguments part of the key - * or NULL to autogenerate the arguments key part + * and a key representing the arguments part. * * @param callback $callback A valid callback * @param array $args Callback arguments - * @param array $options Options * @return string * @throws Exception */ - public function generateKey($callback, array $args = array(), array $options = array()) + public function generateKey($callback, array $args = array()) { - return $this->_generateKey($callback, $args, $options); + return $this->generateCallbackKey($callback, $args); } /** * Generate a unique key in base of a key representing the callback part - * and a key representing the arguments part merged using md5($callbackKey.$argumentsKey). + * and a key representing the arguments part. * * @param callback $callback A valid callback * @param array $args Callback arguments - * @param array $options Options * @return string - * @throws Exception\InvalidArgumentException - * @throws Exception\RuntimeException + * @throws Exception */ - protected function _generateKey($callback, array $args, array $options) + protected function generateCallbackKey($callback, array $args) { - $callbackKey = ''; - $argumentKey = ''; - - // generate callback key part - if (isset($options['callback_key'])) { - $callbackKey = (string) $options['callback_key']; - - if (!is_callable($callback, false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - } else { - if (!is_callable($callback, false, $callbackKey)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } + if (!is_callable($callback, false, $callbackKey)) { + throw new Exception\InvalidArgumentException('Invalid callback'); + } - // functions, methods and classnames are case-insensitive - $callbackKey = strtolower($callbackKey); + // functions, methods and classnames are case-insensitive + $callbackKey = strtolower($callbackKey); - // generate a unique key of object callbacks - if (is_object($callback)) { // Closures & __invoke - $object = $callback; - } elseif (isset($callback[0])) { // array($object, 'method') - $object = $callback[0]; - } - if (isset($object)) { - try { - $serializedObject = @serialize($object); - } catch (\Exception $e) { - throw new Exception\RuntimeException( - "Can't serialize callback: see previous exception" - , 0, $e); - } - - if (!$serializedObject) { - $lastErr = error_get_last(); - throw new Exception\RuntimeException( - "Can't serialize callback: " - . $lastErr['message'] - ); - } - $callbackKey.= $serializedObject; - } + // generate a unique key of object callbacks + if (is_object($callback)) { // Closures & __invoke + $object = $callback; + } elseif (isset($callback[0])) { // array($object, 'method') + $object = $callback[0]; } - - // generate argument key part - if (isset($options['argument_key'])) { - $argumentKey = (string)$options['argument_key']; - } elseif ($args) { + if (isset($object)) { try { - $serializedArgs = @serialize(array_values($args)); + $serializedObject = @serialize($object); } catch (\Exception $e) { throw new Exception\RuntimeException( - "Can't serialize arguments: see previous exception" - , 0, $e); + "Can't serialize callback: see previous exception", 0, $e + ); } - if (!$serializedArgs) { + if (!$serializedObject) { $lastErr = error_get_last(); throw new Exception\RuntimeException( - "Can't serialize arguments: " - . $lastErr['message'] + "Can't serialize callback: " . $lastErr['message'] ); } + $callbackKey.= $serializedObject; + } + + return md5($callbackKey) . $this->generateArgumentsKey($args); + } + + /** + * Generate a unique key of the argument part. + * + * @param array $args + * @return string + * @throws Exception + */ + protected function generateArgumentsKey(array $args) + { + if (!$args) { + return ''; + } + + try { + $serializedArgs = @serialize(array_values($args)); + } catch (\Exception $e) { + throw new Exception\RuntimeException( + "Can't serialize arguments: see previous exception" + , 0, $e); + } - $argumentKey = $serializedArgs; + if (!$serializedArgs) { + $lastErr = error_get_last(); + throw new Exception\RuntimeException( + "Can't serialize arguments: " . $lastErr['message'] + ); } - // merge and return the key parts - return md5($callbackKey.$argumentKey); + return md5($serializedArgs); } } diff --git a/src/Pattern/CaptureCache.php b/src/Pattern/CaptureCache.php index 834662c47..d90d5e19a 100644 --- a/src/Pattern/CaptureCache.php +++ b/src/Pattern/CaptureCache.php @@ -21,8 +21,7 @@ namespace Zend\Cache\Pattern; -use Zend\Cache\Exception, - Zend\Cache\Storage\Adapter\AdapterInterface as StorageAdapter; +use Zend\Cache\Exception; /** * @category Zend diff --git a/src/Pattern/ClassCache.php b/src/Pattern/ClassCache.php index 34f0e7a6d..5b14fb54e 100644 --- a/src/Pattern/ClassCache.php +++ b/src/Pattern/ClassCache.php @@ -55,22 +55,21 @@ public function setOptions(PatternOptions $options) * * @param string $method Method name to call * @param array $args Method arguments - * @param array $options Cache options * @return mixed * @throws Exception */ - public function call($method, array $args = array(), array $options = array()) + public function call($method, array $args = array()) { - $classOptions = $this->getOptions(); - $classname = $classOptions->getClass(); - $method = strtolower($method); - $callback = $classname . '::' . $method; + $options = $this->getOptions(); + $classname = $options->getClass(); + $method = strtolower($method); + $callback = $classname . '::' . $method; - $cache = $classOptions->getCacheByDefault(); + $cache = $options->getCacheByDefault(); if ($cache) { - $cache = !in_array($method, $classOptions->getClassNonCacheMethods()); + $cache = !in_array($method, $options->getClassNonCacheMethods()); } else { - $cache = in_array($method, $classOptions->getClassCacheMethods()); + $cache = in_array($method, $options->getClassCacheMethods()); } if (!$cache) { @@ -81,34 +80,40 @@ public function call($method, array $args = array(), array $options = array()) } } - // speed up key generation - if (!isset($options['callback_key'])) { - $options['callback_key'] = $callback; - } - - return parent::call($callback, $args, $options); + return parent::call($callback, $args); } /** - * Generate a key from the method name and arguments + * Generate a unique key in base of a key representing the callback part + * and a key representing the arguments part. * - * @param string $method The method name - * @param array $args Method arguments + * @param string $method The method + * @param array $args Callback arguments * @return string * @throws Exception */ - public function generateKey($method, array $args = array(), array $options = array()) + public function generateKey($method, array $args = array()) { - // speed up key generation - $classOptions = $this->getOptions(); - if (!isset($options['callback_key'])) { - $callback = $classOptions->getClass() . '::' . strtolower($method); - $options['callback_key'] = $callback; - } else { - $callback = $classOptions->getClass() . '::' . $method; - } + return $this->generateCallbackKey( + $this->getOptions()->getClass() . '::' . $method, + $args + ); + } - return parent::generateKey($callback, $args, $options); + /** + * Generate a unique key in base of a key representing the callback part + * and a key representing the arguments part. + * + * @param callback $callback A valid callback + * @param array $args Callback arguments + * @return string + * @throws Exception + */ + protected function generateCallbackKey($callback, array $args) + { + $callbackKey = md5(strtolower($callback)); + $argumentKey = $this->generateArgumentsKey($args); + return $callbackKey . $argumentKey; } /** diff --git a/src/Pattern/ObjectCache.php b/src/Pattern/ObjectCache.php index b692a74da..67fac77aa 100644 --- a/src/Pattern/ObjectCache.php +++ b/src/Pattern/ObjectCache.php @@ -54,15 +54,14 @@ public function setOptions(PatternOptions $options) * * @param string $method Method name to call * @param array $args Method arguments - * @param array $options Cache options * @return mixed * @throws Exception */ - public function call($method, array $args = array(), array $options = array()) + public function call($method, array $args = array()) { - $classOptions = $this->getOptions(); - $object = $classOptions->getObject(); - $method = strtolower($method); + $options = $this->getOptions(); + $object = $options->getObject(); + $method = strtolower($method); // handle magic methods switch ($method) { @@ -72,8 +71,8 @@ public function call($method, array $args = array(), array $options = array()) $object->{$property} = $value; - if (!$classOptions->getObjectCacheMagicProperties() - || property_exists($object, $property) + if (!$options->getObjectCacheMagicProperties() + || property_exists($object, $property) ) { // no caching if property isn't magic // or caching magic properties is disabled @@ -83,20 +82,20 @@ public function call($method, array $args = array(), array $options = array()) // remove cached __get and __isset $removeKeys = null; if (method_exists($object, '__get')) { - $removeKeys[] = $this->generateKey('__get', array($property), $options); + $removeKeys[] = $this->generateKey('__get', array($property)); } if (method_exists($object, '__isset')) { - $removeKeys[] = $this->generateKey('__isset', array($property), $options); + $removeKeys[] = $this->generateKey('__isset', array($property)); } if ($removeKeys) { - $classOptions->getStorage()->removeMulti($removeKeys); + $options->getStorage()->removeItems($removeKeys); } return; case '__get': $property = array_shift($args); - if (!$classOptions->getObjectCacheMagicProperties() + if (!$options->getObjectCacheMagicProperties() || property_exists($object, $property) ) { // no caching if property isn't magic @@ -105,23 +104,12 @@ public function call($method, array $args = array(), array $options = array()) } array_unshift($args, $property); - - if (!isset($options['callback_key'])) { - if ((isset($options['entity_key']) - && ($entityKey = $options['entity_key']) !== null) - || ($entityKey = $classOptions->getObjectKey() !== null) - ) { - $options['callback_key'] = $entityKey . '::' . strtolower($method); - unset($options['entity_key']); - } - } - - return parent::call(array($object, '__get'), $args, $options); + return parent::call(array($object, '__get'), $args); case '__isset': $property = array_shift($args); - if (!$classOptions->getObjectCacheMagicProperties() + if (!$options->getObjectCacheMagicProperties() || property_exists($object, $property) ) { // no caching if property isn't magic @@ -129,24 +117,14 @@ public function call($method, array $args = array(), array $options = array()) return isset($object->{$property}); } - if (!isset($options['callback_key'])) { - if ((isset($options['entity_key']) - && ($entityKey = $options['entity_key']) !== null) - || ($entityKey = $classOptions->getObjectKey() !== null) - ) { - $options['callback_key'] = $entityKey . '::' . strtolower($method); - unset($options['entity_key']); - } - } - - return parent::call(array($object, '__isset'), array($property), $options); + return parent::call(array($object, '__isset'), array($property)); case '__unset': $property = array_shift($args); unset($object->{$property}); - if (!$classOptions->getObjectCacheMagicProperties() + if (!$options->getObjectCacheMagicProperties() || property_exists($object, $property) ) { // no caching if property isn't magic @@ -157,64 +135,65 @@ public function call($method, array $args = array(), array $options = array()) // remove previous cached __get and __isset calls $removeKeys = null; if (method_exists($object, '__get')) { - $removeKeys[] = $this->generateKey('__get', array($property), $options); + $removeKeys[] = $this->generateKey('__get', array($property)); } if (method_exists($object, '__isset')) { - $removeKeys[] = $this->generateKey('__isset', array($property), $options); + $removeKeys[] = $this->generateKey('__isset', array($property)); } if ($removeKeys) { - $classOptions->getStorage()->removeMulti($removeKeys); + $options->getStorage()->removeItems($removeKeys); } return; } - $cache = $classOptions->getCacheByDefault(); + $cache = $options->getCacheByDefault(); if ($cache) { - $cache = !in_array($method, $classOptions->getObjectNonCacheMethods()); + $cache = !in_array($method, $options->getObjectNonCacheMethods()); } else { - $cache = in_array($method, $classOptions->getObjectCacheMethods()); + $cache = in_array($method, $options->getObjectCacheMethods()); } if (!$cache) { if ($args) { return call_user_func_array(array($object, $method), $args); - } - return $object->{$method}(); - } - - if (!isset($options['callback_key'])) { - if ((isset($options['entity_key']) && ($entityKey = $options['entity_key']) !== null) - || (($entityKey = $classOptions->getObjectKey()) !== null) - ) { - $options['callback_key'] = $entityKey . '::' . strtolower($method); - unset($options['entity_key']); } + return $object->{$method}(); } - return parent::call(array($object, $method), $args, $options); + return parent::call(array($object, $method), $args); } /** - * Generate a unique key from the method name and arguments + * Generate a unique key in base of a key representing the callback part + * and a key representing the arguments part. * - * @param string $method The method name - * @param array $args Method arguments - * @param array $options Options + * @param string $method The method + * @param array $args Callback arguments * @return string * @throws Exception */ - public function generateKey($method, array $args = array(), array $options = array()) + public function generateKey($method, array $args = array()) { - $classOptions = $this->getOptions(); - if (!isset($options['callback_key'])) { - if ( (isset($options['entity_key']) && ($entityKey = $options['entity_key']) !== null) - || (($entityKey = $classOptions->getObjectKey()) !== null)) { - $options['callback_key'] = $entityKey . '::' . strtolower($method); - unset($options['entity_key']); - } - } + return $this->generateCallbackKey( + array($this->getOptions()->getObject(), $method), + $args + ); + } - return parent::generateKey(array($classOptions->getObject(), $method), $args, $options); + /** + * Generate a unique key in base of a key representing the callback part + * and a key representing the arguments part. + * + * @param callback $callback A valid callback + * @param array $args Callback arguments + * @return string + * @throws Exception + */ + protected function generateCallbackKey($callback, array $args = array()) + { + $callbackKey = md5($this->getOptions()->getObjectKey() . '::' . strtolower($callback[1])); + $argumentKey = $this->generateArgumentsKey($args); + return $callbackKey . $argumentKey; } /** @@ -314,7 +293,7 @@ public function __toString() * @return mixed * @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke */ - public function __invoke() + public function __invoke() { return $this->call('__invoke', func_get_args()); } diff --git a/src/Pattern/OutputCache.php b/src/Pattern/OutputCache.php index 88a1ea48e..4f3251e74 100644 --- a/src/Pattern/OutputCache.php +++ b/src/Pattern/OutputCache.php @@ -22,8 +22,7 @@ namespace Zend\Cache\Pattern; use Zend\Cache\Exception, - Zend\Cache\StorageFactory, - Zend\Cache\Storage\Adapter\AdapterInterface as StorageAdapter; + Zend\Cache\StorageFactory; /** * @category Zend @@ -62,7 +61,7 @@ public function setOptions(PatternOptions $options) * else start buffering output until end() is called or the script ends. * * @param string $key Key - * @param array $storageOptions Options passing to Zend\Cache\Storage\Adapter\AdapterInterface::getItem + * @param array $storageOptions Options passing to Zend\Cache\Storage\StorageInterface::getItem * @return boolean * @throws Exception */ @@ -89,7 +88,7 @@ public function start($key, array $storageOptions = array()) * Stops bufferung output, write buffered data to cache using the given key on start() * and displays the buffer. * - * @param array $storageOptions Options passed to Zend\Cache\Storage\Adapter\AdapterInterface::setItem + * @param array $storageOptions Options passed to Zend\Cache\Storage\StorageInterface::setItem * @return boolean TRUE on success, FALSE on failure writing to cache * @throws Exception */ diff --git a/src/Pattern/PatternOptions.php b/src/Pattern/PatternOptions.php index 8f0cd12aa..945105c46 100644 --- a/src/Pattern/PatternOptions.php +++ b/src/Pattern/PatternOptions.php @@ -23,7 +23,7 @@ use Zend\Cache\Exception, Zend\Cache\StorageFactory, - Zend\Cache\Storage\Adapter\AdapterInterface as StorageAdapter, + Zend\Cache\Storage\StorageInterface as Storage, Zend\Stdlib\Options; /** @@ -149,7 +149,7 @@ class PatternOptions extends Options * - ClassCache * - ObjectCache * - OutputCache - * @var null|StorageAdapter + * @var null|Storage */ protected $storage; @@ -170,7 +170,7 @@ class PatternOptions extends Options /** * Used by: * - CaptureCache - * @var null|StorageAdapter + * @var null|Storage */ protected $tagStorage; @@ -623,6 +623,9 @@ public function setObjectKey($objectKey) */ public function getObjectKey() { + if (!$this->objectKey) { + return get_class($this->getObject()); + } return $this->objectKey; } @@ -686,13 +689,12 @@ public function getPublicDir() * - ObjectCache * - OutputCache * - * @param string|array|StorageAdapter $storage + * @param string|array|Storage $storage * @return PatternOptions */ public function setStorage($storage) { - $storage = $this->storageFactory($storage); - $this->storage = $storage; + $this->storage = $this->storageFactory($storage); return $this; } @@ -705,7 +707,7 @@ public function setStorage($storage) * - ObjectCache * - OutputCache * - * @return null|StorageAdapter + * @return null|Storage */ public function getStorage() { @@ -772,13 +774,12 @@ public function getTags() * Used by: * - CaptureCache * - * @param string|array|StorageAdapter $tagStorage + * @param string|array|Storage $tagStorage * @return PatternOptions */ public function setTagStorage($tagStorage) { - $tagStorage = $this->storageFactory($tagStorage); - $this->tagStorage = $tagStorage; + $this->tagStorage = $this->storageFactory($tagStorage); return $this; } @@ -788,7 +789,7 @@ public function setTagStorage($tagStorage) * Used by: * - CaptureCache * - * @return null|StorageAdapter + * @return null|Storage */ public function getTagStorage() { @@ -858,7 +859,7 @@ protected function normalizeUmask($umask, $comparison) /** * Create a storage object from a given specification * - * @param array|string|StorageAdapter $storage + * @param array|string|Storage $storage * @return StorageAdapter */ protected function storageFactory($storage) @@ -867,9 +868,9 @@ protected function storageFactory($storage) $storage = StorageFactory::factory($storage); } elseif (is_string($storage)) { $storage = StorageFactory::adapterFactory($storage); - } elseif ( !($storage instanceof StorageAdapter) ) { + } elseif ( !($storage instanceof Storage) ) { throw new Exception\InvalidArgumentException( - 'The storage must be an instanceof Zend\Cache\Storage\Adapter\AdapterInterface ' + 'The storage must be an instanceof Zend\Cache\Storage\StorageInterface ' . 'or an array passed to Zend\Cache\Storage::factory ' . 'or simply the name of the storage adapter' ); diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 21ecea584..7534b53e0 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -31,6 +31,7 @@ Zend\Cache\Storage\ExceptionEvent, Zend\Cache\Storage\PostEvent, Zend\Cache\Storage\Plugin, + Zend\Cache\Storage\StorageInterface, Zend\EventManager\EventManager, Zend\EventManager\EventsCapableInterface; @@ -41,7 +42,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -abstract class AbstractAdapter implements AdapterInterface, EventsCapableInterface +abstract class AbstractAdapter implements StorageInterface, EventsCapableInterface { /** * The used EventManager if any @@ -84,27 +85,6 @@ abstract class AbstractAdapter implements AdapterInterface, EventsCapableInterfa */ protected $options; - /** - * Is a statement active - * - * @var bool - */ - protected $stmtActive = false; - - /** - * List of keys used for the active statement - * - * @var null|array - */ - protected $stmtKeys = null; - - /** - * Options used on starting the active statement - * - * @var null|array - */ - protected $stmtOptions = null; - /** * Constructor * @@ -130,7 +110,7 @@ public function __construct($options = null) */ public function __destruct() { - foreach ($this->getPlugins() as $plugin) { + foreach ($this->getPluginRegistry() as $plugin) { $this->removePlugin($plugin); } @@ -347,13 +327,16 @@ public function removePlugin(Plugin\PluginInterface $plugin) } /** - * Get all registered plugins + * Return registry of plugins * * @return SplObjectStorage */ - public function getPlugins() + public function getPluginRegistry() { - return $this->getPluginRegistry(); + if (!$this->pluginRegistry instanceof SplObjectStorage) { + $this->pluginRegistry = new SplObjectStorage(); + } + return $this->pluginRegistry; } /* reading */ @@ -361,14 +344,7 @@ public function getPlugins() /** * Get an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure @@ -378,7 +354,7 @@ public function getPlugins() * @triggers getItem.post(PostEvent) * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array(), & $success = null, & $casToken = null) + public function getItem($key, & $success = null, & $casToken = null) { if (!$this->getOptions()->getReadable()) { $success = false; @@ -386,13 +362,18 @@ public function getItem($key, array $options = array(), & $success = null, & $ca } $this->normalizeKey($key); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, - 'success' => & $success, - 'casToken' => & $casToken, - )); + + $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); @@ -400,7 +381,13 @@ public function getItem($key, array $options = array(), & $success = null, & $ca return $eventRs->last(); } - $result = $this->internalGetItem($args['key'], $args['options'], $args['success'], $args['casToken']); + if (isset($args['success'], $args['casToken'])) { + $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']); + } elseif (isset($args['success'])) { + $result = $this->internalGetItem($args['key'], $args['success']); + } else { + $result = $this->internalGetItem($args['key']); + } return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -411,32 +398,18 @@ public function getItem($key, array $options = array(), & $success = null, & $ca /** * Internal method to get an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - abstract protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null); + abstract protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null); /** * Get multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Associative array of keys and values * @throws Exception\ExceptionInterface * @@ -444,17 +417,15 @@ abstract protected function internalGetItem(& $normalizedKey, array & $normalize * @triggers getItems.post(PostEvent) * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + public function getItems(array $keys) { if (!$this->getOptions()->getReadable()) { return array(); } $this->normalizeKeys($keys); - $this->normalizeOptions($options); $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, + 'keys' => & $keys, )); try { @@ -463,7 +434,7 @@ public function getItems(array $keys, array $options = array()) return $eventRs->last(); } - $result = $this->internalGetItems($args['keys'], $args['options']); + $result = $this->internalGetItems($args['keys']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array(); @@ -474,23 +445,16 @@ public function getItems(array $keys, array $options = array()) /** * Internal method to get multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { $success = null; $result = array(); foreach ($normalizedKeys as $normalizedKey) { - $value = $this->internalGetItem($normalizedKey, $normalizedOptions, $success); + $value = $this->internalGetItem($normalizedKey, $success); if ($success) { $result[$normalizedKey] = $value; } @@ -502,14 +466,7 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Test if an item exists. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -517,17 +474,15 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized * @triggers hasItem.post(PostEvent) * @triggers hasItem.exception(ExceptionEvent) */ - public function hasItem($key, array $options = array()) + public function hasItem($key) { if (!$this->getOptions()->getReadable()) { return false; } $this->normalizeKey($key); - $this->normalizeOptions($options); $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, + 'key' => & $key, )); try { @@ -536,7 +491,7 @@ public function hasItem($key, array $options = array()) return $eventRs->last(); } - $result = $this->internalHasItem($args['key'], $args['options']); + $result = $this->internalHasItem($args['key']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -547,35 +502,21 @@ public function hasItem($key, array $options = array()) /** * Internal method to test if an item exists. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { $success = null; - $this->internalGetItem($normalizedKey, $normalizedOptions, $success); + $this->internalGetItem($normalizedKey, $success); return $success; } /** * Test multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Array of found keys * @throws Exception\ExceptionInterface * @@ -583,17 +524,15 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * @triggers hasItems.post(PostEvent) * @triggers hasItems.exception(ExceptionEvent) */ - public function hasItems(array $keys, array $options = array()) + public function hasItems(array $keys) { if (!$this->getOptions()->getReadable()) { return array(); } $this->normalizeKeys($keys); - $this->normalizeOptions($options); $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, + 'keys' => & $keys, )); try { @@ -602,7 +541,7 @@ public function hasItems(array $keys, array $options = array()) return $eventRs->last(); } - $result = $this->internalHasItems($args['keys'], $args['options']); + $result = $this->internalHasItems($args['keys']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array(); @@ -613,22 +552,15 @@ public function hasItems(array $keys, array $options = array()) /** * Internal method to test multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $keys - * @param array $options * @return array Array of found keys * @throws Exception\ExceptionInterface */ - protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalHasItems(array & $normalizedKeys) { $result = array(); foreach ($normalizedKeys as $normalizedKey) { - if ($this->internalHasItem($normalizedKey, $normalizedOptions)) { + if ($this->internalHasItem($normalizedKey)) { $result[] = $normalizedKey; } } @@ -638,14 +570,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized /** * Get metadata of an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * @@ -653,17 +578,15 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * @triggers getMetadata.post(PostEvent) * @triggers getMetadata.exception(ExceptionEvent) */ - public function getMetadata($key, array $options = array()) + public function getMetadata($key) { if (!$this->getOptions()->getReadable()) { return false; } $this->normalizeKey($key); - $this->normalizeOptions($options); $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, + 'key' => & $key, )); try { @@ -672,7 +595,7 @@ public function getMetadata($key, array $options = array()) return $eventRs->last(); } - $result = $this->internalGetMetadata($args['key'], $args['options']); + $result = $this->internalGetMetadata($args['key']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -683,20 +606,13 @@ public function getMetadata($key, array $options = array()) /** * Internal method to get metadata of an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) + protected function internalGetMetadata(& $normalizedKey) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalHasItem($normalizedKey)) { return false; } @@ -706,14 +622,7 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti /** * Get multiple metadata * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface * @@ -721,17 +630,15 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti * @triggers getMetadatas.post(PostEvent) * @triggers getMetadatas.exception(ExceptionEvent) */ - public function getMetadatas(array $keys, array $options = array()) + public function getMetadatas(array $keys) { if (!$this->getOptions()->getReadable()) { return array(); } $this->normalizeKeys($keys); - $this->normalizeOptions($options); $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, + 'keys' => & $keys, )); try { @@ -740,7 +647,7 @@ public function getMetadatas(array $keys, array $options = array()) return $eventRs->last(); } - $result = $this->internalGetMetadatas($args['keys'], $args['options']); + $result = $this->internalGetMetadatas($args['keys']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array(); @@ -751,22 +658,15 @@ public function getMetadatas(array $keys, array $options = array()) /** * Internal method to get multiple metadata * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface */ - protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetMetadatas(array & $normalizedKeys) { $result = array(); foreach ($normalizedKeys as $normalizedKey) { - $metadata = $this->internalGetMetadata($normalizedKey, $normalizedOptions); + $metadata = $this->internalGetMetadata($normalizedKey); if ($metadata !== false) { $result[$normalizedKey] = $metadata; } @@ -779,17 +679,8 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal /** * Store an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -797,18 +688,16 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal * @triggers setItem.post(PostEvent) * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + public function setItem($key, $value) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, + 'key' => & $key, + 'value' => & $value, )); try { @@ -817,7 +706,7 @@ public function setItem($key, $value, array $options = array()) return $eventRs->last(); } - $result = $this->internalSetItem($args['key'], $args['value'], $args['options']); + $result = $this->internalSetItem($args['key'], $args['value']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -828,35 +717,17 @@ public function setItem($key, $value, array $options = array()) /** * Internal method to store an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - abstract protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions); + abstract protected function internalSetItem(& $normalizedKey, & $value); /** * Store multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param array $keyValuePairs - * @param array $options * @return array Array of not stored keys * @throws Exception\ExceptionInterface * @@ -864,17 +735,15 @@ abstract protected function internalSetItem(& $normalizedKey, & $value, array & * @triggers setItems.post(PostEvent) * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs, array $options = array()) + public function setItems(array $keyValuePairs) { if (!$this->getOptions()->getWritable()) { return array_keys($keyValuePairs); } $this->normalizeKeyValuePairs($keyValuePairs); - $this->normalizeOptions($options); $args = new ArrayObject(array( 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, )); try { @@ -883,7 +752,7 @@ public function setItems(array $keyValuePairs, array $options = array()) return $eventRs->last(); } - $result = $this->internalSetItems($args['keyValuePairs'], $args['options']); + $result = $this->internalSetItems($args['keyValuePairs']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array_keys($keyValuePairs); @@ -894,24 +763,16 @@ public function setItems(array $keyValuePairs, array $options = array()) /** * Internal method to store multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalSetItems(array & $normalizedKeyValuePairs) { $failedKeys = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { - if (!$this->internalSetItem($normalizedKey, $value, $normalizedOptions)) { + if (!$this->internalSetItem($normalizedKey, $value)) { $failedKeys[] = $normalizedKey; } } @@ -921,17 +782,8 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n /** * Add an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -939,18 +791,16 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * @triggers addItem.post(PostEvent) * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + public function addItem($key, $value) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, + 'key' => & $key, + 'value' => & $value, )); try { @@ -959,7 +809,7 @@ public function addItem($key, $value, array $options = array()) return $eventRs->last(); } - $result = $this->internalAddItem($args['key'], $args['value'], $args['options']); + $result = $this->internalAddItem($args['key'], $args['value']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -970,41 +820,23 @@ public function addItem($key, $value, array $options = array()) /** * Internal method to add an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalAddItem(& $normalizedKey, & $value) { - if ($this->internalHasItem($normalizedKey, $normalizedOptions)) { + if ($this->internalHasItem($normalizedKey)) { return false; } - return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); + return $this->internalSetItem($normalizedKey, $value); } /** * Add multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param array $keyValuePairs - * @param array $options * @return array Array of not stored keys * @throws Exception\ExceptionInterface * @@ -1012,17 +844,15 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz * @triggers addItems.post(PostEvent) * @triggers addItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs, array $options = array()) + public function addItems(array $keyValuePairs) { if (!$this->getOptions()->getWritable()) { return array_keys($keyValuePairs); } $this->normalizeKeyValuePairs($keyValuePairs); - $this->normalizeOptions($options); $args = new ArrayObject(array( 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, )); try { @@ -1031,7 +861,7 @@ public function addItems(array $keyValuePairs, array $options = array()) return $eventRs->last(); } - $result = $this->internalAddItems($args['keyValuePairs'], $args['options']); + $result = $this->internalAddItems($args['keyValuePairs']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array_keys($keyValuePairs); @@ -1042,24 +872,15 @@ public function addItems(array $keyValuePairs, array $options = array()) /** * Internal method to add multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalAddItems(array & $normalizedKeyValuePairs) { $result = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { - if (!$this->internalAddItem($normalizedKey, $value, $normalizedOptions)) { + if (!$this->internalAddItem($normalizedKey, $value)) { $result[] = $normalizedKey; } } @@ -1069,17 +890,8 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n /** * Replace an existing item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -1087,18 +899,16 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n * @triggers replaceItem.post(PostEvent) * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value, array $options = array()) + public function replaceItem($key, $value) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, + 'key' => & $key, + 'value' => & $value, )); try { @@ -1107,7 +917,7 @@ public function replaceItem($key, $value, array $options = array()) return $eventRs->last(); } - $result = $this->internalReplaceItem($args['key'], $args['value'], $args['options']); + $result = $this->internalReplaceItem($args['key'], $args['value']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -1118,42 +928,24 @@ public function replaceItem($key, $value, array $options = array()) /** * Internal method to replace an existing item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalReplaceItem(& $normalizedKey, & $value) { - if (!$this->internalhasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalhasItem($normalizedKey)) { return false; } - return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); + return $this->internalSetItem($normalizedKey, $value); } /** * Replace multiple existing items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param array $keyValuePairs - * @param array $options * @return array Array of not stored keys * @throws Exception\ExceptionInterface * @@ -1161,17 +953,15 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm * @triggers replaceItems.post(PostEvent) * @triggers replaceItems.exception(ExceptionEvent) */ - public function replaceItems(array $keyValuePairs, array $options = array()) + public function replaceItems(array $keyValuePairs) { if (!$this->getOptions()->getWritable()) { return array_keys($keyValuePairs); } $this->normalizeKeyValuePairs($keyValuePairs); - $this->normalizeOptions($options); $args = new ArrayObject(array( 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, )); try { @@ -1180,7 +970,7 @@ public function replaceItems(array $keyValuePairs, array $options = array()) return $eventRs->last(); } - $result = $this->internalReplaceItems($args['keyValuePairs'], $args['options']); + $result = $this->internalReplaceItems($args['keyValuePairs']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array_keys($keyValuePairs); @@ -1191,24 +981,15 @@ public function replaceItems(array $keyValuePairs, array $options = array()) /** * Internal method to replace multiple existing items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalReplaceItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalReplaceItems(array & $normalizedKeyValuePairs) { $result = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { - if (!$this->internalReplaceItem($normalizedKey, $value, $normalizedOptions)) { + if (!$this->internalReplaceItem($normalizedKey, $value)) { $result[] = $normalizedKey; } } @@ -1221,36 +1002,25 @@ protected function internalReplaceItems(array & $normalizedKeyValuePairs, array * It uses the token received from getItem() to check if the item has * changed before overwriting it. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param mixed $token * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @see getItem() * @see setItem() */ - public function checkAndSetItem($token, $key, $value, array $options = array()) + public function checkAndSetItem($token, $key, $value) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'token' => & $token, - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, + 'token' => & $token, + 'key' => & $key, + 'value' => & $value, )); try { @@ -1259,7 +1029,7 @@ public function checkAndSetItem($token, $key, $value, array $options = array()) return $eventRs->last(); } - $result = $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value'], $args['options']); + $result = $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -1270,44 +1040,28 @@ public function checkAndSetItem($token, $key, $value, array $options = array()) /** * Internal method to set an item only if token matches * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param mixed $token * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface * @see getItem() * @see setItem() */ - protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) + protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value) { - $oldValue = $this->internalGetItem($normalizedKey, $normalizedOptions); + $oldValue = $this->internalGetItem($normalizedKey); if ($oldValue !== $token) { return false; } - return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); + return $this->internalSetItem($normalizedKey, $value); } /** * Reset lifetime of an item * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -1315,17 +1069,15 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, * @triggers touchItem.post(PostEvent) * @triggers touchItem.exception(ExceptionEvent) */ - public function touchItem($key, array $options = array()) + public function touchItem($key) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, + 'key' => & $key, )); try { @@ -1334,7 +1086,7 @@ public function touchItem($key, array $options = array()) return $eventRs->last(); } - $result = $this->internalTouchItem($args['key'], $args['options']); + $result = $this->internalTouchItem($args['key']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -1345,47 +1097,25 @@ public function touchItem($key, array $options = array()) /** * Internal method to reset lifetime of an item * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) + protected function internalTouchItem(& $normalizedKey) { $success = null; - $value = $this->internalGetItem($normalizedKey, $normalizedOptions, $success); + $value = $this->internalGetItem($normalizedKey, $success); if (!$success) { return false; } - // rewrite item to update mtime/ttl - if (!isset($normalizedOptions['tags'])) { - $info = $this->internalGetMetadata($normalizedKey, $normalizedOptions); - if (isset($info['tags'])) { - $normalizedOptions['tags'] = & $info['tags']; - } - } - - return $this->internalReplaceItem($normalizedKey, $value, $normalizedOptions); + return $this->internalReplaceItem($normalizedKey, $value); } /** * Reset lifetime of multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Array of not updated keys * @throws Exception\ExceptionInterface * @@ -1393,17 +1123,15 @@ protected function internalTouchItem(& $normalizedKey, array & $normalizedOption * @triggers touchItems.post(PostEvent) * @triggers touchItems.exception(ExceptionEvent) */ - public function touchItems(array $keys, array $options = array()) + public function touchItems(array $keys) { if (!$this->getOptions()->getWritable()) { return $keys; } $this->normalizeKeys($keys); - $this->normalizeOptions($options); $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, + 'keys' => & $keys, )); try { @@ -1412,7 +1140,7 @@ public function touchItems(array $keys, array $options = array()) return $eventRs->last(); } - $result = $this->internalTouchItems($args['keys'], $args['options']); + $result = $this->internalTouchItems($args['keys']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { return $this->triggerException(__FUNCTION__, $args, $keys, $e); @@ -1422,22 +1150,15 @@ public function touchItems(array $keys, array $options = array()) /** * Internal method to reset lifetime of multiple items. * - * Options: - * - ttl - * - The namespace to us - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Array of not updated keys * @throws Exception\ExceptionInterface */ - protected function internalTouchItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalTouchItems(array & $normalizedKeys) { $result = array(); foreach ($normalizedKeys as $normalizedKey) { - if (!$this->internalTouchItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalTouchItem($normalizedKey)) { $result[] = $normalizedKey; } } @@ -1447,12 +1168,7 @@ protected function internalTouchItems(array & $normalizedKeys, array & $normaliz /** * Remove an item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -1460,17 +1176,15 @@ protected function internalTouchItems(array & $normalizedKeys, array & $normaliz * @triggers removeItem.post(PostEvent) * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + public function removeItem($key) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'options' => & $options, + 'key' => & $key, )); try { @@ -1479,7 +1193,7 @@ public function removeItem($key, array $options = array()) return $eventRs->last(); } - $result = $this->internalRemoveItem($args['key'], $args['options']); + $result = $this->internalRemoveItem($args['key']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -1490,26 +1204,16 @@ public function removeItem($key, array $options = array()) /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - abstract protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions); + abstract protected function internalRemoveItem(& $normalizedKey); /** * Remove multiple items. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Array of not removed keys * @throws Exception\ExceptionInterface * @@ -1517,17 +1221,15 @@ abstract protected function internalRemoveItem(& $normalizedKey, array & $normal * @triggers removeItems.post(PostEvent) * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItems(array $keys, array $options = array()) + public function removeItems(array $keys) { if (!$this->getOptions()->getWritable()) { return $keys; } - $this->normalizeOptions($options); $this->normalizeKeys($keys); $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, + 'keys' => & $keys, )); try { @@ -1536,7 +1238,7 @@ public function removeItems(array $keys, array $options = array()) return $eventRs->last(); } - $result = $this->internalRemoveItems($args['keys'], $args['options']); + $result = $this->internalRemoveItems($args['keys']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { return $this->triggerException(__FUNCTION__, $args, $keys, $e); @@ -1546,20 +1248,15 @@ public function removeItems(array $keys, array $options = array()) /** * Internal method to remove multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $keys - * @param array $options * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ - protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalRemoveItems(array & $normalizedKeys) { $result = array(); foreach ($normalizedKeys as $normalizedKey) { - if (!$this->internalRemoveItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalRemoveItem($normalizedKey)) { $result[] = $normalizedKey; } } @@ -1569,15 +1266,8 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali /** * Increment an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key * @param int $value - * @param array $options * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface * @@ -1585,18 +1275,16 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali * @triggers incrementItem.post(PostEvent) * @triggers incrementItem.exception(ExceptionEvent) */ - public function incrementItem($key, $value, array $options = array()) + public function incrementItem($key, $value) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, + 'key' => & $key, + 'value' => & $value, )); try { @@ -1605,7 +1293,7 @@ public function incrementItem($key, $value, array $options = array()) return $eventRs->last(); } - $result = $this->internalIncrementItem($args['key'], $args['value'], $args['options']); + $result = $this->internalIncrementItem($args['key'], $args['value']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -1616,29 +1304,22 @@ public function incrementItem($key, $value, array $options = array()) /** * Internal method to increment an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalIncrementItem(& $normalizedKey, & $value) { $success = null; $value = (int) $value; - $get = (int) $this->internalGetItem($normalizedKey, $normalizedOptions, $success); + $get = (int) $this->internalGetItem($normalizedKey, $success); $newValue = $get + $value; if ($success) { - $this->internalReplaceItem($normalizedKey, $newValue, $normalizedOptions); + $this->internalReplaceItem($normalizedKey, $newValue); } else { - $this->internalAddItem($normalizedKey, $newValue, $normalizedOptions); + $this->internalAddItem($normalizedKey, $newValue); } return $newValue; @@ -1647,14 +1328,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no /** * Increment multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keyValuePairs - * @param array $options * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface * @@ -1662,17 +1336,15 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no * @triggers incrementItems.post(PostEvent) * @triggers incrementItems.exception(ExceptionEvent) */ - public function incrementItems(array $keyValuePairs, array $options = array()) + public function incrementItems(array $keyValuePairs) { if (!$this->getOptions()->getWritable()) { return array(); } - $this->normalizeOptions($options); $this->normalizeKeyValuePairs($keyValuePairs); $args = new ArrayObject(array( 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, )); try { @@ -1681,7 +1353,7 @@ public function incrementItems(array $keyValuePairs, array $options = array()) return $eventRs->last(); } - $result = $this->internalIncrementItems($args['keyValuePairs'], $args['options']); + $result = $this->internalIncrementItems($args['keyValuePairs']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array(); @@ -1692,22 +1364,15 @@ public function incrementItems(array $keyValuePairs, array $options = array()) /** * Internal method to increment multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface */ - protected function internalIncrementItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalIncrementItems(array & $normalizedKeyValuePairs) { $result = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { - $newValue = $this->internalIncrementItem($normalizedKey, $value, $normalizedOptions); + $newValue = $this->internalIncrementItem($normalizedKey, $value); if ($newValue !== false) { $result[$normalizedKey] = $newValue; } @@ -1718,15 +1383,8 @@ protected function internalIncrementItems(array & $normalizedKeyValuePairs, arra /** * Decrement an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key * @param int $value - * @param array $options * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface * @@ -1734,18 +1392,16 @@ protected function internalIncrementItems(array & $normalizedKeyValuePairs, arra * @triggers decrementItem.post(PostEvent) * @triggers decrementItem.exception(ExceptionEvent) */ - public function decrementItem($key, $value, array $options = array()) + public function decrementItem($key, $value) { if (!$this->getOptions()->getWritable()) { return false; } - $this->normalizeOptions($options); $this->normalizeKey($key); $args = new ArrayObject(array( - 'key' => & $key, - 'value' => & $value, - 'options' => & $options, + 'key' => & $key, + 'value' => & $value, )); try { @@ -1754,7 +1410,7 @@ public function decrementItem($key, $value, array $options = array()) return $eventRs->last(); } - $result = $this->internalDecrementItem($args['key'], $args['value'], $args['options']); + $result = $this->internalDecrementItem($args['key'], $args['value']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = false; @@ -1765,29 +1421,22 @@ public function decrementItem($key, $value, array $options = array()) /** * Internal method to decrement an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalDecrementItem(& $normalizedKey, & $value) { $success = null; $value = (int) $value; - $get = (int) $this->internalGetItem($normalizedKey, $normalizedOptions, $success); + $get = (int) $this->internalGetItem($normalizedKey, $success); $newValue = $get - $value; if ($success) { - $this->internalReplaceItem($normalizedKey, $newValue, $normalizedOptions); + $this->internalReplaceItem($normalizedKey, $newValue); } else { - $this->internalAddItem($normalizedKey, $newValue, $normalizedOptions); + $this->internalAddItem($normalizedKey, $newValue); } return $newValue; @@ -1796,14 +1445,7 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no /** * Decrement multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keyValuePairs - * @param array $options * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface * @@ -1811,17 +1453,15 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no * @triggers incrementItems.post(PostEvent) * @triggers incrementItems.exception(ExceptionEvent) */ - public function decrementItems(array $keyValuePairs, array $options = array()) + public function decrementItems(array $keyValuePairs) { if (!$this->getOptions()->getWritable()) { return array(); } - $this->normalizeOptions($options); $this->normalizeKeyValuePairs($keyValuePairs); $args = new ArrayObject(array( 'keyValuePairs' => & $keyValuePairs, - 'options' => & $options, )); try { @@ -1830,7 +1470,7 @@ public function decrementItems(array $keyValuePairs, array $options = array()) return $eventRs->last(); } - $result = $this->internalDecrementItems($args['keyValuePairs'], $args['options']); + $result = $this->internalDecrementItems($args['keyValuePairs']); return $this->triggerPost(__FUNCTION__, $args, $result); } catch (\Exception $e) { $result = array(); @@ -1841,22 +1481,15 @@ public function decrementItems(array $keyValuePairs, array $options = array()) /** * Internal method to decrement multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Associative array of keys and new values * @throws Exception\ExceptionInterface */ - protected function internalDecrementItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalDecrementItems(array & $normalizedKeyValuePairs) { $result = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { - $newValue = $this->decrementItem($normalizedKey, $value, $normalizedOptions); + $newValue = $this->decrementItem($normalizedKey, $value); if ($newValue !== false) { $result[$normalizedKey] = $newValue; } @@ -1864,521 +1497,6 @@ protected function internalDecrementItems(array & $normalizedKeyValuePairs, arra return $result; } - /* non-blocking */ - - /** - * Request multiple items. - * - * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - select optional - * - An array of the information the returned item contains - * (Default: array('key', 'value')) - * - callback optional - * - An result callback will be invoked for each item in the result set. - * - The first argument will be the item array. - * - The callback does not have to return anything. - * - * @param array $keys - * @param array $options - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - * - * @triggers getDelayed.pre(PreEvent) - * @triggers getDelayed.post(PostEvent) - * @triggers getDelayed.exception(ExceptionEvent) - */ - public function getDelayed(array $keys, array $options = array()) - { - if (!$this->getOptions()->getReadable()) { - return false; - } elseif (!$keys) { - // empty statement - return true; - } - - $this->normalizeKeys($keys); - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'keys' => & $keys, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalGetDelayed($args['keys'], $args['options']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to request multiple items. - * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * - select - * - An array of the information the returned item contains - * - callback optional - * - An result callback will be invoked for each item in the result set. - * - The first argument will be the item array. - * - The callback does not have to return anything. - * - * @param array $normalizedKeys - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - $this->stmtOptions = array_merge($this->getOptions()->toArray(), $normalizedOptions); - $this->stmtKeys = & $normalizedKeys; - $this->stmtActive = true; - - if (isset($normalizedOptions['callback'])) { - $callback = $normalizedOptions['callback']; - if (!is_callable($callback, false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - - while ( ($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } - } - - return true; - } - - /* find */ - - /** - * Find items. - * - * Options: - * - ttl optional - * - The time-to-live (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - Tags to search for used with matching modes of - * Adapter::MATCH_TAGS_* - * - * @param int $mode Matching mode (Value of Adapter::MATCH_*) - * @param array $options - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - * - * @triggers find.pre(PreEvent) - * @triggers find.post(PostEvent) - * @triggers find.exception(ExceptionEvent) - */ - public function find($mode = self::MATCH_ACTIVE, array $options = array()) - { - if (!$this->getOptions()->getReadable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_ACTIVE, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalFind($args['mode'], $args['options']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * internal method to find items. - * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * - tags - * - Tags to search for used with matching modes of - * Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalFind(& $normalizedMode, array & $normalizedOptions) - { - throw new Exception\UnsupportedMethodCallException('find isn\'t supported by this adapter'); - } - - /** - * Fetches the next item from result set - * - * @return array|boolean The next item or false - * @throws Exception\ExceptionInterface - * @see fetchAll() - * - * @triggers fetch.pre(PreEvent) - * @triggers fetch.post(PostEvent) - * @triggers fetch.exception(ExceptionEvent) - */ - public function fetch() - { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalFetch(); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to fetch the next item from result set - * - * @return array|boolean The next item or false - * @throws Exception\ExceptionInterface - */ - protected function internalFetch() - { - if (!$this->stmtActive) { - return false; - } - - $options = $this->stmtOptions; - $success = null; - - do { - $key = array_shift($this->stmtKeys); - if ($key === null) { - break; - } - - $item = array(); - $value = $info = $exist = null; - foreach ($options['select'] as $select) { - if ($select == 'key') { - $item['key'] = $key; - } elseif ($select == 'value') { - $value = $this->internalGetItem($key, $options, $success); - if (!$success) { - $exist = false; - break; - } - $exist = true; - $item['value'] = $value; - } else { - if ($info === null) { - $info = $this->internalGetMetadata($key, $options); - if ($info === false) { - $exist = false; - break; - } - $exist = true; - } - $item[$select] = isset($info[$select]) ? $info[$select] : null; - } - } - - // goto next if not exists - if ($exist === false || ($exist === null && !$this->internalHasItem($key, $options))) { - continue; - } - - return $item; - } while (true); - - // clear statement - $this->stmtActive = false; - $this->stmtKeys = null; - $this->stmtOptions = null; - - return false; - } - - /** - * Returns all items of result set. - * - * @return array The result set as array containing all items - * @throws Exception\ExceptionInterface - * @see fetch() - * - * @triggers fetchAll.pre(PreEvent) - * @triggers fetchAll.post(PostEvent) - * @triggers fetchAll.exception(ExceptionEvent) - */ - public function fetchAll() - { - $args = new ArrayObject(); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalFetchAll(); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = array(); - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to return all items of result set. - * - * @return array The result set as array containing all items - * @throws Exception\ExceptionInterface - * @see fetch() - */ - protected function internalFetchAll() - { - $rs = array(); - while (($item = $this->internalFetch()) !== false) { - $rs[] = $item; - } - return $rs; - } - - /* cleaning */ - - /** - * Clear items off all namespaces. - * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - tags optional - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $mode Matching mode (Value of Adapter::MATCH_*) - * @param array $options - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - * - * @triggers clear.pre(PreEvent) - * @triggers clear.post(PostEvent) - * @triggers clear.exception(ExceptionEvent) - */ - public function clear($mode = self::MATCH_EXPIRED, array $options = array()) - { - if (!$this->getOptions()->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalClear($args['mode'], $args['options']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to clear items off all namespaces. - * - * Options: - * - ttl - * - The time-to-life - * - tags - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - throw new Exception\RuntimeException( - "This adapter doesn't support to clear items off all namespaces" - ); - } - - /** - * Clear items by namespace. - * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $mode Matching mode (Value of Adapter::MATCH_*) - * @param array $options - * @return boolean - * @throws Exception\ExceptionInterface - * @see clear() - * - * @triggers clearByNamespace.pre(PreEvent) - * @triggers clearByNamespace.post(PostEvent) - * @triggers clearByNamespace.exception(ExceptionEvent) - */ - public function clearByNamespace($mode = self::MATCH_EXPIRED, array $options = array()) - { - if (!$this->getOptions()->getWritable()) { - return false; - } - - $this->normalizeOptions($options); - $this->normalizeMatchingMode($mode, self::MATCH_EXPIRED, $options); - $args = new ArrayObject(array( - 'mode' => & $mode, - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalClearByNamespace($args['mode'], $args['options']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Clear items by namespace. - * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clear() - */ - protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) - { - throw new Exception\RuntimeException( - "This adapter doesn't support to clear items by namespace" - ); - } - - /** - * Optimize adapter storage. - * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - * @param array $options - * @return boolean - * @throws Exception\ExceptionInterface - * - * @triggers optimize.pre(PreEvent) - * @triggers optimize.post(PostEvent) - * @triggers optimize.exception(ExceptionEvent) - */ - public function optimize(array $options = array()) - { - if (!$this->getOptions()->getWritable()) { - return false; - } - - $args = new ArrayObject(array( - 'options' => & $options - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalOptimize($args['options']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to optimize adapter storage. - * - * Options: - * - namespace - * - The namespace to use - * - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - */ - protected function internalOptimize(array & $normalizedOptions) - { - return true; - } - /* status */ /** @@ -2421,185 +1539,8 @@ protected function internalGetCapabilities() return $this->capabilities; } - /** - * Get storage capacity. - * - * @param array $options - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - * - * @triggers getCapacity.pre(PreEvent) - * @triggers getCapacity.post(PostEvent) - * @triggers getCapacity.exception(ExceptionEvent) - */ - public function getCapacity(array $options = array()) - { - $this->normalizeOptions($options); - $args = new ArrayObject(array( - 'options' => & $options, - )); - - try { - $eventRs = $this->triggerPre(__FUNCTION__, $args); - if ($eventRs->stopped()) { - return $eventRs->last(); - } - - $result = $this->internalGetCapacity($args['options']); - return $this->triggerPost(__FUNCTION__, $args, $result); - } catch (\Exception $e) { - $result = false; - return $this->triggerException(__FUNCTION__, $args, $result, $e); - } - } - - /** - * Internal method to get storage capacity. - * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - */ - abstract protected function internalGetCapacity(array & $normalizedOptions); - /* internal */ - /** - * Validates and normalizes the $options argument - * - * @param array $options - * @return void - */ - protected function normalizeOptions(array &$options) - { - $baseOptions = $this->getOptions(); - - // ttl - if (isset($options['ttl'])) { - $this->normalizeTtl($options['ttl']); - } else { - $options['ttl'] = $baseOptions->getTtl(); - } - - // namespace - if (isset($options['namespace'])) { - $this->normalizeNamespace($options['namespace']); - } else { - $options['namespace'] = $baseOptions->getNamespace(); - } - - // tags - if (isset($options['tags'])) { - $this->normalizeTags($options['tags']); - } else { - $options['tags'] = null; - } - - // select - if (isset($options['select'])) { - $this->normalizeSelect($options['select']); - } else { - $options['select'] = array('key', 'value'); - } - } - - /** - * Validates and normalize a TTL. - * - * @param int|float $ttl - * @return void - * @throws Exception\InvalidArgumentException - */ - protected function normalizeTtl(&$ttl) - { - if (!is_int($ttl)) { - $ttl = (float) $ttl; - - // convert to int if possible - if ($ttl === (float) (int) $ttl) { - $ttl = (int) $ttl; - } - } - - if ($ttl < 0) { - throw new Exception\InvalidArgumentException("TTL can't be negative"); - } - } - - /** - * Validates and normalize a namespace. - * - * @param string $namespace - * @return void - * @throws Exception\InvalidArgumentException - */ - protected function normalizeNamespace(&$namespace) - { - $namespace = (string) $namespace; - $pattern = $this->getOptions()->getNamespacePattern(); - if ($pattern && !preg_match($pattern, $namespace)) { - throw new Exception\InvalidArgumentException( - "The namespace '{$namespace}' doesn't match against pattern '{$pattern}'" - ); - } - } - - /** - * Validates and normalize tags array - * - * @param array $tags - * @return void - * @throws Exception\InvalidArgumentException - */ - protected function normalizeTags(&$tags) - { - if (!is_array($tags)) { - throw new Exception\InvalidArgumentException('Tags have to be an array'); - } - - foreach ($tags as &$tag) { - $tag = (string) $tag; - if ($tag === '') { - throw new Exception\InvalidArgumentException('Empty tags are not allowed'); - } - } - - $tags = array_values(array_unique($tags)); - } - - /** - * Validates and normalize select array - * - * @param string[]|string - * @return void - */ - protected function normalizeSelect(&$select) - { - if (!is_array($select)) { - $select = array((string) $select); - } else { - $select = array_unique($select); - } - } - - /** - * Normalize the matching mode needed on (clear and find) - * - * @todo normalize matching mode with given tags - * @param int $mode Matching mode to normalize - * @param int $default Default matching mode - * @return void - */ - protected function normalizeMatchingMode(&$mode, $default, array &$normalizedOptions) - { - $mode = (int) $mode; - if (($mode & self::MATCH_EXPIRED) != self::MATCH_EXPIRED - && ($mode & self::MATCH_ACTIVE) != self::MATCH_ACTIVE - ) { - $mode = $mode | (int) $default; - } - } - /** * Validates and normalizes a key * @@ -2607,7 +1548,7 @@ protected function normalizeMatchingMode(&$mode, $default, array &$normalizedOpt * @return void * @throws Exception\InvalidArgumentException On an invalid key */ - protected function normalizeKey(&$key) + protected function normalizeKey(& $key) { $key = (string) $key; @@ -2629,7 +1570,7 @@ protected function normalizeKey(&$key) * @return void * @throws Exception\InvalidArgumentException On an invalid key */ - protected function normalizeKeys(array &$keys) + protected function normalizeKeys(array & $keys) { if (!$keys) { throw new Exception\InvalidArgumentException( @@ -2657,18 +1598,4 @@ protected function normalizeKeyValuePairs(array & $keyValuePairs) } $keyValuePairs = $normalizedKeyValuePairs; } - - /** - * Return registry of plugins - * - * @return SplObjectStorage - */ - protected function getPluginRegistry() - { - if (!$this->pluginRegistry instanceof SplObjectStorage) { - $this->pluginRegistry = new SplObjectStorage(); - } - return $this->pluginRegistry; - } - } diff --git a/src/Storage/Adapter/AbstractZendServer.php b/src/Storage/Adapter/AbstractZendServer.php index 349cdb1cf..35e3114ce 100644 --- a/src/Storage/Adapter/AbstractZendServer.php +++ b/src/Storage/Adapter/AbstractZendServer.php @@ -47,21 +47,18 @@ abstract class AbstractZendServer extends AbstractAdapter /** * Internal method to get an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) + protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) { - $internalKey = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR . $normalizedKey; - $result = $this->zdcFetch($internalKey); + $prefix = $this->getOptions()->getNamespace() . self::NAMESPACE_SEPARATOR; + $internalKey = $prefix . $normalizedKey; + + $result = $this->zdcFetch($internalKey); if ($result === false) { $success = false; $result = null; @@ -76,27 +73,22 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, /** * Internal method to get multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { - $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; + $prefix = $this->getOptions()->getNamespace() . self::NAMESPACE_SEPARATOR; + $prefixL = strlen($prefix); $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { $internalKeys[] = $prefix . $normalizedKey; } - $fetch = $this->zdcFetchMulti($internalKeys); - $prefixL = strlen($prefix); - $result = array(); + $fetch = $this->zdcFetchMulti($internalKeys); + $result = array(); foreach ($fetch as $k => & $v) { $result[ substr($k, $prefixL) ] = $v; } @@ -107,45 +99,37 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Internal method to test if an item exists. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { - $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; + + $prefix = $this->getOptions()->getNamespace() . self::NAMESPACE_SEPARATOR; return ($this->zdcFetch($prefix . $normalizedKey) !== false); } /** * Internal method to test multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $keys - * @param array $options * @return array Array of found keys * @throws Exception\ExceptionInterface */ - protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalHasItems(array & $normalizedKeys) { - $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; + $prefix = $this->getOptions()->getNamespace() . self::NAMESPACE_SEPARATOR; + $prefixL = strlen($prefix); $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { $internalKeys[] = $prefix . $normalizedKey; } - $fetch = $this->zdcFetchMulti($internalKeys); - $prefixL = strlen($prefix); - $result = array(); + $fetch = $this->zdcFetchMulti($internalKeys); + $result = array(); foreach ($fetch as $internalKey => & $value) { $result[] = substr($internalKey, $prefixL); } @@ -156,29 +140,25 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized /** * Get metadata for multiple items * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and metadata * * @triggers getMetadatas.pre(PreEvent) * @triggers getMetadatas.post(PostEvent) * @triggers getMetadatas.exception(ExceptionEvent) */ - protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetMetadatas(array & $normalizedKeys) { - $prefix = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR; + $prefix = $this->getOptions()->getNamespace() . self::NAMESPACE_SEPARATOR; + $prefixL = strlen($prefix); + $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { $internalKeys[] = $prefix . $normalizedKey; } - $fetch = $this->zdcFetchMulti($internalKeys); - $prefixL = strlen($prefix); - $result = array(); + $fetch = $this->zdcFetchMulti($internalKeys); + $result = array(); foreach ($fetch as $internalKey => $value) { $result[ substr($internalKey, $prefixL) ] = array(); } @@ -191,91 +171,32 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal /** * Internal method to store an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalSetItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR . $normalizedKey; - $this->zdcStore($internalKey, $value, $normalizedOptions['ttl']); + $options = $this->getOptions(); + $internalKey = $options->getNamespace() . self::NAMESPACE_SEPARATOR . $normalizedKey; + $this->zdcStore($internalKey, $value, $options->getTtl()); return true; } /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) + protected function internalRemoveItem(& $normalizedKey) { - $internalKey = $normalizedOptions['namespace'] . self::NAMESPACE_SEPARATOR . $normalizedKey; + $internalKey = $this->getOptions()->getNamespace() . self::NAMESPACE_SEPARATOR . $normalizedKey; return $this->zdcDelete($internalKey); } - /* cleaning */ - - /** - * Internal method to clear items off all namespaces. - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - // clear all - if (($normalizedMode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { - $this->zdcClear(); - } - - // expired items will be deleted automatic - - return true; - } - - /** - * Clear items by namespace. - * - * Options: - * - namespace - * - The namespace to use - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clear() - */ - protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) - { - // clear all - if (($normalizedMode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { - $this->zdcClearByNamespace($normalizedOptions['namespace']); - } - - // expired items will be deleted automatic - - return true; - } - /* status */ /** @@ -304,16 +225,12 @@ protected function internalGetCapabilities() 'supportedMetadata' => array(), 'maxTtl' => 0, 'staticTtl' => true, - 'tagging' => false, 'ttlPrecision' => 1, 'useRequestTime' => false, 'expiredRead' => false, 'maxKeyLength' => 0, 'namespaceIsPrefix' => true, 'namespaceSeparator' => self::NAMESPACE_SEPARATOR, - 'iterable' => false, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, ) ); } @@ -360,21 +277,4 @@ abstract protected function zdcFetchMulti(array $internalKeys); * @throws Exception\RuntimeException */ abstract protected function zdcDelete($internalKey); - - /** - * Clear items of all namespaces from Zend Data Cache (zdc) - * - * @return void - * @throws Exception\RuntimeException - */ - abstract protected function zdcClear(); - - /** - * Clear items of the given namespace from Zend Data Cache (zdc) - * - * @param string $namespace - * @return void - * @throws Exception\RuntimeException - */ - abstract protected function zdcClearByNamespace($namespace); } diff --git a/src/Storage/Adapter/AdapterInterface.php b/src/Storage/Adapter/AdapterInterface.php deleted file mode 100644 index d89071c2e..000000000 --- a/src/Storage/Adapter/AdapterInterface.php +++ /dev/null @@ -1,428 +0,0 @@ -adapter = $adapter; return $this; @@ -162,15 +156,8 @@ public function getKeyPattern() */ public function setNamespace($namespace) { - $namespace = (string)$namespace; + $namespace = (string) $namespace; if ($this->namespace !== $namespace) { - $pattern = $this->getNamespacePattern(); - if ($pattern && !preg_match($pattern, $namespace)) { - throw new Exception\InvalidArgumentException( - "The namespace '{$namespace}' doesn't match agains pattern '{$pattern}'" - ); - } - $this->triggerOptionEvent('namespace', $namespace); $this->namespace = $namespace; } @@ -188,48 +175,6 @@ public function getNamespace() return $this->namespace; } - /** - * Set namespace pattern - * - * @param null|string $pattern - * @return AdapterOptions - */ - public function setNamespacePattern($pattern) - { - $pattern = (string) $pattern; - if ($this->namespacePattern !== $pattern) { - if ($pattern !== '') { - // validate pattern - if (@preg_match($pattern, '') === false) { - $err = error_get_last(); - throw new Exception\InvalidArgumentException("Invalid pattern '{$pattern}': {$err['message']}"); - - // validate current namespace - } elseif (($ns = $this->getNamespace()) && !preg_match($pattern, $ns)) { - throw new Exception\RuntimeException( - "The current namespace '{$ns}' doesn't match agains pattern '{$pattern}'" - . " - please change the namespace first" - ); - } - } - - $this->triggerOptionEvent('namespace_pattern', $pattern); - $this->namespacePattern = $pattern; - } - - return $this; - } - - /** - * Get namespace pattern - * - * @return string - */ - public function getNamespacePattern() - { - return $this->namespacePattern; - } - /** * Enable/Disable reading data from cache. * diff --git a/src/Storage/Adapter/Apc.php b/src/Storage/Adapter/Apc.php index 3eb71e1c0..af8d7f864 100644 --- a/src/Storage/Adapter/Apc.php +++ b/src/Storage/Adapter/Apc.php @@ -21,12 +21,18 @@ namespace Zend\Cache\Storage\Adapter; -use APCIterator, +use APCIterator as BaseApcIterator, ArrayObject, stdClass, Traversable, Zend\Cache\Exception, - Zend\Cache\Storage\Capabilities; + Zend\Cache\Storage\Capabilities, + Zend\Cache\Storage\ClearByPrefixInterface, + Zend\Cache\Storage\ClearByNamespaceInterface, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\IterableInterface, + Zend\Cache\Storage\AvailableSpaceCapableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface; /** * @package Zend_Cache @@ -35,31 +41,17 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Apc extends AbstractAdapter +class Apc + extends AbstractAdapter + implements ClearByPrefixInterface, ClearByNamespaceInterface, FlushableInterface, IterableInterface, + AvailableSpaceCapableInterface, TotalSpaceCapableInterface { /** - * Map selected properties on getDelayed & find - * to APCIterator selector + * Buffered total space in bytes * - * Init on constructor after ext/apc has been tested - * - * @var null|array + * @var null|int|float */ - protected static $selectMap = null; - - /** - * The used namespace separator - * - * @var string - */ - protected $namespaceSeparator = ':'; - - /** - * Statement - * - * @var null|APCIterator - */ - protected $stmtIterator = null; + protected $totalSpace; /** * Constructor @@ -85,25 +77,6 @@ public function __construct($options = null) ); } - // init select map - if (static::$selectMap === null) { - static::$selectMap = array( - // 'key' => \APC_ITER_KEY, - 'value' => \APC_ITER_VALUE, - 'mtime' => \APC_ITER_MTIME, - 'ctime' => \APC_ITER_CTIME, - 'atime' => \APC_ITER_ATIME, - 'rtime' => \APC_ITER_DTIME, - 'ttl' => \APC_ITER_TTL, - 'num_hits' => \APC_ITER_NUM_HITS, - 'ref_count' => \APC_ITER_REFCOUNT, - 'mem_size' => \APC_ITER_MEM_SIZE, - - // virtual keys - 'internal_key' => \APC_ITER_KEY, - ); - } - parent::__construct($options); } @@ -139,26 +112,113 @@ public function getOptions() return $this->options; } + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + if ($this->totalSpace !== null) { + $smaInfo = apc_sma_info(true); + $this->totalSpace = $smaInfo['num_seg'] * $smaInfo['seg_size']; + } + + return $this->totalSpace; + } + + /* AvailableSpaceCapableInterface */ + + /** + * Get available space in bytes + * + * @return int|float + */ + public function getAvailableSpace() + { + $smaInfo = apc_sma_info(true); + return $smaInfo['avail_mem']; + } + + /* IterableInterface */ + + /** + * Get the storage iterator + * + * @return ApcIterator + */ + public function getIterator() + { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $pattern = '/^' . preg_quote($prefix, '/') . '/'; + $format = 0; + + $baseIt = new BaseApcIterator('user', $pattern, 0, 1, \APC_LIST_ACTIVE); + return new ApcIterator($this, $baseIt, $prefix); + } + + /* FlushableInterface */ + + /** + * Flush the whole storage + * + * @return boolean + */ + public function flush() + { + return apc_clear_cache('user'); + } + + /* ClearByNamespaceInterface */ + + /** + * Remove items by given namespace + * + * @param string $prefix + * @return boolean + */ + public function clearByNamespace($namespace) + { + $options = $this->getOptions(); + $prefix = $namespace . $options->getNamespaceSeparator(); + $pattern = '/^' . preg_quote($prefix, '/') . '+/'; + return apc_delete(new BaseApcIterator('user', $pattern, 0, 1, \APC_LIST_ACTIVE)); + } + + /* ClearByPrefixInterface */ + + /** + * Remove items matching given prefix + * + * @param string $prefix + * @return boolean + */ + public function clearByPrefix($prefix) + { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator() . $prefix; + $pattern = '/^' . preg_quote($prefix, '/') . '+/'; + return apc_delete(new BaseApcIterator('user', $pattern, 0, 1, \APC_LIST_ACTIVE)); + } /* reading */ /** * Internal method to get an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) + protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKey = $prefix . $normalizedKey; $result = apc_fetch($internalKey, $success); @@ -173,19 +233,14 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, /** * Internal method to get multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { - $namespaceSep = $this->getOptions()->getNamespaceSeparator(); - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { @@ -207,36 +262,29 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Internal method to test if an item exists. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); return apc_exists($prefix . $normalizedKey); } /** * Internal method to test multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $keys - * @param array $options * @return array Array of found keys * @throws Exception\ExceptionInterface */ - protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalHasItems(array & $normalizedKeys) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { $internalKeys[] = $prefix . $normalizedKey; @@ -257,12 +305,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized /** * Get metadata of an item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $normalizedKey - * @param array $normalizedOptions * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * @@ -270,17 +313,19 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * @triggers getMetadata.post(PostEvent) * @triggers getMetadata.exception(ExceptionEvent) */ - protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) + protected function internalGetMetadata(& $normalizedKey) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; // @see http://pecl.php.net/bugs/bug.php?id=22564 if (!apc_exists($internalKey)) { $metadata = false; } else { - $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE; + $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE ^ \APC_ITER_REFCOUNT; $regexp = '/^' . preg_quote($internalKey, '/') . '$/'; - $it = new APCIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); + $it = new BaseApcIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); $metadata = $it->current(); } @@ -295,29 +340,26 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti /** * Get metadata of multiple items * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and metadata * * @triggers getMetadatas.pre(PreEvent) * @triggers getMetadatas.post(PostEvent) * @triggers getMetadatas.exception(ExceptionEvent) */ - protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetMetadatas(array & $normalizedKeys) { $keysRegExp = array(); foreach ($normalizedKeys as $normalizedKey) { $keysRegExp[] = preg_quote($normalizedKey, '/'); } - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $regexp = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/'; - $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE; - $it = new APCIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $regexp = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/'; + $format = \APC_ITER_ALL ^ \APC_ITER_VALUE ^ \APC_ITER_TYPE ^ \APC_ITER_REFCOUNT; + + $it = new BaseApcIterator('user', $regexp, $format, 100, \APC_LIST_ACTIVE); $result = array(); $prefixL = strlen($prefix); foreach ($it as $internalKey => $metadata) { @@ -338,48 +380,39 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal /** * Internal method to store an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalSetItem(& $normalizedKey, & $value) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKey = $prefix . $normalizedKey; - if (!apc_store($internalKey, $value, $normalizedOptions['ttl'])) { + $ttl = $options->getTtl(); + + if (!apc_store($internalKey, $value, $ttl)) { $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( - "apc_store('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + "apc_store('{$internalKey}', <{$type}>, {$ttl}) failed" ); } + return true; } /** * Internal method to store multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalSetItems(array & $normalizedKeyValuePairs) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKeyValuePairs = array(); foreach ($normalizedKeyValuePairs as $normalizedKey => &$value) { @@ -387,7 +420,7 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n $internalKeyValuePairs[$internalKey] = &$value; } - $failedKeys = apc_store($internalKeyValuePairs, null, $normalizedOptions['ttl']); + $failedKeys = apc_store($internalKeyValuePairs, null, $options->getTtl()); $failedKeys = array_keys($failedKeys); // remove prefix @@ -402,29 +435,26 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n /** * Add an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalAddItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - if (!apc_add($internalKey, $value, $normalizedOptions['ttl'])) { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $ttl = $options->getTtl(); + + if (!apc_add($internalKey, $value, $ttl)) { if (apc_exists($internalKey)) { return false; } $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( - "apc_add('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + "apc_add('{$internalKey}', <{$type}>, {$ttl}) failed" ); } @@ -434,27 +464,22 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to add multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalAddItems(array & $normalizedKeyValuePairs) { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKeyValuePairs = array(); - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { $internalKey = $prefix . $normalizedKey; $internalKeyValuePairs[$internalKey] = $value; } - $failedKeys = apc_add($internalKeyValuePairs, null, $normalizedOptions['ttl']); + $failedKeys = apc_add($internalKeyValuePairs, null, $options->getTtl()); $failedKeys = array_keys($failedKeys); // remove prefix @@ -469,29 +494,26 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n /** * Internal method to replace an existing item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalReplaceItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $ttl = $options->getTtl(); + if (!apc_exists($internalKey)) { return false; } - if (!apc_store($internalKey, $value, $normalizedOptions['ttl'])) { + if (!apc_store($internalKey, $value, $ttl)) { $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( - "apc_store('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + "apc_store('{$internalKey}', <{$type}>, {$ttl}) failed" ); } @@ -501,37 +523,31 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) + protected function internalRemoveItem(& $normalizedKey) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; return apc_delete($internalKey); } /** * Internal method to remove multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $keys - * @param array $options * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ - protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalRemoveItems(array & $normalizedKeys) { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKeys = array(); - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); foreach ($normalizedKeys as $normalizedKey) { $internalKeys[] = $prefix . $normalizedKey; } @@ -550,30 +566,27 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali /** * Internal method to increment an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalIncrementItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - $value = (int)$value; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $ttl = $options->getTtl(); + $value = (int) $value; $newValue = apc_inc($internalKey, $value); // initial value if ($newValue === false) { + $ttl = $options->getTtl(); $newValue = $value; - if (!apc_add($internalKey, $newValue, $normalizedOptions['ttl'])) { + if (!apc_add($internalKey, $newValue, $ttl)) { throw new Exception\RuntimeException( - "apc_add('{$internalKey}', {$newValue}, {$normalizedOptions['ttl']}) failed" + "apc_add('{$internalKey}', {$newValue}, {$ttl}) failed" ); } } @@ -584,31 +597,26 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no /** * Internal method to decrement an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalDecrementItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - $value = (int)$value; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $value = (int) $value; $newValue = apc_dec($internalKey, $value); // initial value if ($newValue === false) { - // initial value + $ttl = $options->getTtl(); $newValue = -$value; - if (!apc_add($internalKey, $newValue, $normalizedOptions['ttl'])) { + if (!apc_add($internalKey, $newValue, $ttl)) { throw new Exception\RuntimeException( - "apc_add('{$internalKey}', {$newValue}, {$normalizedOptions['ttl']}) failed" + "apc_add('{$internalKey}', {$newValue}, {$ttl}) failed" ); } } @@ -616,192 +624,6 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no return $newValue; } - /* non-blocking */ - - /** - * Internal method to request multiple items. - * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * - select - * - An array of the information the returned item contains - * - callback optional - * - An result callback will be invoked for each item in the result set. - * - The first argument will be the item array. - * - The callback does not have to return anything. - * - * @param array $normalizedKeys - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - if (isset($normalizedOptions['callback']) && !is_callable($normalizedOptions['callback'], false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - - $format = 0; - foreach ($normalizedOptions['select'] as $property) { - if (isset(self::$selectMap[$property])) { - $format = $format | self::$selectMap[$property]; - } - } - - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $search = array(); - foreach ($normalizedKeys as $normalizedKey) { - $search[] = preg_quote($normalizedKey, '/'); - } - $search = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $search) . ')$/'; - - $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); - $this->stmtActive = true; - $this->stmtOptions = & $normalizedOptions; - - if (isset($normalizedOptions['callback'])) { - $callback = & $normalizedOptions['callback']; - while (($item = $this->fetch()) !== false) { - call_user_func($callback, $item); - } - } - - return true; - } - - /* find */ - - /** - * internal method to find items. - * - * Options: - * - namespace - * - The namespace to use - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalFind(& $normalizedMode, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - // This adapter doesn't support to read expired items - if (($normalizedMode & self::MATCH_ACTIVE) == self::MATCH_ACTIVE) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $search = '/^' . preg_quote($prefix, '/') . '+/'; - - $format = 0; - foreach ($normalizedOptions['select'] as $property) { - if (isset(self::$selectMap[$property])) { - $format = $format | self::$selectMap[$property]; - } - } - - $this->stmtIterator = new APCIterator('user', $search, $format, 1, \APC_LIST_ACTIVE); - $this->stmtActive = true; - $this->stmtOptions = & $normalizedOptions; - } - - return true; - } - - /** - * Internal method to fetch the next item from result set - * - * @return array|boolean The next item or false - * @throws Exception\ExceptionInterface - */ - protected function internalFetch() - { - if (!$this->stmtActive) { - return false; - } - - $prefix = $this->stmtOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $prefixL = strlen($prefix); - - do { - if (!$this->stmtIterator->valid()) { - // clear stmt - $this->stmtActive = false; - $this->stmtIterator = null; - $this->stmtOptions = null; - - return false; - } - - // @see http://pecl.php.net/bugs/bug.php?id=22564 - $exist = apc_exists($this->stmtIterator->key()); - if ($exist) { - $result = $this->stmtIterator->current(); - $this->normalizeMetadata($result); - - $select = $this->stmtOptions['select']; - if (in_array('key', $select)) { - $internalKey = $this->stmtIterator->key(); - $result['key'] = substr($internalKey, $prefixL); - } - } - - $this->stmtIterator->next(); - } while (!$exist); - - return $result; - } - - /* cleaning */ - - /** - * Internal method to clear items off all namespaces. - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - return $this->clearByRegEx('/.*/', $normalizedMode, $normalizedOptions); - } - - /** - * Clear items by namespace. - * - * Options: - * - namespace - * - The namespace to use - * - tags - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clear() - */ - protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) - { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $regex = '/^' . preg_quote($prefix, '/') . '+/'; - return $this->clearByRegEx($regex, $normalizedMode, $normalizedOptions); - } - /* status */ /** @@ -828,28 +650,18 @@ protected function internalGetCapabilities() 'resource' => false, ), 'supportedMetadata' => array( - 'atime', - 'ctime', 'internal_key', - 'mem_size', - 'mtime', - 'num_hits', - 'ref_count', - 'rtime', - 'ttl', + 'atime', 'ctime', 'mtime', 'rtime', + 'size', 'hits', 'ttl', ), 'maxTtl' => 0, 'staticTtl' => true, - 'tagging' => false, 'ttlPrecision' => 1, 'useRequestTime' => (bool) ini_get('apc.use_request_time'), 'expiredRead' => false, 'maxKeyLength' => 5182, 'namespaceIsPrefix' => true, 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), - 'iterable' => true, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, ) ); @@ -869,76 +681,30 @@ protected function internalGetCapabilities() return $this->capabilities; } - /** - * Internal method to get storage capacity. - * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - */ - protected function internalGetCapacity(array & $normalizedOptions) - { - $mem = apc_sma_info(true); - return array( - 'free' => $mem['avail_mem'], - 'total' => $mem['num_seg'] * $mem['seg_size'], - ); - } - /* internal */ - /** - * Clear cached items based on key regex - * - * @param string $regex - * @param int $mode - * @param array $options - * @return bool - */ - protected function clearByRegEx($regex, $mode, array &$options) - { - if (($mode & self::MATCH_ACTIVE) != self::MATCH_ACTIVE) { - // no need to clear expired items - return true; - } - - return apc_delete(new APCIterator('user', $regex, 0, 1, \APC_LIST_ACTIVE)); - } - /** * Normalize metadata to work with APC * * @param array $metadata * @return void */ - protected function normalizeMetadata(array &$metadata) + protected function normalizeMetadata(array & $metadata) { - // rename - if (isset($metadata['creation_time'])) { - $metadata['ctime'] = $metadata['creation_time']; - unset($metadata['creation_time']); - } - - if (isset($metadata['access_time'])) { - $metadata['atime'] = $metadata['access_time']; - unset($metadata['access_time']); - } - - if (isset($metadata['deletion_time'])) { - $metadata['rtime'] = $metadata['deletion_time']; - unset($metadata['deletion_time']); - } - - // remove namespace prefix - if (isset($metadata['key'])) { - $pos = strpos($metadata['key'], $this->getOptions()->getNamespaceSeparator()); - if ($pos !== false) { - $metadata['internal_key'] = $metadata['key']; - } else { - $metadata['internal_key'] = $metadata['key']; - } - - unset($metadata['key']); - } + $metadata['internal_key'] = $metadata['key']; + $metadata['ctime'] = $metadata['creation_time']; + $metadata['atime'] = $metadata['access_time']; + $metadata['rtime'] = $metadata['deletion_time']; + $metadata['size'] = $metadata['mem_size']; + $metadata['hits'] = $metadata['num_hits']; + + unset( + $metadata['key'], + $metadata['creation_time'], + $metadata['access_time'], + $metadata['deletion_time'], + $metadata['mem_size'], + $metadata['num_hits'] + ); } } diff --git a/src/Storage/Adapter/ApcIterator.php b/src/Storage/Adapter/ApcIterator.php new file mode 100644 index 000000000..08f97a833 --- /dev/null +++ b/src/Storage/Adapter/ApcIterator.php @@ -0,0 +1,179 @@ +storage = $storage; + $this->baseIterator = $baseIterator; + $this->prefixLength = strlen($prefix); + } + + /** + * Get storage instance + * + * @return StorageInterface + */ + public function getStorage() + { + return $this->storage; + } + + /** + * Get iterator mode + * + * @return int Value of IteratorInterface::CURRENT_AS_* + */ + public function getMode() + { + return $this->mode; + } + + /** + * Set iterator mode + * + * @param int $mode + * @return ApcIterator Fluent interface + */ + public function setMode($mode) + { + $this->mode = (int) $mode; + return $this; + } + + /* Iterator */ + + /** + * Get current key, value or metadata. + * + * @return mixed + */ + public function current() + { + if ($this->mode == IteratorInterface::CURRENT_AS_SELF) { + return $this; + } + + $key = $this->key(); + + if ($this->mode == IteratorInterface::CURRENT_AS_VALUE) { + return $this->storage->getItem($key); + } elseif ($this->mode == IteratorInterface::CURRENT_AS_METADATA) { + return $this->storage->getMetadata($key); + } + + return $key; + } + + /** + * Get current key + * + * @return string + */ + public function key() + { + $key = $this->baseIterator->key(); + + // remove namespace prefix + return substr($key, $this->prefixLength); + } + + /** + * Move forward to next element + * + * @return void + */ + public function next() + { + $this->baseIterator->next(); + } + + /** + * Checks if current position is valid + * + * @return boolean + */ + public function valid() + { + return $this->baseIterator->valid(); + } + + /** + * Rewind the Iterator to the first element. + * + * @return void + */ + public function rewind() + { + return $this->baseIterator->rewind(); + } +} diff --git a/src/Storage/Adapter/Filesystem.php b/src/Storage/Adapter/Filesystem.php index b6b700e3e..97b6d90ec 100644 --- a/src/Storage/Adapter/Filesystem.php +++ b/src/Storage/Adapter/Filesystem.php @@ -27,7 +27,17 @@ Exception as BaseException, Zend\Cache\Exception, Zend\Cache\Storage, + Zend\Cache\Storage\StorageInterface, Zend\Cache\Storage\Capabilities, + Zend\Cache\Storage\ClearExpiredInterface, + Zend\Cache\Storage\ClearByNamespaceInterface, + Zend\Cache\Storage\ClearByPrefixInterface, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\IterableInterface, + Zend\Cache\Storage\AvailableSpaceCapableInterface, + Zend\Cache\Storage\OptimizableInterface, + Zend\Cache\Storage\TagableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface, Zend\Cache\Utils, Zend\Stdlib\ErrorHandler; @@ -38,21 +48,19 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Filesystem extends AbstractAdapter +class Filesystem + extends AbstractAdapter + implements FlushableInterface, ClearExpiredInterface, ClearByNamespaceInterface, ClearByPrefixInterface, + TagableInterface, IterableInterface, OptimizableInterface, + AvailableSpaceCapableInterface, TotalSpaceCapableInterface { - /** - * GlobIterator used as statement - * - * @var GlobIterator|null - */ - protected $stmtGlob = null; /** - * Matching mode of active statement + * Buffered total space in bytes * - * @var integer|null + * @var null|int|float */ - protected $stmtMatch = null; + protected $totalSpace; /** * An identity for the last filespec @@ -99,19 +107,358 @@ public function getOptions() return $this->options; } + /* FlushableInterface */ + + /** + * Flush the whole storage + * + * @return boolean + */ + public function flush() + { + $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME; + $dir = $this->getOptions()->getCacheDir(); + $clearFolder = null; + $clearFolder = function ($dir) use (& $clearFolder, $flags) { + $it = new GlobIterator($dir . \DIRECTORY_SEPARATOR . '*', $flags); + foreach ($it as $pathname) { + if ($it->isDir()) { + $clearFolder($pathname); + rmdir($pathname); + } else { + unlink($pathname); + } + } + }; + + ErrorHandler::start(); + $clearFolder($dir); + $error = ErrorHandler::stop(); + if ($error) { + throw new Exception\RuntimeException("Flushing directory '{$dir}' failed", 0, $error); + } + + return true; + } + + /* ClearExpiredInterface */ + + /** + * Remove expired items + * + * @return boolean + */ + public function clearExpired() + { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + + $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_FILEINFO; + $path = $options->getCacheDir() + . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel()) + . \DIRECTORY_SEPARATOR . $prefix . '*.dat'; + $glob = new GlobIterator($path, $flags); + $time = time(); + $ttl = $options->getTtl(); + + ErrorHandler::start(); + foreach ($glob as $entry) { + $mtime = $entry->getMTime(); + if ($time >= $mtime + $ttl) { + $pathname = $entry->getPathname(); + unlink($pathname); + + $tagPathname = substr($pathname, 0, -4) . '.tag'; + if (file_exists($tagPathname)) { + unlink($tagPathname); + } + + $ifoPathname = substr($pathname, 0, -4) . '.ifo'; + if (file_exists($ifoPathname)) { + unlink($ifoPathname); + } + } + } + $error = ErrorHandler::stop(); + if ($error) { + throw new Exception\RuntimeException("Failed to clear expired items", 0, $error); + } + + return true; + } + + /* ClearByNamespaceInterface */ + + /** + * Remove items by given namespace + * + * @param string $namespace + * @return boolean + */ + public function clearByNamespace($namespace) + { + $options = $this->getOptions(); + $nsPrefix = $namespace . $options->getNamespaceSeparator(); + + $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME; + $path = $options->getCacheDir() + . str_repeat(\DIRECTORY_SEPARATOR . $nsPrefix . '*', $options->getDirLevel()) + . \DIRECTORY_SEPARATOR . $nsPrefix . '*'; + $glob = new GlobIterator($path, $flags); + $time = time(); + $ttl = $options->getTtl(); + + ErrorHandler::start(); + foreach ($glob as $pathname) { + unlink($pathname); + } + $error = ErrorHandler::stop(); + if ($error) { + throw new Exception\RuntimeException("Failed to remove file '{$pathname}'", 0, $error); + } + + return true; + } + + /* ClearByPrefixInterface */ + + /** + * Remove items matching given prefix + * + * @param string $prefix + * @return boolean + */ + public function clearByPrefix($prefix) + { + $options = $this->getOptions(); + $nsPrefix = $options->getNamespace() . $options->getNamespaceSeparator(); + + $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME; + $path = $options->getCacheDir() + . str_repeat(\DIRECTORY_SEPARATOR . $nsPrefix . '*', $options->getDirLevel()) + . \DIRECTORY_SEPARATOR . $nsPrefix . $prefix . '*'; + $glob = new GlobIterator($path, $flags); + $time = time(); + $ttl = $options->getTtl(); + + ErrorHandler::start(); + foreach ($glob as $pathname) { + unlink($pathname); + } + $error = ErrorHandler::stop(); + if ($error) { + throw new Exception\RuntimeException("Failed to remove file '{$pathname}'", 0, $error); + } + + return true; + } + + /* TagableInterface */ + + /** + * Set tags to an item by given key. + * An empty array will remove all tags. + * + * @param string $key + * @param string[] $tags + * @return boolean + */ + public function setTags($key, array $tags) + { + $this->normalizeKey($key); + if (!$this->internalHasItem($key)) { + return false; + } + + $filespec = $this->getFileSpec($key); + + if (!$tags) { + $this->unlink($filespec . '.tag'); + return true; + } + + $this->putFileContent($filespec . '.tag', implode("\n", $tags)); + return true; + } + + /** + * Get tags of an item by given key + * + * @param string $key + * @return string[]|FALSE + */ + public function getTags($key) + { + $this->normalizeKey($key); + if (!$this->internalHasItem($key)) { + return false; + } + + $filespec = $this->getFileSpec($key); + $tags = array(); + if (file_exists($filespec . '.tag')) { + $tags = explode("\n", $this->getFileContent($filespec . '.tag')); + } + + return $tags; + } + + /** + * Remove items matching given tags. + * + * If $disjunction only one of the given tags must match + * else all given tags must match. + * + * @param string[] $tags + * @param boolean $disjunction + * @return boolean + */ + public function clearByTags(array $tags, $disjunction = false) + { + if (!$tags) { + return true; + } + + $tagCount = count($tags); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + + $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME; + $path = $options->getCacheDir() + . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel()) + . \DIRECTORY_SEPARATOR . $prefix . '*.tag'; + $glob = new GlobIterator($path, $flags); + $time = time(); + $ttl = $options->getTtl(); + + foreach ($glob as $pathname) { + $diff = array_diff($tags, explode("\n", $this->getFileContent($pathname))); + + $rem = false; + if ($disjunction && count($diff) < $tagCount) { + $rem = true; + } elseif (!$disjunction && !$diff) { + $rem = true; + } + + if ($rem) { + unlink($pathname); + + $datPathname = substr($pathname, 0, -4) . '.dat'; + if (file_exists($datPathname)) { + unlink($datPathname); + } + + $ifoPathname = substr($pathname, 0, -4) . '.ifo'; + if (file_exists($ifoPathname)) { + unlink($ifoPathname); + } + } + } + + return true; + } + + /* IterableInterface */ + + /** + * Get the storage iterator + * + * @return FilesystemIterator + */ + public function getIterator() + { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $path = $options->getCacheDir() + . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel()) + . \DIRECTORY_SEPARATOR . $prefix . '*.dat'; + return new FilesystemIterator($this, $path, $prefix); + } + + /* OptimizableInterface */ + + /** + * Optimize the storage + * + * @return void + * @return Exception\RuntimeException + */ + public function optimize() + { + $baseOptions = $this->getOptions(); + if ($baseOptions->getDirLevel()) { + // removes only empty directories + $this->rmDir( + $baseOptions->getCacheDir(), + $baseOptions->getNamespace() . $baseOptions->getNamespaceSeparator() + ); + } + return true; + } + + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + if ($this->totalSpace !== null) { + $path = $this->getOptions()->getCacheDir(); + + ErrorHandler::start(); + $total = disk_total_space($path); + $error = ErrorHandler::stop(); + if ($total === false) { + throw new Exception\RuntimeException("Can't detect total space of '{$path}'", 0, $error); + } + + // clean total space buffer on change cache_dir + $events = $this->events(); + $handle = null; + $totalSpace = & $this->totalSpace; + $callback = function ($event) use (& $events, & $handle, & $totalSpace) { + $params = $event->getParams(); + if (isset($params['cache_dir'])) { + $totalSpace = null; + $events->detach($handle); + } + }; + $handle = $this->events()->attach($callback); + } + return $this->totalSpace; + } + + /* AvailableSpaceCapableInterface */ + + /** + * Get available space in bytes + * + * @return int|float + */ + public function getAvailableSpace() + { + $path = $this->getOptions()->getCacheDir(); + + ErrorHandler::start(); + $avail = disk_free_space($path); + $error = ErrorHandler::stop(); + if ($avail === false) { + throw new Exception\RuntimeException("Can't detect free space of '{$path}'", 0, $error); + } + + return $avail; + } + /* reading */ /** * Get an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure @@ -121,27 +468,27 @@ public function getOptions() * @triggers getItem.post(PostEvent) * @triggers getItem.exception(ExceptionEvent) */ - public function getItem($key, array $options = array(), & $success = null, & $casToken = null) + public function getItem($key, & $success = null, & $casToken = null) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getReadable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::getItem($key, $options, $success, $casToken); + $argn = func_num_args(); + if ($argn > 2) { + return parent::getItem($key, $success, $casToken); + } elseif ($argn > 1) { + return parent::getItem($key, $success); + } else { + return parent::getItem($key); + } } /** * Get multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Associative array of keys and values * @throws Exception\ExceptionInterface * @@ -149,45 +496,37 @@ public function getItem($key, array $options = array(), & $success = null, & $ca * @triggers getItems.post(PostEvent) * @triggers getItems.exception(ExceptionEvent) */ - public function getItems(array $keys, array $options = array()) + public function getItems(array $keys) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getReadable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::getItems($keys, $options); + return parent::getItems($keys); } /** * Internal method to get an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) + protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalHasItem($normalizedKey)) { $success = false; return null; } try { - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - $baseOptions = $this->getOptions(); - $data = $this->getFileContent($filespec . '.dat'); + $filespec = $this->getFileSpec($normalizedKey); + $data = $this->getFileContent($filespec . '.dat'); - if ($baseOptions->getReadControl()) { + if ($this->getOptions()->getReadControl()) { if ( ($info = $this->readInfoFile($filespec . '.ifo')) && isset($info['hash'], $info['algo']) && Utils::generateHash($info['algo'], $data, true) != $info['hash'] @@ -199,20 +538,14 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, } // use filemtime + filesize as CAS token - $casToken = filemtime($filespec . '.dat') . filesize($filespec . '.dat'); + if (func_num_args() > 2) { + $casToken = filemtime($filespec . '.dat') . filesize($filespec . '.dat'); + } $success = true; return $data; - } catch (Exception $e) { + } catch (BaseException $e) { $success = false; - - try { - // remove cache file on exception - $this->internalRemoveItem($normalizedKey, $normalizedOptions); - } catch (Exception $tmp) { - // do not throw remove exception on this point - } - throw $e; } } @@ -220,26 +553,15 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, /** * Internal method to get multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { - $baseOptions = $this->getOptions(); - - // Don't change arguments passed by reference - $keys = $normalizedKeys; - $options = $normalizedOptions; - - $result = array(); + $options = $this->getOptions(); + $keys = $normalizedKeys; // Don't change argument passed by reference + $result = array(); while ($keys) { // LOCK_NB if more than one items have to read @@ -248,12 +570,12 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized // read items foreach ($keys as $i => $key) { - if (!$this->internalHasItem($key, $options)) { + if (!$this->internalHasItem($key)) { unset($keys[$i]); continue; } - $filespec = $this->getFileSpec($key, $options); + $filespec = $this->getFileSpec($key); $data = $this->getFileContent($filespec . '.dat', $nonBlocking, $wouldblock); if ($nonBlocking && $wouldblock) { continue; @@ -261,7 +583,7 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized unset($keys[$i]); } - if ($baseOptions->getReadControl()) { + if ($options->getReadControl()) { $info = $this->readInfoFile($filespec . '.ifo'); if (isset($info['hash'], $info['algo']) && Utils::generateHash($info['algo'], $data, true) != $info['hash'] @@ -275,8 +597,8 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized $result[$key] = $data; } - // Don't check ttl after first iteration - $options['ttl'] = 0; + // TODO: Don't check ttl after first iteration + // $options['ttl'] = 0; } return $result; @@ -285,14 +607,7 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Test if an item exists. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -300,27 +615,20 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized * @triggers hasItem.post(PostEvent) * @triggers hasItem.exception(ExceptionEvent) */ - public function hasItem($key, array $options = array()) + public function hasItem($key) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getReadable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::hasItem($key, $options); + return parent::hasItem($key); } /** * Test multiple items. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Array of found keys * @throws Exception\ExceptionInterface * @@ -328,46 +636,39 @@ public function hasItem($key, array $options = array()) * @triggers hasItems.post(PostEvent) * @triggers hasItems.exception(ExceptionEvent) */ - public function hasItems(array $keys, array $options = array()) + public function hasItems(array $keys) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getReadable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::hasItems($keys, $options); + return parent::hasItems($keys); } /** * Internal method to test if an item exists. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { - $ttl = $normalizedOptions['ttl']; - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - - if (!file_exists($filespec . '.dat')) { + $file = $this->getFileSpec($normalizedKey) . '.dat'; + if (!file_exists($file)) { return false; } + $ttl = $this->getOptions()->getTtl(); if ($ttl) { ErrorHandler::start(); - $mtime = filemtime($filespec . '.dat'); + $mtime = filemtime($file); $error = ErrorHandler::stop(); if (!$mtime) { throw new Exception\RuntimeException( - "Error getting mtime of file '{$filespec}.dat'", 0, $error + "Error getting mtime of file '{$file}'", 0, $error ); } @@ -383,66 +684,61 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) * Get metadata * * @param string $key - * @param array $options * @return array|boolean Metadata on success, false on failure */ - public function getMetadata($key, array $options = array()) + public function getMetadata($key) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getReadable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::getMetadata($key, $options); + return parent::getMetadata($key); } /** * Get metadatas * * @param array $keys - * @param array $options * @return array Associative array of keys and metadata */ public function getMetadatas(array $keys, array $options = array()) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getReadable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getReadable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::getMetadatas($keys, $options); + return parent::getMetadatas($keys); } /** * Get info by key * * @param string $normalizedKey - * @param array $normalizedOptions * @return array|boolean Metadata on success, false on failure */ - protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) + protected function internalGetMetadata(& $normalizedKey) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalHasItem($normalizedKey)) { return false; } - $baseOptions = $this->getOptions(); - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - - $metadata = $this->readInfoFile($filespec . '.ifo'); - if (!$metadata) { - $metadata = array(); - } + $options = $this->getOptions(); + $filespec = $this->getFileSpec($normalizedKey); + $file = $filespec . '.dat'; - $metadata['filespec'] = $filespec; - $metadata['mtime'] = filemtime($filespec . '.dat'); + $metadata = array( + 'filespec' => $filespec, + 'mtime' => filemtime($file) + ); - if (!$baseOptions->getNoCtime()) { - $metadata['ctime'] = filectime($filespec . '.dat'); + if (!$options->getNoCtime()) { + $metadata['ctime'] = filectime($file); } - if (!$baseOptions->getNoAtime()) { - $metadata['atime'] = fileatime($filespec . '.dat'); + if (!$options->getNoAtime()) { + $metadata['atime'] = fileatime($file); } return $metadata; @@ -451,64 +747,33 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti /** * Internal method to get multiple metadata * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface */ - protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetMetadatas(array & $normalizedKeys) { - $baseOptions = $this->getOptions(); - $result = array(); - - // Don't change arguments passed by reference - $keys = $normalizedKeys; - $options = $normalizedOptions; - - while ($keys) { - - // LOCK_NB if more than one items have to read - $nonBlocking = count($keys) > 1; - $wouldblock = null; - - foreach ($keys as $i => $key) { - if (!$this->internalHasItem($key, $options)) { - unset($keys[$i]); - continue; - } - - $filespec = $this->getFileSpec($key, $options); - - $metadata = $this->readInfoFile($filespec . '.ifo', $nonBlocking, $wouldblock); - if ($nonBlocking && $wouldblock) { - continue; - } elseif (!$metadata) { - $metadata = array(); - } + $options = $this->getOptions(); + $result = array(); - $metadata['filespec'] = $filespec; - $metadata['mtime'] = filemtime($filespec . '.dat'); + foreach ($normalizedKeys as $normalizedKey) { + $filespec = $this->getFileSpec($normalizedKey); + $file = $filespec . '.dat'; - if (!$baseOptions->getNoCtime()) { - $metadata['ctime'] = filectime($filespec . '.dat'); - } + $metadata = array( + 'filespec' => $filespec, + 'mtime' => filemtime($file), + ); - if (!$baseOptions->getNoAtime()) { - $metadata['atime'] = fileatime($filespec . '.dat'); - } + if (!$options->getNoCtime()) { + $metadata['ctime'] = filectime($file); + } - $result[$key] = $metadata; - unset($keys[$i]); + if (!$options->getNoAtime()) { + $metadata['atime'] = fileatime($file); } - // Don't check ttl after first iteration - $options['ttl'] = 0; + $result[$normalizedKey] = $metadata; } return $result; @@ -519,15 +784,8 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal /** * Store an item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -535,27 +793,19 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal * @triggers setItem.post(PostEvent) * @triggers setItem.exception(ExceptionEvent) */ - public function setItem($key, $value, array $options = array()) + public function setItem($key, $value) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - - return parent::setItem($key, $value, $options); + return parent::setItem($key, $value); } /** * Store multiple items. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param array $keyValuePairs - * @param array $options * @return array Array of not stored keys * @throws Exception\ExceptionInterface * @@ -563,28 +813,21 @@ public function setItem($key, $value, array $options = array()) * @triggers setItems.post(PostEvent) * @triggers setItems.exception(ExceptionEvent) */ - public function setItems(array $keyValuePairs, array $options = array()) + public function setItems(array $keyValuePairs) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::setItems($keyValuePairs, $options); + return parent::setItems($keyValuePairs); } /** * Add an item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -592,27 +835,20 @@ public function setItems(array $keyValuePairs, array $options = array()) * @triggers addItem.post(PostEvent) * @triggers addItem.exception(ExceptionEvent) */ - public function addItem($key, $value, array $options = array()) + public function addItem($key, $value) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::addItem($key, $value, $options); + return parent::addItem($key, $value); } /** * Add multiple items. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param array $keyValuePairs - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -620,28 +856,21 @@ public function addItem($key, $value, array $options = array()) * @triggers addItems.post(PostEvent) * @triggers addItems.exception(ExceptionEvent) */ - public function addItems(array $keyValuePairs, array $options = array()) + public function addItems(array $keyValuePairs) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::addItems($keyValuePairs, $options); + return parent::addItems($keyValuePairs); } /** * Replace an existing item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -649,27 +878,20 @@ public function addItems(array $keyValuePairs, array $options = array()) * @triggers replaceItem.post(PostEvent) * @triggers replaceItem.exception(ExceptionEvent) */ - public function replaceItem($key, $value, array $options = array()) + public function replaceItem($key, $value) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::replaceItem($key, $value, $options); + return parent::replaceItem($key, $value); } /** * Replace multiple existing items. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param array $keyValuePairs - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -677,56 +899,47 @@ public function replaceItem($key, $value, array $options = array()) * @triggers replaceItems.post(PostEvent) * @triggers replaceItems.exception(ExceptionEvent) */ - public function replaceItems(array $keyValuePairs, array $options = array()) + public function replaceItems(array $keyValuePairs) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::replaceItems($keyValuePairs, $options); + return parent::replaceItems($keyValuePairs); } /** * Internal method to store an item. * - * Options: - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalSetItem(& $normalizedKey, & $value) { - $baseOptions = $this->getOptions(); - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $options = $this->getOptions(); + $filespec = $this->getFileSpec($normalizedKey); $this->prepareDirectoryStructure($filespec); $info = null; - if ($baseOptions->getReadControl()) { - $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); - $info['algo'] = $baseOptions->getReadControlAlgo(); - } - if (isset($options['tags'])) { - $info['tags'] = $normalizedOptions['tags']; + if ($options->getReadControl()) { + $info['hash'] = Utils::generateHash($options->getReadControlAlgo(), $value, true); + $info['algo'] = $options->getReadControlAlgo(); } // write files try { // set umask for files - $oldUmask = umask($baseOptions->getFileUmask()); + $oldUmask = umask($options->getFileUmask()); $contents = array($filespec . '.dat' => & $value); if ($info) { $contents[$filespec . '.ifo'] = serialize($info); } else { $this->unlink($filespec . '.ifo'); + $this->unlink($filespec . '.tag'); } while ($contents) { @@ -746,7 +959,7 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz return true; - } catch (Exception $e) { + } catch (BaseException $e) { // reset umask on exception umask($oldUmask); throw $e; @@ -756,18 +969,11 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to store multiple items. * - * Options: - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalSetItems(array & $normalizedKeyValuePairs) { $baseOptions = $this->getOptions(); $oldUmask = null; @@ -775,7 +981,7 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n // create an associated array of files and contents to write $contents = array(); foreach ($normalizedKeyValuePairs as $key => & $value) { - $filespec = $this->getFileSpec($key, $normalizedOptions); + $filespec = $this->getFileSpec($key); $this->prepareDirectoryStructure($filespec); // *.dat file @@ -787,13 +993,11 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n $info['hash'] = Utils::generateHash($baseOptions->getReadControlAlgo(), $value, true); $info['algo'] = $baseOptions->getReadControlAlgo(); } - if (isset($normalizedOptions['tags'])) { - $info['tags'] = & $normalizedOptions['tags']; - } if ($info) { $contents[$filespec . '.ifo'] = serialize($info); } else { $this->unlink($filespec . '.ifo'); + $this->unlink($filespec . '.tag'); } } @@ -820,7 +1024,7 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n // return OK return array(); - } catch (Exception $e) { + } catch (BaseException $e) { // reset umask on exception umask($oldUmask); throw $e; @@ -833,76 +1037,55 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n * It uses the token received from getItem() to check if the item has * changed before overwriting it. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * - tags optional - * - An array of tags - * * @param mixed $token * @param string $key * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @see getItem() * @see setItem() */ - public function checkAndSetItem($token, $key, $value, array $options = array()) + public function checkAndSetItem($token, $key, $value) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::checkAndSetItem($token, $key, $value, $options); + return parent::checkAndSetItem($token, $key, $value); } /** * Internal method to set an item only if token matches * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param mixed $token * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface * @see getItem() * @see setItem() */ - protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) + protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalHasItem($normalizedKey)) { return false; } // use filemtime + filesize as CAS token - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); - $check = filemtime($filespec . '.dat') . filesize($filespec . '.dat'); + $file = $this->getFileSpec($normalizedKey) . '.dat'; + $check = filemtime($file) . filesize($file); if ($token !== $check) { return false; } - return $this->internalSetItem($normalizedKey, $value, $normalizedOptions); + return $this->internalSetItem($normalizedKey, $value); } /** * Reset lifetime of an item * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -910,25 +1093,20 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, * @triggers touchItem.post(PostEvent) * @triggers touchItem.exception(ExceptionEvent) */ - public function touchItem($key, array $options = array()) + public function touchItem($key) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::touchItem($key, $options); + return parent::touchItem($key); } /** * Reset lifetime of multiple items. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Array of not updated keys * @throws Exception\ExceptionInterface * @@ -936,37 +1114,30 @@ public function touchItem($key, array $options = array()) * @triggers touchItems.post(PostEvent) * @triggers touchItems.exception(ExceptionEvent) */ - public function touchItems(array $keys, array $options = array()) + public function touchItems(array $keys) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::touchItems($keys, $options); + return parent::touchItems($keys); } /** * Internal method to reset lifetime of an item * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) + protected function internalTouchItem(& $normalizedKey) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalHasItem($normalizedKey)) { return false; } - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $filespec = $this->getFileSpec($normalizedKey); ErrorHandler::start(); $touch = touch($filespec . '.dat'); @@ -983,12 +1154,7 @@ protected function internalTouchItem(& $normalizedKey, array & $normalizedOption /** * Remove an item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $key - * @param array $options * @return boolean * @throws Exception\ExceptionInterface * @@ -996,25 +1162,20 @@ protected function internalTouchItem(& $normalizedKey, array & $normalizedOption * @triggers removeItem.post(PostEvent) * @triggers removeItem.exception(ExceptionEvent) */ - public function removeItem($key, array $options = array()) + public function removeItem($key) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::removeItem($key, $options); + return parent::removeItem($key); } /** * Remove multiple items. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param array $keys - * @param array $options * @return array Array of not removed keys * @throws Exception\ExceptionInterface * @@ -1022,177 +1183,36 @@ public function removeItem($key, array $options = array()) * @triggers removeItems.post(PostEvent) * @triggers removeItems.exception(ExceptionEvent) */ - public function removeItems(array $keys, array $options = array()) + public function removeItems(array $keys) { - $baseOptions = $this->getOptions(); - if ($baseOptions->getWritable() && $baseOptions->getClearStatCache()) { + $options = $this->getOptions(); + if ($options->getWritable() && $options->getClearStatCache()) { clearstatcache(); } - return parent::removeItems($keys, $options); + return parent::removeItems($keys); } /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) + protected function internalRemoveItem(& $normalizedKey) { - $filespec = $this->getFileSpec($normalizedKey, $normalizedOptions); + $filespec = $this->getFileSpec($normalizedKey); if (!file_exists($filespec . '.dat')) { return false; } else { $this->unlink($filespec . '.dat'); + $this->unlink($filespec . '.tag'); $this->unlink($filespec . '.ifo'); } return true; } - /* non-blocking */ - - /** - * internal method to find items. - * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalFind(& $normalizedMode, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - try { - $baseOptions = $this->getOptions(); - - $prefix = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator(); - $find = $baseOptions->getCacheDir() - . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $baseOptions->getDirLevel()) - . \DIRECTORY_SEPARATOR . $prefix . '*.dat'; - $glob = new GlobIterator($find); - - $this->stmtActive = true; - $this->stmtGlob = $glob; - $this->stmtMatch = $normalizedMode; - $this->stmtOptions = $normalizedOptions; - } catch (BaseException $e) { - throw new Exception\RuntimeException("new GlobIterator({$find}) failed", 0, $e); - } - - return true; - } - - /** - * Internal method to fetch the next item from result set - * - * @return array|boolean The next item or false - * @throws Exception\ExceptionInterface - */ - protected function internalFetch() - { - if (!$this->stmtActive) { - return false; - } - - if ($this->stmtGlob !== null) { - $result = $this->fetchByGlob(); - - if ($result === false) { - // clear statement - $this->stmtActive = false; - $this->stmtGlob = null; - $this->stmtMatch = null; - $this->stmtOptions = null; - } - } else { - $result = parent::internalFetch(); - } - - return $result; - } - - /* cleaning */ - - /** - * Internal method to clear items off all namespaces. - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - return $this->clearByPrefix('', $normalizedMode, $normalizedOptions); - } - - /** - * Clear items by namespace. - * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clear() - */ - protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) - { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); - return $this->clearByPrefix($prefix, $normalizedMode, $normalizedOptions); - } - - /** - * Internal method to optimize adapter storage. - * - * Options: - * - namespace - * - The namespace to use - * - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - */ - protected function internalOptimize(array & $normalizedOptions) - { - $baseOptions = $this->getOptions(); - if ($baseOptions->getDirLevel()) { - // removes only empty directories - $this->rmDir( - $baseOptions->getCacheDir(), - $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator() - ); - } - - return true; - } - /* status */ /** @@ -1232,15 +1252,11 @@ protected function internalGetCapabilities() 'supportedMetadata' => $metadata, 'maxTtl' => 0, 'staticTtl' => false, - 'tagging' => true, 'ttlPrecision' => 1, 'expiredRead' => true, 'maxKeyLength' => 251, // 255 - strlen(.dat | .ifo) 'namespaceIsPrefix' => true, 'namespaceSeparator' => $options->getNamespaceSeparator(), - 'iterable' => true, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, ) ); @@ -1278,227 +1294,8 @@ protected function internalGetCapabilities() return $this->capabilities; } - /** - * Internal method to get storage capacity. - * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - */ - protected function internalGetCapacity(array & $normalizedOptions) - { - return Utils::getDiskCapacity($this->getOptions()->getCacheDir()); - } - /* internal */ - /** - * Fetch by glob - * - * @return array|bool - */ - protected function fetchByGlob() - { - $options = $this->stmtOptions; - $mode = $this->stmtMatch; - - $prefix = $options['namespace'] . $this->getOptions()->getNamespaceSeparator(); - $prefixL = strlen($prefix); - - do { - try { - $valid = $this->stmtGlob->valid(); - } catch (\LogicException $e) { - // @link https://bugs.php.net/bug.php?id=55701 - // GlobIterator throws LogicException with message - // 'The parent constructor was not called: the object is in an invalid state' - $valid = false; - } - if (!$valid) { - return false; - } - - $item = array(); - $meta = null; - - $current = $this->stmtGlob->current(); - $this->stmtGlob->next(); - - $filename = $current->getFilename(); - if ($prefix !== '') { - if (substr($filename, 0, $prefixL) != $prefix) { - continue; - } - - // remove prefix and suffix (.dat) - $key = substr($filename, $prefixL, -4); - } else { - // remove suffix (.dat) - $key = substr($filename, 0, -4); - } - - // if MATCH_ALL mode do not check expired - if (($mode & self::MATCH_ALL) != self::MATCH_ALL) { - $mtime = $current->getMTime(); - - // if MATCH_EXPIRED -> filter not expired items - if (($mode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { - if ( time() < ($mtime + $options['ttl']) ) { - continue; - } - - // if MATCH_ACTIVE -> filter expired items - } else { - if ( time() >= ($mtime + $options['ttl']) ) { - continue; - } - } - } - - // check tags only if one of the tag matching mode is selected - if (($mode & 070) > 0) { - - $meta = $this->internalGetMetadata($key, $options); - - // if MATCH_TAGS mode -> check if all given tags available in current cache - if (($mode & self::MATCH_TAGS_AND) == self::MATCH_TAGS_AND ) { - if (!isset($meta['tags']) || count(array_diff($options['tags'], $meta['tags'])) > 0) { - continue; - } - - // if MATCH_NO_TAGS mode -> check if no given tag available in current cache - } elseif( ($mode & self::MATCH_TAGS_NEGATE) == self::MATCH_TAGS_NEGATE ) { - if (isset($meta['tags']) && count(array_diff($options['tags'], $meta['tags'])) != count($options['tags'])) { - continue; - } - - // if MATCH_ANY_TAGS mode -> check if any given tag available in current cache - } elseif ( ($mode & self::MATCH_TAGS_OR) == self::MATCH_TAGS_OR ) { - if (!isset($meta['tags']) || count(array_diff($options['tags'], $meta['tags'])) == count($options['tags'])) { - continue; - } - - } - } - - foreach ($options['select'] as $select) { - if ($select == 'key') { - $item['key'] = $key; - } else if ($select == 'value') { - $item['value'] = $this->getFileContent($current->getPathname()); - } else if ($select != 'key') { - if ($meta === null) { - $meta = $this->internalGetMetadata($key, $options); - } - $item[$select] = isset($meta[$select]) ? $meta[$select] : null; - } - } - - return $item; - } while (true); - } - - /** - * Clear by prefix - * - * @param $prefix - * @param $mode - * @param array $opts - * @return bool - * @throws RuntimeException - */ - protected function clearByPrefix($prefix, $mode, array &$opts) - { - $baseOptions = $this->getOptions(); - if (!$baseOptions->getWritable()) { - return false; - } - - $ttl = $opts['ttl']; - - if ($baseOptions->getClearStatCache()) { - clearstatcache(); - } - - try { - $find = $baseOptions->getCacheDir() - . str_repeat(\DIRECTORY_SEPARATOR . $prefix . '*', $baseOptions->getDirLevel()) - . \DIRECTORY_SEPARATOR . $prefix . '*.dat'; - $glob = new GlobIterator($find); - } catch (BaseException $e) { - throw new Exception\RuntimeException('Instantiating GlobIterator failed', 0, $e); - } - - $time = time(); - - foreach ($glob as $entry) { - - // if MATCH_ALL mode do not check expired - if (($mode & self::MATCH_ALL) != self::MATCH_ALL) { - - $mtime = $entry->getMTime(); - if (($mode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { - if ( $time <= ($mtime + $ttl) ) { - continue; - } - - // if Zend_Cache::MATCH_ACTIVE mode selected do not remove expired data - } else { - if ( $time >= ($mtime + $ttl) ) { - continue; - } - } - } - - // remove file suffix (*.dat) - $pathnameSpec = substr($entry->getPathname(), 0, -4); - - //////////////////////////////////////// - // on this time all expire tests match - //////////////////////////////////////// - - // check tags only if one of the tag matching mode is selected - if (($mode & 070) > 0) { - - $info = $this->readInfoFile($pathnameSpec . '.ifo'); - - // if MATCH_TAGS mode -> check if all given tags available in current cache - if (($mode & self::MATCH_TAGS) == self::MATCH_TAGS ) { - if (!isset($info['tags']) - || count(array_diff($opts['tags'], $info['tags'])) > 0 - ) { - continue; - } - - // if MATCH_NO_TAGS mode -> check if no given tag available in current cache - } elseif(($mode & self::MATCH_NO_TAGS) == self::MATCH_NO_TAGS) { - if (isset($info['tags']) - && count(array_diff($opts['tags'], $info['tags'])) != count($opts['tags']) - ) { - continue; - } - - // if MATCH_ANY_TAGS mode -> check if any given tag available in current cache - } elseif ( ($mode & self::MATCH_ANY_TAGS) == self::MATCH_ANY_TAGS ) { - if (!isset($info['tags']) - || count(array_diff($opts['tags'], $info['tags'])) == count($opts['tags']) - ) { - continue; - } - } - } - - //////////////////////////////////////// - // on this time all tests match - //////////////////////////////////////// - - $this->unlink($pathnameSpec . '.dat'); // delete data file - $this->unlink($pathnameSpec . '.ifo'); // delete info file - } - - return true; - } - /** * Removes directories recursive by namespace * @@ -1537,16 +1334,14 @@ protected function rmDir($dir, $prefix) * Get file spec of the given key and namespace * * @param string $normalizedKey - * @param array $normalizedOptions * @return string */ - protected function getFileSpec($normalizedKey, array & $normalizedOptions) + protected function getFileSpec($normalizedKey) { - $baseOptions = $this->getOptions(); - $prefix = $normalizedOptions['namespace'] . $baseOptions->getNamespaceSeparator(); - - $path = $baseOptions->getCacheDir() . \DIRECTORY_SEPARATOR; - $level = $baseOptions->getDirLevel(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $path = $options->getCacheDir() . \DIRECTORY_SEPARATOR; + $level = $options->getDirLevel(); $fileSpecId = $path . $prefix . $normalizedKey . '/' . $level; if ($this->lastFileSpecId !== $fileSpecId) { diff --git a/src/Storage/Adapter/FilesystemIterator.php b/src/Storage/Adapter/FilesystemIterator.php new file mode 100644 index 000000000..b8e376199 --- /dev/null +++ b/src/Storage/Adapter/FilesystemIterator.php @@ -0,0 +1,194 @@ +storage = $storage; + $this->globIterator = new GlobIterator($path, GlobIterator::KEY_AS_FILENAME); + $this->prefix = $prefix; + $this->prefixLength = strlen($prefix); + } + + /** + * Get storage instance + * + * @return StorageInterface + */ + public function getStorage() + { + return $this->storage; + } + + /** + * Get iterator mode + * + * @return int Value of IteratorInterface::CURRENT_AS_* + */ + public function getMode() + { + return $this->mode; + } + + /** + * Set iterator mode + * + * @param int $mode + * @return ApcIterator Fluent interface + */ + public function setMode($mode) + { + $this->mode = (int) $mode; + return $this; + } + + /* Iterator */ + + /** + * Get current key, value or metadata. + * + * @return mixed + */ + public function current() + { + if ($this->mode == IteratorInterface::CURRENT_AS_SELF) { + return $this; + } + + $key = $this->key(); + + if ($this->mode == IteratorInterface::CURRENT_AS_VALUE) { + return $this->storage->getItem($key); + } elseif ($this->mode == IteratorInterface::CURRENT_AS_METADATA) { + return $this->storage->getMetadata($key); + } + + return $key; + } + + /** + * Get current key + * + * @return string + */ + public function key() + { + $filename = $this->globIterator->key(); + + // return without namespace prefix and file suffix + return substr($filename, $this->prefixLength, -4); + } + + /** + * Move forward to next element + * + * @return void + */ + public function next() + { + $this->globIterator->next(); + } + + /** + * Checks if current position is valid + * + * @return boolean + */ + public function valid() + { + try { + return $this->globIterator->valid(); + } catch (\LogicException $e) { + // @link https://bugs.php.net/bug.php?id=55701 + // GlobIterator throws LogicException with message + // 'The parent constructor was not called: the object is in an invalid state' + return false; + } + } + + /** + * Rewind the Iterator to the first element. + * + * @return void + */ + public function rewind() + { + return $this->globIterator->rewind(); + } +} diff --git a/src/Storage/Adapter/FilesystemOptions.php b/src/Storage/Adapter/FilesystemOptions.php index d69ca3bc1..0271bd216 100644 --- a/src/Storage/Adapter/FilesystemOptions.php +++ b/src/Storage/Adapter/FilesystemOptions.php @@ -88,15 +88,6 @@ class FilesystemOptions extends AdapterOptions */ protected $keyPattern = '/^[a-z0-9_\+\-]*$/Di'; - /** - * Overwrite default namespace pattern - * - * Defined in AdapterOptions. - * - * @var string - */ - protected $namespacePattern = '/^[a-z0-9_\+\-]*$/Di'; - /** * Namespace separator * diff --git a/src/Storage/Adapter/KeyListIterator.php b/src/Storage/Adapter/KeyListIterator.php new file mode 100644 index 000000000..12dc88fd6 --- /dev/null +++ b/src/Storage/Adapter/KeyListIterator.php @@ -0,0 +1,191 @@ +storage = $storage; + $this->keys = $keys; + $this->count = count($keys); + } + + /** + * Get storage instance + * + * @return StorageInterface + */ + public function getStorage() + { + return $this->storage; + } + + /** + * Get iterator mode + * + * @return int Value of IteratorInterface::CURRENT_AS_* + */ + public function getMode() + { + return $this->mode; + } + + /** + * Set iterator mode + * + * @param int $mode + * @return KeyListIterator Fluent interface + */ + public function setMode($mode) + { + $this->mode = (int) $mode; + return $this; + } + + /** + * Get current key, value or metadata. + * + * @return mixed + */ + public function current() + { + if ($this->mode == IteratorInterface::CURRENT_AS_SELF) { + return $this; + } + + $key = $this->key(); + + if ($this->mode == IteratorInterface::CURRENT_AS_METADATA) { + return $this->storage->getMetadata($key); + } elseif ($this->mode == IteratorInterface::CURRENT_AS_VALUE) { + return $this->storage->getItem($key); + } + + return $key; + } + + /** + * Get current key + * + * @return string + */ + public function key() + { + return $this->keys[$this->position]; + } + + /** + * Checks if current position is valid + * + * @return boolean + */ + public function valid() + { + return $this->position < $this->count; + } + + /** + * Move forward to next element + * + * @return void + */ + public function next() + { + $this->position++; + } + + /** + * Rewind the Iterator to the first element. + * + * @return void + */ + public function rewind() + { + $this->position = 0; + } + + /** + * Count number of items + * + * @return int + */ + public function count() + { + return $this->count(); + } +} diff --git a/src/Storage/Adapter/Memcached.php b/src/Storage/Adapter/Memcached.php index 94076c336..aa9aa718e 100644 --- a/src/Storage/Adapter/Memcached.php +++ b/src/Storage/Adapter/Memcached.php @@ -29,7 +29,10 @@ Zend\Cache\Exception, Zend\Cache\Storage\Event, Zend\Cache\Storage\CallbackEvent, - Zend\Cache\Storage\Capabilities; + Zend\Cache\Storage\Capabilities, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\AvailableSpaceCapableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface; /** * @package Zend_Cache @@ -37,9 +40,10 @@ * @subpackage Storage * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @todo Implement the find() method */ -class Memcached extends AbstractAdapter +class Memcached + extends AbstractAdapter + implements FlushableInterface, AvailableSpaceCapableInterface, TotalSpaceCapableInterface { /** * Major version of ext/memcached @@ -88,6 +92,7 @@ public function __construct($options = null) $this->memcached->setOption($k, $v); } } + $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options->getNamespace()); $servers = $options->getServers(); if (!$servers) { @@ -96,6 +101,8 @@ public function __construct($options = null) } $this->memcached->addServers($servers); + + // get notified on change options $memc = $this->memcached; $memcMV = static::$extMemcachedMajorVersion; @@ -112,6 +119,10 @@ public function __construct($options = null) } } + if (isset($params['namespace'])) { + $memc->setOption(MemcachedResource::OPT_PREFIX_KEY, $params['namespace']); + } + // TODO: update on change/add server(s) }); } @@ -148,32 +159,75 @@ public function getOptions() return $this->options; } + /* FlushableInterface */ + + /** + * Flush the whole storage + * + * @return boolean + */ + public function flush() + { + if (!$this->memcached->flush()) { + throw $this->getExceptionByResultCode($this->memcached->getResultCode()); + } + return true; + } + + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + $stats = $this->memcached->getStats(); + if ($stats === false) { + throw new Exception\RuntimeException($this->memcached->getResultMessage()); + } + + $mem = array_pop($stats); + return $mem['limit_maxbytes']; + } + + /* AvailableSpaceCapableInterface */ + + /** + * Get available space in bytes + * + * @return int|float + */ + public function getAvailableSpace() + { + $stats = $this->memcached->getStats(); + if ($stats === false) { + throw new Exception\RuntimeException($this->memcached->getResultMessage()); + } + + $mem = array_pop($stats); + return $mem['limit_maxbytes'] - $mem['bytes']; + } + /* reading */ /** * Internal method to get an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) + protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - // TODO: option to enable CAS feature - //if (array_key_exists('token', $normalizedOptions)) { + if (func_num_args() > 2) { $result = $this->memcached->get($normalizedKey, null, $casToken); - //} else { - // $result = $this->memcached->get($normalizedKey); - //} + } else { + $result = $this->memcached->get($normalizedKey); + } $success = true; if ($result === false || $result === null) { @@ -193,19 +247,12 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, /** * Internal method to get multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $result = $this->memcached->getMulti($normalizedKeys); if ($result === false) { throw $this->getExceptionByResultCode($this->memcached->getResultCode()); @@ -217,19 +264,12 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Internal method to test if an item exists. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $value = $this->memcached->get($normalizedKey); if ($value === false || $value === null) { $rsCode = $this->memcached->getResultCode(); @@ -248,19 +288,12 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) /** * Internal method to test multiple items. * - * Options: - * - namespace - * - The namespace to use - * - * @param array $keys - * @param array $options + * @param array $normalizedKeys * @return array Array of found keys * @throws Exception\ExceptionInterface */ - protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalHasItems(array & $normalizedKeys) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $result = $this->memcached->getMulti($normalizedKeys); if ($result === false) { throw $this->getExceptionByResultCode($this->memcached->getResultCode()); @@ -272,23 +305,12 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized /** * Get metadata of multiple items * - * Options: - * - namespace optional - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and metadata * @throws Exception\ExceptionInterface - * - * @triggers getMetadatas.pre(PreEvent) - * @triggers getMetadatas.post(PostEvent) - * @triggers getMetadatas.exception(ExceptionEvent) */ - protected function internalGetMetadatas(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetMetadatas(array & $normalizedKeys) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $result = $this->memcached->getMulti($normalizedKeys); if ($result === false) { throw $this->getExceptionByResultCode($this->memcached->getResultCode()); @@ -306,23 +328,14 @@ protected function internalGetMetadatas(array & $normalizedKeys, array & $normal /** * Internal method to store an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalSetItem(& $normalizedKey, & $value) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - $expiration = $this->expirationTime($normalizedOptions['ttl']); + $expiration = $this->expirationTime(); if (!$this->memcached->set($normalizedKey, $value, $expiration)) { throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } @@ -333,22 +346,13 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to store multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalSetItems(array & $normalizedKeyValuePairs) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - $expiration = $this->expirationTime($normalizedOptions['ttl']); + $expiration = $this->expirationTime(); if (!$this->memcached->setMulti($normalizedKeyValuePairs, $expiration)) { throw $this->getExceptionByResultCode($this->memcached->getResultCode()); } @@ -359,23 +363,14 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n /** * Add an item. * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalAddItem(& $normalizedKey, & $value) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - $expiration = $this->expirationTime($normalizedOptions['ttl']); + $expiration = $this->expirationTime(); if (!$this->memcached->add($normalizedKey, $value, $expiration)) { if ($this->memcached->getResultCode() == MemcachedResource::RES_NOTSTORED) { return false; @@ -389,23 +384,14 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to replace an existing item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalReplaceItem(& $normalizedKey, & $value) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - $expiration = $this->expirationTime($normalizedOptions['ttl']); + $expiration = $this->expirationTime(); if (!$this->memcached->replace($normalizedKey, $value, $expiration)) { if ($this->memcached->getResultCode() == MemcachedResource::RES_NOTSTORED) { return false; @@ -419,28 +405,17 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm /** * Internal method to set an item only if token matches * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param mixed $token * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface * @see getItem() * @see setItem() */ - protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, array & $normalizedOptions) + protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - $expiration = $this->expirationTime($normalizedOptions['ttl']); + $expiration = $this->expirationTime(); $result = $this->memcached->cas($token, $normalizedKey, $value, $expiration); if ($result === false) { @@ -457,18 +432,12 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value, /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) + protected function internalRemoveItem(& $normalizedKey) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); $result = $this->memcached->delete($normalizedKey); if ($result === false) { @@ -486,23 +455,17 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio /** * Internal method to remove multiple items. * - * Options: - * - namespace - * - The namespace to use - * - * @param array $keys - * @param array $options + * @param array $normalizedKeys * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ - protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalRemoveItems(array & $normalizedKeys) { // support for removing multiple items at once has been added in ext/memcached-2.0.0 if (static::$extMemcachedMajorVersion < 2) { - return parent::internalRemoveItems($normalizedKeys, $normalizedOptions); + return parent::internalRemoveItems($normalizedKeys); } - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); $rsCodes = $this->memcached->deleteMulti($normalizedKeys); $missingKeys = array(); @@ -521,22 +484,13 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali /** * Internal method to increment an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalIncrementItem(& $normalizedKey, & $value) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $value = (int)$value; $newValue = $this->memcached->increment($normalizedKey, $value); @@ -545,9 +499,8 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no // initial value if ($rsCode == MemcachedResource::RES_NOTFOUND) { - $newValue = $value; - $expiration = $this->expirationTime($normalizedOptions['ttl']); - $this->memcached->add($normalizedKey, $newValue, $expiration); + $newValue = $value; + $this->memcached->add($normalizedKey, $newValue, $this->expirationTime()); $rsCode = $this->memcached->getResultCode(); } @@ -562,22 +515,13 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no /** * Internal method to decrement an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalDecrementItem(& $normalizedKey, & $value) { - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - $value = (int)$value; $newValue = $this->memcached->decrement($normalizedKey, $value); @@ -586,9 +530,8 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no // initial value if ($rsCode == MemcachedResource::RES_NOTFOUND) { - $newValue = -$value; - $expiration = $this->expirationTime($normalizedOptions['ttl']); - $this->memcached->add($normalizedKey, $newValue, $expiration); + $newValue = -$value; + $this->memcached->add($normalizedKey, $newValue, $this->expirationTime()); $rsCode = $this->memcached->getResultCode(); } @@ -600,154 +543,6 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no return $newValue; } - /* non-blocking */ - - /** - * Internal method to request multiple items. - * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * - select - * - An array of the information the returned item contains - * - callback optional - * - An result callback will be invoked for each item in the result set. - * - The first argument will be the item array. - * - The callback does not have to return anything. - * - * @param array $normalizedKeys - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalGetDelayed(array & $normalizedKeys, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - if (isset($normalizedOptions['callback']) && !is_callable($normalizedOptions['callback'], false)) { - throw new Exception\InvalidArgumentException('Invalid callback'); - } - - $this->memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $normalizedOptions['namespace']); - - // redirect callback - if (isset($normalizedOptions['callback'])) { - $cb = function (MemcachedResource $memc, array & $item) use (& $normalizedOptions) { - $select = & $normalizedOptions['select']; - - // handle selected key - if (!in_array('key', $select)) { - unset($item['key']); - } - - // handle selected value - if (!in_array('value', $select)) { - unset($item['value']); - } - - call_user_func($normalizedOptions['callback'], $item); - }; - - if (!$this->memcached->getDelayed($normalizedKeys, false, $cb)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - } else { - if (!$this->memcached->getDelayed($normalizedKeys)) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - $this->stmtActive = true; - $this->stmtOptions = & $normalizedOptions; - } - - return true; - } - - /** - * Internal method to fetch the next item from result set - * - * @return array|boolean The next item or false - * @throws Exception\ExceptionInterface - */ - protected function internalFetch() - { - if (!$this->stmtActive) { - return false; - } - - $result = $this->memcached->fetch(); - if (!empty($result)) { - $select = & $this->stmtOptions['select']; - - // handle selected key - if (!in_array('key', $select)) { - unset($result['key']); - } - - // handle selected value - if (!in_array('value', $select)) { - unset($result['value']); - } - - } else { - // clear stmt - $this->stmtActive = false; - $this->stmtOptions = null; - } - - return $result; - } - - /** - * Internal method to return all items of result set. - * - * @return array The result set as array containing all items - * @throws Exception\ExceptionInterface - * @see fetch() - */ - protected function internalFetchAll() - { - $result = $this->memcached->fetchAll(); - if ($result === false) { - throw new Exception\RuntimeException("Memcached::fetchAll() failed"); - } - - $select = $this->stmtOptions['select']; - foreach ($result as & $elem) { - if (!in_array('key', $select)) { - unset($elem['key']); - } - } - - return $result; - } - - /* cleaning */ - - /** - * Internal method to clear items off all namespaces. - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - if (!$this->memcached->flush()) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - return true; - } - /* status */ /** @@ -776,15 +571,11 @@ protected function internalGetCapabilities() 'supportedMetadata' => array(), 'maxTtl' => 0, 'staticTtl' => true, - 'tagging' => false, 'ttlPrecision' => 1, 'useRequestTime' => false, 'expiredRead' => false, 'maxKeyLength' => 255, 'namespaceIsPrefix' => true, - 'iterable' => false, - 'clearAllNamespaces' => true, - 'clearByNamespace' => false, ) ); } @@ -792,27 +583,6 @@ protected function internalGetCapabilities() return $this->capabilities; } - /** - * Internal method to get storage capacity. - * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - */ - protected function internalGetCapacity(array & $normalizedOptions) - { - $stats = $this->memcached->getStats(); - if ($stats === false) { - throw $this->getExceptionByResultCode($this->memcached->getResultCode()); - } - - $mem = array_pop($stats); - return array( - 'free' => $mem['limit_maxbytes'] - $mem['bytes'], - 'total' => $mem['limit_maxbytes'], - ); - } - /* internal */ /** @@ -827,11 +597,11 @@ protected function internalGetCapacity(array & $normalizedOptions) * expiration value is larger than that, the server will consider it to be * real Unix time value rather than an offset from current time. * - * @param int $ttl * @return int */ - protected function expirationTime($ttl) + protected function expirationTime() { + $ttl = $this->getOptions()->getTtl(); if ($ttl > 2592000) { return time() + $ttl; } diff --git a/src/Storage/Adapter/Memory.php b/src/Storage/Adapter/Memory.php index ca916e766..b69756b67 100644 --- a/src/Storage/Adapter/Memory.php +++ b/src/Storage/Adapter/Memory.php @@ -25,7 +25,13 @@ stdClass, Zend\Cache\Exception, Zend\Cache\Storage\Capabilities, - Zend\Cache\Storage\Adapter\MemoryOptions, + Zend\Cache\Storage\ClearExpiredInterface, + Zend\Cache\Storage\ClearByPrefixInterface, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\IterableInterface, + Zend\Cache\Storage\TagableInterface, + Zend\Cache\Storage\AvailableSpaceCapableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface, Zend\Cache\Utils; /** @@ -35,7 +41,10 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Memory extends AbstractAdapter +class Memory + extends AbstractAdapter + implements ClearExpiredInterface, ClearByPrefixInterface, FlushableInterface, TagableInterface, + IterableInterface, AvailableSpaceCapableInterface, TotalSpaceCapableInterface { /** * Data Array @@ -46,7 +55,7 @@ class Memory extends AbstractAdapter * => array( * 0 => * 1 => - * 2 => + * ['tags' => ] * ) * ) * ) @@ -85,31 +94,220 @@ public function getOptions() return $this->options; } + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + return $this->getOptions()->getMemoryLimit(); + } + + /* AvailableSpaceCapableInterface */ + + /** + * Get available space in bytes + * + * @return int|float + */ + public function getAvailableSpace() + { + $total = $this->getOptions()->getMemoryLimit(); + $avail = $total - (float) memory_get_usage(true); + return ($avail > 0) ? $avail : 0; + } + + /* IterableInterface */ + + /** + * Get the storage iterator + * + * @return MemoryIterator + */ + public function getIterator() + { + $ns = $this->getOptions()->getNamespace(); + $keys = array(); + + if (isset($this->data[$ns])) { + foreach ($this->data[$ns] as $key => & $tmp) { + if ($this->internalHasItem($key)) { + $keys[] = $key; + } + } + } + + return new KeyListIterator($this, $keys); + } + + /* FlushableInterface */ + + /** + * Flush the whole storage + * + * @return boolean + */ + public function flush() + { + $this->data = array(); + return true; + } + + /* ClearExpiredInterface */ + + /** + * Remove expired items + * + * @return boolean + */ + public function clearExpired() + { + $ttl = $this->getOptions()->getTtl(); + if ($ttl <= 0) { + return true; + } + + $ns = $this->getOptions()->getNamespace(); + if (!isset($this->data[$ns])) { + return true; + } + + $data = & $this->data[$ns]; + foreach ($data as $key => & $item) { + if (microtime(true) >= $data[$key][1] + $ttl) { + unset($data[$key]); + } + } + + return true; + } + + /* ClearByPrefixInterface */ + + /** + * Remove items matching given prefix + * + * @param string $prefix + * @return boolean + */ + public function clearByPrefix($prefix) + { + $ns = $this->getOptions()->getNamespace(); + if (!isset($this->data[$ns])) { + return true; + } + + $prefixL = strlen($prefix); + $data = & $this->data[$ns]; + foreach ($data as $key => & $item) { + if (substr($key, 0, $prefixL) === $prefix) { + unset($data[$key]); + } + } + + return true; + } + + /* TagableInterface */ + + /** + * Set tags to an item by given key. + * An empty array will remove all tags. + * + * @param string $key + * @param string[] $tags + * @return boolean + */ + public function setTags($key, array $tags) + { + $ns = $this->getOptions()->getNamespace(); + if (!$this->data[$ns]) { + return false; + } + + $data = & $this->data[$ns]; + if (isset($data[$key])) { + $data[$key]['tags'] = $tags; + return true; + } + + return false; + } + + /** + * Get tags of an item by given key + * + * @param string $key + * @return string[]|FALSE + */ + public function getTags($key) + { + $ns = $this->getOptions()->getNamespace(); + if (!$this->data[$ns]) { + return false; + } + + $data = & $this->data[$ns]; + if (!isset($data[$key])) { + return false; + } + + return isset($data[$key]['tags']) ? $data[$key]['tags'] : array(); + } + + /** + * Remove items matching given tags. + * + * If $disjunction only one of the given tags must match + * else all given tags must match. + * + * @param string[] $tags + * @param boolean $disjunction + * @return boolean + */ + public function clearByTags(array $tags, $disjunction = false) + { + $ns = $this->getOptions()->getNamespace(); + if (!$this->data[$ns]) { + return true; + } + + $tagCount = count($tags); + $data = & $this->data[$ns]; + foreach ($data as $key => & $item) { + if (isset($item['tags'])) { + $diff = array_diff($tags, $item['tags']); + if (($disjunction && count($diff) < $tagCount) || (!$disjunction && !$diff)) { + unset($data[$key]); + } + } + } + + return true; + } + /* reading */ /** * Internal method to get an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) + protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) { - $ns = $normalizedOptions['namespace']; + $options = $this->getOptions(); + $ns = $options->getNamespace(); $success = isset($this->data[$ns][$normalizedKey]); if ($success) { $data = & $this->data[$ns][$normalizedKey]; - $ttl = $normalizedOptions['ttl']; + $ttl = $options->getTtl(); if ($ttl && microtime(true) >= ($data[1] + $ttl) ) { $success = false; } @@ -126,31 +324,26 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, /** * Internal method to get multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { - $ns = $normalizedOptions['namespace']; + $options = $this->getOptions(); + $ns = $options->getNamespace(); if (!isset($this->data[$ns])) { return array(); } $data = & $this->data[$ns]; - $ttl = $normalizedOptions['ttl']; + $ttl = $options->getTtl(); + $now = microtime(true); $result = array(); foreach ($normalizedKeys as $normalizedKey) { if (isset($data[$normalizedKey])) { - if (!$ttl || microtime(true) < ($data[$normalizedKey][1] + $ttl) ) { + if (!$ttl || $now < ($data[$normalizedKey][1] + $ttl) ) { $result[$normalizedKey] = $data[$normalizedKey][0]; } } @@ -162,26 +355,21 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Internal method to test if an item exists. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { - $ns = $normalizedOptions['namespace']; + $options = $this->getOptions(); + $ns = $options->getNamespace(); if (!isset($this->data[$ns][$normalizedKey])) { return false; } // check if expired - $ttl = $normalizedOptions['ttl']; + $ttl = $options->getTtl(); if ($ttl && microtime(true) >= ($this->data[$ns][$normalizedKey][1] + $ttl) ) { return false; } @@ -192,31 +380,26 @@ protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) /** * Internal method to test multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $keys - * @param array $options * @return array Array of found keys * @throws Exception\ExceptionInterface */ - protected function internalHasItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalHasItems(array & $normalizedKeys) { - $ns = $normalizedOptions['namespace']; + $options = $this->getOptions(); + $ns = $options->getNamespace(); if (!isset($this->data[$ns])) { return array(); } $data = & $this->data[$ns]; - $ttl = $normalizedOptions['ttl']; + $ttl = $options->getTtl(); + $now = microtime(true); $result = array(); foreach ($normalizedKeys as $normalizedKey) { if (isset($data[$normalizedKey])) { - if (!$ttl || microtime(true) < ($data[$normalizedKey][1] + $ttl) ) { + if (!$ttl || $now < ($data[$normalizedKey][1] + $ttl) ) { $result[] = $normalizedKey; } } @@ -228,14 +411,7 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized /** * Get metadata of an item. * - * Options: - * - ttl optional - * - The time-to-life (Default: ttl of object) - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $normalizedKey - * @param array $normalizedOptions * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface * @@ -243,16 +419,15 @@ protected function internalHasItems(array & $normalizedKeys, array & $normalized * @triggers getMetadata.post(PostEvent) * @triggers getMetadata.exception(ExceptionEvent) */ - protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) + protected function internalGetMetadata(& $normalizedKey) { - if (!$this->internalHasItem($normalizedKey, $normalizedOptions)) { + if (!$this->internalHasItem($normalizedKey)) { return false; } - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); return array( 'mtime' => $this->data[$ns][$normalizedKey][1], - 'tags' => $this->data[$ns][$normalizedKey][2], ); } @@ -261,29 +436,24 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti /** * Internal method to store an item. * - * Options: - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalSetItem(& $normalizedKey, & $value) { - if (!$this->hasFreeCapacity()) { - $memoryLimit = $this->getOptions()->getMemoryLimit(); - throw new Exception\OutOfCapacityException( + $options = $this->getOptions(); + + if (!$this->hasAvailableSpace()) { + $memoryLimit = $options->getMemoryLimit(); + throw new Exception\OutOfSpaceException( "Memory usage exceeds limit ({$memoryLimit})." ); } - $ns = $normalizedOptions['namespace']; - $this->data[$ns][$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); + $ns = $options->getNamespace(); + $this->data[$ns][$normalizedKey] = array($value, microtime(true)); return true; } @@ -291,34 +461,30 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to store multiple items. * - * Options: - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalSetItems(array & $normalizedKeyValuePairs) { - if (!$this->hasFreeCapacity()) { - $memoryLimit = $this->getOptions()->getMemoryLimit(); - throw new Exception\OutOfCapacityException( - 'Memory usage exceeds limit ({$memoryLimit}).' + $options = $this->getOptions(); + + if (!$this->hasAvailableSpace()) { + $memoryLimit = $options->getMemoryLimit(); + throw new Exception\OutOfSpaceException( + "Memory usage exceeds limit ({$memoryLimit})." ); } - $ns = $normalizedOptions['namespace']; + $ns = $options->getNamespace(); if (!isset($this->data[$ns])) { $this->data[$ns] = array(); } $data = & $this->data[$ns]; + $now = microtime(true); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { - $data[$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); + $data[$normalizedKey] = array($value, $now); } return array(); @@ -327,60 +493,50 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n /** * Add an item. * - * Options: - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalAddItem(& $normalizedKey, & $value) { - if (!$this->hasFreeCapacity()) { - $memoryLimit = $this->getOptions()->getMemoryLimit(); - throw new Exception\OutOfCapacityException( + $options = $this->getOptions(); + + if (!$this->hasAvailableSpace()) { + $memoryLimit = $options->getMemoryLimit(); + throw new Exception\OutOfSpaceException( "Memory usage exceeds limit ({$memoryLimit})." ); } - $ns = $normalizedOptions['namespace']; + $ns = $options->getNamespace(); if (isset($this->data[$ns][$normalizedKey])) { return false; } - $this->data[$ns][$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); + $this->data[$ns][$normalizedKey] = array($value, microtime(true)); return true; } /** * Internal method to add multiple items. * - * Options: - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalAddItems(array & $normalizedKeyValuePairs) { - if (!$this->hasFreeCapacity()) { - $memoryLimit = $this->getOptions()->getMemoryLimit(); - throw new Exception\OutOfCapacityException( - 'Memory usage exceeds limit ({$memoryLimit}).' + $options = $this->getOptions(); + + if (!$this->hasAvailableSpace()) { + $memoryLimit = $options->getMemoryLimit(); + throw new Exception\OutOfSpaceException( + "Memory usage exceeds limit ({$memoryLimit})." ); } - $ns = $normalizedOptions['namespace']; + $ns = $options->getNamespace(); if (!isset($this->data[$ns])) { $this->data[$ns] = array(); } @@ -392,7 +548,7 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n if (isset($data[$normalizedKey])) { $result[] = $normalizedKey; } else { - $data[$normalizedKey] = array($value, $now, $normalizedOptions['tags']); + $data[$normalizedKey] = array($value, $now); } } @@ -402,27 +558,18 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n /** * Internal method to replace an existing item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalReplaceItem(& $normalizedKey, & $value) { - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); if (!isset($this->data[$ns][$normalizedKey])) { return false; } - $this->data[$ns][$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); + $this->data[$ns][$normalizedKey] = array($value, microtime(true)); return true; } @@ -430,22 +577,13 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm /** * Internal method to replace multiple existing items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - An array of tags - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalReplaceItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalReplaceItems(array & $normalizedKeyValuePairs) { - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); if (!isset($this->data[$ns])) { return array_keys($normalizedKeyValuePairs); } @@ -456,7 +594,7 @@ protected function internalReplaceItems(array & $normalizedKeyValuePairs, array if (!isset($data[$normalizedKey])) { $result[] = $normalizedKey; } else { - $data[$normalizedKey] = array($value, microtime(true), $normalizedOptions['tags']); + $data[$normalizedKey] = array($value, microtime(true)); } } @@ -466,18 +604,13 @@ protected function internalReplaceItems(array & $normalizedKeyValuePairs, array /** * Internal method to reset lifetime of an item * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalTouchItem(& $normalizedKey, array & $normalizedOptions) + protected function internalTouchItem(& $normalizedKey) { - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); if (!isset($this->data[$ns][$normalizedKey])) { return false; @@ -490,18 +623,13 @@ protected function internalTouchItem(& $normalizedKey, array & $normalizedOption /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) + protected function internalRemoveItem(& $normalizedKey) { - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); if (!isset($this->data[$ns][$normalizedKey])) { return false; } @@ -519,21 +647,14 @@ protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptio /** * Internal method to increment an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalIncrementItem(& $normalizedKey, & $value) { - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); $data = & $this->data[$ns]; if (isset($data[$normalizedKey])) { $data[$normalizedKey][0]+= $value; @@ -542,7 +663,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no } else { // initial value $newValue = $value; - $data[$normalizedKey] = array($newValue, microtime(true), null); + $data[$normalizedKey] = array($newValue, microtime(true)); } return $newValue; @@ -551,21 +672,14 @@ protected function internalIncrementItem(& $normalizedKey, & $value, array & $no /** * Internal method to decrement an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalDecrementItem(& $normalizedKey, & $value) { - $ns = $normalizedOptions['namespace']; + $ns = $this->getOptions()->getNamespace(); $data = & $this->data[$ns]; if (isset($data[$normalizedKey])) { $data[$normalizedKey][0]-= $value; @@ -574,203 +688,12 @@ protected function internalDecrementItem(& $normalizedKey, & $value, array & $no } else { // initial value $newValue = -$value; - $data[$normalizedKey] = array($newValue, microtime(true), null); + $data[$normalizedKey] = array($newValue, microtime(true)); } return $newValue; } - /* find */ - - /** - * internal method to find items. - * - * Options: - * - ttl - * - The time-to-live - * - namespace - * - The namespace to use - * - tags - * - Tags to search for used with matching modes of - * Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see fetch() - * @see fetchAll() - */ - protected function internalFind(& $normalizedMode, array & $normalizedOptions) - { - if ($this->stmtActive) { - throw new Exception\RuntimeException('Statement already in use'); - } - - $tags = & $normalizedOptions['tags']; - $emptyTags = $keys = array(); - foreach ($this->data[ $normalizedOptions['namespace'] ] as $key => &$item) { - - // compare expired / active - if (($normalizedMode & self::MATCH_ALL) != self::MATCH_ALL) { - - // if MATCH_EXPIRED -> filter active items - if (($normalizedMode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { - if ($this->internalHasItem($key, $normalizedOptions)) { - continue; - } - - // if MATCH_ACTIVE -> filter expired items - } else { - if (!$this->internalHasItem($key, $normalizedOptions)) { - continue; - } - } - } - - // compare tags - if ($tags !== null) { - $tagsStored = isset($item[2]) ? $item[2] : $emptyTags; - - if ( ($normalizedMode & self::MATCH_TAGS_OR) == self::MATCH_TAGS_OR ) { - $matched = (count(array_diff($tags, $tagsStored)) != count($tags)); - } elseif ( ($normalizedMode & self::MATCH_TAGS_AND) == self::MATCH_TAGS_AND ) { - $matched = (count(array_diff($tags, $tagsStored)) == 0); - } - - // negate - if ( ($normalizedMode & self::MATCH_TAGS_NEGATE) == self::MATCH_TAGS_NEGATE ) { - $matched = !$matched; - } - - if (!$matched) { - continue; - } - } - - $keys[] = $key; - } - - // don't check expiry on fetch - $normalizedOptions['ttl'] = 0; - - $this->stmtKeys = $keys; - $this->stmtOptions = $normalizedOptions; - $this->stmtActive = true; - - return true; - } - - /** - * Internal method to fetch the next item from result set - * - * @return array|boolean The next item or false - * @throws Exception\ExceptionInterface - */ - protected function internalFetch() - { - if (!$this->stmtActive) { - return false; - } - - $options = & $this->stmtOptions; - - // get the next valid item - do { - $key = array_shift($this->stmtKeys); - if ($key === null) { - break; - } - - if (!$this->internalHasItem($key, $options)) { - continue; - } - - break; - } while (true); - - // free statement after last item - if (!$key) { - $this->stmtActive = false; - $this->stmtKeys = null; - $this->stmtOptions = null; - - return false; - } - - $ref = & $this->data[ $options['namespace'] ][$key]; - $result = array(); - foreach ($options['select'] as $select) { - if ($select == 'key') { - $result['key'] = $key; - } elseif ($select == 'value') { - $result['value'] = $ref[0]; - } elseif ($select == 'mtime') { - $result['mtime'] = $ref[1]; - } elseif ($select == 'tags') { - $result['tags'] = $ref[2]; - } else { - $result[$select] = null; - } - } - - return $result; - } - - /* cleaning */ - - /** - * Internal method to clear items off all namespaces. - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - if (!$normalizedOptions['tags'] && ($normalizedMode & self::MATCH_ALL) == self::MATCH_ALL) { - $this->data = array(); - } else { - foreach ($this->data as & $data) { - $this->clearNamespacedDataArray($data, $normalizedMode, $normalizedOptions); - } - } - - return true; - } - - /** - * Clear items by namespace. - * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - tags - * - Tags to search for used with matching modes of Adapter::MATCH_TAGS_* - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clear() - */ - protected function internalClearByNamespace(& $normalizedMode, array & $normalizedOptions) - { - if (isset($this->data[ $normalizedOptions['namespace'] ])) { - if (!$normalizedOptions['tags'] && ($normalizedMode & self::MATCH_ALL) == self::MATCH_ALL) { - unset($this->data[ $normalizedOptions['namespace'] ]); - } else { - $this->clearNamespacedDataArray($this->data[ $normalizedOptions['namespace'] ], $normalizedMode, $normalizedOptions); - } - } - - return true; - } - /* status */ /** @@ -796,21 +719,14 @@ protected function internalGetCapabilities() 'object' => true, 'resource' => true, ), - 'supportedMetadata' => array( - 'mtime', - 'tags', - ), + 'supportedMetadata' => array('mtime'), 'maxTtl' => PHP_INT_MAX, 'staticTtl' => false, - 'tagging' => true, 'ttlPrecision' => 0.05, 'expiredRead' => true, 'maxKeyLength' => 0, 'namespaceIsPrefix' => false, 'namespaceSeparator' => '', - 'iterable' => true, - 'clearAllNamespaces' => true, - 'clearByNamespace' => true, ) ); } @@ -818,35 +734,14 @@ protected function internalGetCapabilities() return $this->capabilities; } - /** - * Internal method to get storage capacity. - * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - */ - protected function internalGetCapacity(array & $normalizedOptions) - { - $total = $this->getOptions()->getMemoryLimit(); - $free = $total - (float) memory_get_usage(true); - return array( - 'total' => $total, - 'free' => ($free >= 0) ? $free : 0, - ); - } - /* internal */ /** - * Has the memory adapter storage free capacity - * to store items - * - * Similar logic as getCapacity() but without triggering - * events and returns boolean. + * Has space available to store items? * * @return boolean */ - protected function hasFreeCapacity() + protected function hasAvailableSpace() { $total = $this->getOptions()->getMemoryLimit(); @@ -855,67 +750,7 @@ protected function hasFreeCapacity() return true; } - $free = $total - (float) memory_get_usage(true); + $free = $total - (float) memory_get_usage(true); return ($free > 0); } - - /** - * Internal method to run a clear command - * on a given data array which doesn't contain namespaces. - * - * Options: - * - ttl required - * - tags required - * - * @param array $data - * @param int $mode - * @param array $options - */ - protected function clearNamespacedDataArray(array &$data, $mode, array &$options) - { - $tags = &$options['tags']; - $time = microtime(true); - $ttl = $options['ttl']; - - $emptyTags = $keys = array(); - foreach ($data as $key => &$item) { - - // compare expired / active - if (($mode & self::MATCH_ALL) != self::MATCH_ALL) { - - // if MATCH_EXPIRED mode selected don't match active items - if (($mode & self::MATCH_EXPIRED) == self::MATCH_EXPIRED) { - if ($ttl == 0 || $time <= ($item[1]+$ttl) ) { - continue; - } - - // if MATCH_ACTIVE mode selected don't match expired items - } elseif ($ttl > 0 && $time >= ($item[1]+$ttl)) { - continue; - } - } - - // compare tags - if ($tags !== null) { - $tagsStored = isset($item[2]) ? $item[2] : $emptyTags; - - if ( ($mode & self::MATCH_TAGS_OR) == self::MATCH_TAGS_OR ) { - $matched = (count(array_diff($tags, $tagsStored)) != count($tags)); - } elseif ( ($mode & self::MATCH_TAGS_AND) == self::MATCH_TAGS_AND ) { - $matched = (count(array_diff($tags, $tagsStored)) == 0); - } - - // negate - if ( ($mode & self::MATCH_TAGS_NEGATE) == self::MATCH_TAGS_NEGATE ) { - $matched = !$matched; - } - - if (!$matched) { - continue; - } - } - - unset($data[$key]); - } - } } diff --git a/src/Storage/Adapter/MemoryOptions.php b/src/Storage/Adapter/MemoryOptions.php index 777ba2b04..b9356e2a1 100644 --- a/src/Storage/Adapter/MemoryOptions.php +++ b/src/Storage/Adapter/MemoryOptions.php @@ -46,7 +46,7 @@ class MemoryOptions extends AdapterOptions * Set memory limit * * - Bytes of less or equal 0 will disable the memory limit - * - If the used memory of PHP exceeds this limit an OutOfCapacityException + * - If the used memory of PHP exceeds this limit an OutOfSpaceException * will be thrown. * * @param int $bytes @@ -55,6 +55,15 @@ class MemoryOptions extends AdapterOptions public function setMemoryLimit($bytes) { $bytes = (int) $bytes; + + // use PHP's memory limit if possible + if ($bytes <= 0) { + $bytes = Utils::bytesFromString(ini_get('memory_limit')); + if ($bytes <= 0) { + $bytes = 0; + } + } + $this->triggerOptionEvent('memory_limit', $bytes); $this->memoryLimit = $bytes; return $this; @@ -63,7 +72,7 @@ public function setMemoryLimit($bytes) /** * Get memory limit * - * If the used memory of PHP exceeds this limit an OutOfCapacityException + * If the used memory of PHP exceeds this limit an OutOfSpaceException * will be thrown. * * @return int @@ -71,6 +80,7 @@ public function setMemoryLimit($bytes) public function getMemoryLimit() { if ($this->memoryLimit === null) { + // By default use half of PHP's memory limit if possible $memoryLimit = Utils::bytesFromString(ini_get('memory_limit')); if ($memoryLimit >= 0) { $this->memoryLimit = floor($memoryLimit / 2); diff --git a/src/Storage/Adapter/WinCache.php b/src/Storage/Adapter/WinCache.php index 8ac4ab37a..1704519ed 100644 --- a/src/Storage/Adapter/WinCache.php +++ b/src/Storage/Adapter/WinCache.php @@ -24,7 +24,10 @@ use ArrayObject, stdClass, Zend\Cache\Exception, - Zend\Cache\Storage\Capabilities; + Zend\Cache\Storage\Capabilities, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\AvailableSpaceCapableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface; /** * @package Zend_Cache @@ -32,16 +35,11 @@ * @subpackage Storage * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @todo Implement the find() method */ -class WinCache extends AbstractAdapter +class WinCache + extends AbstractAdapter + implements FlushableInterface, AvailableSpaceCapableInterface, TotalSpaceCapableInterface { - /** - * The used namespace separator - * - * @var string - */ - protected $namespaceSeparator = ':'; /** * Constructor @@ -102,27 +100,59 @@ public function getOptions() return $this->options; } + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + $mem = wincache_ucache_meminfo(); + return $mem['memory_total']; + } + + /* AvailableSpaceCapableInterface */ + + /** + * Get available space in bytes + * + * @return int|float + */ + public function getAvailableSpace() + { + $mem = wincache_ucache_meminfo(); + return $mem['memory_free']; + } + + /* FlushableInterface */ + + /** + * Flush the whole storage + * + * @return boolean + */ + public function flush() + { + return wincache_ucache_clear(); + } + /* reading */ /** * Internal method to get an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @param boolean $success * @param mixed $casToken * @return mixed Data on success, null on failure * @throws Exception\ExceptionInterface */ - protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, & $success = null, & $casToken = null) + protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKey = $prefix . $normalizedKey; $result = wincache_ucache_get($internalKey, $success); @@ -136,18 +166,14 @@ protected function internalGetItem(& $normalizedKey, array & $normalizedOptions, /** * Internal method to get multiple items. * - * Options: - * - namespace - * - The namespace to use - * * @param array $normalizedKeys - * @param array $normalizedOptions * @return array Associative array of keys and values * @throws Exception\ExceptionInterface */ - protected function internalGetItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalGetItems(array & $normalizedKeys) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { $internalKeys[] = $prefix . $normalizedKey; @@ -159,7 +185,7 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized $prefixL = strlen($prefix); $result = array(); foreach ($fetch as $internalKey => & $value) { - $result[ substr($internalKey, $prefixL) ] = $value; + $result[ substr($internalKey, $prefixL) ] = & $value; } return $result; @@ -168,40 +194,29 @@ protected function internalGetItems(array & $normalizedKeys, array & $normalized /** * Internal method to test if an item exists. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalHasItem(& $normalizedKey, array & $normalizedOptions) + protected function internalHasItem(& $normalizedKey) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); return wincache_ucache_exists($prefix . $normalizedKey); } /** * Get metadata of an item. * - * Options: - * - namespace optional - * - The namespace to use (Default: namespace of object) - * * @param string $normalizedKey - * @param array $normalizedOptions * @return array|boolean Metadata on success, false on failure * @throws Exception\ExceptionInterface - * - * @triggers getMetadata.pre(PreEvent) - * @triggers getMetadata.post(PostEvent) - * @triggers getMetadata.exception(ExceptionEvent) */ - protected function internalGetMetadata(& $normalizedKey, array & $normalizedOptions) + protected function internalGetMetadata(& $normalizedKey) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; $info = wincache_ucache_info(true, $internalKey); if (isset($info['ucache_entries'][1])) { @@ -218,25 +233,22 @@ protected function internalGetMetadata(& $normalizedKey, array & $normalizedOpti /** * Internal method to store an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalSetItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalSetItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - if (!wincache_ucache_set($internalKey, $value, $normalizedOptions['ttl'])) { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $ttl = $options->getTtl(); + + if (!wincache_ucache_set($internalKey, $value, $ttl)) { $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( - "wincache_ucache_set('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + "wincache_ucache_set('{$internalKey}', <{$type}>, {$ttl}) failed" ); } @@ -246,20 +258,14 @@ protected function internalSetItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to store multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalSetItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalSetItems(array & $normalizedKeyValuePairs) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $prefixL = strlen($prefix); $internalKeyValuePairs = array(); @@ -268,7 +274,7 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n $internalKeyValuePairs[$internalKey] = $value; } - $result = wincache_ucache_set($internalKeyValuePairs, null, $normalizedOptions['ttl']); + $result = wincache_ucache_set($internalKeyValuePairs, null, $options->getTtl()); // remove key prefic foreach ($result as & $key) { @@ -281,25 +287,22 @@ protected function internalSetItems(array & $normalizedKeyValuePairs, array & $n /** * Add an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * - * @param string $key + * @param string $normalizedKey * @param mixed $value - * @param array $options * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalAddItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalAddItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; - if (!wincache_ucache_add($internalKey, $value, $normalizedOptions['ttl'])) { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; + $ttl = $options->getTtl(); + + if (!wincache_ucache_add($internalKey, $value, $ttl)) { $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( - "wincache_ucache_add('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + "wincache_ucache_add('{$internalKey}', <{$type}>, {$ttl}) failed" ); } @@ -309,27 +312,23 @@ protected function internalAddItem(& $normalizedKey, & $value, array & $normaliz /** * Internal method to add multiple items. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param array $normalizedKeyValuePairs - * @param array $normalizedOptions * @return array Array of not stored keys * @throws Exception\ExceptionInterface */ - protected function internalAddItems(array & $normalizedKeyValuePairs, array & $normalizedOptions) + protected function internalAddItems(array & $normalizedKeyValuePairs) { + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $prefixL = strlen($prefix); + $internalKeyValuePairs = array(); - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); foreach ($normalizedKeyValuePairs as $normalizedKey => $value) { $internalKey = $prefix . $normalizedKey; $internalKeyValuePairs[$internalKey] = $value; } - $result = wincache_ucache_add($internalKeyValuePairs, null, $normalizedOptions['ttl']); + $result = wincache_ucache_add($internalKeyValuePairs, null, $options->getTtl()); // remove key prefic foreach ($result as & $key) { @@ -342,29 +341,25 @@ protected function internalAddItems(array & $normalizedKeyValuePairs, array & $n /** * Internal method to replace an existing item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param mixed $value - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalReplaceItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalReplaceItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; if (!wincache_ucache_exists($internalKey)) { return false; } - if (!wincache_ucache_set($internalKey, $value, $normalizedOptions['ttl'])) { + $ttl = $options->getTtl(); + if (!wincache_ucache_set($internalKey, $value, $ttl)) { $type = is_object($value) ? get_class($value) : gettype($value); throw new Exception\RuntimeException( - "wincache_ucache_set('{$internalKey}', <{$type}>, {$normalizedOptions['ttl']}) failed" + "wincache_ucache_set('{$internalKey}', <{$type}>, {$ttl}) failed" ); } @@ -374,36 +369,29 @@ protected function internalReplaceItem(& $normalizedKey, & $value, array & $norm /** * Internal method to remove an item. * - * Options: - * - namespace - * - The namespace to use - * * @param string $normalizedKey - * @param array $normalizedOptions * @return boolean * @throws Exception\ExceptionInterface */ - protected function internalRemoveItem(& $normalizedKey, array & $normalizedOptions) + protected function internalRemoveItem(& $normalizedKey) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; return wincache_ucache_delete($internalKey); } /** * Internal method to remove multiple items. * - * Options: - * - namespace - * - The namespace to use - * - * @param array $keys - * @param array $options + * @param array $normalizedKeys * @return array Array of not removed keys * @throws Exception\ExceptionInterface */ - protected function internalRemoveItems(array & $normalizedKeys, array & $normalizedOptions) + protected function internalRemoveItems(array & $normalizedKeys) { - $prefix = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator(); + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); $internalKeys = array(); foreach ($normalizedKeys as $normalizedKey) { @@ -427,65 +415,35 @@ protected function internalRemoveItems(array & $normalizedKeys, array & $normali /** * Internal method to increment an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalIncrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalIncrementItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; return wincache_ucache_inc($internalKey, (int)$value); } /** * Internal method to decrement an item. * - * Options: - * - ttl - * - The time-to-life - * - namespace - * - The namespace to use - * * @param string $normalizedKey * @param int $value - * @param array $normalizedOptions * @return int|boolean The new value on success, false on failure * @throws Exception\ExceptionInterface */ - protected function internalDecrementItem(& $normalizedKey, & $value, array & $normalizedOptions) + protected function internalDecrementItem(& $normalizedKey, & $value) { - $internalKey = $normalizedOptions['namespace'] . $this->getOptions()->getNamespaceSeparator() . $normalizedKey; + $options = $this->getOptions(); + $prefix = $options->getNamespace() . $options->getNamespaceSeparator(); + $internalKey = $prefix . $normalizedKey; return wincache_ucache_dec($internalKey, (int)$value); } - /* cleaning */ - - /** - * Internal method to clear items off all namespaces. - * - * Options: - * - ttl - * - The time-to-life - * - * @param int $normalizedMode Matching mode (Value of Adapter::MATCH_*) - * @param array $normalizedOptions - * @return boolean - * @throws Exception\ExceptionInterface - * @see clearByNamespace() - */ - protected function internalClear(& $normalizedMode, array & $normalizedOptions) - { - return wincache_ucache_clear(); - } - /* status */ /** @@ -512,10 +470,7 @@ protected function internalGetCapabilities() 'resource' => false, ), 'supportedMetadata' => array( - 'ttl', - 'num_hits', - 'internal_key', - 'mem_size' + 'internal_key', 'ttl', 'hits', 'size' ), 'maxTtl' => 0, 'staticTtl' => true, @@ -524,9 +479,6 @@ protected function internalGetCapabilities() 'expiredRead' => false, 'namespaceIsPrefix' => true, 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(), - 'iterable' => false, - 'clearAllNamespaces' => true, - 'clearByNamespace' => false, ) ); @@ -546,22 +498,6 @@ protected function internalGetCapabilities() return $this->capabilities; } - /** - * Internal method to get storage capacity. - * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface - */ - protected function internalGetCapacity(array & $normalizedOptions) - { - $mem = wincache_ucache_meminfo(); - return array( - 'free' => $mem['memory_free'], - 'total' => $mem['memory_total'], - ); - } - /* internal */ /** @@ -572,24 +508,16 @@ protected function internalGetCapacity(array & $normalizedOptions) */ protected function normalizeMetadata(array & $metadata) { - if (isset($metadata['hitcount'])) { - $metadata['num_hits'] = $metadata['hitcount']; - unset($metadata['hitcount']); - } - - if (isset($metadata['ttl_seconds'])) { - $metadata['ttl'] = $metadata['ttl_seconds']; - unset($metadata['ttl_seconds']); - } - - if (isset($metadata['value_size'])) { - $metadata['mem_size'] = $metadata['value_size']; - unset($metadata['value_size']); - } - - if (isset($metadata['key_name'])) { - $metadata['internal_key'] = $metadata['key_name']; - unset($metadata['key_name']); - } + $metadata['internal_key'] = $metadata['key_name']; + $metadata['hits'] = $metadata['hitcount']; + $metadata['ttl'] = $metadata['ttl_seconds']; + $metadata['size'] = $metadata['value_size']; + + unset( + $metadata['key_name'], + $metadata['hitcount'], + $metadata['ttl_seconds'], + $metadata['value_size'] + ); } } diff --git a/src/Storage/Adapter/ZendServerDisk.php b/src/Storage/Adapter/ZendServerDisk.php index 01c88bcde..53f3cedc7 100644 --- a/src/Storage/Adapter/ZendServerDisk.php +++ b/src/Storage/Adapter/ZendServerDisk.php @@ -22,8 +22,12 @@ namespace Zend\Cache\Storage\Adapter; use ArrayObject, - Zend\Cache\Utils, - Zend\Cache\Exception; + Zend\Cache\Exception, + Zend\Cache\Storage\ClearByNamespaceInterface, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\AvailableSpaceCapableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface, + Zend\Stdlib\ErrorHandler; /** * @category Zend @@ -32,9 +36,19 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class ZendServerDisk extends AbstractZendServer +class ZendServerDisk + extends AbstractZendServer + implements FlushableInterface, ClearByNamespaceInterface, + AvailableSpaceCapableInterface, TotalSpaceCapableInterface { + /** + * Buffered total space in bytes + * + * @var null|int|float + */ + protected $totalSpace; + /** * Constructor * @@ -53,18 +67,76 @@ public function __construct($options = array()) parent::__construct($options); } + /* FlushableInterface */ + /** - * Internal method to get storage capacity. + * Flush the whole storage * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface + * @return boolean */ - protected function internalGetCapacity(array & $normalizedOptions) + public function flush() { - return Utils::getDiskCapacity(ini_get('zend_datacache.disk.save_path')); + return zend_disk_cache_clear(); } + /* ClearByNamespaceInterface */ + + /** + * Remove items of given namespace + * + * @param string $namespace + * @return boolean + */ + public function clearByNamespace($namespace) + { + return zend_disk_cache_clear($namespace); + } + + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + if ($this->totalSpace !== null) { + $path = $this->getOptions()->getCacheDir(); + + ErrorHandler::start(); + $total = disk_total_space($path); + $error = ErrorHandler::stop(); + if ($total === false) { + throw new Exception\RuntimeException("Can't detect total space of '{$path}'", 0, $error); + } + } + return $this->totalSpace; + } + + /* AvailableSpaceCapableInterface */ + + /** + * Get available space in bytes + * + * @return int|float + */ + public function getAvailableSpace() + { + $path = $this->getOptions()->getCacheDir(); + + ErrorHandler::start(); + $avail = disk_free_space($path); + $error = ErrorHandler::stop(); + if ($avail === false) { + throw new Exception\RuntimeException("Can't detect free space of '{$path}'", 0, $error); + } + + return $avail; + } + + /* internal */ + /** * Store data into Zend Data Disk Cache * @@ -123,35 +195,4 @@ protected function zdcDelete($internalKey) { return zend_disk_cache_delete($internalKey); } - - /** - * Clear items of all namespaces from Zend Data Disk Cache - * - * @return void - * @throws Exception\RuntimeException - */ - protected function zdcClear() - { - if (!zend_disk_cache_clear()) { - throw new Exception\RuntimeException( - 'zend_disk_cache_clear() failed' - ); - } - } - - /** - * Clear items of the given namespace from Zend Data Disk Cache - * - * @param string $namespace - * @return void - * @throws Exception\RuntimeException - */ - protected function zdcClearByNamespace($namespace) - { - if (!zend_disk_cache_clear($namespace)) { - throw new Exception\RuntimeException( - "zend_disk_cache_clear({$namespace}) failed" - ); - } - } } diff --git a/src/Storage/Adapter/ZendServerShm.php b/src/Storage/Adapter/ZendServerShm.php index 3ce9d18ce..5c1f8d0be 100644 --- a/src/Storage/Adapter/ZendServerShm.php +++ b/src/Storage/Adapter/ZendServerShm.php @@ -22,7 +22,10 @@ namespace Zend\Cache\Storage\Adapter; use ArrayObject, - Zend\Cache\Exception; + Zend\Cache\Exception, + Zend\Cache\Storage\ClearByNamespaceInterface, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\TotalSpaceCapableInterface; /** * @category Zend @@ -31,7 +34,9 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class ZendServerShm extends AbstractZendServer +class ZendServerShm + extends AbstractZendServer + implements FlushableInterface, ClearByNamespaceInterface, TotalSpaceCapableInterface { /** @@ -52,23 +57,45 @@ public function __construct($options = array()) parent::__construct($options); } + /* FlushableInterface */ + /** - * Internal method to get storage capacity. + * Flush the whole storage * - * @param array $normalizedOptions - * @return array|boolean Associative array of capacity, false on failure - * @throws Exception\ExceptionInterface + * @return boolean */ - protected function internalGetCapacity(array & $normalizedOptions) + public function flush() { - $total = (int)ini_get('zend_datacache.shm.memory_cache_size'); - $total*= 1048576; // MB -> Byte - return array( - 'total' => $total, - // TODO: How to get free capacity status - ); + return zend_shm_cache_clear(); } + /* ClearByNamespaceInterface */ + + /** + * Remove items of given namespace + * + * @param string $namespace + * @return boolean + */ + public function clearByNamespace($namespace) + { + return zend_shm_cache_clear($namespace); + } + + /* TotalSpaceCapableInterface */ + + /** + * Get total space in bytes + * + * @return int|float + */ + public function getTotalSpace() + { + return (int) ini_get('zend_datacache.shm.memory_cache_size') * 1048576; + } + + /* internal */ + /** * Store data into Zend Data SHM Cache * @@ -127,35 +154,4 @@ protected function zdcDelete($internalKey) { return zend_shm_cache_delete($internalKey); } - - /** - * Clear items of all namespaces from Zend Data SHM Cache - * - * @return void - * @throws Exception\RuntimeException - */ - protected function zdcClear() - { - if (!zend_shm_cache_clear()) { - throw new Exception\RuntimeException( - 'zend_shm_cache_clear() failed' - ); - } - } - - /** - * Clear items of the given namespace from Zend Data SHM Cache - * - * @param string $namespace - * @return void - * @throws Exception\RuntimeException - */ - protected function zdcClearByNamespace($namespace) - { - if (!zend_shm_cache_clear($namespace)) { - throw new Exception\RuntimeException( - "zend_shm_cache_clear({$namespace}) failed" - ); - } - } } diff --git a/src/Storage/AdapterBroker.php b/src/Storage/AdapterBroker.php index 95cf6e200..7e9a99630 100644 --- a/src/Storage/AdapterBroker.php +++ b/src/Storage/AdapterBroker.php @@ -49,9 +49,9 @@ class AdapterBroker extends PluginBroker */ protected function validatePlugin($plugin) { - if (!$plugin instanceof Adapter\AdapterInterface) { + if (!$plugin instanceof StorageInterface) { throw new Exception\RuntimeException( - 'Cache storage adapters must implement Zend\Cache\Storage\Adapter\AdapterInterface' + 'Cache storage adapters must implement Zend\Cache\Storage\StorageInterface' ); } return true; diff --git a/src/Storage/AvailableSpaceCapableInterface.php b/src/Storage/AvailableSpaceCapableInterface.php new file mode 100644 index 000000000..6e1ab7442 --- /dev/null +++ b/src/Storage/AvailableSpaceCapableInterface.php @@ -0,0 +1,39 @@ +adapter = $adapter; + $this->storage = $storage; $this->marker = $marker; $this->baseCapabilities = $baseCapabilities; @@ -163,7 +141,7 @@ public function __construct( */ public function getAdapter() { - return $this->adapter; + return $this->storage; } /** @@ -446,93 +424,6 @@ public function setNamespaceSeparator(stdClass $marker, $separator) return $this->setCapability($marker, 'namespaceSeparator', (string) $separator); } - /** - * Get if items are iterable - * - * @return boolean - */ - public function getIterable() - { - return $this->getCapability('iterable', false); - } - - /** - * Set if items are iterable - * - * @param stdClass $marker - * @param boolean $flag - * @return Capabilities Fluent interface - */ - public function setIterable(stdClass $marker, $flag) - { - return $this->setCapability($marker, 'iterable', (bool)$flag); - } - - /** - * Get support to clear items of all namespaces - * - * @return boolean - */ - public function getClearAllNamespaces() - { - return $this->getCapability('clearAllNamespaces', false); - } - - /** - * Set support to clear items of all namespaces - * - * @param stdClass $marker - * @param boolean $flag - * @return Capabilities Fluent interface - */ - public function setClearAllNamespaces(stdClass $marker, $flag) - { - return $this->setCapability($marker, 'clearAllNamespaces', (bool)$flag); - } - - /** - * Get support to clear items by namespace - * - * @return boolean - */ - public function getClearByNamespace() - { - return $this->getCapability('clearByNamespace', false); - } - - /** - * Set support to clear items by namespace - * - * @param stdClass $marker - * @param boolean $flag - * @return Capabilities Fluent interface - */ - public function setClearByNamespace(stdClass $marker, $flag) - { - return $this->setCapability($marker, 'clearByNamespace', (bool)$flag); - } - - /** - * Set value for tagging - * - * @param mixed tagging - * @return $this - */ - public function setTagging(stdClass $marker, $tagging) - { - return $this->setCapability($marker, 'tagging', (bool) $tagging); - } - - /** - * Get value for tagging - * - * @return mixed - */ - public function getTagging() - { - return $this->getCapability('tagging', false); - } - /** * Get a capability * @@ -572,8 +463,8 @@ protected function setCapability(stdClass $marker, $name, $value) $this->$property = $value; // trigger event - if ($this->adapter instanceof EventsCapableInterface) { - $this->adapter->events()->trigger('capability', $this->adapter, new ArrayObject(array( + if ($this->storage instanceof EventsCapableInterface) { + $this->storage->events()->trigger('capability', $this->storage, new ArrayObject(array( $name => $value ))); } diff --git a/src/Storage/ClearByNamespaceInterface.php b/src/Storage/ClearByNamespaceInterface.php new file mode 100644 index 000000000..6d1e88644 --- /dev/null +++ b/src/Storage/ClearByNamespaceInterface.php @@ -0,0 +1,40 @@ +target = $adapter; + $this->target = $storage; return $this; } /** * Alias of getTarget * - * @return Adapter\AdapterInterface + * @return StorageInterface */ public function getStorage() { diff --git a/src/Storage/ExceptionEvent.php b/src/Storage/ExceptionEvent.php index 145c0c265..d7158a14d 100644 --- a/src/Storage/ExceptionEvent.php +++ b/src/Storage/ExceptionEvent.php @@ -59,7 +59,7 @@ class ExceptionEvent extends PostEvent * @param Exception $exception * @return void */ - public function __construct($name, Adapter\AdapterInterface $storage, ArrayObject $params, & $result, Exception $exception) + public function __construct($name, StorageInterface $storage, ArrayObject $params, & $result, Exception $exception) { parent::__construct($name, $storage, $params, $result); $this->setException($exception); diff --git a/src/Storage/FlushableInterface.php b/src/Storage/FlushableInterface.php new file mode 100644 index 000000000..1a25f482c --- /dev/null +++ b/src/Storage/FlushableInterface.php @@ -0,0 +1,39 @@ +handles[$index] = & $handles; - $callback = array($this, 'clearByFactor'); + $callback = array($this, 'clearExpiredByFactor'); $handles[] = $events->attach('setItem.post', $callback, $priority); $handles[] = $events->attach('setItems.post', $callback, $priority); $handles[] = $events->attach('addItem.post', $callback, $priority); @@ -96,22 +97,21 @@ public function detach(EventManagerInterface $events) } /** - * Clear storage by factor on a success _RESULT_ + * Clear expired items by factor after writing new item(s) * * @param PostEvent $event * @return void */ - public function clearByFactor(PostEvent $event) + public function clearExpiredByFactor(PostEvent $event) { - $options = $this->getOptions(); - $factor = $options->getClearingFactor(); - if ($factor && $event->getResult() && mt_rand(1, $factor) == 1) { - $params = $event->getParams(); - if ($options->getClearByNamespace()) { - $event->getStorage()->clearByNamespace(Adapter::MATCH_EXPIRED, $params['options']); - } else { - $event->getStorage()->clear(Adapter::MATCH_EXPIRED, $params['options']); - } + $storage = $event->getStorage(); + if ( !($storage instanceof ClearExpiredInterface) ) { + return; + } + + $factor = $this->getOptions()->getClearingFactor(); + if ($factor && mt_rand(1, $factor) == 1) { + $storage->clearExpired(); } } } diff --git a/src/Storage/Plugin/ExceptionHandler.php b/src/Storage/Plugin/ExceptionHandler.php index 4e8bc202b..ba64a6a40 100644 --- a/src/Storage/Plugin/ExceptionHandler.php +++ b/src/Storage/Plugin/ExceptionHandler.php @@ -70,13 +70,6 @@ public function attach(EventManagerInterface $events, $priority = 1) $handles[] = $events->attach('getMetadata.exception', $callback, $priority); $handles[] = $events->attach('getMetadatas.exception', $callback, $priority); - // non-blocking - $handles[] = $events->attach('getDelayed.exception', $callback, $priority); - $handles[] = $events->attach('find.exception', $callback, $priority); - - $handles[] = $events->attach('fetch.exception', $callback, $priority); - $handles[] = $events->attach('fetchAll.exception', $callback, $priority); - // write $handles[] = $events->attach('setItem.exception', $callback, $priority); $handles[] = $events->attach('setItems.exception', $callback, $priority); @@ -102,14 +95,6 @@ public function attach(EventManagerInterface $events, $priority = 1) $handles[] = $events->attach('decrementItem.exception', $callback, $priority); $handles[] = $events->attach('decrementItems.exception', $callback, $priority); - // clear - $handles[] = $events->attach('clear.exception', $callback, $priority); - $handles[] = $events->attach('clearByNamespace.exception', $callback, $priority); - - // additional - $handles[] = $events->attach('optimize.exception', $callback, $priority); - $handles[] = $events->attach('getCapacity.exception', $callback, $priority); - return $this; } diff --git a/src/Storage/Plugin/IgnoreUserAbort.php b/src/Storage/Plugin/IgnoreUserAbort.php index 4c8703b4d..7710a97ba 100644 --- a/src/Storage/Plugin/IgnoreUserAbort.php +++ b/src/Storage/Plugin/IgnoreUserAbort.php @@ -42,9 +42,9 @@ class IgnoreUserAbort extends AbstractPlugin protected $handles = array(); /** - * The storage adapter target who activated ignore_user_abort. + * The storage who activated ignore_user_abort. * - * @var null|\Zend\Cache\Storage\Adapter\AdapterInterface + * @var null|Zend\Cache\Storage\StorageInterface */ protected $activatedTarget = null; diff --git a/src/Storage/Plugin/OptimizeByFactor.php b/src/Storage/Plugin/OptimizeByFactor.php index a72f24096..64d8de293 100644 --- a/src/Storage/Plugin/OptimizeByFactor.php +++ b/src/Storage/Plugin/OptimizeByFactor.php @@ -23,6 +23,7 @@ use Traversable, Zend\Cache\Exception, + Zend\Cache\Storage\OptimizableInterface, Zend\Cache\Storage\PostEvent, Zend\EventManager\EventManagerInterface; @@ -61,10 +62,8 @@ public function attach(EventManagerInterface $events, $priority = 1) $this->handles[$index] = & $handles; $callback = array($this, 'optimizeByFactor'); - $handles[] = $events->attach('removeItem.post', $callback, $priority); - $handles[] = $events->attach('removeItems.post', $callback, $priority); - $handles[] = $events->attach('clear.post', $callback, $priority); - $handles[] = $events->attach('clearByNamespace.post', $callback, $priority); + $handles[] = $events->attach('removeItem.post', $callback, $priority); + $handles[] = $events->attach('removeItems.post', $callback, $priority); return $this; } @@ -102,10 +101,14 @@ public function detach(EventManagerInterface $events) */ public function optimizeByFactor(PostEvent $event) { + $storage = $event->getStorage(); + if ( !($storage instanceof OptimizableInterface) ) { + return; + } + $factor = $this->getOptions()->getOptimizingFactor(); - if ($factor && $event->getResult() && mt_rand(1, $factor) == 1) { - $params = $event->getParams(); - $event->getStorage()->optimize($params['options']); + if ($factor && mt_rand(1, $factor) == 1) { + $storage->optimize(); } } } diff --git a/src/Storage/Plugin/PluginOptions.php b/src/Storage/Plugin/PluginOptions.php index 1d3fb9ee3..828c95956 100644 --- a/src/Storage/Plugin/PluginOptions.php +++ b/src/Storage/Plugin/PluginOptions.php @@ -42,13 +42,6 @@ class PluginOptions extends Options */ protected $clearingFactor = 0; - /** - * Used by: - * - ClearByFactor - * @var int - */ - protected $clearByNamespace = true; - /** * Used by: * - ExceptionHandler @@ -95,7 +88,7 @@ class PluginOptions extends Options * Set automatic clearing factor * * Used by: - * - ClearByFactor + * - ClearExpiredByFactor * * @param int $clearingFactor * @return PluginOptions @@ -110,7 +103,7 @@ public function setClearingFactor($clearingFactor) * Get automatic clearing factor * * Used by: - * - ClearByFactor + * - ClearExpiredByFactor * * @return int */ @@ -119,34 +112,6 @@ public function getClearingFactor() return $this->clearingFactor; } - /** - * Set flag indicating whether or not to clear by namespace - * - * Used by: - * - ClearByFactor - * - * @param bool $clearByNamespace - * @return PluginOptions - */ - public function setClearByNamespace($clearByNamespace) - { - $this->clearByNamespace = $clearByNamespace; - return $this; - } - - /** - * Clear items by namespace? - * - * Used by: - * - ClearByFactor - * - * @return bool - */ - public function getClearByNamespace() - { - return $this->clearByNamespace; - } - /** * Set callback to call on intercepted exception * diff --git a/src/Storage/Plugin/Serializer.php b/src/Storage/Plugin/Serializer.php index 3916e5eee..027091ebd 100644 --- a/src/Storage/Plugin/Serializer.php +++ b/src/Storage/Plugin/Serializer.php @@ -77,10 +77,6 @@ public function attach(EventManagerInterface $events, $priority = 1) $handles[] = $events->attach('getItem.post', array($this, 'onReadItemPost'), $postPriority); $handles[] = $events->attach('getItems.post', array($this, 'onReadItemsPost'), $postPriority); - // fetch / fetchAll - $handles[] = $events->attach('fetch.post', array($this, 'onFetchPost'), $postPriority); - $handles[] = $events->attach('fetchAll.post', array($this, 'onFetchAllPost'), $postPriority); - // write $handles[] = $events->attach('setItem.pre', array($this, 'onWriteItemPre'), $prePriority); $handles[] = $events->attach('setItems.pre', array($this, 'onWriteItemsPre'), $prePriority); @@ -139,8 +135,7 @@ public function detach(EventManagerInterface $events) */ public function onReadItemPost(PostEvent $event) { - $options = $this->getOptions(); - $serializer = $options->getSerializer(); + $serializer = $this->getOptions()->getSerializer(); $result = $event->getResult(); $result = $serializer->unserialize($result); $event->setResult($result); @@ -154,8 +149,7 @@ public function onReadItemPost(PostEvent $event) */ public function onReadItemsPost(PostEvent $event) { - $options = $this->getOptions(); - $serializer = $options->getSerializer(); + $serializer = $this->getOptions()->getSerializer(); $result = $event->getResult(); foreach ($result as &$value) { $value = $serializer->unserialize($value); @@ -163,42 +157,6 @@ public function onReadItemsPost(PostEvent $event) $event->setResult($result); } - /** - * On fetch post - * - * @param PostEvent $event - * @return void - */ - public function onFetchPost(PostEvent $event) - { - $options = $this->getOptions(); - $serializer = $options->getSerializer(); - $item = $event->getResult(); - if (isset($item['value'])) { - $item['value'] = $serializer->unserialize($item['value']); - } - $event->setResult($item); - } - - /** - * On fetch all post - * - * @param PostEvent $event - * @return void - */ - public function onFetchAllPost(PostEvent $event) - { - $options = $this->getOptions(); - $serializer = $options->getSerializer(); - $result = $event->getResult(); - foreach ($result as &$item) { - if (isset($item['value'])) { - $item['value'] = $serializer->unserialize($item['value']); - } - } - $event->setResult($result); - } - /** * On write item pre * @@ -207,8 +165,7 @@ public function onFetchAllPost(PostEvent $event) */ public function onWriteItemPre(Event $event) { - $options = $this->getOptions(); - $serializer = $options->getSerializer(); + $serializer = $this->getOptions()->getSerializer(); $params = $event->getParams(); $params['value'] = $serializer->serialize($params['value']); } @@ -221,8 +178,7 @@ public function onWriteItemPre(Event $event) */ public function onWriteItemsPre(Event $event) { - $options = $this->getOptions(); - $serializer = $options->getSerializer(); + $serializer = $this->getOptions()->getSerializer(); $params = $event->getParams(); foreach ($params['keyValuePairs'] as &$value) { $value = $serializer->serialize($value); @@ -237,21 +193,22 @@ public function onWriteItemsPre(Event $event) */ public function onIncrementItemPre(Event $event) { - $event->stopPropagation(true); - - $cache = $event->getTarget(); + $storage = $event->getTarget(); $params = $event->getParams(); - $token = null; - $oldValue = $cache->getItem( - $params['key'], - array('token' => &$token) + $params['options'] - ); - return $cache->checkAndSetItem( - $token, - $oldValue + $params['value'], - $params['key'], - $params['options'] - ); + $casToken = null; + $success = null; + $oldValue = $storage->getItem($params['key'], $success, $casToken); + $newValue = $oldValue + $params['value']; + + if ($success) { + $storage->checkAndSetItem($casToken, $params['key'], $oldValue + $params['value']); + $result = $newValue; + } else { + $result = false; + } + + $event->stopPropagation(true); + return $result; } /** @@ -262,19 +219,25 @@ public function onIncrementItemPre(Event $event) */ public function onIncrementItemsPre(Event $event) { - $event->stopPropagation(true); - - $cache = $event->getTarget(); - $params = $event->getParams(); - $keyValuePairs = $cache->getItems(array_keys($params['keyValuePairs']), $params['options']); - foreach ($params['keyValuePairs'] as $key => &$value) { + $storage = $event->getTarget(); + $params = $event->getParams(); + $keyValuePairs = $storage->getItems(array_keys($params['keyValuePairs'])); + foreach ($params['keyValuePairs'] as $key => & $value) { if (isset($keyValuePairs[$key])) { $keyValuePairs[$key]+= $value; } else { $keyValuePairs[$key] = $value; } } - return $cache->setItems($keyValuePairs, $params['options']); + + $failedKeys = $storage->setItems($keyValuePairs); + $result = array(); + foreach ($failedKeys as $failedKey) { + unset($keyValuePairs[$failedKey]); + } + + $event->stopPropagation(true); + return $keyValuePairs; } /** @@ -285,21 +248,22 @@ public function onIncrementItemsPre(Event $event) */ public function onDecrementItemPre(Event $event) { - $event->stopPropagation(true); - - $cache = $event->getTarget(); + $storage = $event->getTarget(); $params = $event->getParams(); - $token = null; - $oldValue = $cache->getItem( - $params['key'], - array('token' => &$token) + $params['options'] - ); - return $cache->checkAndSetItem( - $token, - $oldValue - $params['value'], - $params['key'], - $params['options'] - ); + $success = null; + $casToken = null; + $oldValue = $storage->getItem($params['key'], $success, $casToken); + $newValue = $oldValue - $params['value']; + + if ($success) { + $storage->checkAndSetItem($casToken, $params['key'], $oldValue + $params['value']); + $result = $newValue; + } else { + $result = false; + } + + $event->stopPropagation(true); + return $result; } /** @@ -310,11 +274,9 @@ public function onDecrementItemPre(Event $event) */ public function onDecrementItemsPre(Event $event) { - $event->stopPropagation(true); - - $cache = $event->getTarget(); + $storage = $event->getTarget(); $params = $event->getParams(); - $keyValuePairs = $cache->getItems(array_keys($params['keyValuePairs']), $params['options']); + $keyValuePairs = $storage->getItems(array_keys($params['keyValuePairs'])); foreach ($params['keyValuePairs'] as $key => &$value) { if (isset($keyValuePairs[$key])) { $keyValuePairs[$key]-= $value; @@ -322,7 +284,14 @@ public function onDecrementItemsPre(Event $event) $keyValuePairs[$key] = -$value; } } - return $cache->setItems($keyValuePairs, $params['options']); + + $failedKeys = $storage->setItems($keyValuePairs); + foreach ($failedKeys as $failedKey) { + unset($keyValuePairs[$failedKey]); + } + + $event->stopPropagation(true); + return $keyValuePairs; } /** diff --git a/src/Storage/PluginBroker.php b/src/Storage/PluginBroker.php index 65cce6657..58f6caf69 100644 --- a/src/Storage/PluginBroker.php +++ b/src/Storage/PluginBroker.php @@ -22,6 +22,7 @@ namespace Zend\Cache\Storage; use Zend\Cache\Exception, + Zend\Cache\Storage\Plugin\PluginInterface, Zend\Loader\PluginBroker as BasePluginBroker; /** @@ -51,9 +52,9 @@ class PluginBroker extends BasePluginBroker */ protected function validatePlugin($plugin) { - if (!$plugin instanceof Plugin) { + if (!$plugin instanceof PluginInterface) { throw new Exception\RuntimeException( - 'Cache storage plugins must implement Zend\Cache\Storage\Plugin' + 'Cache storage plugins must implement Zend\Cache\Storage\Plugin\PluginInterface' ); } return true; diff --git a/src/Storage/PluginLoader.php b/src/Storage/PluginLoader.php index 5f79c9210..5161da174 100644 --- a/src/Storage/PluginLoader.php +++ b/src/Storage/PluginLoader.php @@ -40,27 +40,14 @@ class PluginLoader extends PluginClassLoader * @var array */ protected $plugins = array( - 'clear_by_factor' => 'Zend\Cache\Storage\Plugin\ClearByFactor', - 'clearbyfactor' => 'Zend\Cache\Storage\Plugin\ClearByFactor', + 'clear_expired_by_factor' => 'Zend\Cache\Storage\Plugin\ClearExpiredByFactor', + 'clearexpiredbyfactor' => 'Zend\Cache\Storage\Plugin\ClearExpiredByFactor', 'exception_handler' => 'Zend\Cache\Storage\Plugin\ExceptionHandler', 'exceptionhandler' => 'Zend\Cache\Storage\Plugin\ExceptionHandler', - //'filter' => 'Zend\Cache\Storage\Plugin\Filter', 'ignore_user_abort' => 'Zend\Cache\Storage\Plugin\IgnoreUserAbort', 'ignoreuserabort' => 'Zend\Cache\Storage\Plugin\IgnoreUserAbort', - //'key_filter' => 'Zend\Cache\Storage\Plugin\KeyFilter', - //'keyfilter' => 'Zend\Cache\Storage\Plugin\KeyFilter', - //'levels' => 'Zend\Cache\Storage\Plugin\Levels', - //'locking' => 'Zend\Cache\Storage\Plugin\Locking', - //'master_file' => 'Zend\Cache\Storage\Plugin\MasterFile', - //'masterfile' => 'Zend\Cache\Storage\Plugin\MasterFile', 'optimize_by_factor' => 'Zend\Cache\Storage\Plugin\OptimizeByFactor', 'optimizebyfactor' => 'Zend\Cache\Storage\Plugin\OptimizeByFactor', - //'reluctant' => 'Zend\Cache\Storage\Plugin\Reluctant', 'serializer' => 'Zend\Cache\Storage\Plugin\Serializer', - //'store_times' => 'Zend\Cache\Storage\Plugin\StoreTimes', - //'storetimes' => 'Zend\Cache\Storage\Plugin\StoreTimes', - //'tagging' => 'Zend\Cache\Storage\Plugin\Tagging', - //'write_control' => 'Zend\Cache\Storage\Plugin\WriteControl', - //'writecontrol' => 'Zend\Cache\Storage\Plugin\WriteControl', ); } diff --git a/src/Storage/PostEvent.php b/src/Storage/PostEvent.php index 497c20bbb..7fe4f28bf 100644 --- a/src/Storage/PostEvent.php +++ b/src/Storage/PostEvent.php @@ -44,13 +44,13 @@ class PostEvent extends Event * * Accept a target and its parameters. * - * @param string $name - * @param Adapter $storage - * @param ArrayObject $params - * @param mixed $result + * @param string $name + * @param StorageInterface $storage + * @param ArrayObject $params + * @param mixed $result * @return void */ - public function __construct($name, Adapter\AdapterInterface $storage, ArrayObject $params, & $result) + public function __construct($name, StorageInterface $storage, ArrayObject $params, & $result) { parent::__construct($name, $storage, $params); $this->setResult($result); diff --git a/src/Storage/StorageInterface.php b/src/Storage/StorageInterface.php new file mode 100644 index 000000000..7936fd0d0 --- /dev/null +++ b/src/Storage/StorageInterface.php @@ -0,0 +1,263 @@ +load($adapterName); } - if ($options !== null) { + if ($options) { $adapter->setOptions($options); } @@ -198,7 +198,7 @@ public static function resetAdapterBroker() /** * Instantiate a storage plugin * - * @param string|Storage\Plugin $pluginName + * @param string|Storage\Plugin $pluginName * @param array|Traversable|Storage\Plugin\PluginOptions $options * @return Storage\Plugin * @throws Exception\RuntimeException @@ -216,7 +216,9 @@ public static function pluginFactory($pluginName, $options = array()) $options = new Storage\Plugin\PluginOptions($options); } - $plugin->setOptions($options); + if ($options) { + $plugin->setOptions($options); + } return $plugin; } diff --git a/src/Utils.php b/src/Utils.php index 7f7eb5d1b..db91b6fb1 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -28,33 +28,6 @@ */ abstract class Utils { - /** - * Get disk capacity - * - * @param string $path A directory of the filesystem or disk partition - * @return array - * @throws Exception\RuntimeException - */ - public static function getDiskCapacity($path) - { - $total = @disk_total_space($path); - if ($total === false) { - $err = error_get_last(); - throw new Exception\RuntimeException($err['message']); - } - - $free = @disk_free_space($path); - if ($free === false) { - $err = error_get_last(); - throw new Exception\RuntimeException($err['message']); - } - - return array( - 'total' => $total, - 'free' => $free, - ); - } - /** * Get php memory capacity * @@ -199,7 +172,7 @@ static protected function getSystemMemoryCapacityOSX() $cmd = 'sysctl -n hw.memsize'; $out = $ret = null; $line = exec($cmd, $out, $ret); - + if ($ret) { $out = implode("\n", $out); throw new Exception\RuntimeException( @@ -214,7 +187,7 @@ static protected function getSystemMemoryCapacityOSX() $cmd = 'vm_stat | grep free'; $out = $ret = null; $line = exec($cmd, $out, $ret); - + if ($ret) { $out = implode("\n", $out); throw new Exception\RuntimeException( diff --git a/test/Pattern/CallbackCacheTest.php b/test/Pattern/CallbackCacheTest.php index b00ddd7bd..9bddc3947 100644 --- a/test/Pattern/CallbackCacheTest.php +++ b/test/Pattern/CallbackCacheTest.php @@ -66,7 +66,7 @@ class CallbackCacheTest extends CommonPatternTest { /** - * @var Zend\Cache\Storage\Adapter\AdapterInterface + * @var Zend\Cache\Storage\StorageInterface */ protected $_storage; @@ -113,26 +113,6 @@ public function testMagicFunctionCall() ); } - public function testCallWithPredefinedCallbackAndArgumentKey() - { - $callback = __NAMESPACE__ . '\TestCallbackCache::emptyMethod'; - $args = array('arg1', 2, 3.33, null); - $options = array( - 'callback_key' => 'callback', - 'argument_key' => 'arguments', - ); - - $expectedKey = md5($options['callback_key'].$options['argument_key']); - $usedKey = null; - $this->_options->getStorage()->events()->attach('setItem.pre', function ($event) use (&$usedKey) { - $params = $event->getParams(); - $usedKey = $params['key']; - }); - - $this->_pattern->call($callback, $args, $options); - $this->assertEquals($expectedKey, $usedKey); - } - public function testGenerateKey() { $callback = __NAMESPACE__ . '\TestCallbackCache::emptyMethod'; @@ -149,23 +129,6 @@ public function testGenerateKey() $this->assertEquals($generatedKey, $usedKey); } - public function testGenerateKeyWithPredefinedCallbackAndArgumentKey() - { - $callback = __NAMESPACE__ . '\TestCallbackCache::emptyMethod'; - $args = array('arg1', 2, 3.33, null); - $options = array( - 'callback_key' => 'callback', - 'argument_key' => 'arguments', - ); - - $expectedKey = md5($options['callback_key'].$options['argument_key']); - - $this->assertEquals( - $expectedKey, - $this->_pattern->generateKey($callback, $args, $options) - ); - } - public function testCallInvalidCallbackException() { $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException'); @@ -212,5 +175,4 @@ protected function _testCall($callback, array $args) $this->assertEquals('', $data); } } - } diff --git a/test/Pattern/CaptureCacheTest.php b/test/Pattern/CaptureCacheTest.php index 43743cb52..4c61aff39 100644 --- a/test/Pattern/CaptureCacheTest.php +++ b/test/Pattern/CaptureCacheTest.php @@ -49,5 +49,4 @@ public function tearDown() // TODO parent::tearDown(); } - } diff --git a/test/Pattern/ClassCacheTest.php b/test/Pattern/ClassCacheTest.php index b0bca4141..09fd02ad8 100644 --- a/test/Pattern/ClassCacheTest.php +++ b/test/Pattern/ClassCacheTest.php @@ -57,7 +57,7 @@ class ClassCacheTest extends CommonPatternTest { /** - * @var Zend\Cache\Storage\Adapter\AdapterInterface + * @var Zend\Cache\Storage\StorageInterface */ protected $_storage; @@ -111,12 +111,6 @@ public function testGenerateKey() $this->assertEquals($generatedKey, $usedKey); } - public function testCallUnknownMethodException() - { - $this->setExpectedException('Zend\\Cache\\Exception\\InvalidArgumentException'); - $this->_pattern->call('notExiststingMethod'); - } - protected function _testCall($method, array $args) { $returnSpec = 'foobar_return(' . implode(', ', $args) . ') : '; @@ -146,5 +140,4 @@ protected function _testCall($method, array $args) $this->assertEquals('', $data); } } - } diff --git a/test/Pattern/ObjectCacheTest.php b/test/Pattern/ObjectCacheTest.php index df39f8e86..99b2aa9ab 100644 --- a/test/Pattern/ObjectCacheTest.php +++ b/test/Pattern/ObjectCacheTest.php @@ -64,7 +64,7 @@ class ObjectCacheTest extends CommonPatternTest { /** - * @var Zend\Cache\Storage\Adapter\AdapterInterface + * @var Zend\Cache\Storage\StorageInterface */ protected $_storage; @@ -125,84 +125,6 @@ public function testGenerateKey() $this->assertEquals($generatedKey, $usedKey); } - public function testGenerateKeyWithPredefinedCallbackAndArgumentKey() - { - $args = array('arg1', 2, 3.33, null); - $options = array( - 'callback_key' => 'callback', - 'argument_key' => 'arguments', - ); - - $expectedKey = md5($options['callback_key'].$options['argument_key']); - - $this->assertEquals( - $expectedKey, - $this->_pattern->generateKey('emptyMethod', $args, $options) - ); - } - - public function testGenerateKeyWithPredefinedEntityKey() - { - $args = array('arg1', 2, 3.33, null); - $options = array( - 'entity_key' => 'object', - 'argument_key' => 'arguments', - ); - $callbackKey = $options['entity_key'].'::emptymethod'; - - $expectedKey = md5($callbackKey.$options['argument_key']); - - $this->assertEquals( - $expectedKey, - $this->_pattern->generateKey('emptyMethod', $args, $options) - ); - } - - public function testGenerateKeyWithClassObjectKey() - { - $args = array('arg1', 2, 3.33, null); - $key = $this->_pattern->generateKey('emptyMethod', $args, array('callback_key' => 'test-object-cache::emptymethod')); - - $class = __NAMESPACE__ . '\TestObjectCache'; - $options = new Cache\Pattern\PatternOptions(array( - 'object' => new $class(), - 'storage' => $this->_storage, - 'objectKey' => 'test-object-cache', - )); - $this->_pattern->setOptions($options); - - $keyWithClassObjectKey = $this->_pattern->generateKey('emptyMethod', $args); - $this->assertEquals($key, $keyWithClassObjectKey); - } - - public function testCallWithClassObjectKey() - { - $class = __NAMESPACE__ . '\TestObjectCache'; - $options = new Cache\Pattern\PatternOptions(array( - 'object' => new $class(), - 'storage' => $this->_storage, - 'objectKey' => 'test-object-cache', - )); - $this->_pattern->setOptions($options); - - $args = array('arg1', 2, 3.33, null); - - $usedCallbackKey = null; - $this->_options->getStorage()->events()->attach('setItem.pre', function ($event) use (&$usedCallbackKey) { - $params = $event->getParams(); - $usedCallbackKey = $params['options']['callback_key']; - }); - - $this->_pattern->call('emptyMethod', $args); - $this->assertEquals('test-object-cache::emptymethod', $usedCallbackKey); - } - - public function testCallUnknownMethodException() - { - $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException'); - $this->_pattern->call('notExiststingMethod'); - } - public function testSetProperty() { $this->_pattern->property = 'testSetProperty'; @@ -258,5 +180,4 @@ protected function _testCall($method, array $args) $this->assertEquals('', $data); } } - } diff --git a/test/Pattern/OutputCacheTest.php b/test/Pattern/OutputCacheTest.php index f08e449d2..3b28fe1b1 100644 --- a/test/Pattern/OutputCacheTest.php +++ b/test/Pattern/OutputCacheTest.php @@ -35,7 +35,7 @@ class OutputCacheTest extends CommonPatternTest { /** - * @var Zend\Cache\Storage\Adapter\AdapterInterface + * @var Zend\Cache\Storage\StorageInterface */ protected $_storage; @@ -112,5 +112,4 @@ public function testThrowMissingKeyException() $this->setExpectedException('Zend\Cache\Exception\MissingKeyException'); $this->_pattern->start(''); // empty key } - } diff --git a/test/PatternFactoryTest.php b/test/PatternFactoryTest.php index 8f3f7b7c0..041fa7a56 100644 --- a/test/PatternFactoryTest.php +++ b/test/PatternFactoryTest.php @@ -67,5 +67,4 @@ public function testFactory() $this->assertNotSame($pattern1, $pattern2); } - } diff --git a/test/Storage/Adapter/AbstractAdapterTest.php b/test/Storage/Adapter/AbstractAdapterTest.php index 9d14cc996..501b05aae 100644 --- a/test/Storage/Adapter/AbstractAdapterTest.php +++ b/test/Storage/Adapter/AbstractAdapterTest.php @@ -57,7 +57,6 @@ public function testGetOptions() $this->assertInternalType('boolean', $options->getReadable()); $this->assertInternalType('integer', $options->getTtl()); $this->assertInternalType('string', $options->getNamespace()); - $this->assertInternalType('string', $options->getNamespacePattern()); $this->assertInternalType('string', $options->getKeyPattern()); } @@ -103,38 +102,12 @@ public function testSetNamespace() $this->assertSame('new_namespace', $this->_options->getNamespace()); } - public function testSetNamespacePattern() - { - $pattern = '/^.*$/'; - $this->_options->setNamespacePattern($pattern); - $this->assertEquals($pattern, $this->_options->getNamespacePattern()); - } - - public function testUnsetNamespacePattern() - { - $this->_options->setNamespacePattern(null); - $this->assertSame('', $this->_options->getNamespacePattern()); - } - public function testSetNamespace0() { $this->_options->setNamespace('0'); $this->assertSame('0', $this->_options->getNamespace()); } - public function testSetNamespacePatternThrowsExceptionOnInvalidPattern() - { - $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException'); - $this->_options->setNamespacePattern('#'); - } - - public function testSetNamespacePatternThrowsExceptionOnInvalidNamespace() - { - $this->_options->setNamespace('ns'); - $this->setExpectedException('Zend\Cache\Exception\RuntimeException'); - $this->_options->setNamespacePattern('/[abc]/'); - } - public function testSetKeyPattern() { $this->_options->setKeyPattern('/^[key]+$/Di'); @@ -161,13 +134,13 @@ public function testPluginRegistry() // no plugin registered $this->assertFalse($this->_storage->hasPlugin($plugin)); - $this->assertEquals(0, count($this->_storage->getPlugins())); + $this->assertEquals(0, count($this->_storage->getPluginRegistry())); $this->assertEquals(0, count($plugin->getHandles())); // register a plugin $this->assertSame($this->_storage, $this->_storage->addPlugin($plugin)); $this->assertTrue($this->_storage->hasPlugin($plugin)); - $this->assertEquals(1, count($this->_storage->getPlugins())); + $this->assertEquals(1, count($this->_storage->getPluginRegistry())); // test registered callback handles $handles = $plugin->getHandles(); @@ -177,7 +150,7 @@ public function testPluginRegistry() // test unregister a plugin $this->assertSame($this->_storage, $this->_storage->removePlugin($plugin)); $this->assertFalse($this->_storage->hasPlugin($plugin)); - $this->assertEquals(0, count($this->_storage->getPlugins())); + $this->assertEquals(0, count($this->_storage->getPluginRegistry())); $this->assertEquals(0, count($plugin->getHandles())); } @@ -268,17 +241,16 @@ public function testGetItemCallsInternalGetItem() { $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItem')); - $options = array('ttl' => 123); - $key = 'key1'; - $result = 'value1'; + $key = 'key1'; + $result = 'value1'; $this->_storage ->expects($this->once()) ->method('internalGetItem') - ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->with($this->equalTo($key)) ->will($this->returnValue($result)); - $rs = $this->_storage->getItem($key, $options); + $rs = $this->_storage->getItem($key); $this->assertEquals($result, $rs); } @@ -286,17 +258,16 @@ public function testGetItemsCallsInternalGetItems() { $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItems')); - $options = array('ttl' => 123); - $keys = array('key1', 'key2'); - $result = array('key2' => 'value2'); + $keys = array('key1', 'key2'); + $result = array('key2' => 'value2'); $this->_storage ->expects($this->once()) ->method('internalGetItems') - ->with($this->equalTo($keys), $this->equalTo($this->normalizeOptions($options))) + ->with($this->equalTo($keys)) ->will($this->returnValue($result)); - $rs = $this->_storage->getItems($keys, $options); + $rs = $this->_storage->getItems($keys); $this->assertEquals($result, $rs); } @@ -309,9 +280,8 @@ public function testInternalGetItemsCallsInternalGetItemForEachKey() $this->_storage = $this->getMockForAbstractAdapter(array('internalGetItem')); - $options = array('ttl' => 123); - $items = array('key1' => 'value1', 'notFound' => false, 'key2' => 'value2'); - $result = array('key1' => 'value1', 'key2' => 'value2'); + $items = array('key1' => 'value1', 'notFound' => false, 'key2' => 'value2'); + $result = array('key1' => 'value1', 'key2' => 'value2'); $i = 0; // method call counter foreach ($items as $k => $v) { @@ -319,11 +289,10 @@ public function testInternalGetItemsCallsInternalGetItemForEachKey() ->method('internalGetItem') ->with( $this->equalTo($k), - $this->equalTo($this->normalizeOptions($options)), $this->equalTo(null), $this->equalTo(null) ) - ->will($this->returnCallback(function ($k, $options, & $success, & $casToken) use ($items) { + ->will($this->returnCallback(function ($k, & $success, & $casToken) use ($items) { if ($items[$k]) { $success = true; return $items[$k]; @@ -342,17 +311,16 @@ public function testHasItemCallsInternalHasItem() { $this->_storage = $this->getMockForAbstractAdapter(array('internalHasItem')); - $options = array('ttl' => 123); - $key = 'key1'; - $result = true; + $key = 'key1'; + $result = true; $this->_storage ->expects($this->once()) ->method('internalHasItem') - ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->with($this->equalTo($key)) ->will($this->returnValue($result)); - $rs = $this->_storage->hasItem($key, $options); + $rs = $this->_storage->hasItem($key); $this->assertSame($result, $rs); } @@ -360,17 +328,16 @@ public function testHasItemsCallsInternalHasItems() { $this->_storage = $this->getMockForAbstractAdapter(array('internalHasItems')); - $options = array('ttl' => 123); - $keys = array('key1', 'key2'); - $result = array('key2'); + $keys = array('key1', 'key2'); + $result = array('key2'); $this->_storage ->expects($this->once()) ->method('internalHasItems') - ->with($this->equalTo($keys), $this->equalTo($this->normalizeOptions($options))) + ->with($this->equalTo($keys)) ->will($this->returnValue($result)); - $rs = $this->_storage->hasItems($keys, $options); + $rs = $this->_storage->hasItems($keys); $this->assertEquals($result, $rs); } @@ -378,20 +345,19 @@ public function testInternalHasItemsCallsInternalHasItem() { $this->_storage = $this->getMockForAbstractAdapter(array('internalHasItem')); - $options = array('ttl' => 123); - $items = array('key1' => true, 'key2' => false); - $result = array('key1'); + $items = array('key1' => true, 'key2' => false); + $result = array('key1'); $i = 0; // method call counter foreach ($items as $k => $v) { $this->_storage ->expects($this->at($i++)) ->method('internalHasItem') - ->with($this->equalTo($k), $this->equalTo($this->normalizeOptions($options))) + ->with($this->equalTo($k)) ->will($this->returnValue($v)); } - $rs = $this->_storage->hasItems(array_keys($items), $options); + $rs = $this->_storage->hasItems(array_keys($items)); $this->assertEquals($result, $rs); } @@ -399,17 +365,16 @@ public function testGetMetadataCallsInternalGetMetadata() { $this->_storage = $this->getMockForAbstractAdapter(array('internalGetMetadata')); - $options = array('ttl' => 123); - $key = 'key1'; - $result = array(); + $key = 'key1'; + $result = array(); $this->_storage ->expects($this->once()) ->method('internalGetMetadata') - ->with($this->equalTo($key), $this->equalTo($this->normalizeOptions($options))) + ->with($this->equalTo($key)) ->will($this->returnValue($result)); - $rs = $this->_storage->getMetadata($key, $options); + $rs = $this->_storage->getMetadata($key); $this->assertSame($result, $rs); } @@ -599,7 +564,6 @@ public function testRemoveItemsFail() $this->assertFalse($this->_storage->removeItems($items, $options)); } */ - // TODO: getDelayed + fatch[All] // TODO: incrementItem[s] + decrementItem[s] // TODO: touchItem[s] @@ -609,45 +573,39 @@ public function testPreEventsCanChangeArguments() $this->checkPreEventCanChangeArguments('getItem', array( 'key' => 'key' ), array( - 'key' => 'changedKey', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', )); $this->checkPreEventCanChangeArguments('getItems', array( 'keys' => array('key') ), array( - 'keys' => array('changedKey'), - 'options' => array('ttl' => 456) + 'keys' => array('changedKey'), )); // hasItem(s) $this->checkPreEventCanChangeArguments('hasItem', array( 'key' => 'key' ), array( - 'key' => 'changedKey', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', )); $this->checkPreEventCanChangeArguments('hasItems', array( 'keys' => array('key'), ), array( - 'keys' => array('changedKey'), - 'options' => array('ttl' => 456) + 'keys' => array('changedKey'), )); // getMetadata(s) $this->checkPreEventCanChangeArguments('getMetadata', array( 'key' => 'key' ), array( - 'key' => 'changedKey', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', )); $this->checkPreEventCanChangeArguments('getMetadatas', array( 'keys' => array('key'), ), array( - 'keys' => array('changedKey'), - 'options' => array('ttl' => 456) + 'keys' => array('changedKey'), )); // setItem(s) @@ -655,16 +613,14 @@ public function testPreEventsCanChangeArguments() 'key' => 'key', 'value' => 'value', ), array( - 'key' => 'changedKey', - 'value' => 'changedValue', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', + 'value' => 'changedValue', )); $this->checkPreEventCanChangeArguments('setItems', array( 'keyValuePairs' => array('key' => 'value'), ), array( 'keyValuePairs' => array('changedKey' => 'changedValue'), - 'options' => array('ttl' => 456) )); // addItem(s) @@ -672,16 +628,14 @@ public function testPreEventsCanChangeArguments() 'key' => 'key', 'value' => 'value', ), array( - 'key' => 'changedKey', - 'value' => 'changedValue', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', + 'value' => 'changedValue', )); $this->checkPreEventCanChangeArguments('addItems', array( 'keyValuePairs' => array('key' => 'value'), ), array( 'keyValuePairs' => array('changedKey' => 'changedValue'), - 'options' => array('ttl' => 456) )); // replaceItem(s) @@ -689,16 +643,14 @@ public function testPreEventsCanChangeArguments() 'key' => 'key', 'value' => 'value', ), array( - 'key' => 'changedKey', - 'value' => 'changedValue', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', + 'value' => 'changedValue', )); $this->checkPreEventCanChangeArguments('replaceItems', array( 'keyValuePairs' => array('key' => 'value'), ), array( 'keyValuePairs' => array('changedKey' => 'changedValue'), - 'options' => array('ttl' => 456) )); // CAS @@ -707,40 +659,35 @@ public function testPreEventsCanChangeArguments() 'key' => 'key', 'value' => 'value', ), array( - 'token' => 'changedToken', - 'key' => 'changedKey', - 'value' => 'changedValue', - 'options' => array('ttl' => 456) + 'token' => 'changedToken', + 'key' => 'changedKey', + 'value' => 'changedValue', )); // touchItem(s) $this->checkPreEventCanChangeArguments('touchItem', array( 'key' => 'key', ), array( - 'key' => 'changedKey', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', )); $this->checkPreEventCanChangeArguments('touchItems', array( 'keys' => array('key'), ), array( - 'keys' => array('changedKey'), - 'options' => array('ttl' => 456) + 'keys' => array('changedKey'), )); // removeItem(s) $this->checkPreEventCanChangeArguments('removeItem', array( 'key' => 'key', ), array( - 'key' => 'changedKey', - 'options' => array('ttl' => 456) + 'key' => 'changedKey', )); $this->checkPreEventCanChangeArguments('removeItems', array( 'keys' => array('key'), ), array( - 'keys' => array('changedKey'), - 'options' => array('ttl' => 456) + 'keys' => array('changedKey'), )); // incrementItem(s) @@ -748,16 +695,14 @@ public function testPreEventsCanChangeArguments() 'key' => 'key', 'value' => 1 ), array( - 'key' => 'changedKey', - 'value' => 2, - 'options' => array('ttl' => 456) + 'key' => 'changedKey', + 'value' => 2, )); $this->checkPreEventCanChangeArguments('incrementItems', array( 'keyValuePairs' => array('key' => 1), ), array( 'keyValuePairs' => array('changedKey' => 2), - 'options' => array('ttl' => 456) )); // decrementItem(s) @@ -765,57 +710,14 @@ public function testPreEventsCanChangeArguments() 'key' => 'key', 'value' => 1 ), array( - 'key' => 'changedKey', - 'value' => 2, - 'options' => array('ttl' => 456) + 'key' => 'changedKey', + 'value' => 2, )); $this->checkPreEventCanChangeArguments('decrementItems', array( 'keyValuePairs' => array('key' => 1), ), array( 'keyValuePairs' => array('changedKey' => 2), - 'options' => array('ttl' => 456) - )); - - // getDelayed - $this->checkPreEventCanChangeArguments('getDelayed', array( - 'keys' => array('key'), - ), array( - 'keys' => array('changedKey'), - 'options' => array('ttl' => 456) - )); - - // find - $this->checkPreEventCanChangeArguments('find', array( - 'mode' => Cache\Storage\Adapter\AdapterInterface::MATCH_ACTIVE, - ), array( - 'mode' => Cache\Storage\Adapter\AdapterInterface::MATCH_ALL, - 'options' => array('ttl' => 456) - )); - - // clear[ByNamespace] - $this->checkPreEventCanChangeArguments('clear', array( - 'mode' => Cache\Storage\Adapter\AdapterInterface::MATCH_ACTIVE, - ), array( - 'mode' => Cache\Storage\Adapter\AdapterInterface::MATCH_ALL, - 'options' => array('ttl' => 456) - )); - - $this->checkPreEventCanChangeArguments('clearByNamespace', array( - 'mode' => Cache\Storage\Adapter\AdapterInterface::MATCH_ACTIVE, - ), array( - 'mode' => Cache\Storage\Adapter\AdapterInterface::MATCH_ALL, - 'options' => array('ttl' => 456) - )); - - // optimize - $this->checkPreEventCanChangeArguments('optimize', array(), array( - 'options' => array('ttl' => 456) - )); - - // getCapacity - $this->checkPreEventCanChangeArguments('getCapacity', array(), array( - 'options' => array('ttl' => 456) )); } @@ -871,30 +773,4 @@ protected function getMockForAbstractAdapter(array $methods = array()) $adapter->setOptions($this->_options); return $adapter; } - - protected function normalizeOptions($options) - { - // ttl - if (!isset($options['ttl'])) { - $options['ttl'] = $this->_options->getTtl(); - } - - // namespace - if (!isset($options['namespace'])) { - $options['namespace'] = $this->_options->getNamespace(); - } - - // tags - if (!isset($options['tags'])) { - $options['tags'] = null; - } - - // select - if (!isset($options['select'])) { - $options['select'] = array('key', 'value'); - } - - return $options; - } - } diff --git a/test/Storage/Adapter/AbstractZendServerTest.php b/test/Storage/Adapter/AbstractZendServerTest.php index dc552d9b5..9a8f07997 100644 --- a/test/Storage/Adapter/AbstractZendServerTest.php +++ b/test/Storage/Adapter/AbstractZendServerTest.php @@ -21,7 +21,7 @@ namespace ZendTest\Cache\Storage\Adapter; -use Zend\Cache\Storage\Adapter\AdapterInterface as Adapter, +use Zend\Cache\Storage\StorageInterface, Zend\Cache\Storage\Adapter\AdapterOptions, Zend\Cache\Storage\Adapter\AbstractZendServer; @@ -54,91 +54,54 @@ public function testGetOptions() $this->assertInternalType('boolean', $options->getReadable()); $this->assertInternalType('integer', $options->getTtl()); $this->assertInternalType('string', $options->getNamespace()); - $this->assertInternalType('string', $options->getNamespacePattern()); $this->assertInternalType('string', $options->getKeyPattern()); } - public function testGetWithDefaultNamespace() + public function testGetItem() { - $this->_options->setNamespace('defaultns'); + $this->_options->setNamespace('ns'); $this->_storage->expects($this->once()) ->method('zdcFetch') - ->with($this->equalTo('defaultns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) + ->with($this->equalTo('ns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) ->will($this->returnValue('value')); $this->assertEquals('value', $this->_storage->getItem('key')); } - public function testGetWithArgNamespace() + public function testGetMetadata() { - $this->_options->setNamespace('defaultns'); + $this->_options->setNamespace('ns'); $this->_storage->expects($this->once()) ->method('zdcFetch') - ->with($this->equalTo('argns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) - ->will($this->returnValue('value')); - - $this->assertEquals('value', $this->_storage->getItem('key', array('namespace' => 'argns'))); - } - - public function testInfoWithDefaultNamespace() - { - $this->_options->setNamespace('defaultns'); - - $this->_storage->expects($this->once()) - ->method('zdcFetch') - ->with($this->equalTo('defaultns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) + ->with($this->equalTo('ns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) ->will($this->returnValue('value')); $this->assertEquals(array(), $this->_storage->getMetadata('key')); } - public function testInfoWithArgNamespace() + public function testHasItem() { - $this->_options->setNamespace('defaultns'); + $this->_options->setNamespace('ns'); $this->_storage->expects($this->once()) ->method('zdcFetch') - ->with($this->equalTo('argns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) - ->will($this->returnValue('value')); - - $this->assertEquals(array(), $this->_storage->getMetadata('key', array('namespace' => 'argns'))); - } - - public function testExistsWithDefaultNamespace() - { - $this->_options->setNamespace('defaultns'); - - $this->_storage->expects($this->once()) - ->method('zdcFetch') - ->with($this->equalTo('defaultns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) + ->with($this->equalTo('ns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) ->will($this->returnValue('value')); $this->assertEquals(true, $this->_storage->hasItem('key')); } - public function testExistsWithArgNamespace() - { - $this->_options->setNamespace('defaultns'); - - $this->_storage->expects($this->once()) - ->method('zdcFetch') - ->with($this->equalTo('argns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) - ->will($this->returnValue('value')); - - $this->assertEquals(true, $this->_storage->hasItem('key', array('namespace' => 'argns'))); - } - - public function testSetWithDefaultNamespaceAndTtl() + public function testSetItem() { $this->_options->setTtl(10); - $this->_options->setNamespace('defaultns'); + $this->_options->setNamespace('ns'); $this->_storage->expects($this->once()) ->method('zdcStore') ->with( - $this->equalTo('defaultns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key'), + $this->equalTo('ns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key'), $this->equalTo('value'), $this->equalTo(10) ) @@ -147,86 +110,15 @@ public function testSetWithDefaultNamespaceAndTtl() $this->assertEquals(true, $this->_storage->setItem('key', 'value')); } - public function testSetWithArgNamespaceAndTtl() + public function testRemoveItem() { - $this->_options->setTtl(10); - $this->_options->setNamespace('defaultns'); - - $this->_storage->expects($this->once()) - ->method('zdcStore') - ->with( - $this->equalTo('argns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key'), - $this->equalTo('value'), - $this->equalTo(100) - ) - ->will($this->returnValue(true)); - - $this->assertEquals(true, $this->_storage->setItem('key', 'value', array('namespace' => 'argns', 'ttl' => 100))); - } - - public function testRemoveWithDefaultNamespace() - { - $this->_options->setNamespace('defaultns'); + $this->_options->setNamespace('ns'); $this->_storage->expects($this->once()) ->method('zdcDelete') - ->with($this->equalTo('defaultns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) + ->with($this->equalTo('ns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) ->will($this->returnValue(true)); $this->assertEquals(true, $this->_storage->removeItem('key')); } - - public function testRemoveWithArgNamespace() - { - $this->_options->setNamespace('defaultns'); - - $this->_storage->expects($this->once()) - ->method('zdcDelete') - ->with($this->equalTo('argns' . AbstractZendServer::NAMESPACE_SEPARATOR . 'key')) - ->will($this->returnValue(true)); - - $this->assertEquals(true, $this->_storage->removeItem('key', array('namespace' => 'argns'))); - } - - public function testClearExpired() - { - $this->_storage->expects($this->never()) - ->method('zdcClear'); - - $this->assertEquals(true, $this->_storage->clear(Adapter::MATCH_EXPIRED)); - } - - public function testClearActive() - { - $this->_storage->expects($this->once()) - ->method('zdcClear') - ->will($this->returnValue(true)); - - $rs = $this->_storage->clear(Adapter::MATCH_ACTIVE); - $this->assertEquals(true, $rs); - } - - public function testClearActiveByDefaultNamespace() - { - $this->_storage->expects($this->once()) - ->method('zdcClearByNamespace') - ->with($this->equalTo($this->_options->getNamespace())) - ->will($this->returnValue(true)); - - $rs = $this->_storage->clearByNamespace(Adapter::MATCH_ACTIVE); - $this->assertEquals(true, $rs); - } - - public function testClearActiveByArgNamespace() - { - $ns = 'namespace'; - $this->_storage->expects($this->once()) - ->method('zdcClearByNamespace') - ->with($this->equalTo($ns)) - ->will($this->returnValue(true)); - - $rs = $this->_storage->clearByNamespace(Adapter::MATCH_ACTIVE, array('namespace' => $ns)); - $this->assertEquals(true, $rs); - } - } diff --git a/test/Storage/Adapter/ApcTest.php b/test/Storage/Adapter/ApcTest.php index b55e30eed..a2ded30df 100644 --- a/test/Storage/Adapter/ApcTest.php +++ b/test/Storage/Adapter/ApcTest.php @@ -91,5 +91,4 @@ public function tearDown() parent::tearDown(); } - } diff --git a/test/Storage/Adapter/CommonAdapterTest.php b/test/Storage/Adapter/CommonAdapterTest.php index a35ec175a..18eb58e55 100644 --- a/test/Storage/Adapter/CommonAdapterTest.php +++ b/test/Storage/Adapter/CommonAdapterTest.php @@ -21,7 +21,15 @@ namespace ZendTest\Cache\Storage\Adapter; -use Zend\Cache\Storage\Adapter\AdapterInterface, +use Zend\Cache\Storage\IterableInterface, + Zend\Cache\Storage\IteratorInterface, + Zend\Cache\Storage\StorageInterface, + Zend\Cache\Storage\ClearExpiredInterface, + Zend\Cache\Storage\ClearByNamespaceInterface, + Zend\Cache\Storage\ClearByPrefixInterface, + Zend\Cache\Storage\FlushableInterface, + Zend\Cache\Storage\OptimizableInterface, + Zend\Cache\Storage\TagableInterface, Zend\Cache, Zend\Stdlib\ErrorHandler; @@ -43,7 +51,7 @@ abstract class CommonAdapterTest extends \PHPUnit_Framework_TestCase /** * The storage adapter * - * @var AdapterInterface + * @var StorageInterface */ protected $_storage; @@ -60,7 +68,7 @@ abstract class CommonAdapterTest extends \PHPUnit_Framework_TestCase public function setUp() { $this->assertInstanceOf( - 'Zend\Cache\Storage\Adapter\AdapterInterface', + 'Zend\Cache\Storage\StorageInterface', $this->_storage, 'Storage adapter instance is needed for tests' ); @@ -276,12 +284,12 @@ public function testGetItemSetsSuccessFlag() $success = null; // $success = false on get missing item - $this->_storage->getItem('unknown', array(), $success); + $this->_storage->getItem('unknown', $success); $this->assertFalse($success); // $success = true on get valid item $this->_storage->setItem('test', 'test'); - $this->_storage->getItem('test', array(), $success); + $this->_storage->getItem('test', $success); $this->assertTrue($success); } @@ -522,88 +530,6 @@ public function testSetGetHasAndRemoveItemsWithNamespace() } } - public function testSetGetHasAndRemoveItemWithSpecificNamespace() - { - $this->_options->setNamespace('defaultns'); - - // write "key" without a namespace - $this->assertTrue( $this->_storage->setItem('key', 'nons')); - - // write "key" with a default namespace - $this->assertTrue( $this->_storage->setItem('key', 'ns1', array('namespace' => 'ns1'))); - - // write "key" with an other default namespace - $this->assertTrue( $this->_storage->setItem('key', 'ns2', array('namespace' => 'ns2'))); - - // test value of ns2 - $this->assertEquals('ns2', $this->_storage->getItem('key', array('namespace' => 'ns2'))); - - // test value of ns1 - $this->assertEquals('ns1', $this->_storage->getItem('key', array('namespace' => 'ns1'))); - - // test value without namespace - $this->assertEquals('nons', $this->_storage->getItem('key')); - - // remove item without namespace - $this->assertTrue($this->_storage->removeItem('key')); - $this->assertFalse($this->_storage->hasItem('key')); - - // remove item of ns1 - $this->assertTrue($this->_storage->removeItem('key', array('namespace' => 'ns1'))); - $this->assertFalse($this->_storage->hasItem('key', array('namespace' => 'ns1'))); - - // remove item of ns2 - $this->assertTrue($this->_storage->removeItem('key', array('namespace' => 'ns2'))); - $this->assertFalse($this->_storage->hasItem('key', array('namespace' => 'ns2'))); - } - - public function testSetGetHasAndRemoveItemsWithSpecificNamespace() - { - $this->_options->setNamespace('defaultns'); - - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3', - ); - - $this->assertSame(array(), $this->_storage->setItems($items, array('namespace' => 'specificns'))); - $this->assertEquals(array(), $this->_storage->hasItems(array_keys($items))); - - $rs = $this->_storage->getItems(array_keys($items), array('namespace' => 'specificns')); - $this->assertInternalType('array', $rs); - foreach ($items as $key => $value) { - $this->assertArrayHasKey($key, $rs); - $this->assertEquals($value, $rs[$key]); - } - - - $rs = $this->_storage->hasItems(array_keys($items), array('namespace' => 'specificns')); - $this->assertInternalType('array', $rs); - $this->assertEquals(count($items), count($rs)); - foreach ($items as $key => $value) { - $this->assertContains($key, $rs); - } - - // remove the first and the last item - $this->assertSame(array('missing'), $this->_storage->removeItems(array('missing', 'key1', 'key3'), array('namespace' => 'specificns'))); - unset($items['key1'], $items['key3']); - - $rs = $this->_storage->getItems(array_keys($items), array('namespace' => 'specificns')); - $this->assertInternalType('array', $rs); - foreach ($items as $key => $value) { - $this->assertArrayHasKey($key, $rs); - $this->assertEquals($value, $rs[$key]); - } - - $rs = $this->_storage->hasItems(array_keys($items), array('namespace' => 'specificns')); - $this->assertInternalType('array', $rs); - $this->assertEquals(count($items), count($rs)); - foreach ($items as $key => $value) { - $this->assertContains($key, $rs); - } - } - public function testSetAndGetExpiredItem() { $capabilities = $this->_storage->getCapabilities(); @@ -623,10 +549,11 @@ public function testSetAndGetExpiredItem() $this->assertEquals('value', $this->_storage->getItem('key')); } + $this->_options->setTtl(0); if ($capabilities->getExpiredRead()) { - $this->assertEquals('value', $this->_storage->getItem('key', array('ttl' => 0))); + $this->assertEquals('value', $this->_storage->getItem('key')); } else { - $this->assertNull($this->_storage->getItem('key', array('ttl' => 0))); + $this->assertNull($this->_storage->getItem('key')); } } @@ -656,8 +583,9 @@ public function testSetAndGetExpiredItems() $this->assertEquals($items, $rs); } + $this->_options->setTtl(0); if ($capabilities->getExpiredRead()) { - $rs = $this->_storage->getItems(array_keys($items), array('ttl' => 0)); + $rs = $this->_storage->getItems(array_keys($items)); ksort($rs); $this->assertEquals($items, $rs); } @@ -792,7 +720,7 @@ public function testCheckAndSetItem() $success = null; $casToken = null; - $this->assertEquals('value', $this->_storage->getItem('key', array(), $success, $casToken)); + $this->assertEquals('value', $this->_storage->getItem('key', $success, $casToken)); $this->assertNotNull($casToken); $this->assertTrue($this->_storage->checkAndSetItem($casToken, 'key', 'newValue')); @@ -800,166 +728,6 @@ public function testCheckAndSetItem() $this->assertEquals('newValue', $this->_storage->getItem('key')); } - public function testGetDelayedAndFetch() - { - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3' - ); - - $this->assertSame(array(), $this->_storage->setItems($items)); - $this->assertTrue($this->_storage->getDelayed(array_keys($items))); - - $fetchedKeys = array(); - while ( $item = $this->_storage->fetch() ) { - $this->assertArrayHasKey('key', $item); - $this->assertArrayHasKey('value', $item); - - $this->assertArrayHasKey($item['key'], $items); - $this->assertEquals($items[$item['key']], $item['value']); - $fetchedKeys[] = $item['key']; - } - sort($fetchedKeys); - $this->assertEquals(array_keys($items), $fetchedKeys); - } - - public function testGetDelayedAndFetchAll() - { - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3' - ); - - $this->assertSame(array(), $this->_storage->setItems($items)); - $this->assertTrue($this->_storage->getDelayed(array_keys($items))); - - $fetchedItems = $this->_storage->fetchAll(); - $this->assertEquals(count($items), count($fetchedItems)); - foreach ($fetchedItems as $item) { - $this->assertArrayHasKey('key', $item); - $this->assertArrayHasKey('value', $item); - $this->assertEquals($items[$item['key']], $item['value']); - } - } - - public function testGetDelayedAndFetchAllWithSelectValue() - { - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3' - ); - - $this->assertSame(array(), $this->_storage->setItems($items)); - $this->assertTrue($this->_storage->getDelayed(array_keys($items), array( - 'select' => 'value' - ))); - - $fetchedItems = $this->_storage->fetchAll(); - $this->assertEquals(count($items), count($fetchedItems)); - foreach ($fetchedItems as $item) { - $this->assertArrayNotHasKey('key', $item); - $this->assertArrayHasKey('value', $item); - $this->assertContains($item['value'], $items); - } - } - - public function testGetDelayedAndFetchAllWithSelectInfo() - { - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3' - ); - - $this->assertSame(array(), $this->_storage->setItems($items)); - - $capabilities = $this->_storage->getCapabilities(); - $this->assertTrue($this->_storage->getDelayed(array_keys($items), array( - 'select' => $capabilities->getSupportedMetadata() - ))); - - $fetchedItems = $this->_storage->fetchAll(); - - $this->assertEquals(count($items), count($fetchedItems)); - foreach ($fetchedItems as $item) { - if (is_array($capabilities->getSupportedMetadata())) { - foreach ($capabilities->getSupportedMetadata() as $selectProperty) { - $this->assertArrayHasKey($selectProperty, $item); - } - } - } - } - - public function testGetDelayedWithCallback() - { - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3' - ); - - $this->assertSame(array(), $this->_storage->setItems($items)); - - $fetchedItems = array(); - $this->assertTrue($this->_storage->getDelayed(array_keys($items), array( - 'callback' => function($item) use (&$fetchedItems) { - $fetchedItems[] = $item; - }, - ))); - - // wait for callback - sleep(1); - - $this->assertEquals(count($items), count($fetchedItems)); - foreach ($fetchedItems as $item) { - $this->assertArrayHasKey('key', $item); - $this->assertArrayHasKey('value', $item); - $this->assertEquals($items[$item['key']], $item['value']); - } - } - - public function testGetDelayedWithCallbackAndSelectInfo() - { - $items = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3' - ); - - $this->assertSame(array(), $this->_storage->setItems($items)); - - $fetchedItems = array(); - $capabilities = $this->_storage->getCapabilities(); - $this->assertTrue($this->_storage->getDelayed(array_keys($items), array( - 'callback' => function($item) use (&$fetchedItems) { - $fetchedItems[] = $item; - }, - 'select' => $capabilities->getSupportedMetadata() - ))); - - // wait for callback - sleep(1); - - $this->assertEquals(count($items), count($fetchedItems)); - foreach ($fetchedItems as $item) { - foreach ($capabilities->getSupportedMetadata() as $selectProperty) { - $this->assertArrayHasKey($selectProperty, $item); - } - } - } - - public function testGetDelayedThrowExceptionOnActiveStatement() - { - $this->assertTrue($this->_storage->setItem('key', 'value')); - $this->assertTrue($this->_storage->getDelayed(array('key'))); - - $this->setExpectedException('Zend\Cache\Exception\ExceptionInterface'); - $this->_storage->getDelayed(array('key')); - } - public function testIncrementItem() { $this->assertTrue($this->_storage->setItem('counter', 10)); @@ -1076,278 +844,187 @@ public function testTouchItemsReturnsGivenKeysIfNonWritable() $this->assertSame(array('key'), $this->_storage->touchItems(array('key'))); } - public function testClearExpiredByNamespace() - { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getClearByNamespace()) { - $this->setExpectedException('Zend\Cache\Exception\RuntimeException'); - $this->_storage->clearByNamespace(AdapterInterface::MATCH_EXPIRED); - return; - } - - $ttl = $capabilities->getTtlPrecision(); - $this->_options->setTtl($ttl); - - $this->assertTrue($this->_storage->setItem('key1', 'value1')); - - // wait until the first item expired - $wait = $ttl + $capabilities->getTtlPrecision(); - usleep($wait * 2000000); - - $this->assertTrue($this->_storage->setItem('key2', 'value2')); - - $this->assertTrue($this->_storage->clearByNamespace(AdapterInterface::MATCH_EXPIRED)); - - if ($capabilities->getUseRequestTime()) { - $this->assertTrue($this->_storage->hasItem('key1')); - } else { - $this->assertFalse($this->_storage->hasItem('key1', array('ttl' => 0))); - } - - $this->assertTrue($this->_storage->hasItem('key2')); - } - - public function testClearActiveByNamespace() + public function testOptimize() { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getClearByNamespace()) { - $this->setExpectedException('Zend\Cache\Exception\RuntimeException'); - $this->_storage->clearByNamespace(AdapterInterface::MATCH_ACTIVE); - return; + if ( !($this->_storage instanceof OptimizableInterface) ) { + $this->markTestSkipped("Storage doesn't implement OptimizableInterface"); } - $ttl = $capabilities->getTtlPrecision(); - $this->_options->setTtl($ttl); - - $this->assertTrue($this->_storage->setItem('key1', 'value1')); - - // wait until the first item expired - $wait = $ttl + $capabilities->getTtlPrecision(); - usleep($wait * 2000000); - - $this->assertTrue($this->_storage->setItem('key2', 'value2')); - - $this->assertTrue($this->_storage->clearByNamespace(AdapterInterface::MATCH_ACTIVE)); - - if ($capabilities->getExpiredRead() && !$capabilities->getUseRequestTime()) { - $this->assertTrue($this->_storage->hasItem('key1', array('ttl' => 0))); - } - $this->assertFalse($this->_storage->hasItem('key2', array('ttl' => 0))); + $this->assertTrue($this->_storage->optimize()); } - public function testClearAllByNamespace() + public function testIterator() { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getClearByNamespace()) { - $this->setExpectedException('Zend\Cache\Exception\RuntimeException'); - $this->_storage->clearByNamespace(AdapterInterface::MATCH_ALL); - return; + if (!$this->_storage instanceof IterableInterface) { + $this->markTestSkipped("Storage doesn't implement IterableInterface"); } $items = array( 'key1' => 'value1', 'key2' => 'value2', - 'key3' => 'value3' ); - $namespaces = array('ns1', 'ns2'); - - foreach ($namespaces as $ns) { - $this->_options->setNamespace($ns); - foreach ($items as $k => $v) { - $this->assertTrue($this->_storage->setItem($ns.$k, $ns.$v)); - } - } - - $clearNs = array_shift($namespaces); - $this->_options->setNamespace($clearNs); - $this->assertTrue($this->_storage->clearByNamespace(AdapterInterface::MATCH_ALL)); + $this->assertSame(array(), $this->_storage->setItems($items)); - // wait - usleep($capabilities->getTtlPrecision() * 2000000); + // check iterator aggregate + $iterator = $this->_storage->getIterator(); + $this->assertInstanceOf('Zend\Cache\Storage\IteratorInterface', $iterator); + $this->assertSame(IteratorInterface::CURRENT_AS_KEY, $iterator->getMode()); + + // check mode CURRENT_AS_KEY + $iterator = $this->_storage->getIterator(); + $iterator->setMode(IteratorInterface::CURRENT_AS_KEY); + $keys = iterator_to_array($iterator, false); + sort($keys); + $this->assertSame(array_keys($items), $keys); + + // check mode CURRENT_AS_VALUE + $iterator = $this->_storage->getIterator(); + $iterator->setMode(IteratorInterface::CURRENT_AS_VALUE); + $result = iterator_to_array($iterator, true); + ksort($result); + $this->assertSame($items, $result); + } - foreach ($items as $k => $v) { - $this->assertFalse($this->_storage->hasItem($clearNs.$k)); + public function testFlush() + { + if ( !($this->_storage instanceof FlushableInterface) ) { + $this->markTestSkipped("Storage doesn't implement OptimizableInterface"); } - foreach ($namespaces as $ns) { - $this->_options->setNamespace($ns); - foreach ($items as $k => $v) { - $this->assertTrue($this->_storage->hasItem($ns.$k)); - } - } + $this->assertSame(array(), $this->_storage->setItems(array( + 'key1' => 'value1', + 'key2' => 'value2', + ))); + + $this->assertTrue($this->_storage->flush()); + $this->assertFalse($this->_storage->hasItem('key1')); + $this->assertFalse($this->_storage->hasItem('key2')); } - public function testClearAll() + public function testClearByPrefix() { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getClearAllNamespaces()) { - $this->setExpectedException('Zend\Cache\Exception\ExceptionInterface'); - $this->_storage->clear(AdapterInterface::MATCH_ALL); - return; + if ( !($this->_storage instanceof ClearByPrefixInterface) ) { + $this->markTestSkipped("Storage doesn't implement ClearByPrefixInterface"); } - $items = array( + $this->assertSame(array(), $this->_storage->setItems(array( 'key1' => 'value1', 'key2' => 'value2', - 'key3' => 'value3' - ); - $namespaces = array('ns1', 'ns2'); - - foreach ($namespaces as $ns) { - $this->_options->setNamespace($ns); - foreach ($items as $k => $v) { - $this->assertTrue($this->_storage->setItem($ns.$k, $ns.$v)); - } - } - - $this->assertTrue($this->_storage->clear(AdapterInterface::MATCH_ALL)); - - // wait - usleep($capabilities->getTtlPrecision() * 2000000); + 'test' => 'value', + ))); - foreach ($namespaces as $ns) { - $this->_options->setNamespace($ns); - foreach ($items as $k => $v) { - $this->assertFalse($this->_storage->hasItem($ns.$k)); - } - } + $this->assertTrue($this->_storage->clearByPrefix('key')); + $this->assertFalse($this->_storage->hasItem('key1')); + $this->assertFalse($this->_storage->hasItem('key2')); + $this->assertTrue($this->_storage->hasItem('test')); } - public function testFindActive() + public function testClearByNamespace() { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getIterable()) { - $this->markTestSkipped("Find isn't supported by this adapter"); + if ( !($this->_storage instanceof ClearByNamespaceInterface) ) { + $this->markTestSkipped("Storage doesn't implement ClearByNamespaceInterface"); } - $this->_options->setTtl($capabilities->getTtlPrecision()); - + // write 2 items of 2 different namespaces + $this->_options->setNamespace('ns1'); $this->assertTrue($this->_storage->setItem('key1', 'value1')); + $this->_options->setNamespace('ns2'); $this->assertTrue($this->_storage->setItem('key2', 'value2')); - // wait until first 2 items expired - usleep(($capabilities->getTtlPrecision() * 1000000) + 1000000); - - $this->assertTrue($this->_storage->setItem('key3', 'value3')); - $this->assertTrue($this->_storage->setItem('key4', 'value4')); - - $this->assertTrue($this->_storage->find(AdapterInterface::MATCH_ACTIVE)); - - if ($capabilities->getUseRequestTime()) { - $expectedItems = array( - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3', - 'key4' => 'value4' - ); - } else { - $expectedItems = array( - 'key3' => 'value3', - 'key4' => 'value4' - ); - } - - $actualItems = array(); - while (($item = $this->_storage->fetch()) !== false) { - // check $item - $this->assertArrayHasKey('key', $item); - $this->assertArrayHasKey('value', $item); + // clear unknown namespace should return true but clear nothing + $this->assertTrue($this->_storage->clearByNamespace('unknown')); + $this->_options->setNamespace('ns1'); + $this->assertTrue($this->_storage->hasItem('key1')); + $this->_options->setNamespace('ns2'); + $this->assertTrue($this->_storage->hasItem('key2')); - $actualItems[ $item['key'] ] = $item['value']; - } + // clear "ns1" + $this->assertTrue($this->_storage->clearByNamespace('ns1')); + $this->_options->setNamespace('ns1'); + $this->assertFalse($this->_storage->hasItem('key1')); + $this->_options->setNamespace('ns2'); + $this->assertTrue($this->_storage->hasItem('key2')); - ksort($actualItems); - $this->assertEquals($expectedItems, $actualItems); + // clear "ns2" + $this->assertTrue($this->_storage->clearByNamespace('ns2')); + $this->_options->setNamespace('ns1'); + $this->assertFalse($this->_storage->hasItem('key1')); + $this->_options->setNamespace('ns2'); + $this->assertFalse($this->_storage->hasItem('key2')); } - public function testFindExpired() + public function testClearExpired() { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getIterable()) { - $this->markTestSkipped("Find isn't supported by this adapter"); + if ( !($this->_storage instanceof ClearExpiredInterface) ) { + $this->markTestSkipped("Storage doesn't implement ClearExpiredInterface"); } - $this->_options->setTtl($capabilities->getTtlPrecision()); + $capabilities = $this->_storage->getCapabilities(); + $ttl = $capabilities->getTtlPrecision(); + $this->_options->setTtl($ttl); $this->assertTrue($this->_storage->setItem('key1', 'value1')); - $this->assertTrue($this->_storage->setItem('key2', 'value2')); - // wait until first 2 items expired - usleep($capabilities->getTtlPrecision() * 2000000); + // wait until the first item expired + $wait = $ttl + $capabilities->getTtlPrecision(); + usleep($wait * 2000000); - $this->assertTrue($this->_storage->setItem('key3', 'value3')); - $this->assertTrue($this->_storage->setItem('key4', 'value4')); + $this->assertTrue($this->_storage->setItem('key2', 'value2')); - $this->assertTrue($this->_storage->find(AdapterInterface::MATCH_EXPIRED)); + $this->assertTrue($this->_storage->clearExpired()); - if ($capabilities->getExpiredRead() && !$capabilities->getUseRequestTime()) { - $expectedItems = array( - 'key1' => 'value1', - 'key2' => 'value2' - ); + if ($capabilities->getUseRequestTime()) { + $this->assertTrue($this->_storage->hasItem('key1')); } else { - $expectedItems = array(); - } - - $actualItems = array(); - while (($item = $this->_storage->fetch()) !== false) { - // check $item - $this->assertArrayHasKey('key', $item); - $this->assertArrayHasKey('value', $item); - $this->assertEquals(2, count($item)); - - $actualItems[ $item['key'] ] = $item['value']; + $this->assertFalse($this->_storage->hasItem('key1', array('ttl' => 0))); } - ksort($actualItems); - $this->assertEquals($expectedItems, $actualItems); + $this->assertTrue($this->_storage->hasItem('key2')); } - /* - public function testGetCapacity() + public function testTagable() { - $capacity = $this->_storage->getCapacity(); + if ( !($this->_storage instanceof TagableInterface) ) { + $this->markTestSkipped("Storage doesn't implement TagableInterface"); + } - $this->assertArrayHasKey('total', $capacity); - $this->assertInternalType('numeric', $capacity['total']); + $capabilities = $this->_storage->getCapabilities(); + $ttl = $capabilities->getTtlPrecision(); + $this->_options->setTtl($ttl); - $this->assertArrayHasKey('free', $capacity); - $this->assertInternalType('numeric', $capacity['free']); + $this->assertSame(array(), $this->_storage->setItems(array( + 'key1' => 'value1', + 'key2' => 'value2', + 'key3' => 'value3', + ))); - $this->assertGreaterThanOrEqual( - $capacity['free'], $capacity['total'], - "The total storage space must be greater or equal than the free space" - ); - } + $this->assertTrue($this->_storage->setTags('key1', array('tag1a', 'tag1b'))); + $this->assertTrue($this->_storage->setTags('key2', array('tag2a', 'tag2b'))); + $this->assertTrue($this->_storage->setTags('key3', array('tag3a', 'tag3b'))); + $this->assertFalse($this->_storage->setTags('missing', array('tag'))); - public function testOptimizeSimpleCall() - { - $rs = $this->_storage->optimize(); - $this->assertTrue($rs); - } + // return tags + $tags = $this->_storage->getTags('key1'); + $this->assertInternalType('array', $tags); + sort($tags); + $this->assertSame(array('tag1a', 'tag1b'), $tags); - public function testTagsAreUsedWhenCaching() - { - $capabilities = $this->_storage->getCapabilities(); - if (!$capabilities->getTagging()) { - $this->markTestSkipped("Tags are not supported by this adapter"); - } + // this should remove nothing + $this->assertTrue($this->_storage->clearByTags(array('tag1a', 'tag2a'))); + $this->assertTrue($this->_storage->hasItem('key1')); + $this->assertTrue($this->_storage->hasItem('key2')); + $this->assertTrue($this->_storage->hasItem('key3')); - // Ensure we don't have expired items in the cache for this test - $this->_options->setTtl(60); - $this->_storage->setItem('someitem', 'somevalue', array('tags' => array('foo'))); - $this->assertTrue($this->_storage->find(AdapterInterface::MATCH_TAGS_OR, array('tags' => array('foo')))); - $actualItems = array(); - while (($item = $this->_storage->fetch()) !== false) { - // check $item - $this->assertArrayHasKey('key', $item); - $this->assertArrayHasKey('value', $item); - - $actualItems[ $item['key'] ] = $item['value']; - } - $this->assertEquals(1, count($actualItems)); - $this->assertArrayHasKey('someitem', $actualItems); - $this->assertEquals('somevalue', $actualItems['someitem']); + // this should remove key1 and key2 + $this->assertTrue($this->_storage->clearByTags(array('tag1a', 'tag2b'), true)); + $this->assertFalse($this->_storage->hasItem('key1')); + $this->assertFalse($this->_storage->hasItem('key2')); + $this->assertTrue($this->_storage->hasItem('key3')); + + // this should remove key3 + $this->assertTrue($this->_storage->clearByTags(array('tag3a', 'tag3b'), true)); + $this->assertFalse($this->_storage->hasItem('key1')); + $this->assertFalse($this->_storage->hasItem('key2')); + $this->assertFalse($this->_storage->hasItem('key3')); } - */ } diff --git a/test/Storage/Adapter/MemcachedTest.php b/test/Storage/Adapter/MemcachedTest.php index 63ade8961..87949e260 100644 --- a/test/Storage/Adapter/MemcachedTest.php +++ b/test/Storage/Adapter/MemcachedTest.php @@ -101,8 +101,8 @@ public function testNoOptionsSetsDefaultServer() public function tearDown() { - if (!empty($this->_storage)) { - $this->_storage->clear(); + if ($this->_storage) { + $this->_storage->flush(); } parent::tearDown(); diff --git a/test/Storage/Adapter/MemoryTest.php b/test/Storage/Adapter/MemoryTest.php index 9bea8fd26..81450cd84 100644 --- a/test/Storage/Adapter/MemoryTest.php +++ b/test/Storage/Adapter/MemoryTest.php @@ -43,12 +43,11 @@ public function setUp() parent::setUp(); } - public function testThrowOutOfCapacityException() + public function testThrowOutOfSpaceException() { $this->_options->setMemoryLimit(memory_get_usage(true) - 8); - $this->setExpectedException('Zend\Cache\Exception\OutOfCapacityException'); + $this->setExpectedException('Zend\Cache\Exception\OutOfSpaceException'); $this->_storage->addItem('test', 'test'); } - } diff --git a/test/Storage/Adapter/WinCacheTest.php b/test/Storage/Adapter/WinCacheTest.php index 712a39d0a..a3d5cbd53 100644 --- a/test/Storage/Adapter/WinCacheTest.php +++ b/test/Storage/Adapter/WinCacheTest.php @@ -70,5 +70,4 @@ public function tearDown() parent::tearDown(); } - } diff --git a/test/Storage/Adapter/ZendServerDiskTest.php b/test/Storage/Adapter/ZendServerDiskTest.php index 4de5b63e5..1e0dbb7b8 100644 --- a/test/Storage/Adapter/ZendServerDiskTest.php +++ b/test/Storage/Adapter/ZendServerDiskTest.php @@ -63,5 +63,4 @@ public function tearDown() parent::tearDown(); } - } diff --git a/test/Storage/Adapter/ZendServerShmTest.php b/test/Storage/Adapter/ZendServerShmTest.php index 54c091820..fbf90e654 100644 --- a/test/Storage/Adapter/ZendServerShmTest.php +++ b/test/Storage/Adapter/ZendServerShmTest.php @@ -68,5 +68,4 @@ public function tearDown() parent::tearDown(); } - } diff --git a/test/Storage/Plugin/ClearByFactorTest.php b/test/Storage/Plugin/ClearExpiredByFactorTest.php similarity index 57% rename from test/Storage/Plugin/ClearByFactorTest.php rename to test/Storage/Plugin/ClearExpiredByFactorTest.php index bf14fac56..d1b179f28 100644 --- a/test/Storage/Plugin/ClearByFactorTest.php +++ b/test/Storage/Plugin/ClearExpiredByFactorTest.php @@ -3,10 +3,10 @@ namespace ZendTest\Cache\Storage\Plugin; use Zend\Cache, Zend\Cache\Storage\PostEvent, - ZendTest\Cache\Storage\TestAsset\MockAdapter, + ZendTest\Cache\Storage\TestAsset\ClearExpiredMockAdapter, ArrayObject; -class ClearByFactorTest extends CommonPluginTest +class ClearExpiredByFactorTest extends CommonPluginTest { /** @@ -18,11 +18,11 @@ class ClearByFactorTest extends CommonPluginTest public function setUp() { - $this->_adapter = new MockAdapter(); + $this->_adapter = new ClearExpiredMockAdapter(); $this->_options = new Cache\Storage\Plugin\PluginOptions(array( 'clearing_factor' => 1, )); - $this->_plugin = new Cache\Storage\Plugin\ClearByFactor(); + $this->_plugin = new Cache\Storage\Plugin\ClearExpiredByFactor(); $this->_plugin->setOptions($this->_options); parent::setUp(); @@ -34,10 +34,10 @@ public function testAddPlugin() // check attached callbacks $expectedListeners = array( - 'setItem.post' => 'clearByFactor', - 'setItems.post' => 'clearByFactor', - 'addItem.post' => 'clearByFactor', - 'addItems.post' => 'clearByFactor', + 'setItem.post' => 'clearExpiredByFactor', + 'setItems.post' => 'clearExpiredByFactor', + 'addItem.post' => 'clearExpiredByFactor', + 'addItems.post' => 'clearExpiredByFactor', ); foreach ($expectedListeners as $eventName => $expectedCallbackMethod) { $listeners = $this->_adapter->events()->getListeners($eventName); @@ -63,50 +63,24 @@ public function testRemovePlugin() $this->assertEquals(0, count($this->_adapter->events()->getEvents())); } - public function testClearByFactorUsingNamespace() + public function testClearExpiredByFactor() { - $adapter = $this->getMock(get_class($this->_adapter), array('clearByNamespace')); + $adapter = $this->getMock(get_class($this->_adapter), array('clearExpired')); $this->_options->setClearingFactor(1); - $this->_options->setClearByNamespace(true); - // test optimize will be called + // test clearByNamespace will be called $adapter ->expects($this->once()) - ->method('clearByNamespace') + ->method('clearExpired') ->will($this->returnValue(true)); // call event callback $result = true; $event = new PostEvent('setItem.post', $adapter, new ArrayObject(array( - 'options' => array(), + 'options' => array(), )), $result); - - $this->_plugin->clearByFactor($event); - - $this->assertTrue($event->getResult()); - } - - public function testClearByFactorAllNamespaces() - { - $adapter = $this->getMock(get_class($this->_adapter), array('clear')); - $this->_options->setClearingFactor(1); - $this->_options->setClearByNamespace(false); - - // test optimize will be called - $adapter - ->expects($this->once()) - ->method('clear') - ->will($this->returnValue(true)); - - // call event callback - $result = true; - $event = new PostEvent('setItem.post', $adapter, new ArrayObject(array( - 'options' => array(), - )), $result); - - $this->_plugin->clearByFactor($event); + $this->_plugin->clearExpiredByFactor($event); $this->assertTrue($event->getResult()); } - } diff --git a/test/Storage/Plugin/ExceptionHandlerTest.php b/test/Storage/Plugin/ExceptionHandlerTest.php index efac4fcff..49321c3eb 100644 --- a/test/Storage/Plugin/ExceptionHandlerTest.php +++ b/test/Storage/Plugin/ExceptionHandlerTest.php @@ -41,12 +41,6 @@ public function testAddPlugin() 'getMetadata.exception' => 'onException', 'getMetadatas.exception' => 'onException', - 'getDelayed.exception' => 'onException', - 'find.exception' => 'onException', - - 'fetch.exception' => 'onException', - 'fetchAll.exception' => 'onException', - 'setItem.exception' => 'onException', 'setItems.exception' => 'onException', @@ -69,12 +63,6 @@ public function testAddPlugin() 'decrementItem.exception' => 'onException', 'decrementItems.exception' => 'onException', - - 'clear.exception' => 'onException', - 'clearByNamespace.exception' => 'onException', - - 'optimize.exception' => 'onException', - 'getCapacity.exception' => 'onException', ); foreach ($expectedListeners as $eventName => $expectedCallbackMethod) { $listeners = $this->_adapter->events()->getListeners($eventName); @@ -138,5 +126,4 @@ public function testDontThrowException() $this->assertFalse($event->getThrowException()); $this->assertSame('test', $event->getResult()); } - } diff --git a/test/Storage/Plugin/IgnoreUserAbortTest.php b/test/Storage/Plugin/IgnoreUserAbortTest.php index 4b64ebf3d..3eccce91c 100644 --- a/test/Storage/Plugin/IgnoreUserAbortTest.php +++ b/test/Storage/Plugin/IgnoreUserAbortTest.php @@ -125,5 +125,4 @@ public function testRemovePlugin() // no events should be attached $this->assertEquals(0, count($this->_adapter->events()->getEvents())); } - } diff --git a/test/Storage/Plugin/OptimizeByFactorTest.php b/test/Storage/Plugin/OptimizeByFactorTest.php index b011051d9..9789f63ed 100644 --- a/test/Storage/Plugin/OptimizeByFactorTest.php +++ b/test/Storage/Plugin/OptimizeByFactorTest.php @@ -3,7 +3,7 @@ namespace ZendTest\Cache\Storage\Plugin; use Zend\Cache, Zend\Cache\Storage\PostEvent, - ZendTest\Cache\Storage\TestAsset\MockAdapter, + ZendTest\Cache\Storage\TestAsset\OptimizableMockAdapter, ArrayObject; class OptimizeByFactorTest extends CommonPluginTest @@ -18,7 +18,7 @@ class OptimizeByFactorTest extends CommonPluginTest public function setUp() { - $this->_adapter = new MockAdapter(); + $this->_adapter = new OptimizableMockAdapter(); $this->_options = new Cache\Storage\Plugin\PluginOptions(array( 'optimizing_factor' => 1, )); @@ -32,10 +32,8 @@ public function testAddPlugin() // check attached callbacks $expectedListeners = array( - 'removeItem.post' => 'optimizeByFactor', - 'removeItems.post' => 'optimizeByFactor', - 'clear.post' => 'optimizeByFactor', - 'clearByNamespace.post' => 'optimizeByFactor', + 'removeItem.post' => 'optimizeByFactor', + 'removeItems.post' => 'optimizeByFactor', ); foreach ($expectedListeners as $eventName => $expectedCallbackMethod) { $listeners = $this->_adapter->events()->getListeners($eventName); @@ -80,5 +78,4 @@ public function testOptimizeByFactor() $this->assertTrue($event->getResult()); } - } diff --git a/test/Storage/Plugin/SerializerTest.php b/test/Storage/Plugin/SerializerTest.php index fb5bcce5e..8ebf853c4 100644 --- a/test/Storage/Plugin/SerializerTest.php +++ b/test/Storage/Plugin/SerializerTest.php @@ -61,9 +61,6 @@ public function testAddPlugin() 'getItem.post' => 'onReadItemPost', 'getItems.post' => 'onReadItemsPost', - 'fetch.post' => 'onFetchPost', - 'fetchAll.post' => 'onFetchAllPost', - 'setItem.pre' => 'onWriteItemPre', 'setItems.pre' => 'onWriteItemsPre', 'addItem.pre' => 'onWriteItemPre', @@ -135,5 +132,4 @@ public function testUnserializeOnReadItems() $this->assertSame(123, $values['key1']); $this->assertSame(456, $values['key2']); } - } diff --git a/test/Storage/TestAsset/ClearExpiredMockAdapter.php b/test/Storage/TestAsset/ClearExpiredMockAdapter.php new file mode 100644 index 000000000..2e9d8bd71 --- /dev/null +++ b/test/Storage/TestAsset/ClearExpiredMockAdapter.php @@ -0,0 +1,12 @@ +calledEvents; } - } diff --git a/test/Storage/TestAsset/OptimizableMockAdapter.php b/test/Storage/TestAsset/OptimizableMockAdapter.php new file mode 100644 index 000000000..04e08862a --- /dev/null +++ b/test/Storage/TestAsset/OptimizableMockAdapter.php @@ -0,0 +1,12 @@ + $adapter, @@ -127,7 +127,7 @@ public function testFactoryWithPlugins() // test plugin structure $i = 0; - foreach ($cache->getPlugins() as $plugin) { + foreach ($cache->getPluginRegistry() as $plugin) { $this->assertInstanceOf('Zend\Cache\Storage\Plugin\\' . $plugins[$i++], $plugin); } } @@ -147,7 +147,7 @@ public function testFactoryWithPluginsAndOptionsArray() 'Serializer', // plugin as name-options pair - 'ClearByFactor' => array( + 'ClearExpiredByFactor' => array( 'clearing_factor' => 1, ), @@ -172,14 +172,14 @@ public function testFactoryWithPluginsAndOptionsArray() $this->assertEquals('test', $storage->getOptions()->getNamespace()); // test plugin structure - foreach ($storage->getPlugins() as $i => $plugin) { + foreach ($storage->getPluginRegistry() as $plugin) { // test plugin options $pluginClass = get_class($plugin); switch ($pluginClass) { - case 'Zend\Cache\Storage\Plugin\ClearByFactor': + case 'Zend\Cache\Storage\Plugin\ClearExpiredByFactor': $this->assertSame( - $factory['plugins']['ClearByFactor']['clearing_factor'], + $factory['plugins']['ClearExpiredByFactor']['clearing_factor'], $plugin->getOptions()->getClearingFactor() ); break; @@ -197,5 +197,4 @@ public function testFactoryWithPluginsAndOptionsArray() } } - } diff --git a/test/TestAsset/DummyPattern.php b/test/TestAsset/DummyPattern.php index d71e3dbdf..7fb86010b 100644 --- a/test/TestAsset/DummyPattern.php +++ b/test/TestAsset/DummyPattern.php @@ -18,5 +18,4 @@ public function getDummyOption() { return $this->_dummyOption; } - } diff --git a/test/TestAsset/DummyStoragePlugin.php b/test/TestAsset/DummyStoragePlugin.php index ec5d88532..f65f55347 100644 --- a/test/TestAsset/DummyStoragePlugin.php +++ b/test/TestAsset/DummyStoragePlugin.php @@ -13,5 +13,4 @@ public function __construct($options = array()) { $this->setOptions($options); } - } diff --git a/test/UtilsTest.php b/test/UtilsTest.php index 99c4673a1..99b49ca7c 100644 --- a/test/UtilsTest.php +++ b/test/UtilsTest.php @@ -30,11 +30,6 @@ class UtilsTest extends \PHPUnit_Framework_TestCase { - public function testGetDiskCapacity() - { - $this->_assertCapacity(Utils::getDiskCapacity(__DIR__)); - } - public function testGetPhpMemoryCapacity() { $this->_assertCapacity(Utils::getPhpMemoryCapacity()); @@ -69,5 +64,4 @@ public function testGenerateHashStrlenRaw() { $this->assertEquals(pack('l', strlen('test')), Utils::generateHash('strlen', 'test', true)); } - } From 25967c67adc42df171a10f88d2cdc63eb2d4b200 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 31 May 2012 09:33:59 +0200 Subject: [PATCH 56/62] format exception classes --- src/Exception/BadMethodCallException.php | 5 +++-- src/Exception/InvalidArgumentException.php | 5 +++-- src/Exception/LogicException.php | 4 +++- src/Exception/OutOfSpaceException.php | 4 +++- src/Exception/RuntimeException.php | 4 +++- src/Exception/UnexpectedValueException.php | 5 +++-- src/Exception/UnsupportedMethodCallException.php | 5 +++-- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Exception/BadMethodCallException.php b/src/Exception/BadMethodCallException.php index 4aa41fa93..f1c5ee9a7 100644 --- a/src/Exception/BadMethodCallException.php +++ b/src/Exception/BadMethodCallException.php @@ -26,7 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class BadMethodCallException extends \BadMethodCallException implements - ExceptionInterface +class BadMethodCallException + extends \BadMethodCallException + implements ExceptionInterface { } diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index c051e6995..80ffa308e 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -26,7 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class InvalidArgumentException extends \InvalidArgumentException implements - ExceptionInterface +class InvalidArgumentException + extends \InvalidArgumentException + implements ExceptionInterface { } diff --git a/src/Exception/LogicException.php b/src/Exception/LogicException.php index 6d4f4b5f3..ae122152e 100644 --- a/src/Exception/LogicException.php +++ b/src/Exception/LogicException.php @@ -26,6 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class LogicException extends \LogicException implements ExceptionInterface +class LogicException + extends \LogicException + implements ExceptionInterface { } diff --git a/src/Exception/OutOfSpaceException.php b/src/Exception/OutOfSpaceException.php index 290592c8d..847843b2d 100644 --- a/src/Exception/OutOfSpaceException.php +++ b/src/Exception/OutOfSpaceException.php @@ -26,6 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class OutOfSpaceException extends \OverflowException implements ExceptionInterface +class OutOfSpaceException + extends \OverflowException + implements ExceptionInterface { } diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index 432113373..e4d939ac1 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -26,6 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class RuntimeException extends \RuntimeException implements ExceptionInterface +class RuntimeException + extends \RuntimeException + implements ExceptionInterface { } diff --git a/src/Exception/UnexpectedValueException.php b/src/Exception/UnexpectedValueException.php index 455da7c99..98581aa65 100644 --- a/src/Exception/UnexpectedValueException.php +++ b/src/Exception/UnexpectedValueException.php @@ -26,7 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class UnexpectedValueException extends \UnexpectedValueException implements - ExceptionInterface +class UnexpectedValueException + extends \UnexpectedValueException + implements ExceptionInterface { } diff --git a/src/Exception/UnsupportedMethodCallException.php b/src/Exception/UnsupportedMethodCallException.php index 73a999b00..d9aa61080 100644 --- a/src/Exception/UnsupportedMethodCallException.php +++ b/src/Exception/UnsupportedMethodCallException.php @@ -26,7 +26,8 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class UnsupportedMethodCallException extends \BadMethodCallException implements - ExceptionInterface +class UnsupportedMethodCallException + extends \BadMethodCallException + implements ExceptionInterface { } From 96613be8f9828b1027e55cd64c599deaa5e4068e Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 31 May 2012 09:47:26 +0200 Subject: [PATCH 57/62] disabled memory_limit of memory cache storage for callback pattern tests --- test/Pattern/CallbackCacheTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/Pattern/CallbackCacheTest.php b/test/Pattern/CallbackCacheTest.php index 9bddc3947..d5082e05c 100644 --- a/test/Pattern/CallbackCacheTest.php +++ b/test/Pattern/CallbackCacheTest.php @@ -72,7 +72,9 @@ class CallbackCacheTest extends CommonPatternTest public function setUp() { - $this->_storage = new Cache\Storage\Adapter\Memory(); + $this->_storage = new Cache\Storage\Adapter\Memory(array( + 'memory_limit' => 0 + )); $this->_options = new Cache\Pattern\PatternOptions(array( 'storage' => $this->_storage, )); From f77af73d199fac37f88273059917da6b37448e20 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 31 May 2012 09:50:01 +0200 Subject: [PATCH 58/62] disabled memory_limit of memory cache storage for pattern tests --- test/Pattern/ClassCacheTest.php | 4 +++- test/Pattern/ObjectCacheTest.php | 4 +++- test/Pattern/OutputCacheTest.php | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test/Pattern/ClassCacheTest.php b/test/Pattern/ClassCacheTest.php index 09fd02ad8..c7dc08e06 100644 --- a/test/Pattern/ClassCacheTest.php +++ b/test/Pattern/ClassCacheTest.php @@ -63,7 +63,9 @@ class ClassCacheTest extends CommonPatternTest public function setUp() { - $this->_storage = new Cache\Storage\Adapter\Memory(); + $this->_storage = new Cache\Storage\Adapter\Memory(array( + 'memory_limit' => 0 + )); $this->_options = new Cache\Pattern\PatternOptions(array( 'class' => __NAMESPACE__ . '\TestClassCache', 'storage' => $this->_storage, diff --git a/test/Pattern/ObjectCacheTest.php b/test/Pattern/ObjectCacheTest.php index 99b2aa9ab..211e830c4 100644 --- a/test/Pattern/ObjectCacheTest.php +++ b/test/Pattern/ObjectCacheTest.php @@ -71,7 +71,9 @@ class ObjectCacheTest extends CommonPatternTest public function setUp() { $class = __NAMESPACE__ . '\TestObjectCache'; - $this->_storage = new Cache\Storage\Adapter\Memory(); + $this->_storage = new Cache\Storage\Adapter\Memory(array( + 'memory_limit' => 0 + )); $this->_options = new Cache\Pattern\PatternOptions(array( 'object' => new $class(), 'storage' => $this->_storage, diff --git a/test/Pattern/OutputCacheTest.php b/test/Pattern/OutputCacheTest.php index 3b28fe1b1..3407197f3 100644 --- a/test/Pattern/OutputCacheTest.php +++ b/test/Pattern/OutputCacheTest.php @@ -48,7 +48,9 @@ class OutputCacheTest extends CommonPatternTest public function setUp() { - $this->_storage = new Cache\Storage\Adapter\Memory(); + $this->_storage = new Cache\Storage\Adapter\Memory(array( + 'memory_limit' => 0 + )); $this->_options = new Cache\Pattern\PatternOptions(array( 'storage' => $this->_storage, )); From bf97fd20580cc0b2a26dc88c6e6876c0bef89d8a Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 31 May 2012 22:15:07 +0200 Subject: [PATCH 59/62] use of offsetExists instead of isset --- src/Storage/Adapter/AbstractAdapter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Storage/Adapter/AbstractAdapter.php b/src/Storage/Adapter/AbstractAdapter.php index 14dae6458..0df497b10 100644 --- a/src/Storage/Adapter/AbstractAdapter.php +++ b/src/Storage/Adapter/AbstractAdapter.php @@ -381,9 +381,9 @@ public function getItem($key, & $success = null, & $casToken = null) return $eventRs->last(); } - if (isset($args['success'], $args['casToken'])) { + if ($args->offsetExists('success') && $args->offsetExists('casToken')) { $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']); - } elseif (isset($args['success'])) { + } elseif ($args->offsetExists('success')) { $result = $this->internalGetItem($args['key'], $args['success']); } else { $result = $this->internalGetItem($args['key']); From ccb455e575faf1b77b167517d08836f672633bd9 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sat, 2 Jun 2012 13:21:07 +0200 Subject: [PATCH 60/62] PHP 5.3.3: Fatal error: Can't inherit abstract function IteratorAggregate::getIterator() (previously declared abstract in Zend\Cache\Storage\IterableInterface) --- src/Storage/IterableInterface.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Storage/IterableInterface.php b/src/Storage/IterableInterface.php index 344d8551d..8a35497d8 100644 --- a/src/Storage/IterableInterface.php +++ b/src/Storage/IterableInterface.php @@ -35,5 +35,7 @@ interface IterableInterface extends \IteratorAggregate * * @return IteratorInterface */ - public function getIterator(); + // PHP 5.3.3: Fatal error: Can't inherit abstract function IteratorAggregate::getIterator() + // (previously declared abstract in Zend\Cache\Storage\IterableInterface) + //public function getIterator(); } From 5417fc2a033dad8ef1b83f24141377f82e569e58 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 13 Jun 2012 04:18:07 +0200 Subject: [PATCH 61/62] phpdoc: Use class level method definition to re-define method return type --- src/Storage/IterableInterface.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Storage/IterableInterface.php b/src/Storage/IterableInterface.php index 8a35497d8..5197c4fcf 100644 --- a/src/Storage/IterableInterface.php +++ b/src/Storage/IterableInterface.php @@ -27,15 +27,9 @@ * @subpackage Storage * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License + * + * @method IteratorInterface getIterator() Get the storage iterator */ interface IterableInterface extends \IteratorAggregate { - /** - * Get the storage iterator - * - * @return IteratorInterface - */ - // PHP 5.3.3: Fatal error: Can't inherit abstract function IteratorAggregate::getIterator() - // (previously declared abstract in Zend\Cache\Storage\IterableInterface) - //public function getIterator(); } From 1d190a2fd2a33252039e634956b39a349186ae60 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 13 Jun 2012 11:49:58 -0500 Subject: [PATCH 62/62] [zendframework/zf2#1403] CS cleanup of exceptions - following PSR-1/2, put extends and implements keywords on same line; list interfaces implemented on separate lines following, only if line length exceeds recommended soft limits --- src/Exception/BadMethodCallException.php | 5 ++--- src/Exception/InvalidArgumentException.php | 5 ++--- src/Exception/LogicException.php | 4 +--- src/Exception/OutOfSpaceException.php | 4 +--- src/Exception/RuntimeException.php | 4 +--- src/Exception/UnexpectedValueException.php | 5 ++--- src/Exception/UnsupportedMethodCallException.php | 5 ++--- 7 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/Exception/BadMethodCallException.php b/src/Exception/BadMethodCallException.php index f1c5ee9a7..4aa41fa93 100644 --- a/src/Exception/BadMethodCallException.php +++ b/src/Exception/BadMethodCallException.php @@ -26,8 +26,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class BadMethodCallException - extends \BadMethodCallException - implements ExceptionInterface +class BadMethodCallException extends \BadMethodCallException implements + ExceptionInterface { } diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index 80ffa308e..c051e6995 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -26,8 +26,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class InvalidArgumentException - extends \InvalidArgumentException - implements ExceptionInterface +class InvalidArgumentException extends \InvalidArgumentException implements + ExceptionInterface { } diff --git a/src/Exception/LogicException.php b/src/Exception/LogicException.php index ae122152e..6d4f4b5f3 100644 --- a/src/Exception/LogicException.php +++ b/src/Exception/LogicException.php @@ -26,8 +26,6 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class LogicException - extends \LogicException - implements ExceptionInterface +class LogicException extends \LogicException implements ExceptionInterface { } diff --git a/src/Exception/OutOfSpaceException.php b/src/Exception/OutOfSpaceException.php index 847843b2d..290592c8d 100644 --- a/src/Exception/OutOfSpaceException.php +++ b/src/Exception/OutOfSpaceException.php @@ -26,8 +26,6 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class OutOfSpaceException - extends \OverflowException - implements ExceptionInterface +class OutOfSpaceException extends \OverflowException implements ExceptionInterface { } diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index e4d939ac1..432113373 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -26,8 +26,6 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class RuntimeException - extends \RuntimeException - implements ExceptionInterface +class RuntimeException extends \RuntimeException implements ExceptionInterface { } diff --git a/src/Exception/UnexpectedValueException.php b/src/Exception/UnexpectedValueException.php index 98581aa65..455da7c99 100644 --- a/src/Exception/UnexpectedValueException.php +++ b/src/Exception/UnexpectedValueException.php @@ -26,8 +26,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class UnexpectedValueException - extends \UnexpectedValueException - implements ExceptionInterface +class UnexpectedValueException extends \UnexpectedValueException implements + ExceptionInterface { } diff --git a/src/Exception/UnsupportedMethodCallException.php b/src/Exception/UnsupportedMethodCallException.php index d9aa61080..73a999b00 100644 --- a/src/Exception/UnsupportedMethodCallException.php +++ b/src/Exception/UnsupportedMethodCallException.php @@ -26,8 +26,7 @@ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class UnsupportedMethodCallException - extends \BadMethodCallException - implements ExceptionInterface +class UnsupportedMethodCallException extends \BadMethodCallException implements + ExceptionInterface { }