diff --git a/src/ArrayStack.php b/src/ArrayStack.php index bfa0433bd..d76cbc366 100644 --- a/src/ArrayStack.php +++ b/src/ArrayStack.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -31,7 +31,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 ArrayStack extends ArrayObject diff --git a/src/ArrayUtils.php b/src/ArrayUtils.php new file mode 100644 index 000000000..f3a9be7de --- /dev/null +++ b/src/ArrayUtils.php @@ -0,0 +1,260 @@ + 0; + } + + /** + * Test whether an array contains one or more integer keys + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasIntegerKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_int')) > 0; + } + + /** + * Test whether an array contains one or more numeric keys. + * + * A numeric key can be one of the following: + * - an integer 1, + * - a string with a number '20' + * - a string with negative number: '-1000' + * - a float: 2.2120, -78.150999 + * - a string with float: '4000.99999', '-10.10' + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasNumericKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_numeric')) > 0; + } + + /** + * Test whether an array is a list + * + * A list is a collection of values assigned to continuous integer keys + * starting at 0 and ending at count() - 1. + * + * For example: + * + * $list = array( 'a','b','c','d' ); + * $list = array( + * 0 => 'foo', + * 1 => 'bar', + * 2 => array( 'foo' => 'baz' ), + * ); + * + * + * @param mixed $value + * @param bool $allowEmpty Is an empty list a valid list? + * @return bool + */ + public static function isList($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return (array_values($value) === $value); + } + + /** + * Test whether an array is a hash table. + * + * An array is a hash table if: + * + * 1. Contains one or more non-integer keys, or + * 2. Integer keys are non-continuous or misaligned (not starting with 0) + * + * For example: + * + * $hash = array( + * 'foo' => 15, + * 'bar' => false, + * ); + * $hash = array( + * 1995 => 'Birth of PHP', + * 2009 => 'PHP 5.3.0', + * 2012 => 'PHP 5.4.0', + * ); + * $hash = array( + * 'formElement, + * 'options' => array( 'debug' => true ), + * ); + * + * + * @param mixed $value + * @param bool $allowEmpty Is an empty array() a valid hash table? + * @return bool + */ + public static function isHashTable($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return (array_values($value) !== $value); + } + + /** + * Convert an iterator to an array. + * + * Converts an iterator to an array. The $recursive flag, on by default, + * hints whether or not you want to do so recursively. + * + * @param array|Traversable $iterator The array or Traversable object to convert + * @param bool $recursive Recursively check all nested structures + * @return array + */ + public static function iteratorToArray($iterator, $recursive = true) + { + if (!is_array($iterator) && !$iterator instanceof Traversable) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object'); + } + + if (!$recursive) { + if (is_array($iterator)) { + return $iterator; + } + + return iterator_to_array($iterator); + } + + if (method_exists($iterator, 'toArray')) { + return $iterator->toArray(); + } + + $array = array(); + foreach ($iterator as $key => $value) { + if (is_scalar($value)) { + $array[$key] = $value; + continue; + } + + if ($value instanceof Traversable) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + if (is_array($value)) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + $array[$key] = $value; + } + + return $array; + } + + /** + * Merge two arrays together. + * + * If an integer key exists in both arrays, the value from the second array + * will be appended the the first array. If both values are arrays, they + * are merged together, else the value of the second array overwrites the + * one of the first array. + * + * @param array $a + * @param array $b + * @return array + */ + public static function merge(array $a, array $b) + { + foreach ($b as $key => $value) { + if (array_key_exists($key, $a)) { + if (is_int($key)) { + $a[] = $value; + } elseif (is_array($value) && is_array($a[$key])) { + $a[$key] = self::merge($a[$key], $value); + } else { + $a[$key] = $value; + } + } else { + $a[$key] = $value; + } + } + + return $a; + } +} diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index a42863973..3d4b86853 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -24,6 +24,7 @@ namespace Zend\Stdlib; use Closure, + ReflectionClass, WeakRef; /** @@ -35,7 +36,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 CallbackHandler @@ -46,21 +47,10 @@ class CallbackHandler protected $callback; /** - * @var string Event to which this handle is subscribed - */ - protected $event; - - /** - * Until callback has been validated, mark as invalid - * @var bool - */ - protected $isValidCallback = false; - - /** - * Callback options, if any + * Callback metadata, if any * @var array */ - protected $options; + protected $metadata; /** * Constructor @@ -70,10 +60,9 @@ class CallbackHandler * @param array $options Options used by the callback handler (e.g., priority) * @return void */ - public function __construct($event, $callback, array $options = array()) + public function __construct($callback, array $metadata = array()) { - $this->event = $event; - $this->options = $options; + $this->metadata = $metadata; $this->registerCallback($callback); } @@ -85,20 +74,25 @@ public function __construct($event, $callback, array $options = array()) * * If a callback is a functor, or an array callback composing an object * instance, this method will pass the object to a WeakRef instance prior - * to registering the callback. See {@link isValid()} for more information - * on how this affects execution. + * to registering the callback. * * @param callback $callback * @return void */ protected function registerCallback($callback) { - // If pecl/weakref is not installed, simply register it - if (!class_exists('WeakRef', false)) { + if (!is_callable($callback)) { + throw new Exception\InvalidCallbackException('Invalid callback provided; not callable'); + } + + // If pecl/weakref is not installed, simply store the callback and return + if (!class_exists('WeakRef')) { $this->callback = $callback; return; } + // If WeakRef exists, we want to use it. + // If we have a non-closure object, pass it to WeakRef, and then // register it. if (is_object($callback) && !$callback instanceof Closure) { @@ -127,46 +121,38 @@ protected function registerCallback($callback) $this->callback = array($target, $method); } - /** - * Get event to which handler is subscribed - * - * @return string - */ - public function getEvent() - { - return $this->event; - } - /** * Retrieve registered callback * * @return Callback - * @throws Exception\InvalidCallbackException If callback is invalid */ public function getCallback() { - if (!$this->isValid()) { - throw new Exception\InvalidCallbackException('Invalid callback provided; not callable'); - } - $callback = $this->callback; + + // String callbacks -- simply return if (is_string($callback)) { return $callback; } + // WeakRef callbacks -- pull it out of the object and return it if ($callback instanceof WeakRef) { return $callback->get(); } + // Non-WeakRef object callback -- return it if (is_object($callback)) { return $callback; } + // Array callback with WeakRef object -- retrieve the object first, and + // then return list($target, $method) = $callback; if ($target instanceof WeakRef) { return array($target->get(), $method); } + // Otherwise, return it return $callback; } @@ -179,187 +165,119 @@ public function getCallback() public function call(array $args = array()) { $callback = $this->getCallback(); - return call_user_func_array($callback, $args); + + $isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); + + if ($isPhp54 && is_string($callback)) { + $this->validateStringCallbackFor54($callback); + } + + // Minor performance tweak; use call_user_func() until > 3 arguments + // reached + switch (count($args)) { + case 0: + if ($isPhp54) { + return $callback(); + } + return call_user_func($callback); + case 1: + if ($isPhp54) { + return $callback(array_shift($args)); + } + return call_user_func($callback, array_shift($args)); + case 2: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + if ($isPhp54) { + return $callback($arg1, $arg2); + } + return call_user_func($callback, $arg1, $arg2); + case 3: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + $arg3 = array_shift($args); + if ($isPhp54) { + return $callback($arg1, $arg2, $arg3); + } + return call_user_func($callback, $arg1, $arg2, $arg3); + default: + return call_user_func_array($callback, $args); + } } /** - * Get all callback options + * Invoke as functor * - * @return array + * @return mixed */ - public function getOptions() + public function __invoke() { - return $this->options; + return $this->call(func_get_args()); } /** - * Retrieve a single option + * Get all callback metadata * - * @param string $name - * @return mixed + * @return array */ - public function getOption($name) + public function getMetadata() { - if (array_key_exists($name, $this->options)) { - return $this->options[$name]; - } - return null; + return $this->metadata; } /** - * Is the composed callback valid? - * - * Typically, this method simply checks to see if we have a valid callback. - * In a few situations, it does more. - * - * * If we have a string callback, we pass execution to - * {@link validateStringCallback()}. - * * If we have an object callback, we test to see if that object is a - * WeakRef {@see http://pecl.php.net/weakref}. If so, we return the value - * of its valid() method. Otherwise, we return the result of is_callable(). - * * If we have a callback array with a string in the first position, we - * pass execution to {@link validateArrayCallback()}. - * * If we have a callback array with an object in the first position, we - * test to see if that object is a WeakRef (@see http://pecl.php.net/weakref). - * If so, we return the value of its valid() method. Otherwise, we return - * the result of is_callable() on the callback. - * - * WeakRef is used to allow listeners to go out of scope. This functionality - * is turn-key if you have pecl/weakref installed; otherwise, you will have - * to manually remove listeners before destroying an object referenced in a - * listener. - * - * @return bool + * Retrieve a single metadatum + * + * @param string $name + * @return mixed */ - public function isValid() + public function getMetadatum($name) { - // If we've already tested this, we can move on. Note: if a callback - // composes a WeakRef, this will never get set, and thus result in - // validation on each call. - if ($this->isValidCallback) { - return $this->callback; - } - - $callback = $this->callback; - - if (is_string($callback)) { - return $this->validateStringCallback($callback); - } - - if ($callback instanceof WeakRef) { - return $callback->valid(); - } - - if (is_object($callback) && is_callable($callback)) { - $this->isValidCallback = true; - return true; - } - - if (!is_array($callback)) { - return false; - } - - list($target, $method) = $callback; - if ($target instanceof WeakRef) { - if (!$target->valid()) { - return false; - } - $target = $target->get(); - return is_callable(array($target, $method)); + if (array_key_exists($name, $this->metadata)) { + return $this->metadata[$name]; } - return $this->validateArrayCallback($callback); + return null; } /** - * Validate a string callback + * Validate a static method call * - * Check first if the string provided is callable. If not see if it is a - * valid class name; if so, determine if the object is invokable. + * Validates that a static method call in PHP 5.4 will actually work * * @param string $callback - * @return bool + * @return true + * @throws Exception\InvalidCallbackException if invalid */ - protected function validateStringCallback($callback) + protected function validateStringCallbackFor54($callback) { - if (is_callable($callback)) { - $this->isValidCallback = true; + if (!strstr($callback, '::')) { return true; } - if (!class_exists($callback)) { - return false; - } + list($class, $method) = explode('::', $callback, 2); - // check __invoke before instantiating - if (!method_exists($callback, '__invoke')) { - return false; + if (!class_exists($class)) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a class that does not exist', + $callback + )); } - $object = new $callback(); - - $this->callback = $object; - $this->isValidCallback = true; - return true; - } - - /** - * Validate an array callback - * - * @param array $callback - * @return bool - */ - protected function validateArrayCallback(array $callback) - { - $context = $callback[0]; - $method = $callback[1]; - if (is_string($context)) { - // Dealing with a class/method callback, and class provided is a string classname - - if (!class_exists($context)) { - return false; - } - - // We need to determine if we need to instantiate the class first - $r = new \ReflectionClass($context); - if (!$r->hasMethod($method)) { - // Explicit method does not exist - if (!$r->hasMethod('__callStatic') && !$r->hasMethod('__call')) { - return false; - } - - if ($r->hasMethod('__callStatic')) { - // We have a __callStatic defined, so the original callback is valid - $this->isValidCallback = true; - return $callback; - } - - // We have __call defined, so we need to instantiate the class - // first, and redefine the callback - $object = new $context(); - $this->callback = array($object, $method); - $this->isValidCallback = true; - return $this->callback; - } - - // Explicit method exists - $rMethod = $r->getMethod($method); - if ($rMethod->isStatic()) { - // Method is static, so original callback is fine - $this->isValidCallback = true; - return $callback; - } - - // Method is an instance method; instantiate object and redefine callback - $object = new $context(); - $this->callback = array($object, $method); - $this->isValidCallback = true; - return $this->callback; - } elseif (is_callable($callback)) { - // The - $this->isValidCallback = true; - return $callback; + $r = new ReflectionClass($class); + if (!$r->hasMethod($method)) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that does not exist', + $callback + )); + } + $m = $r->getMethod($method); + if (!$m->isStatic()) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that is not static', + $callback + )); } - return false; + return true; } } diff --git a/src/ErrorHandler.php b/src/ErrorHandler.php new file mode 100644 index 000000000..ad56b6919 --- /dev/null +++ b/src/ErrorHandler.php @@ -0,0 +1,119 @@ + 0 - ); - } -} diff --git a/src/IteratorToArray.php b/src/IteratorToArray.php deleted file mode 100644 index 123bf2e35..000000000 --- a/src/IteratorToArray.php +++ /dev/null @@ -1,63 +0,0 @@ -toArray(); - } - - $array = array(); - foreach ($iterator as $key => $value) { - if (is_scalar($value)) { - $array[$key] = $value; - continue; - } - - if ($value instanceof Traversable) { - $array[$key] = static::convert($value, $recursive); - continue; - } - - if (is_array($value)) { - $array[$key] = static::convert($value, $recursive); - continue; - } - - $array[$key] = $value; - } - - return $array; - } -} diff --git a/src/Options.php b/src/Options.php index 1d9def4fb..bbaacdb67 100644 --- a/src/Options.php +++ b/src/Options.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -28,40 +28,38 @@ /** * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 Options implements ParameterObject { /** - * @param array|Traversable|null $config + * @param array|Traversable|null $options * @return Options * @throws Exception\InvalidArgumentException */ - public function __construct($config = null) + public function __construct($options = null) { - if (is_null($config)) { - return; + if (null !== $options) { + $this->setFromArray($options); } - $this->processArray($config); } /** - * @param array|Traversable $config + * @param array|Traversable $options * @return void */ - protected function processArray($config) + public function setFromArray($options) { - if (!is_array($config) && !$config instanceof Traversable) { + if (!is_array($options) && !$options instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( 'Parameter provided to %s must be an array or Traversable', __METHOD__ )); } - foreach ($config as $key => $value) { - $setter = $this->assembleSetterNameFromConfigKey($key); - $this->{$setter}($value); + foreach ($options as $key => $value) { + $this->__set($key, $value); } } @@ -70,14 +68,14 @@ protected function processArray($config) * @return string name of setter method * @throws Exception\BadMethodCallException if setter method is undefined */ - protected function assembleSetterNameFromConfigKey($key) + protected function assembleSetterNameFromKey($key) { $parts = explode('_', $key); $parts = array_map('ucfirst', $parts); $setter = 'set' . implode('', $parts); if (!method_exists($this, $setter)) { throw new Exception\BadMethodCallException( - 'The configuration key "' . $key . '" does not ' + 'The option "' . $key . '" does not ' . 'have a matching ' . $setter . ' setter method ' . 'which must be defined' ); @@ -90,14 +88,14 @@ protected function assembleSetterNameFromConfigKey($key) * @return string name of getter method * @throws Exception\BadMethodCallException if getter method is undefined */ - protected function assembleGetterNameFromConfigKey($key) + protected function assembleGetterNameFromKey($key) { $parts = explode('_', $key); $parts = array_map('ucfirst', $parts); $getter = 'get' . implode('', $parts); if (!method_exists($this, $getter)) { throw new Exception\BadMethodCallException( - 'The configuration key "' . $key . '" does not ' + 'The option "' . $key . '" does not ' . 'have a matching ' . $getter . ' getter method ' . 'which must be defined' ); @@ -113,7 +111,7 @@ protected function assembleGetterNameFromConfigKey($key) */ public function __set($key, $value) { - $setter = $this->assembleSetterNameFromConfigKey($key); + $setter = $this->assembleSetterNameFromKey($key); $this->{$setter}($value); } @@ -124,7 +122,7 @@ public function __set($key, $value) */ public function __get($key) { - $getter = $this->assembleGetterNameFromConfigKey($key); + $getter = $this->assembleGetterNameFromKey($key); return $this->{$getter}(); } @@ -135,8 +133,7 @@ public function __get($key) */ public function __isset($key) { - $getter = $this->assembleGetterNameFromConfigKey($key); - return !is_null($this->{$getter}()); + return null !== $this->__get($key); } /** @@ -147,9 +144,8 @@ public function __isset($key) */ public function __unset($key) { - $setter = $this->assembleSetterNameFromConfigKey($key); try { - $this->{$setter}(null); + $this->__set($key, null); } catch(\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException( 'The class property $' . $key . ' cannot be unset as' diff --git a/src/ParameterObject.php b/src/ParameterObject.php index 55bb2d691..80399282e 100644 --- a/src/ParameterObject.php +++ b/src/ParameterObject.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -26,7 +26,7 @@ /** * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ interface ParameterObject diff --git a/src/PriorityQueue.php b/src/PriorityQueue.php index 390a3d2d9..6f063419b 100644 --- a/src/PriorityQueue.php +++ b/src/PriorityQueue.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -41,7 +41,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 PriorityQueue implements Countable, IteratorAggregate, Serializable diff --git a/src/SplPriorityQueue.php b/src/SplPriorityQueue.php index d15d81caa..5752283de 100644 --- a/src/SplPriorityQueue.php +++ b/src/SplPriorityQueue.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -33,7 +33,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 SplPriorityQueue extends \SplPriorityQueue implements Serializable diff --git a/src/SplQueue.php b/src/SplQueue.php index 031ba917e..9b8d5118a 100644 --- a/src/SplQueue.php +++ b/src/SplQueue.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -30,7 +30,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 SplQueue extends \SplQueue implements Serializable diff --git a/src/SplStack.php b/src/SplStack.php index a908997ba..01aa0a0c3 100644 --- a/src/SplStack.php +++ b/src/SplStack.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -30,7 +30,7 @@ * * @category Zend * @package Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 SplStack extends \SplStack implements Serializable diff --git a/test/ArrayUtilsTest.php b/test/ArrayUtilsTest.php new file mode 100644 index 000000000..01c73e5f6 --- /dev/null +++ b/test/ArrayUtilsTest.php @@ -0,0 +1,378 @@ + 'bar' + )), + array(array( + '15', + 'foo' => 'bar', + 'baz' => array('baz') + )), + array(array( + 0 => false, + 2 => null + )), + array(array( + -100 => 'foo', + 100 => 'bar' + )), + array(array( + 1 => 0 + )), + ); + } + + public static function validLists() + { + return array( + array(array(null)), + array(array(true)), + array(array(false)), + array(array(0)), + array(array(-0.9999)), + array(array('string')), + array(array(new stdClass)), + array(array( + 0 => 'foo', + 1 => 'bar', + 2 => false, + 3 => null, + 4 => array(), + 5 => new stdClass() + )) + ); + } + + public static function validArraysWithStringKeys() + { + return array( + array(array( + 'foo' => 'bar', + )), + array(array( + 'bar', + 'foo' => 'bar', + 'baz', + )), + ); + } + + public static function validArraysWithNumericKeys() + { + return array( + array(array( + 'foo', + 'bar' + )), + array(array( + '0' => 'foo', + '1' => 'bar', + )), + array(array( + 'bar', + '1' => 'bar', + 3 => 'baz' + )), + array(array( + -10000 => null, + '-10000' => null, + )), + array(array( + '-00000.00009' => 'foo' + )), + array(array( + 1 => 0 + )), + ); + } + + public static function validArraysWithIntegerKeys() + { + return array( + array(array( + 'foo', + 'bar,' + )), + array(array( + 100 => 'foo', + 200 => 'bar' + )), + array(array( + -100 => 'foo', + 0 => 'bar', + 100 => 'baz' + )), + array(array( + 'foo', + 'bar', + 1000 => 'baz' + )), + ); + } + + public static function invalidArrays() + { + return array( + array(new stdClass()), + array(15), + array('foo'), + array(new ArrayObject()), + ); + } + + public static function mergeArrays() + { + return array( + 'merge-integer-and-string keys' => array( + array( + 'foo', + 3 => 'bar', + 'baz' => 'baz' + ), + array( + 'baz', + ), + array( + 0 => 'foo', + 3 => 'bar', + 'baz' => 'baz', + 4 => 'baz' + ) + ), + 'merge-arrays-recursively' => array( + array( + 'foo' => array( + 'baz' + ) + ), + array( + 'foo' => array( + 'baz' + ) + ), + array( + 'foo' => array( + 0 => 'baz', + 1 => 'baz' + ) + ) + ), + 'replace-string-keys' => array( + array( + 'foo' => 'bar', + 'bar' => array() + ), + array( + 'foo' => 'baz', + 'bar' => 'bat' + ), + array( + 'foo' => 'baz', + 'bar' => 'bat' + ) + ), + ); + } + + public static function validIterators() + { + return array( + array(array( + 'foo' => 'bar', + ), array( + 'foo' => 'bar', + )), + array(new Config(array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), + array(new ArrayObject(array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), + ); + } + + public static function invalidIterators() + { + return array( + array(null), + array(true), + array(false), + array(0), + array(1), + array(0.0), + array(1.0), + array('string'), + array(new stdClass), + ); + } + + /** + * @dataProvider validArraysWithStringKeys + */ + public function testValidArraysWithStringKeys($test) + { + $this->assertTrue(ArrayUtils::hasStringKeys($test)); + } + + /** + * @dataProvider validArraysWithIntegerKeys + */ + public function testValidArraysWithIntegerKeys($test) + { + $this->assertTrue(ArrayUtils::hasIntegerKeys($test)); + } + + /** + * @dataProvider validArraysWithNumericKeys + */ + public function testValidArraysWithNumericKeys($test) + { + $this->assertTrue(ArrayUtils::hasNumericKeys($test)); + } + + /** + * @dataProvider invalidArrays + */ + public function testInvalidArraysAlwaysReturnFalse($test) + { + $this->assertFalse(ArrayUtils::hasStringKeys($test, False)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, False)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, False)); + $this->assertFalse(ArrayUtils::isList($test, False)); + $this->assertFalse(ArrayUtils::isHashTable($test, False)); + + $this->assertFalse(ArrayUtils::hasStringKeys($test, false)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, false)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, false)); + $this->assertFalse(ArrayUtils::isList($test, false)); + $this->assertFalse(ArrayUtils::isHashTable($test, false)); + } + + /** + * @dataProvider validLists + */ + public function testLists($test) + { + $this->assertTrue(ArrayUtils::isList($test)); + $this->assertTrue(ArrayUtils::hasIntegerKeys($test)); + $this->assertTrue(ArrayUtils::hasNumericKeys($test)); + $this->assertFalse(ArrayUtils::hasStringKeys($test)); + $this->assertFalse(ArrayUtils::isHashTable($test)); + } + + /** + * @dataProvider validHashTables + */ + public function testHashTables($test) + { + $this->assertTrue(ArrayUtils::isHashTable($test)); + $this->assertFalse(ArrayUtils::isList($test)); + } + + public function testEmptyArrayReturnsTrue() + { + $test = array(); + $this->assertTrue(ArrayUtils::hasStringKeys($test, true)); + $this->assertTrue(ArrayUtils::hasIntegerKeys($test, true)); + $this->assertTrue(ArrayUtils::hasNumericKeys($test, true)); + $this->assertTrue(ArrayUtils::isList($test, true)); + $this->assertTrue(ArrayUtils::isHashTable($test, true)); + } + + public function testEmptyArrayReturnsFalse() + { + $test = array(); + $this->assertFalse(ArrayUtils::hasStringKeys($test, false)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, false)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, false)); + $this->assertFalse(ArrayUtils::isList($test, false)); + $this->assertFalse(ArrayUtils::isHashTable($test, false)); + } + + /** + * @dataProvider mergeArrays + */ + public function testMerge($a, $b, $expected) + { + $this->assertEquals($expected, ArrayUtils::merge($a, $b)); + } + + /** + * @dataProvider validIterators + */ + public function testValidIteratorsReturnArrayRepresentation($test, $expected) + { + $result = ArrayUtils::iteratorToArray($test); + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider invalidIterators + */ + public function testInvalidIteratorsRaiseInvalidArgumentException($test) + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $this->assertFalse(ArrayUtils::iteratorToArray($test)); + } +} diff --git a/test/CallbackHandlerTest.php b/test/CallbackHandlerTest.php index 826c72de8..c30507dfe 100644 --- a/test/CallbackHandlerTest.php +++ b/test/CallbackHandlerTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,7 +29,7 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 CallbackHandlerTest extends \PHPUnit_Framework_TestCase @@ -41,82 +41,113 @@ public function setUp() } } - public function testGetEventShouldReturnEvent() + public function testCallbackShouldStoreMetadata() { - $handler = new CallbackHandler('foo', 'rand'); - $this->assertEquals('foo', $handler->getEvent()); + $handler = new CallbackHandler('rand', array('event' => 'foo')); + $this->assertEquals('foo', $handler->getMetadatum('event')); + $this->assertEquals(array('event' => 'foo'), $handler->getMetadata()); } public function testCallbackShouldBeStringIfNoHandlerPassedToConstructor() { - $handler = new CallbackHandler('foo', 'rand'); + $handler = new CallbackHandler('rand'); $this->assertSame('rand', $handler->getCallback()); } public function testCallbackShouldBeArrayIfHandlerPassedToConstructor() { - $handler = new CallbackHandler('foo', array('\\ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); - $this->assertSame(array('\\ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'), $handler->getCallback()); + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); + $this->assertSame(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'), $handler->getCallback()); } public function testCallShouldInvokeCallbackWithSuppliedArguments() { - $handler = new CallbackHandler('foo', array( $this, 'handleCall' )); + $handler = new CallbackHandler(array( $this, 'handleCall' )); $args = array('foo', 'bar', 'baz'); $handler->call($args); $this->assertSame($args, $this->args); } - public function testPassingInvalidCallbackShouldRaiseInvalidCallbackExceptionDuringCall() + public function testPassingInvalidCallbackShouldRaiseInvalidCallbackExceptionDuringInstantiation() { $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); - $handler = new CallbackHandler('Invokable', 'boguscallback'); - $handler->call(); + $handler = new CallbackHandler('boguscallback'); } public function testCallShouldReturnTheReturnValueOfTheCallback() { - $handler = new CallbackHandler('foo', array('\\ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); - if (!is_callable(array('\\ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'))) { - echo "\nClass exists? " . var_export(class_exists('\\ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback'), 1) . "\n"; + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); + if (!is_callable(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'))) { + echo "\nClass exists? " . var_export(class_exists('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback'), 1) . "\n"; echo "Include path: " . get_include_path() . "\n"; } $this->assertEquals('bar', $handler->call(array())); } - public function testStringCallbackResolvingToClassNameShouldCallViaInvoke() + public function testStringCallbackResolvingToClassDefiningInvokeNameShouldRaiseException() { - $handler = new CallbackHandler('foo', '\\ZendTest\\Stdlib\\SignalHandlers\\Invokable'); - $this->assertEquals('__invoke', $handler->call(), var_export($handler->getCallback(), 1)); + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\Invokable'); } public function testStringCallbackReferringToClassWithoutDefinedInvokeShouldRaiseException() { $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); - $handler = new CallbackHandler('foo', '\\ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod'); + $class = new SignalHandlers\InstanceMethod(); + $handler = new CallbackHandler($class); + } + + public function testCallbackConsistingOfStringContextWithNonStaticMethodShouldNotRaiseExceptionButWillRaiseEStrict() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod', 'handler')); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); $handler->call(); + restore_error_handler(); + $this->assertTrue($error); } - public function testCallbackConsistingOfStringContextWithNonStaticMethodShouldInstantiateContext() + public function testStringCallbackConsistingOfNonStaticMethodShouldRaiseException() { - $handler = new CallbackHandler('foo', array( 'ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod', 'callable' )); - $this->assertEquals('callable', $handler->call()); + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::handler'); + + if (version_compare(PHP_VERSION, '5.4.0rc1', '>=')) { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler->call(); + } else { + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $handler->call(); + restore_error_handler(); + $this->assertTrue($error); + } } - public function testCallbackToClassImplementingOverloadingShouldSucceed() + public function testCallbackToClassImplementingOverloadingButNotInvocableShouldRaiseException() { - $handler = new CallbackHandler('foo', array( '\\ZendTest\\Stdlib\\SignalHandlers\\Overloadable', 'foo' )); - $this->assertEquals('foo', $handler->call()); + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('foo', array( 'ZendTest\\Stdlib\\SignalHandlers\\Overloadable', 'foo' )); } public function testClosureCallbackShouldBeInvokedByCall() { - $handler = new CallbackHandler(null, function () { + $handler = new CallbackHandler(function () { return 'foo'; }); $this->assertEquals('foo', $handler->call()); } + public function testHandlerShouldBeInvocable() + { + $handler = new CallbackHandler(array($this, 'handleCall')); + $handler('foo', 'bar'); + $this->assertEquals(array('foo', 'bar'), $this->args); + } + public function handleCall() { $this->args = func_get_args(); diff --git a/test/ErrorHandlerTest.php b/test/ErrorHandlerTest.php new file mode 100644 index 000000000..0c53059bd --- /dev/null +++ b/test/ErrorHandlerTest.php @@ -0,0 +1,82 @@ +assertFalse(ErrorHandler::started()); + + ErrorHandler::start(); + $this->assertTrue(ErrorHandler::started()); + + ErrorHandler::stop(); + $this->assertFalse(ErrorHandler::started()); + } + + public function testStartThrowsLogicException() + { + ErrorHandler::start(); + + $this->setExpectedException('Zend\Stdlib\Exception\LogicException'); + ErrorHandler::start(); + } + + public function testStopThrowsLogicException() + { + $this->setExpectedException('Zend\Stdlib\Exception\LogicException'); + ErrorHandler::stop(); + } + + public function testReturnCatchedError() + { + ErrorHandler::start(); + strpos(); // Invalid argument list + $err = ErrorHandler::stop(); + + $this->assertInstanceOf('ErrorException', $err); + } + + public function testThrowCatchedError() + { + ErrorHandler::start(); + strpos(); // Invalid argument list + + $this->setExpectedException('ErrorException'); + ErrorHandler::stop(true); + } + + public function testAddErrors() + { + ErrorHandler::start(); + ErrorHandler::addError(1, 'test-msg1', 'test-file1', 100); + ErrorHandler::addError(2, 'test-msg2', 'test-file2', 200); + $err = ErrorHandler::stop(); + + $this->assertInstanceOf('ErrorException', $err); + $this->assertEquals('test-file2', $err->getFile()); + $this->assertEquals('test-msg2', $err->getMessage()); + $this->assertEquals(200, $err->getLine()); + $this->assertEquals(0, $err->getCode()); + $this->assertEquals(2, $err->getSeverity()); + + $previous = $err->getPrevious(); + $this->assertInstanceOf('ErrorException', $previous); + $this->assertEquals('test-file1', $previous->getFile()); + $this->assertEquals('test-msg1', $previous->getMessage()); + $this->assertEquals(100, $previous->getLine()); + $this->assertEquals(0, $previous->getCode()); + $this->assertEquals(1, $previous->getSeverity()); + } +} diff --git a/test/IsAssocArrayTest.php b/test/IsAssocArrayTest.php deleted file mode 100644 index 14fc59ce1..000000000 --- a/test/IsAssocArrayTest.php +++ /dev/null @@ -1,56 +0,0 @@ - 'bar', - )), - array(array( - 'bar', - 'foo' => 'bar', - 'baz', - )), - ); - } - - public static function invalidAssocArrays() - { - return array( - array(null), - array(true), - array(false), - array(0), - array(1), - array(0.0), - array(1.0), - array('string'), - array(array(0, 1, 2)), - array(new stdClass), - ); - } - - /** - * @dataProvider validAssocArrays - */ - public function testValidAssocArraysReturnTrue($test) - { - $this->assertTrue(IsAssocArray::test($test)); - } - - /** - * @dataProvider invalidAssocArrays - */ - public function testInvalidAssocArraysReturnFalse($test) - { - $this->assertFalse(IsAssocArray::test($test)); - } -} diff --git a/test/IteratorToArrayTest.php b/test/IteratorToArrayTest.php deleted file mode 100644 index 5f30b8fb4..000000000 --- a/test/IteratorToArrayTest.php +++ /dev/null @@ -1,90 +0,0 @@ - 'bar', - ), array( - 'foo' => 'bar', - )), - array(new Config(array( - 'foo' => array( - 'bar' => array( - 'baz' => array( - 'baz' => 'bat', - ), - ), - ), - )), array( - 'foo' => array( - 'bar' => array( - 'baz' => array( - 'baz' => 'bat', - ), - ), - ), - )), - array(new ArrayObject(array( - 'foo' => array( - 'bar' => array( - 'baz' => array( - 'baz' => 'bat', - ), - ), - ), - )), array( - 'foo' => array( - 'bar' => array( - 'baz' => array( - 'baz' => 'bat', - ), - ), - ), - )), - ); - } - - public static function invalidIterators() - { - return array( - array(null), - array(true), - array(false), - array(0), - array(1), - array(0.0), - array(1.0), - array('string'), - array(new stdClass), - ); - } - - /** - * @dataProvider validIterators - */ - public function testValidIteratorsReturnArrayRepresentation($test, $expected) - { - $result = IteratorToArray::convert($test); - $this->assertEquals($expected, $result); - } - - /** - * @dataProvider invalidIterators - */ - public function testInvalidIteratorsRaiseInvalidArgumentException($test) - { - $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); - $this->assertFalse(IteratorToArray::convert($test)); - } -} diff --git a/test/PriorityQueueTest.php b/test/PriorityQueueTest.php index ecb56d1ce..3986ca4ff 100644 --- a/test/PriorityQueueTest.php +++ b/test/PriorityQueueTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -29,7 +29,7 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 PriorityQueueTest extends \PHPUnit_Framework_TestCase diff --git a/test/SignalHandlers/InstanceMethod.php b/test/SignalHandlers/InstanceMethod.php index cf06a79b1..393d32710 100644 --- a/test/SignalHandlers/InstanceMethod.php +++ b/test/SignalHandlers/InstanceMethod.php @@ -3,7 +3,7 @@ class InstanceMethod { - public function callable() + public function handler() { return __FUNCTION__; } diff --git a/test/SplPriorityQueueTest.php b/test/SplPriorityQueueTest.php index 6c8182a84..fe8a987ff 100644 --- a/test/SplPriorityQueueTest.php +++ b/test/SplPriorityQueueTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,7 +29,7 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 SplPriorityQueueTest extends \PHPUnit_Framework_TestCase diff --git a/test/SplQueueTest.php b/test/SplQueueTest.php index f54b373e4..7412a68e0 100644 --- a/test/SplQueueTest.php +++ b/test/SplQueueTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,7 +29,7 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 SplQueueTest extends \PHPUnit_Framework_TestCase diff --git a/test/SplStackTest.php b/test/SplStackTest.php index 423324142..3fbb6a842 100644 --- a/test/SplStackTest.php +++ b/test/SplStackTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,7 +29,7 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @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 SplStackTest extends \PHPUnit_Framework_TestCase