diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php
index beff2f6db..8099c75ff 100644
--- a/src/AbstractOptions.php
+++ b/src/AbstractOptions.php
@@ -5,17 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
use Traversable;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
abstract class AbstractOptions implements ParameterObjectInterface
{
/**
@@ -28,8 +23,6 @@ abstract class AbstractOptions implements ParameterObjectInterface
/**
* @param array|Traversable|null $options
- * @return AbstractOptions
- * @throws Exception\InvalidArgumentException
*/
public function __construct($options = null)
{
@@ -41,7 +34,7 @@ public function __construct($options = null)
/**
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
- * @return void
+ * @return AbstractOptions Provides fluent interface
*/
public function setFromArray($options)
{
@@ -55,6 +48,7 @@ public function setFromArray($options)
foreach ($options as $key => $value) {
$this->__set($key, $value);
}
+ return $this;
}
/**
@@ -115,6 +109,7 @@ public function __get($key)
. 'which must be defined'
);
}
+
return $this->{$getter}();
}
@@ -131,14 +126,14 @@ public function __isset($key)
/**
* @see ParameterObject::__unset()
* @param string $key
- * @return void
* @throws Exception\InvalidArgumentException
+ * @return void
*/
public function __unset($key)
{
try {
$this->__set($key, null);
- } catch (\InvalidArgumentException $e) {
+ } catch (Exception\BadMethodCallException $e) {
throw new Exception\InvalidArgumentException(
'The class property $' . $key . ' cannot be unset as'
. ' NULL is an invalid value for it',
diff --git a/src/ArraySerializableInterface.php b/src/ArraySerializableInterface.php
index a179f4e42..7bd6f6edd 100644
--- a/src/ArraySerializableInterface.php
+++ b/src/ArraySerializableInterface.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
interface ArraySerializableInterface
{
/**
diff --git a/src/ArrayStack.php b/src/ArrayStack.php
index f94f4522b..50eaad6e6 100644
--- a/src/ArrayStack.php
+++ b/src/ArrayStack.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -15,9 +14,6 @@
/**
* ArrayObject that acts as a stack with regards to iteration
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class ArrayStack extends ArrayObject
{
diff --git a/src/ArrayUtils.php b/src/ArrayUtils.php
index b2870efe0..b073f3b45 100644
--- a/src/ArrayUtils.php
+++ b/src/ArrayUtils.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -16,9 +15,6 @@
* Utility class for testing and manipulation of PHP arrays.
*
* Declared abstract, as we have no need for instantiation.
- *
- * @category Zend
- * @package Zend_Stdlib
*/
abstract class ArrayUtils
{
@@ -164,6 +160,36 @@ public static function isHashTable($value, $allowEmpty = false)
return (array_values($value) !== $value);
}
+ /**
+ * Checks if a value exists in an array.
+ *
+ * Due to "foo" == 0 === TRUE with in_array when strict = false, an option
+ * has been added to prevent this. When $strict = 0/false, the most secure
+ * non-strict check is implemented. if $strict = -1, the default in_array
+ * non-strict behaviour is used.
+ *
+ * @param mixed $needle
+ * @param array $haystack
+ * @param int|bool $strict
+ * @return bool
+ */
+ public static function inArray($needle, array $haystack, $strict = false)
+ {
+ if (!$strict) {
+ if (is_int($needle) || is_float($needle)) {
+ $needle = (string) $needle;
+ }
+ if (is_string($needle)) {
+ foreach ($haystack as &$h) {
+ if (is_int($h) || is_float($h)) {
+ $h = (string) $h;
+ }
+ }
+ }
+ }
+ return in_array($needle, $haystack, $strict);
+ }
+
/**
* Convert an iterator to an array.
*
diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php
index 22effba7d..bd60a6756 100644
--- a/src/CallbackHandler.php
+++ b/src/CallbackHandler.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -20,9 +19,6 @@
* A handler for a event, event, filterchain, etc. Abstracts PHP callbacks,
* primarily to allow for lazy-loading and ensuring availability of default
* arguments (currying).
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class CallbackHandler
{
diff --git a/src/DateTime.php b/src/DateTime.php
index 032fc94ff..308a25b53 100644
--- a/src/DateTime.php
+++ b/src/DateTime.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -16,9 +15,6 @@
* DateTime
*
* An extension of the \DateTime object.
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class DateTime extends \DateTime
{
@@ -44,5 +40,4 @@ public static function createFromISO8601($time, DateTimeZone $timezone = null)
return self::createFromFormat($format, $time);
}
-
}
diff --git a/src/DispatchableInterface.php b/src/DispatchableInterface.php
index 2e6fa95f9..ab672fa13 100644
--- a/src/DispatchableInterface.php
+++ b/src/DispatchableInterface.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -13,10 +12,6 @@
use Zend\Stdlib\RequestInterface as Request;
use Zend\Stdlib\ResponseInterface as Response;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
interface DispatchableInterface
{
/**
diff --git a/src/ErrorHandler.php b/src/ErrorHandler.php
index 05204831e..92f399575 100644
--- a/src/ErrorHandler.php
+++ b/src/ErrorHandler.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -15,53 +14,48 @@
/**
* ErrorHandler that can be used to catch internal PHP errors
* and convert to a ErrorException instance.
- *
- * @category Zend
- * @package Zend_Stdlib
*/
abstract class ErrorHandler
{
/**
- * Flag to mark started
+ * Active stack
*
- * @var bool
+ * @var array
*/
- protected static $started = false;
+ protected static $stack = array();
/**
- * All errors as one instance of ErrorException
- * using the previous exception support.
+ * Check if this error handler is active
*
- * @var null|ErrorException
+ * @return boolean
*/
- protected static $errorException = null;
+ public static function started()
+ {
+ return (bool) static::getNestedLevel();
+ }
/**
- * If the error handler has been started.
+ * Get the current nested level
*
- * @return bool
+ * @return int
*/
- public static function started()
+ public static function getNestedLevel()
{
- return static::$started;
+ return count(static::$stack);
}
/**
* Starting the error handler
*
* @param int $errorLevel
- * @throws Exception\LogicException If already started
*/
public static function start($errorLevel = \E_WARNING)
{
- if (static::started() === true) {
- throw new Exception\LogicException('ErrorHandler already started');
+ if (!static::$stack) {
+ set_error_handler(array(get_called_class(), 'addError'), $errorLevel);
}
- static::$started = true;
- static::$errorException = null;
-
- set_error_handler(array(get_called_class(), 'addError'), $errorLevel);
+ static::$stack[] = null;
}
/**
@@ -69,30 +63,43 @@ public static function start($errorLevel = \E_WARNING)
*
* @param bool $throw Throw the ErrorException if any
* @return null|ErrorException
- * @throws Exception\LogicException If not started before
* @throws ErrorException If an error has been catched and $throw is true
*/
public static function stop($throw = false)
{
- if (static::started() === false) {
- throw new Exception\LogicException('ErrorHandler not started');
- }
+ $errorException = null;
- $errorException = static::$errorException;
+ if (static::$stack) {
+ $errorException = array_pop(static::$stack);
- static::$started = false;
- static::$errorException = null;
- restore_error_handler();
+ if (!static::$stack) {
+ restore_error_handler();
+ }
- if ($errorException && $throw) {
- throw $errorException;
+ if ($errorException && $throw) {
+ throw $errorException;
+ }
}
return $errorException;
}
/**
- * Add an error to the stack.
+ * Stop all active handler
+ *
+ * @return void
+ */
+ public static function clean()
+ {
+ if (static::$stack) {
+ restore_error_handler();
+ }
+
+ static::$stack = array();
+ }
+
+ /**
+ * Add an error to the stack
*
* @param int $errno
* @param string $errstr
@@ -102,6 +109,7 @@ public static function stop($throw = false)
*/
public static function addError($errno, $errstr = '', $errfile = '', $errline = 0)
{
- static::$errorException = new ErrorException($errstr, 0, $errno, $errfile, $errline, static::$errorException);
+ $stack = & static::$stack[ count(static::$stack) - 1 ];
+ $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack);
}
}
diff --git a/src/Exception/BadMethodCallException.php b/src/Exception/BadMethodCallException.php
index 079dbfe59..6cf1c9ecc 100644
--- a/src/Exception/BadMethodCallException.php
+++ b/src/Exception/BadMethodCallException.php
@@ -5,17 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Exception;
/**
* Bad method call exception
- *
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Exception
*/
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
diff --git a/src/Exception/DomainException.php b/src/Exception/DomainException.php
index cf6b43b16..2744570f2 100644
--- a/src/Exception/DomainException.php
+++ b/src/Exception/DomainException.php
@@ -5,17 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Exception;
/**
* Domain exception
- *
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Exception
*/
class DomainException extends \DomainException implements ExceptionInterface
{
diff --git a/src/Exception/ExceptionInterface.php b/src/Exception/ExceptionInterface.php
index c3013a0f0..0424a4ea9 100644
--- a/src/Exception/ExceptionInterface.php
+++ b/src/Exception/ExceptionInterface.php
@@ -5,17 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Exception;
/**
* Exception marker interface
- *
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Exception
*/
interface ExceptionInterface
{
diff --git a/src/Exception/ExtensionNotLoadedException.php b/src/Exception/ExtensionNotLoadedException.php
new file mode 100644
index 000000000..b883641a6
--- /dev/null
+++ b/src/Exception/ExtensionNotLoadedException.php
@@ -0,0 +1,17 @@
+strategies = new ArrayObject();
+ $this->filterComposite = new FilterComposite();
}
/**
@@ -44,7 +47,19 @@ public function __construct()
*/
public function getStrategy($name)
{
- return $this->strategies[$name];
+ if (isset($this->strategies[$name])) {
+ return $this->strategies[$name];
+ }
+
+ if (!isset($this->strategies['*'])) {
+ throw new Exception\InvalidArgumentException(sprintf(
+ '%s: no strategy by name of "%s", and no wildcard strategy present',
+ __METHOD__,
+ $name
+ ));
+ }
+
+ return $this->strategies['*'];
}
/**
@@ -55,7 +70,8 @@ public function getStrategy($name)
*/
public function hasStrategy($name)
{
- return array_key_exists($name, $this->strategies);
+ return array_key_exists($name, $this->strategies)
+ || array_key_exists('*', $this->strategies);
}
/**
@@ -114,4 +130,67 @@ public function hydrateValue($name, $value)
}
return $value;
}
+
+ /**
+ * Get the filter instance
+ *
+ * @return Filter\FilterComposite
+ */
+ public function getFilter()
+ {
+ return $this->filterComposite;
+ }
+
+ /**
+ * Add a new filter to take care of what needs to be hydrated.
+ * To exclude e.g. the method getServiceLocator:
+ *
+ *
+ * $composite->addFilter("servicelocator",
+ * function($property) {
+ * list($class, $method) = explode('::', $property);
+ * if ($method === 'getServiceLocator') {
+ * return false;
+ * }
+ * return true;
+ * }, FilterComposite::CONDITION_AND
+ * );
+ *
+ *
+ * @param string $name Index in the composite
+ * @param callable|Zend\Stdlib\Hydrator\Filter\FilterInterface $filter
+ * @param int $condition
+ * @return Filter\FilterComposite
+ */
+ public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR)
+ {
+ return $this->filterComposite->addFilter($name, $filter, $condition);
+ }
+
+ /**
+ * Check whether a specific filter exists at key $name or not
+ *
+ * @param string $name Index in the composite
+ * @return bool
+ */
+ public function hasFilter($name)
+ {
+ return $this->filterComposite->hasFilter($name);
+ }
+
+ /**
+ * Remove a filter from the composition.
+ * To not extract "has" methods, you simply need to unregister it
+ *
+ *
+ * $filterComposite->removeFilter('has');
+ *
+ *
+ * @param $name
+ * @return Filter\FilterComposite
+ */
+ public function removeFilter($name)
+ {
+ return $this->filterComposite->removeFilter($name);
+ }
}
diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php
index fbe214db9..09dfebba1 100644
--- a/src/Hydrator/ArraySerializable.php
+++ b/src/Hydrator/ArraySerializable.php
@@ -5,18 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator;
use Zend\Stdlib\Exception;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
class ArraySerializable extends AbstractHydrator
{
@@ -39,9 +33,14 @@ public function extract($object)
$self = $this;
$data = $object->getArrayCopy();
- array_walk($data, function (&$value, $name) use ($self) {
- $value = $self->extractValue($name, $value);
+ array_walk($data, function (&$value, $name) use ($self, &$data) {
+ if (!$self->getFilter()->filter($name)) {
+ unset($data[$name]);
+ } else {
+ $value = $self->extractValue($name, $value);
+ }
});
+
return $data;
}
diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php
index 06b2336fa..d29185fe6 100644
--- a/src/Hydrator/ClassMethods.php
+++ b/src/Hydrator/ClassMethods.php
@@ -5,34 +5,83 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator;
+use ReflectionMethod;
+use Traversable;
use Zend\Stdlib\Exception;
+use Zend\Stdlib\ArrayUtils;
+use Zend\Stdlib\Hydrator\Filter\FilterComposite;
+use Zend\Stdlib\Hydrator\Filter\FilterProviderInterface;
+use Zend\Stdlib\Hydrator\Filter\MethodMatchFilter;
+use Zend\Stdlib\Hydrator\Filter\GetFilter;
+use Zend\Stdlib\Hydrator\Filter\HasFilter;
+use Zend\Stdlib\Hydrator\Filter\IsFilter;
+use Zend\Stdlib\Hydrator\Filter\NumberOfParameterFilter;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
-class ClassMethods extends AbstractHydrator
+class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface
{
/**
* Flag defining whether array keys are underscore-separated (true) or camel case (false)
* @var bool
*/
- protected $underscoreSeparatedKeys;
+ protected $underscoreSeparatedKeys = true;
/**
* Define if extract values will use camel case or name with underscore
- * @param bool $underscoreSeparatedKeys
+ * @param bool|array $underscoreSeparatedKeys
*/
public function __construct($underscoreSeparatedKeys = true)
{
parent::__construct();
+ $this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys);
+
+ $this->filterComposite->addFilter("is", new IsFilter());
+ $this->filterComposite->addFilter("has", new HasFilter());
+ $this->filterComposite->addFilter("get", new GetFilter());
+ $this->filterComposite->addFilter("parameter", new NumberOfParameterFilter(), FilterComposite::CONDITION_AND);
+ }
+
+ /**
+ * @param array|\Traversable $options
+ * @return ClassMethods
+ * @throws Exception\InvalidArgumentException
+ */
+ public function setOptions($options)
+ {
+ if ($options instanceof Traversable) {
+ $options = ArrayUtils::iteratorToArray($options);
+ } elseif (!is_array($options)) {
+ throw new Exception\InvalidArgumentException(
+ 'The options parameter must be an array or a Traversable'
+ );
+ }
+ if (isset($options['underscoreSeparatedKeys'])) {
+ $this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param boolean $underscoreSeparatedKeys
+ * @return ClassMethods
+ */
+ public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys)
+ {
$this->underscoreSeparatedKeys = $underscoreSeparatedKeys;
+
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getUnderscoreSeparatedKeys()
+ {
+ return $this->underscoreSeparatedKeys;
}
/**
@@ -40,7 +89,7 @@ public function __construct($underscoreSeparatedKeys = true)
*
* Extracts the getter/setter of the given $object.
*
- * @param object $object
+ * @param object $object
* @return array
* @throws Exception\BadMethodCallException for a non-object $object
*/
@@ -52,15 +101,35 @@ public function extract($object)
));
}
+ $filter = null;
+ if ($object instanceof FilterProviderInterface) {
+ $filter = new FilterComposite(
+ array($object->getFilter()),
+ array(new MethodMatchFilter("getFilter"))
+ );
+ } else {
+ $filter = $this->filterComposite;
+ }
+
$transform = function ($letters) {
$letter = array_shift($letters);
+
return '_' . strtolower($letter);
};
$attributes = array();
$methods = get_class_methods($object);
foreach ($methods as $method) {
- if (!preg_match('/^(get|has|is)[A-Z]\w*/', $method)) {
+ if (
+ !$filter->filter(
+ get_class($object) . '::' . $method
+ )
+ ) {
+ continue;
+ }
+
+ $reflectionMethod = new ReflectionMethod(get_class($object) . '::' . $method);
+ if ($reflectionMethod->getNumberOfParameters() > 0) {
continue;
}
@@ -84,8 +153,8 @@ public function extract($object)
*
* Hydrates an object by getter/setter methods of the object.
*
- * @param array $data
- * @param object $object
+ * @param array $data
+ * @param object $object
* @return object
* @throws Exception\BadMethodCallException for a non-object $object
*/
@@ -99,6 +168,7 @@ public function hydrate(array $data, $object)
$transform = function ($letters) {
$letter = substr(array_shift($letters), 1, 1);
+
return ucfirst($letter);
};
@@ -113,6 +183,8 @@ public function hydrate(array $data, $object)
$object->$method($value);
}
}
+
return $object;
}
+
}
diff --git a/src/Hydrator/Filter/FilterComposite.php b/src/Hydrator/Filter/FilterComposite.php
new file mode 100644
index 000000000..1c8dc63ed
--- /dev/null
+++ b/src/Hydrator/Filter/FilterComposite.php
@@ -0,0 +1,198 @@
+orFilter = new ArrayObject($orFilter);
+ $this->andFilter = new ArrayObject($andFilter);
+ }
+
+ /**
+ * Add a filter to the composite. Has to be indexed with $name in
+ * order to identify a specific filter.
+ *
+ * This example will exclude all methods from the hydration, that starts with 'getService'
+ *
+ * $composite->addFilter('exclude',
+ * function($method) {
+ * if (preg_match('/^getService/', $method) {
+ * return false;
+ * }
+ * return true;
+ * }, FilterComposite::CONDITION_AND
+ * );
+ *
+ *
+ * @param string $name
+ * @param callable|FilterInterface $filter
+ * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND
+ * @throws InvalidArgumentException
+ * @return FilterComposite
+ */
+ public function addFilter($name, $filter, $condition = self::CONDITION_OR)
+ {
+ if ( !is_callable($filter) && !($filter instanceof FilterInterface) ) {
+ throw new InvalidArgumentException(
+ 'The value of ' . $name . ' should be either a callable or ' .
+ 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface'
+ );
+ }
+
+ if ($condition === self::CONDITION_OR) {
+ $this->orFilter[$name] = $filter;
+ } elseif ($condition === self::CONDITION_AND) {
+ $this->andFilter[$name] = $filter;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Remove a filter from the composition
+ *
+ * @param $name string Identifier for the filter
+ * @return FilterComposite
+ */
+ public function removeFilter($name)
+ {
+ if (isset($this->orFilter[$name])) {
+ unset($this->orFilter[$name]);
+ }
+
+ if (isset($this->andFilter[$name])) {
+ unset($this->andFilter[$name]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Check if $name has a filter registered
+ *
+ * @param $name string Identifier for the filter
+ * @return bool
+ */
+ public function hasFilter($name)
+ {
+ return isset($this->orFilter[$name]) || isset($this->andFilter[$name]);
+ }
+
+ /**
+ * Filter the composite based on the AND and OR condition
+ * Will return true if one from the "or conditions" and all from
+ * the "and condition" returns true. Otherwise false
+ *
+ * @param $property string Parameter will be e.g. Parent\Namespace\Class::method
+ * @return bool
+ */
+ public function filter($property)
+ {
+ $andCount = count($this->andFilter);
+ $orCount = count($this->orFilter);
+ // return true if no filters are registered
+ if ($orCount === 0 && $andCount === 0) {
+ return true;
+ } elseif ($orCount === 0 && $andCount !== 0) {
+ $returnValue = true;
+ } else {
+ $returnValue = false;
+ }
+
+ // Check if 1 from the or filters return true
+ foreach ($this->orFilter as $filter) {
+ if (is_callable($filter)) {
+ if ( $filter($property) === true) {
+ $returnValue = true;
+ break;
+ }
+ continue;
+ } else {
+ if ( $filter->filter($property) === true) {
+ $returnValue = true;
+ break;
+ }
+ }
+ }
+
+ // Check if all of the and condition return true
+ foreach ($this->andFilter as $filter) {
+ if (is_callable($filter)) {
+ if ($filter($property) === false) {
+ return false;
+ }
+ continue;
+ } else {
+ if ($filter->filter($property) === false) {
+ return false;
+ }
+ }
+ }
+
+ return $returnValue;
+ }
+}
diff --git a/src/Hydrator/Filter/FilterInterface.php b/src/Hydrator/Filter/FilterInterface.php
new file mode 100644
index 000000000..56cb4ecf6
--- /dev/null
+++ b/src/Hydrator/Filter/FilterInterface.php
@@ -0,0 +1,21 @@
+method = $method;
+ $this->exclude = $exclude;
+ }
+
+ public function filter($property)
+ {
+ $pos = strpos($property, '::');
+ if ($pos !== false) {
+ $pos += 2;
+ } else {
+ $pos = 0;
+ }
+ if (substr($property, $pos) === $this->method) {
+ return $this->exclude ? false : true;
+ }
+ return $this->exclude ? true : false;
+ }
+}
diff --git a/src/Hydrator/Filter/NumberOfParameterFilter.php b/src/Hydrator/Filter/NumberOfParameterFilter.php
new file mode 100644
index 000000000..df6e123f4
--- /dev/null
+++ b/src/Hydrator/Filter/NumberOfParameterFilter.php
@@ -0,0 +1,53 @@
+numberOfParameters = 0;
+ }
+
+ /**
+ * @param string $property the name of the property
+ * @throws InvalidArgumentException
+ */
+ public function filter($property)
+ {
+ try {
+ $reflectionMethod = new ReflectionMethod($property);
+ } catch( ReflectionException $exception) {
+ throw new InvalidArgumentException(
+ "Method $property doesn't exist"
+ );
+ }
+
+ if ($reflectionMethod->getNumberOfParameters() !== $this->numberOfParameters) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/Hydrator/HydratorInterface.php b/src/Hydrator/HydratorInterface.php
index 0fb1c965b..c6b3e89e2 100644
--- a/src/Hydrator/HydratorInterface.php
+++ b/src/Hydrator/HydratorInterface.php
@@ -5,16 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
interface HydratorInterface
{
/**
diff --git a/src/Hydrator/HydratorOptionsInterface.php b/src/Hydrator/HydratorOptionsInterface.php
new file mode 100644
index 000000000..deda37155
--- /dev/null
+++ b/src/Hydrator/HydratorOptionsInterface.php
@@ -0,0 +1,19 @@
+extractValue($name, $value);
+ array_walk($data, function (&$value, $name) use ($self, &$data) {
+ if (!$self->getFilter()->filter($name)) {
+ unset($data[$name]);
+ } else {
+ $value = $self->extractValue($name, $value);
+ }
});
return $data;
}
diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php
index b372665d1..6fe230204 100644
--- a/src/Hydrator/Reflection.php
+++ b/src/Hydrator/Reflection.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator;
@@ -13,11 +12,6 @@
use ReflectionClass;
use Zend\Stdlib\Exception;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
class Reflection extends AbstractHydrator
{
/**
@@ -37,6 +31,9 @@ public function extract($object)
$result = array();
foreach (self::getReflProperties($object) as $property) {
$propertyName = $property->getName();
+ if (!$this->filterComposite->filter($propertyName)) {
+ continue;
+ }
$value = $property->getValue($object);
$result[$propertyName] = $this->extractValue($propertyName, $value);
diff --git a/src/Hydrator/Strategy/ClosureStrategy.php b/src/Hydrator/Strategy/ClosureStrategy.php
new file mode 100644
index 000000000..1367b5c06
--- /dev/null
+++ b/src/Hydrator/Strategy/ClosureStrategy.php
@@ -0,0 +1,100 @@
+addStrategy('category', new ClosureStrategy(
+ * function(Category $value) {
+ * return (int)$value->id;
+ * },
+ * function($value) {
+ * return new Category((int)$value);
+ * }
+ * ));
+ *
+ * @param callable $extractFunc - anonymous function, that extract values
+ * from object
+ * @param callable $hydrateFunc - anonymous function, that hydrate values
+ * into object
+ */
+ public function __construct($extractFunc = null, $hydrateFunc = null)
+ {
+ if (isset($extractFunc)) {
+ if (!is_callable($extractFunc)) {
+ throw new \Exception('$extractFunc must be callable');
+ }
+
+ $this->extractFunc = $extractFunc;
+ } else {
+ $this->extractFunc = function($value) {
+ return $value;
+ };
+ }
+
+ if (isset($hydrateFunc)) {
+ if (!is_callable($hydrateFunc)) {
+ throw new \Exception('$hydrateFunc must be callable');
+ }
+
+ $this->hydrateFunc = $hydrateFunc;
+ } else {
+ $this->hydrateFunc = function($value) {
+ return $value;
+ };
+ }
+ }
+
+ /**
+ * Converts the given value so that it can be extracted by the hydrator.
+ *
+ * @param mixed $value The original value.
+ * @return mixed Returns the value that should be extracted.
+ */
+ public function extract($value)
+ {
+ $func = $this->extractFunc;
+
+ return $func($value);
+ }
+
+ /**
+ * Converts the given value so that it can be hydrated by the hydrator.
+ *
+ * @param mixed $value The original value.
+ * @return mixed Returns the value that should be hydrated.
+ */
+ public function hydrate($value)
+ {
+ $func = $this->hydrateFunc;
+
+ return $func($value);
+ }
+}
diff --git a/src/Hydrator/Strategy/DefaultStrategy.php b/src/Hydrator/Strategy/DefaultStrategy.php
index 1bd92f624..d98f1f4c7 100644
--- a/src/Hydrator/Strategy/DefaultStrategy.php
+++ b/src/Hydrator/Strategy/DefaultStrategy.php
@@ -5,16 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator\Strategy;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
class DefaultStrategy implements StrategyInterface
{
/**
diff --git a/src/Hydrator/Strategy/SerializableStrategy.php b/src/Hydrator/Strategy/SerializableStrategy.php
new file mode 100644
index 000000000..f286a8611
--- /dev/null
+++ b/src/Hydrator/Strategy/SerializableStrategy.php
@@ -0,0 +1,122 @@
+setSerializer($serializer);
+ if($serializerOptions) {
+ $this->setSerializerOptions($serializerOptions);
+ }
+ }
+
+ /**
+ * Serialize the given value so that it can be extracted by the hydrator.
+ *
+ * @param mixed $value The original value.
+ * @return mixed Returns the value that should be extracted.
+ */
+ public function extract($value)
+ {
+ $serializer = $this->getSerializer();
+ return $serializer->serialize($value);
+ }
+
+ /**
+ * Unserialize the given value so that it can be hydrated by the hydrator.
+ *
+ * @param mixed $value The original value.
+ * @return mixed Returns the value that should be hydrated.
+ */
+ public function hydrate($value)
+ {
+ $serializer = $this->getSerializer();
+ return $serializer->unserialize($value);
+ }
+
+ /**
+ * Set serializer
+ *
+ * @param string|SerializerAdapter $serializer
+ * @return Serializer
+ */
+ public function setSerializer($serializer)
+ {
+ if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) {
+ throw new InvalidArgumentException(sprintf(
+ '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; '
+ . 'received "%s"',
+ __METHOD__,
+ (is_object($serializer) ? get_class($serializer) : gettype($serializer))
+ ));
+ }
+ $this->serializer = $serializer;
+ return $this;
+ }
+
+ /**
+ * Get serializer
+ *
+ * @return SerializerAdapter
+ */
+ public function getSerializer()
+ {
+ if (is_string($this->serializer)) {
+ $options = $this->getSerializerOptions();
+ $this->setSerializer(SerializerFactory::factory($this->serializer, $options));
+ } elseif (null === $this->serializer) {
+ $this->setSerializer(SerializerFactory::getDefaultAdapter());
+ }
+
+ return $this->serializer;
+ }
+
+ /**
+ * Set configuration options for instantiating a serializer adapter
+ *
+ * @param mixed $serializerOptions
+ * @return SerializableStrategy
+ */
+ public function setSerializerOptions($serializerOptions)
+ {
+ $this->serializerOptions = $serializerOptions;
+ return $this;
+ }
+
+ /**
+ * Get configuration options for instantiating a serializer adapter
+ *
+ * @return mixed
+ */
+ public function getSerializerOptions()
+ {
+ return $this->serializerOptions;
+ }
+}
diff --git a/src/Hydrator/Strategy/StrategyInterface.php b/src/Hydrator/Strategy/StrategyInterface.php
index 83a27549d..85c21cc3f 100644
--- a/src/Hydrator/Strategy/StrategyInterface.php
+++ b/src/Hydrator/Strategy/StrategyInterface.php
@@ -5,16 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator\Strategy;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
interface StrategyInterface
{
/**
diff --git a/src/Hydrator/StrategyEnabledInterface.php b/src/Hydrator/StrategyEnabledInterface.php
index 721f58e7c..5cbb5580a 100644
--- a/src/Hydrator/StrategyEnabledInterface.php
+++ b/src/Hydrator/StrategyEnabledInterface.php
@@ -5,18 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib\Hydrator;
use Zend\Stdlib\Hydrator\Strategy\StrategyInterface;
-/**
- * @category Zend
- * @package Zend_Stdlib
- * @subpackage Hydrator
- */
interface StrategyEnabledInterface
{
/**
diff --git a/src/InitializableInterface.php b/src/InitializableInterface.php
new file mode 100644
index 000000000..b0bd2605f
--- /dev/null
+++ b/src/InitializableInterface.php
@@ -0,0 +1,23 @@
+getContent();
return $request;
}
-
}
diff --git a/src/MessageInterface.php b/src/MessageInterface.php
index e5b735ab4..0abb1ff6b 100644
--- a/src/MessageInterface.php
+++ b/src/MessageInterface.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
interface MessageInterface
{
/**
diff --git a/src/ParameterObjectInterface.php b/src/ParameterObjectInterface.php
index ca724a464..416b8c298 100644
--- a/src/ParameterObjectInterface.php
+++ b/src/ParameterObjectInterface.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
interface ParameterObjectInterface
{
/**
diff --git a/src/Parameters.php b/src/Parameters.php
index 895ca051e..421f49649 100644
--- a/src/Parameters.php
+++ b/src/Parameters.php
@@ -5,17 +5,12 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
use ArrayObject;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
class Parameters extends ArrayObject implements ParametersInterface
{
/**
diff --git a/src/ParametersInterface.php b/src/ParametersInterface.php
index fb70410ca..e955b2ac7 100644
--- a/src/ParametersInterface.php
+++ b/src/ParametersInterface.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -19,9 +18,6 @@
* Basically, an ArrayObject. You could simply define something like:
* class QueryParams extends ArrayObject implements Parameters {}
* and have 90% of the functionality
- *
- * @category Zend
- * @package Zend_Stdlib
*/
interface ParametersInterface extends ArrayAccess, Countable, Serializable, Traversable
{
diff --git a/src/PriorityQueue.php b/src/PriorityQueue.php
index cf4ebef66..5c0c13db9 100644
--- a/src/PriorityQueue.php
+++ b/src/PriorityQueue.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -25,9 +24,6 @@
* This class aggregates items for the queue itself, but also composes an
* "inner" iterator in the form of an SplPriorityQueue object for performing
* the actual iteration.
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class PriorityQueue implements Countable, IteratorAggregate, Serializable
{
diff --git a/src/Request.php b/src/Request.php
index 60c3752fa..8427bc08f 100644
--- a/src/Request.php
+++ b/src/Request.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
class Request extends Message implements RequestInterface
{
// generic request implementation
diff --git a/src/RequestInterface.php b/src/RequestInterface.php
index b858d6dd0..4a2252de4 100644
--- a/src/RequestInterface.php
+++ b/src/RequestInterface.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
interface RequestInterface extends MessageInterface
{
}
diff --git a/src/Response.php b/src/Response.php
index 035155ea5..1c2ea76b1 100644
--- a/src/Response.php
+++ b/src/Response.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
class Response extends Message implements ResponseInterface
{
// generic response implementation
diff --git a/src/ResponseInterface.php b/src/ResponseInterface.php
index ea6b88b48..cf5d0edd4 100644
--- a/src/ResponseInterface.php
+++ b/src/ResponseInterface.php
@@ -5,15 +5,10 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
-/**
- * @category Zend
- * @package Zend_Stdlib
- */
interface ResponseInterface extends MessageInterface
{
diff --git a/src/SplPriorityQueue.php b/src/SplPriorityQueue.php
index 20ced9cb2..5baa967ff 100644
--- a/src/SplPriorityQueue.php
+++ b/src/SplPriorityQueue.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -17,9 +16,6 @@
*
* Also, provides predictable heap order for datums added with the same priority
* (i.e., they will be emitted in the same order they are enqueued).
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class SplPriorityQueue extends \SplPriorityQueue implements Serializable
{
diff --git a/src/SplQueue.php b/src/SplQueue.php
index 1291e5f26..e18ebc682 100644
--- a/src/SplQueue.php
+++ b/src/SplQueue.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -14,9 +13,6 @@
/**
* Serializable version of SplQueue
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class SplQueue extends \SplQueue implements Serializable
{
diff --git a/src/SplStack.php b/src/SplStack.php
index e739cebfd..3bb8f6796 100644
--- a/src/SplStack.php
+++ b/src/SplStack.php
@@ -5,7 +5,6 @@
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_Stdlib
*/
namespace Zend\Stdlib;
@@ -14,9 +13,6 @@
/**
* Serializable version of SplStack
- *
- * @category Zend
- * @package Zend_Stdlib
*/
class SplStack extends \SplStack implements Serializable
{
diff --git a/src/StringUtils.php b/src/StringUtils.php
new file mode 100644
index 000000000..ce463131f
--- /dev/null
+++ b/src/StringUtils.php
@@ -0,0 +1,189 @@
+setEncoding($encoding, $convertEncoding);
+ return $wrapper;
+ }
+ }
+
+ throw new Exception\RuntimeException(
+ 'No wrapper found supporting "' . $encoding . '"'
+ . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '')
+ );
+ }
+
+ /**
+ * Get a list of all known single-byte character encodings
+ *
+ * @return string[]
+ */
+ public static function getSingleByteEncodings()
+ {
+ return static::$singleByteEncodings;
+ }
+
+ /**
+ * Check if a given encoding is a known single-byte character encoding
+ *
+ * @param string $encoding
+ * @return boolean
+ */
+ public static function isSingleByteEncoding($encoding)
+ {
+ return in_array(strtoupper($encoding), static::$singleByteEncodings);
+ }
+
+ /**
+ * Check if a given string is valid UTF-8 encoded
+ *
+ * @param string $str
+ * @return boolean
+ */
+ public static function isValidUtf8($str)
+ {
+ return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1);
+ }
+
+ /**
+ * Is PCRE compiled with Unicode support?
+ *
+ * @return bool
+ */
+ public static function hasPcreUnicodeSupport()
+ {
+ if (static::$hasPcreUnicodeSupport === null) {
+ ErrorHandler::start();
+ static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1;
+ ErrorHandler::stop();
+ }
+ return static::$hasPcreUnicodeSupport;
+ }
+}
diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php
new file mode 100644
index 000000000..948b77513
--- /dev/null
+++ b/src/StringWrapper/AbstractStringWrapper.php
@@ -0,0 +1,271 @@
+convertEncoding = $convertEncodingUpper;
+ } else {
+ $this->convertEncoding = null;
+ }
+ $this->encoding = $encodingUpper;
+
+ return $this;
+ }
+
+ /**
+ * Get the defined character encoding to work with
+ *
+ * @return string
+ * @throws Exception\LogicException If no encoding was defined
+ */
+ public function getEncoding()
+ {
+ return $this->encoding;
+ }
+
+ /**
+ * Get the defined character encoding to convert to
+ *
+ * @return string|null
+ */
+ public function getConvertEncoding()
+ {
+ return $this->convertEncoding;
+ }
+
+ /**
+ * Convert a string from defined character encoding to the defined convert encoding
+ *
+ * @param string $str
+ * @param boolean $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false)
+ {
+ $encoding = $this->getEncoding();
+ $convertEncoding = $this->getConvertEncoding();
+ if ($convertEncoding === null) {
+ throw new Exception\LogicException(
+ 'No convert encoding defined'
+ );
+ }
+
+ if ($encoding === $convertEncoding) {
+ return $str;
+ }
+
+ $from = $reverse ? $convertEncoding : $encoding;
+ $to = $reverse ? $encoding : $convertEncoding;
+ throw new Exception\RuntimeException(sprintf(
+ 'Converting from "%s" to "%s" isn\'t supported by this string wrapper',
+ $from,
+ $to
+ ));
+ }
+
+ /**
+ * Wraps a string to a given number of characters
+ *
+ * @param string $str
+ * @param integer $width
+ * @param string $break
+ * @param boolean $cut
+ * @return string|false
+ */
+ public function wordWrap($string, $width = 75, $break = "\n", $cut = false)
+ {
+ $string = (string) $string;
+ if ($string === '') {
+ return '';
+ }
+
+ $break = (string) $break;
+ if ($break === '') {
+ throw new Exception\InvalidArgumentException('Break string cannot be empty');
+ }
+
+ $width = (int) $width;
+ if ($width === 0 && $cut) {
+ throw new Exception\InvalidArgumentException('Cannot force cut when width is zero');
+ }
+
+ if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
+ return wordwrap($string, $width, $break, $cut);
+ }
+
+ $stringWidth = $this->strlen($string);
+ $breakWidth = $this->strlen($break);
+
+ $result = '';
+ $lastStart = $lastSpace = 0;
+
+ for ($current = 0; $current < $stringWidth; $current++) {
+ $char = $this->substr($string, $current, 1);
+
+ $possibleBreak = $char;
+ if ($breakWidth !== 1) {
+ $possibleBreak = $this->substr($string, $current, $breakWidth);
+ }
+
+ if ($possibleBreak === $break) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth);
+ $current += $breakWidth - 1;
+ $lastStart = $lastSpace = $current + 1;
+ continue;
+ }
+
+ if ($char === ' ') {
+ if ($current - $lastStart >= $width) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
+ $lastStart = $current + 1;
+ }
+
+ $lastSpace = $current;
+ continue;
+ }
+
+ if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
+ $lastStart = $lastSpace = $current;
+ continue;
+ }
+
+ if ($current - $lastStart >= $width && $lastStart < $lastSpace) {
+ $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break;
+ $lastStart = $lastSpace = $lastSpace + 1;
+ continue;
+ }
+ }
+
+ if ($lastStart !== $current) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Pad a string to a certain length with another string
+ *
+ * @param string $input
+ * @param integer $padLength
+ * @param string $padString
+ * @param integer $padType
+ * @return string
+ */
+ public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT)
+ {
+ if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
+ return str_pad($input, $padLength, $padString, $padType);
+ }
+
+ $lengthOfPadding = $padLength - $this->strlen($input);
+ if ($lengthOfPadding <= 0) {
+ return $input;
+ }
+
+ $padStringLength = $this->strlen($padString);
+ if ($padStringLength === 0) {
+ return $input;
+ }
+
+ $repeatCount = floor($lengthOfPadding / $padStringLength);
+
+ if ($padType === STR_PAD_BOTH) {
+ $lastStringLeft = '';
+ $lastStringRight = '';
+ $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2;
+
+ $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength;
+ $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2);
+ $lastStringRightLength += $lastStringLength % 2;
+
+ $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength);
+ $lastStringRight = $this->substr($padString, 0, $lastStringRightLength);
+
+ return str_repeat($padString, $repeatCountLeft) . $lastStringLeft
+ . $input
+ . str_repeat($padString, $repeatCountRight) . $lastStringRight;
+ }
+
+ $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength);
+
+ if ($padType === STR_PAD_LEFT) {
+ return str_repeat($padString, $repeatCount) . $lastString . $input;
+ }
+
+ return $input . str_repeat($padString, $repeatCount) . $lastString;
+ }
+}
diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php
new file mode 100644
index 000000000..f3f2c6187
--- /dev/null
+++ b/src/StringWrapper/Iconv.php
@@ -0,0 +1,292 @@
+getEncoding());
+ }
+
+ /**
+ * Returns the portion of string specified by the start and length parameters
+ *
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @param string $encoding
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ return iconv_substr($str, $offset, $length, $this->getEncoding());
+ }
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @param string $encoding
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return iconv_strpos($haystack, $needle, $offset, $this->getEncoding());
+ }
+
+ /**
+ * Convert a string from defined encoding to the defined convert encoding
+ *
+ * @param string $str
+ * @param boolean $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false)
+ {
+ $encoding = $this->getEncoding();
+ $convertEncoding = $this->getConvertEncoding();
+ if ($convertEncoding === null) {
+ throw new Exception\LogicException(
+ 'No convert encoding defined'
+ );
+ }
+
+ if ($encoding === $convertEncoding) {
+ return $str;
+ }
+
+ $fromEncoding = $reverse ? $convertEncoding : $encoding;
+ $toEncoding = $reverse ? $encoding : $convertEncoding;
+
+ // automatically add "//IGNORE" to not stop converting on invalid characters
+ // invalid characters triggers a notice anyway
+ return iconv($fromEncoding, $toEncoding . '//IGNORE', $str);
+ }
+}
diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php
new file mode 100644
index 000000000..536cb4363
--- /dev/null
+++ b/src/StringWrapper/Intl.php
@@ -0,0 +1,86 @@
+getEncoding());
+ }
+
+ /**
+ * Returns the portion of string specified by the start and length parameters
+ *
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @param string $encoding
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ return mb_substr($str, $offset, $length, $this->getEncoding());
+ }
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @param string $encoding
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return mb_strpos($haystack, $needle, $offset, $this->getEncoding());
+ }
+
+ /**
+ * Convert a string from defined encoding to the defined convert encoding
+ *
+ * @param string $str
+ * @param boolean $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false)
+ {
+ $encoding = $this->getEncoding();
+ $convertEncoding = $this->getConvertEncoding();
+
+ if ($convertEncoding === null) {
+ throw new Exception\LogicException(
+ 'No convert encoding defined'
+ );
+ }
+
+ if ($encoding === $convertEncoding) {
+ return $str;
+ }
+
+ $fromEncoding = $reverse ? $convertEncoding : $encoding;
+ $toEncoding = $reverse ? $encoding : $convertEncoding;
+ return mb_convert_encoding($str, $toEncoding, $fromEncoding);
+ }
+}
diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php
new file mode 100644
index 000000000..505109880
--- /dev/null
+++ b/src/StringWrapper/Native.php
@@ -0,0 +1,133 @@
+convertEncoding = $encodingUpper;
+ }
+
+ if ($convertEncoding !== null) {
+ if ($encodingUpper !== strtoupper($convertEncoding)) {
+ throw new Exception\InvalidArgumentException(
+ 'Wrapper doesn\'t support to convert between character encodings'
+ );
+ }
+
+ $this->convertEncoding = $encodingUpper;
+ } else {
+ $this->convertEncoding = null;
+ }
+ $this->encoding = $encodingUpper;
+
+ return $this;
+ }
+
+ /**
+ * Returns the length of the given string
+ *
+ * @param string $str
+ * @return int|false
+ */
+ public function strlen($str)
+ {
+ return strlen($str);
+ }
+
+ /**
+ * Returns the portion of string specified by the start and length parameters
+ *
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ return substr($str, $offset, $length);
+ }
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return strpos($haystack, $needle, $offset);
+ }
+}
diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php
new file mode 100644
index 000000000..dfe1550ae
--- /dev/null
+++ b/src/StringWrapper/StringWrapperInterface.php
@@ -0,0 +1,113 @@
+assertFalse(ErrorHandler::started());
+ $this->assertSame(0, ErrorHandler::getNestedLevel());
ErrorHandler::start();
- $this->assertTrue(ErrorHandler::started());
+ $this->assertSame(1, ErrorHandler::getNestedLevel());
+
+ ErrorHandler::start();
+ $this->assertSame(2, ErrorHandler::getNestedLevel());
ErrorHandler::stop();
- $this->assertFalse(ErrorHandler::started());
+ $this->assertSame(1, ErrorHandler::getNestedLevel());
+
+ ErrorHandler::stop();
+ $this->assertSame(0, ErrorHandler::getNestedLevel());
}
- public function testStartThrowsLogicException()
+ public function testClean()
{
ErrorHandler::start();
+ $this->assertSame(1, ErrorHandler::getNestedLevel());
- $this->setExpectedException('Zend\Stdlib\Exception\LogicException');
ErrorHandler::start();
+ $this->assertSame(2, ErrorHandler::getNestedLevel());
+
+ ErrorHandler::clean();
+ $this->assertSame(0, ErrorHandler::getNestedLevel());
}
- public function testStopThrowsLogicException()
+ public function testStarted()
{
- $this->setExpectedException('Zend\Stdlib\Exception\LogicException');
+ $this->assertFalse(ErrorHandler::started());
+
+ ErrorHandler::start();
+ $this->assertTrue(ErrorHandler::started());
+
ErrorHandler::stop();
+ $this->assertFalse(ErrorHandler::started());
}
public function testReturnCatchedError()
@@ -65,7 +80,7 @@ public function testThrowCatchedError()
ErrorHandler::stop(true);
}
- public function testAddErrors()
+ public function testAddError()
{
ErrorHandler::start();
ErrorHandler::addError(1, 'test-msg1', 'test-file1', 100);
diff --git a/test/FilterTest.php b/test/FilterTest.php
new file mode 100644
index 000000000..481b6481c
--- /dev/null
+++ b/test/FilterTest.php
@@ -0,0 +1,55 @@
+assertTrue($hasValidation->filter('hasFoo'));
+ $this->assertTrue($hasValidation->filter('Foo::hasFoo'));
+ $this->assertFalse($hasValidation->filter('FoohasFoo'));
+ $this->assertFalse($hasValidation->filter('Bar::FoohasFoo'));
+ $this->assertFalse($hasValidation->filter('hAsFoo'));
+ $this->assertFalse($hasValidation->filter('Blubb::hAsFoo'));
+ $this->assertFalse($hasValidation->filter(get_class($this). '::hAsFoo'));
+ }
+
+ public function testGetValidation()
+ {
+ $hasValidation = new GetFilter();
+ $this->assertTrue($hasValidation->filter('getFoo'));
+ $this->assertTrue($hasValidation->filter('Bar::getFoo'));
+ $this->assertFalse($hasValidation->filter('GetFooBar'));
+ $this->assertFalse($hasValidation->filter('Foo::GetFooBar'));
+ $this->assertFalse($hasValidation->filter('GETFoo'));
+ $this->assertFalse($hasValidation->filter('Blubb::GETFoo'));
+ $this->assertFalse($hasValidation->filter(get_class($this).'::GETFoo'));
+ }
+
+ public function testIsValidation()
+ {
+ $hasValidation = new IsFilter();
+ $this->assertTrue($hasValidation->filter('isFoo'));
+ $this->assertTrue($hasValidation->filter('Blubb::isFoo'));
+ $this->assertFalse($hasValidation->filter('IsFooBar'));
+ $this->assertFalse($hasValidation->filter('Foo::IsFooBar'));
+ $this->assertFalse($hasValidation->filter('ISFoo'));
+ $this->assertFalse($hasValidation->filter('Bar::ISFoo'));
+ $this->assertFalse($hasValidation->filter(get_class($this).'::ISFoo'));
+ }
+
+}
diff --git a/test/HydratorClosureStrategyTest.php b/test/HydratorClosureStrategyTest.php
new file mode 100644
index 000000000..ae4d227ef
--- /dev/null
+++ b/test/HydratorClosureStrategyTest.php
@@ -0,0 +1,126 @@
+hydrator = new ObjectProperty();
+ }
+
+ public function testAddingStrategy()
+ {
+ $this->assertAttributeCount(0, 'strategies', $this->hydrator);
+
+ $this->hydrator->addStrategy('myStrategy', new ClosureStrategy());
+
+ $this->assertAttributeCount(1, 'strategies', $this->hydrator);
+ }
+
+ public function testCheckStrategyEmpty()
+ {
+ $this->assertFalse($this->hydrator->hasStrategy('myStrategy'));
+ }
+
+ public function testCheckStrategyNotEmpty()
+ {
+ $this->hydrator->addStrategy('myStrategy', new ClosureStrategy());
+
+ $this->assertTrue($this->hydrator->hasStrategy('myStrategy'));
+ }
+
+ public function testRemovingStrategy()
+ {
+ $this->assertAttributeCount(0, 'strategies', $this->hydrator);
+
+ $this->hydrator->addStrategy('myStrategy', new ClosureStrategy());
+ $this->assertAttributeCount(1, 'strategies', $this->hydrator);
+
+ $this->hydrator->removeStrategy('myStrategy');
+ $this->assertAttributeCount(0, 'strategies', $this->hydrator);
+ }
+
+ public function testRetrieveStrategy()
+ {
+ $strategy = new ClosureStrategy();
+ $this->hydrator->addStrategy('myStrategy', $strategy);
+
+ $this->assertEquals($strategy, $this->hydrator->getStrategy('myStrategy'));
+ }
+
+ public function testExtractingObjects()
+ {
+ $this->hydrator->addStrategy('field1', new ClosureStrategy(
+ function($value) {
+ return sprintf('%s', $value);
+ },
+ null
+ ));
+ $this->hydrator->addStrategy('field2', new ClosureStrategy(
+ function($value) {
+ return sprintf('hello, %s!', $value);
+ },
+ null
+ ));
+
+ $entity = new TestAsset\HydratorClosureStrategyEntity(111, 'world');
+ $values = $this->hydrator->extract($entity);
+
+ $this->assertEquals(111, $values['field1']);
+ $this->assertEquals('hello, world!', $values['field2']);
+ }
+
+ public function testHydratingObjects()
+ {
+ $this->hydrator->addStrategy('field2', new ClosureStrategy(
+ null,
+ function($value) {
+ return sprintf('hello, %s!', $value);
+ }
+ ));
+ $this->hydrator->addStrategy('field3', new ClosureStrategy(
+ null,
+ function($value) {
+ return new TestAsset\HydratorClosureStrategyEntity($value, sprintf('111%s', $value));
+ }
+ ));
+
+ $entity = new TestAsset\HydratorClosureStrategyEntity(111, 'world');
+
+ $values = $this->hydrator->extract($entity);
+ $values['field3'] = 333;
+
+ $this->assertCount(2, (array)$entity);
+ $this->hydrator->hydrate($values, $entity);
+ $this->assertCount(3, (array)$entity);
+
+ $this->assertInstanceOf('ZendTest\Stdlib\TestAsset\HydratorClosureStrategyEntity', $entity->field3);
+ }
+
+}
diff --git a/test/HydratorTest.php b/test/HydratorTest.php
index 02377a130..1c6938185 100644
--- a/test/HydratorTest.php
+++ b/test/HydratorTest.php
@@ -12,10 +12,21 @@
use Zend\Stdlib\Hydrator\ClassMethods;
use Zend\Stdlib\Hydrator\Reflection;
+use Zend\Stdlib\Hydrator\ObjectProperty;
+use Zend\Stdlib\Hydrator\ArraySerializable;
+use Zend\Stdlib\Hydrator\Filter\FilterComposite;
use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCase;
+use ZendTest\Stdlib\TestAsset\ClassMethodsFilterProviderInterface;
use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore;
use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing;
+use ZendTest\Stdlib\TestAsset\ClassMethodsInvalidParameter;
use ZendTest\Stdlib\TestAsset\Reflection as ReflectionAsset;
+use ZendTest\Stdlib\TestAsset\ReflectionFilter;
+use ZendTest\Stdlib\TestAsset\ObjectProperty as ObjectPropertyAsset;
+use ZendTest\Stdlib\TestAsset\ArraySerializable as ArraySerializableAsset;
+use Zend\Stdlib\Hydrator\Strategy\DefaultStrategy;
+use Zend\Stdlib\Hydrator\Strategy\SerializableStrategy;
+
/**
* @category Zend
@@ -41,6 +52,11 @@ class HydratorTest extends \PHPUnit_Framework_TestCase
*/
protected $classMethodsUnderscore;
+ /**
+ * @var ClassMethodsInvalidParameter
+ */
+ protected $classMethodsInvalidParameter;
+
/**
* @var ReflectionAsset
*/
@@ -51,7 +67,9 @@ public function setUp()
$this->classMethodsCamelCase = new ClassMethodsCamelCase();
$this->classMethodsCamelCaseMissing = new ClassMethodsCamelCaseMissing();
$this->classMethodsUnderscore = new ClassMethodsUnderscore();
+ $this->classMethodsInvalidParameter = new ClassMethodsInvalidParameter();
$this->reflection = new ReflectionAsset;
+ $this->classMethodsInvalidParameter = new ClassMethodsInvalidParameter();
}
public function testInitiateValues()
@@ -163,6 +181,16 @@ public function testHydratorClassMethodsUnderscore()
$this->assertEquals($test->hasBar(), false);
}
+ public function testHydratorClassMethodsOptions()
+ {
+ $hydrator = new ClassMethods();
+ $this->assertTrue($hydrator->getUnderscoreSeparatedKeys());
+ $hydrator->setOptions(array('underscoreSeparatedKeys' => false));
+ $this->assertFalse($hydrator->getUnderscoreSeparatedKeys());
+ $hydrator->setUnderscoreSeparatedKeys(true);
+ $this->assertTrue($hydrator->getUnderscoreSeparatedKeys());
+ }
+
public function testHydratorClassMethodsIgnoresInvalidValues()
{
$hydrator = new ClassMethods(true);
@@ -189,6 +217,39 @@ public function testHydratorClassMethodsDefaultBehaviorIsConvertUnderscoreToCame
$this->assertEquals($test->getFooBarBaz(), 'bar');
}
+ public function testRetrieveWildStrategyAndOther()
+ {
+ $hydrator = new ClassMethods();
+ $hydrator->addStrategy('default', new DefaultStrategy());
+ $hydrator->addStrategy('*', new SerializableStrategy('phpserialize'));
+ $default = $hydrator->getStrategy('default');
+ $this->assertEquals(get_class($default), 'Zend\Stdlib\Hydrator\Strategy\DefaultStrategy');
+ $serializable = $hydrator->getStrategy('*');
+ $this->assertEquals(get_class($serializable), 'Zend\Stdlib\Hydrator\Strategy\SerializableStrategy');
+ }
+
+ public function testUseWildStrategyByDefault()
+ {
+ $hydrator = new ClassMethods();
+ $datas = $hydrator->extract($this->classMethodsUnderscore);
+ $this->assertEquals($datas['foo_bar'], '1');
+ $hydrator->addStrategy('*', new SerializableStrategy('phpserialize'));
+ $datas = $hydrator->extract($this->classMethodsUnderscore);
+ $this->assertEquals($datas['foo_bar'], 's:1:"1";');
+ }
+
+ public function testUseWildStrategyAndOther()
+ {
+ $hydrator = new ClassMethods();
+ $datas = $hydrator->extract($this->classMethodsUnderscore);
+ $this->assertEquals($datas['foo_bar'], '1');
+ $hydrator->addStrategy('foo_bar', new DefaultStrategy());
+ $hydrator->addStrategy('*', new SerializableStrategy('phpserialize'));
+ $datas = $hydrator->extract($this->classMethodsUnderscore);
+ $this->assertEquals($datas['foo_bar'], '1');
+ $this->assertEquals($datas['foo_bar_baz'], 's:1:"2";');
+ }
+
public function testHydratorClassMethodsCamelCaseWithSetterMissing()
{
$hydrator = new ClassMethods(false);
@@ -203,4 +264,137 @@ public function testHydratorClassMethodsCamelCaseWithSetterMissing()
$this->assertEquals($test->getFooBar(), 'foo');
$this->assertEquals($test->getFooBarBaz(), '2');
}
+
+ public function testHydratorClassMethodsManipulateFilter()
+ {
+ $hydrator = new ClassMethods(false);
+ $datas = $hydrator->extract($this->classMethodsCamelCase);
+
+ $this->assertTrue(isset($datas['fooBar']));
+ $this->assertEquals($datas['fooBar'], '1');
+ $this->assertTrue(isset($datas['fooBarBaz']));
+ $this->assertFalse(isset($datas['foo_bar']));
+ $this->assertTrue(isset($datas['isFoo']));
+ $this->assertEquals($datas['isFoo'], true);
+ $this->assertTrue(isset($datas['isBar']));
+ $this->assertEquals($datas['isBar'], true);
+ $this->assertTrue(isset($datas['hasFoo']));
+ $this->assertEquals($datas['hasFoo'], true);
+ $this->assertTrue(isset($datas['hasBar']));
+ $this->assertEquals($datas['hasBar'], true);
+
+ $hydrator->removeFilter('has');
+ $datas = $hydrator->extract($this->classMethodsCamelCase);
+ $this->assertTrue(isset($datas['hasFoo'])); //method is getHasFoo
+ $this->assertFalse(isset($datas['hasBar'])); //method is hasBar
+ }
+
+ public function testHydratorClassMethodsWithCustomFilter()
+ {
+ $hydrator = new ClassMethods(false);
+ $datas = $hydrator->extract($this->classMethodsCamelCase);
+ $hydrator->addFilter("exclude",
+ function($property) {
+ list($class, $method) = explode('::', $property);
+
+ if($method == 'getHasFoo') {
+ return false;
+ }
+
+ return true;
+ }, FilterComposite::CONDITION_AND
+ );
+
+ $datas = $hydrator->extract($this->classMethodsCamelCase);
+ $this->assertFalse(isset($datas['hasFoo']));
+ }
+
+ /**
+ * @dataProvider filterProvider
+ */
+ public function testArraySerializableFilter($hydrator, $serializable)
+ {
+ $this->assertSame(
+ array(
+ "foo" => "bar",
+ "bar" => "foo",
+ "blubb" => "baz",
+ "quo" => "blubb"
+ ),
+ $hydrator->extract($serializable)
+ );
+
+ $hydrator->addFilter("foo", function($property) {
+ if ($property == "foo") {
+ return false;
+ }
+ return true;
+ });
+
+ $this->assertSame(
+ array(
+ "bar" => "foo",
+ "blubb" => "baz",
+ "quo" => "blubb"
+ ),
+ $hydrator->extract($serializable)
+ );
+
+ $hydrator->addFilter("len", function($property) {
+ if (strlen($property) !== 3) {
+ return false;
+ }
+ return true;
+ }, FilterComposite::CONDITION_AND);
+
+ $this->assertSame(
+ array(
+ "bar" => "foo",
+ "quo" => "blubb"
+ ),
+ $hydrator->extract($serializable)
+ );
+
+ $hydrator->removeFilter("len");
+ $hydrator->removeFilter("foo");
+
+ $this->assertSame(
+ array(
+ "foo" => "bar",
+ "bar" => "foo",
+ "blubb" => "baz",
+ "quo" => "blubb"
+ ),
+ $hydrator->extract($serializable)
+ );
+ }
+
+ public function filterProvider()
+ {
+ return array(
+ array(new ObjectProperty(), new ObjectPropertyAsset),
+ array(new ArraySerializable(), new ArraySerializableAsset),
+ array(new Reflection(), new ReflectionFilter)
+ );
+ }
+
+ public function testHydratorClassMethodsWithInvalidNumberOfParameters()
+ {
+ $hydrator = new ClassMethods(false);
+ $datas = $hydrator->extract($this->classMethodsInvalidParameter);
+
+ $this->assertTrue($datas['hasBar']);
+ $this->assertEquals('Bar', $datas['foo']);
+ $this->assertFalse($datas['isBla']);
+ }
+
+ public function testObjectBasedFilters()
+ {
+ $hydrator = new ClassMethods(false);
+ $foo = new ClassMethodsFilterProviderInterface();
+ $data = $hydrator->extract($foo);
+ $this->assertFalse(array_key_exists("filter", $data));
+ $this->assertSame("bar", $data["foo"]);
+ $this->assertSame("foo", $data["bar"]);
+ }
}
diff --git a/test/OptionsTest.php b/test/OptionsTest.php
index cb89f0e17..d073a432b 100644
--- a/test/OptionsTest.php
+++ b/test/OptionsTest.php
@@ -47,7 +47,6 @@ public function testNonStrictOptionsDoesNotThrowException()
}
}
-
public function testConstructionWithNull()
{
try {
@@ -65,4 +64,34 @@ public function testUnsetting()
unset($options->testField);
$this->assertEquals(false, isset($options->test_field));
}
+
+ public function testUnsetThrowsInvalidArgumentException()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ $options = new TestOptions;
+ unset($options->foobarField);
+ }
+
+ public function testGetThrowsBadMethodCallException()
+ {
+ $this->setExpectedException('BadMethodCallException');
+ $options = new TestOptions();
+ $options->fieldFoobar;
+ }
+
+ public function testSetFromArrayAcceptsArray()
+ {
+ $array = array('test_field' => 3);
+ $options = new TestOptions();
+
+ $this->assertSame($options, $options->setFromArray($array));
+ $this->assertEquals(3, $options->test_field);
+ }
+
+ public function testSetFromArrayThrowsInvalidArgumentException()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ $options = new TestOptions;
+ $options->setFromArray('asd');
+ }
}
diff --git a/test/Strategy/SerializableStrategyTest.php b/test/Strategy/SerializableStrategyTest.php
new file mode 100644
index 000000000..f36980de2
--- /dev/null
+++ b/test/Strategy/SerializableStrategyTest.php
@@ -0,0 +1,53 @@
+setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException');
+ $serializerStrategy = new SerializableStrategy(false);
+ }
+
+ public function testUseBadSerilizerObject()
+ {
+ $serializer = Serializer::factory('phpserialize');
+ $serializerStrategy = new SerializableStrategy($serializer);
+ $this->assertEquals($serializer, $serializerStrategy->getSerializer());
+ }
+
+ public function testUseBadSerilizerString()
+ {
+ $serializerStrategy = new SerializableStrategy('phpserialize');
+ $this->assertEquals('Zend\Serializer\Adapter\PhpSerialize', get_class($serializerStrategy->getSerializer()));
+ }
+
+ public function testCanSerialize()
+ {
+ $serializer = Serializer::factory('phpserialize');
+ $serializerStrategy = new SerializableStrategy($serializer);
+ $serialized = $serializerStrategy->extract('foo');
+ $this->assertEquals($serialized, 's:3:"foo";');
+ }
+
+ public function testCanUnserialize()
+ {
+ $serializer = Serializer::factory('phpserialize');
+ $serializerStrategy = new SerializableStrategy($serializer);
+ $serialized = $serializerStrategy->hydrate('s:3:"foo";');
+ $this->assertEquals($serialized, 'foo');
+ }
+}
diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php
new file mode 100644
index 000000000..694d68ebf
--- /dev/null
+++ b/test/StringUtilsTest.php
@@ -0,0 +1,160 @@
+assertTrue(StringUtils::isSingleByteEncoding($encoding));
+ }
+
+ public function getNonSingleByteEncodings()
+ {
+ return array(
+ array('UTf-8'),
+ array('UTf-16'),
+ array('usC-2'),
+ array('CESU-8'),
+ );
+ }
+
+ /**
+ * @dataProvider getNonSingleByteEncodings
+ * @param string $encoding
+ */
+ public function testIsSingleByteEncodingReturnsFalse($encoding)
+ {
+ $this->assertFalse(StringUtils::isSingleByteEncoding($encoding));
+ }
+
+ public function testGetWrapper()
+ {
+ $wrapper = StringUtils::getWrapper('ISO-8859-1');
+ if (extension_loaded('mbstring')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\MbString', $wrapper);
+ } elseif (extension_loaded('iconv')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Iconv', $wrapper);
+ } else {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Native', $wrapper);
+ }
+
+ try {
+ $wrapper = StringUtils::getWrapper('UTF-8');
+ if (extension_loaded('intl')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Intl', $wrapper);
+ } elseif (extension_loaded('mbstring')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\MbString', $wrapper);
+ } elseif (extension_loaded('iconv')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Iconv', $wrapper);
+ }
+ } catch (Exception $e) {
+ if (extension_loaded('intl')
+ || extension_loaded('mbstring')
+ || extension_loaded('iconv')
+ ) {
+ $this->fail("Failed to get intl, mbstring or iconv wrapper for UTF-8");
+ }
+ }
+
+ try {
+ $wrapper = StringUtils::getWrapper('UTF-8', 'ISO-8859-1');
+ if (extension_loaded('mbstring')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\MbString', $wrapper);
+ } elseif (extension_loaded('iconv')) {
+ $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Iconv', $wrapper);
+ }
+ } catch (Exception $e) {
+ if (extension_loaded('mbstring') || extension_loaded('iconv')) {
+ $this->fail("Failed to get mbstring or iconv wrapper for UTF-8 and ISO-8859-1");
+ }
+ }
+ }
+
+ public function getUtf8StringValidity()
+ {
+ return array(
+ // valid
+ array('', true),
+ array("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+ . "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
+ . ' !"#$%&\'()*+,-./0123456789:;<=>?'
+ . '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'
+ . '`abcdefghijklmnopqrstuvwxyz{|}~',
+ true
+ ),
+
+ // invalid
+ array(true, false),
+ array(123, false),
+ array(123.45, false),
+ array("\xFF", false),
+ array("\x90a", false),
+ );
+ }
+
+ /**
+ * @dataProvider getUtf8StringValidity
+ * @param string $str
+ * @param boolean $valid
+ */
+ public function testIsValidUtf8($str, $valid)
+ {
+ $this->assertSame($valid, StringUtils::isValidUtf8($str));
+ }
+
+ public function testHasPcreUnicodeSupport()
+ {
+ ErrorHandler::start();
+ $expected = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1;
+ ErrorHandler::stop();
+
+ $this->assertSame($expected, StringUtils::hasPcreUnicodeSupport());
+ }
+}
diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php
new file mode 100644
index 000000000..7546c0d7b
--- /dev/null
+++ b/test/StringWrapper/CommonStringWrapperTest.php
@@ -0,0 +1,298 @@
+getWrapper($encoding);
+ if (!$wrapper) {
+ $this->markTestSkipped("Encoding {$encoding} not supported");
+ }
+
+ $result = $wrapper->strlen($str);
+ $this->assertSame($expected, $result);
+ }
+
+ public function substrProvider()
+ {
+ return array(
+ array('ascii', 'abcdefghijkl', 1, 5, 'bcdef'),
+ array('utf-8', 'abcdefghijkl', 1, 5, 'bcdef'),
+ array('utf-8', 'äöüß', 1, 2, 'öü'),
+ );
+ }
+
+ /**
+ * @dataProvider substrProvider
+ * @param string $encoding
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @param mixed $expected
+ */
+ public function testSubstr($encoding, $str, $offset, $length, $expected)
+ {
+ $wrapper = $this->getWrapper($encoding);
+ if (!$wrapper) {
+ $this->markTestSkipped("Encoding {$encoding} not supported");
+ }
+
+ $result = $wrapper->substr($str, $offset, $length);
+ $this->assertSame($expected, $result);
+ }
+
+ public function strposProvider()
+ {
+ return array(
+ array('ascii', 'abcdefghijkl', 'g', 3, 6),
+ array('utf-8', 'abcdefghijkl', 'g', 3, 6),
+ array('utf-8', 'äöüß', 'ü', 1, 2),
+ );
+ }
+
+ /**
+ * @dataProvider strposProvider
+ * @param string $encoding
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @param mixed $expected
+ */
+ public function testStrpos($encoding, $haystack, $needle, $offset, $expected)
+ {
+ $wrapper = $this->getWrapper($encoding);
+ if (!$wrapper) {
+ $this->markTestSkipped("Encoding {$encoding} not supported");
+ }
+
+ $result = $wrapper->strpos($haystack, $needle, $offset);
+ $this->assertSame($expected, $result);
+ }
+
+ public function convertProvider()
+ {
+ return array(
+ array('ascii', 'ascii', 'abc', 'abc'),
+ array('ascii', 'utf-8', 'abc', 'abc'),
+ array('utf-8', 'ascii', 'abc', 'abc'),
+ array('utf-8', 'iso-8859-15', '€', "\xA4"),
+ array('utf-8', 'iso-8859-16', '€', "\xA4"), // ISO-8859-16 is wrong @ mbstring
+ );
+ }
+
+ /**
+ * @dataProvider convertProvider
+ * @param string $str
+ * @param string $encoding
+ * @param string $convertEncoding
+ * @param mixed $expected
+ */
+ public function testConvert($encoding, $convertEncoding, $str, $expected)
+ {
+ $wrapper = $this->getWrapper($encoding, $convertEncoding);
+ if (!$wrapper) {
+ $this->markTestSkipped("Encoding {$encoding} or {$convertEncoding} not supported");
+ }
+
+ $result = $wrapper->convert($str);
+ $this->assertSame($expected, $result);
+
+ // backword
+ $result = $wrapper->convert($expected, true);
+ $this->assertSame($str, $result);
+ }
+
+ public function wordWrapProvider()
+ {
+ return array(
+ // Standard cut tests
+ 'cut-single-line' =>
+ array('utf-8', 'äbüöcß', 2, ' ', true, 'äb üö cß'),
+ 'cut-multi-line' =>
+ array('utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, 'äb üö c ß äb üö cß'),
+ 'cut-multi-line-short-words' =>
+ array('utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true,
+ "Ä very\nlong\nwööööööö\nööööörd."),
+ 'cut-multi-line-with-previous-new-lines' =>
+ array('utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false,
+ "Ä very\nlong\nwöööööööööööörd."),
+ 'long-break' =>
+ array('utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false,
+ "Ä very
long wöö
öööööööö
öörd."),
+
+ // Alternative cut tests
+ 'cut-beginning-single-space' =>
+ array('utf-8', ' äüöäöü', 3, ' ', true, ' äüö äöü'),
+ 'cut-ending-single-space' =>
+ array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '),
+ 'cut-ending-single-space-with-non-space-divider' =>
+ array('utf-8', 'äöüäöü ', 3, '-', true, 'äöü-äöü-'),
+ 'cut-ending-two-spaces' =>
+ array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '),
+ 'no-cut-ending-single-space' =>
+ array('utf-8', '12345 ', 5, '-', false, '12345-'),
+ 'no-cut-ending-two-spaces' =>
+ array('utf-8', '12345 ', 5, '-', false, '12345- '),
+ 'cut-ending-three-spaces' =>
+ array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '),
+ 'cut-ending-two-breaks' =>
+ array('utf-8', 'äüöäöü--', 3, '-', true, 'äüö-äöü--'),
+ 'cut-tab' =>
+ array('utf-8', "äbü\töcß", 3, ' ', true, "äbü \töc ß"),
+ 'cut-new-line-with-space' =>
+ array('utf-8', "äbü\nößt", 3, ' ', true, "äbü \nöß t"),
+ 'cut-new-line-with-new-line' =>
+ array('utf-8', "äbü\nößte", 3, "\n", true, "äbü\nößt\ne"),
+
+ // Break cut tests
+ 'cut-break-before' =>
+ array('ascii', 'foobar-foofoofoo', 8, '-', true, 'foobar-foofoofo-o'),
+ 'cut-break-with' =>
+ array('ascii', 'foobar-foobar', 6, '-', true, 'foobar-foobar'),
+ 'cut-break-within' =>
+ array('ascii', 'foobar-foobar', 7, '-', true, 'foobar-foobar'),
+ 'cut-break-within-end' =>
+ array('ascii', 'foobar-', 7, '-', true, 'foobar-'),
+ 'cut-break-after' =>
+ array('ascii', 'foobar-foobar', 5, '-', true, 'fooba-r-fooba-r'),
+
+ // Standard no-cut tests
+ 'no-cut-single-line' =>
+ array('utf-8', 'äbüöcß', 2, ' ', false, 'äbüöcß'),
+ 'no-cut-multi-line' =>
+ array('utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, "äbüöc\nß\näbüöcß"),
+ 'no-cut-multi-word' =>
+ array('utf-8', 'äöü äöü äöü', 5, "\n", false, "äöü\näöü\näöü"),
+
+ // Break no-cut tests
+ 'no-cut-break-before' =>
+ array('ascii', 'foobar-foofoofoo', 8, '-', false, 'foobar-foofoofoo'),
+ 'no-cut-break-with' =>
+ array('ascii', 'foobar-foobar', 6, '-', false, 'foobar-foobar'),
+ 'no-cut-break-within' =>
+ array('ascii', 'foobar-foobar', 7, '-', false, 'foobar-foobar'),
+ 'no-cut-break-within-end' =>
+ array('ascii', 'foobar-', 7, '-', false, 'foobar-'),
+ 'no-cut-break-after' =>
+ array('ascii', 'foobar-foobar', 5, '-', false, 'foobar-foobar'),
+ );
+ }
+
+ /**
+ * @dataProvider wordWrapProvider
+ * @param string $encoding
+ * @param string $str
+ * @param integer $width
+ * @param string $break
+ * @param boolean $cut
+ * @param mixed $expected
+ */
+ public function testWordWrap($encoding, $string, $width, $break, $cut, $expected)
+ {
+ $wrapper = $this->getWrapper($encoding);
+ if (!$wrapper) {
+ $this->markTestSkipped("Encoding {$encoding} not supported");
+ }
+
+ $result = $wrapper->wordWrap($string, $width, $break, $cut);
+ $this->assertSame($expected, $result);
+ }
+
+ public function testWordWrapInvalidArgument()
+ {
+ $wrapper = $this->getWrapper();
+ if (!$wrapper) {
+ $this->fail("Can't instantiate wrapper");
+ }
+
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ "Cannot force cut when width is zero"
+ );
+ $wrapper->wordWrap('a', 0, "\n", true);
+ }
+
+ public function strPadProvider()
+ {
+ return array(
+ // single-byte
+ 'left-padding_single-byte' =>
+ array('ascii', 'aaa', 5, 'o', STR_PAD_LEFT, 'ooaaa'),
+ 'center-padding_single-byte' =>
+ array('ascii', 'aaa', 6, 'o', STR_PAD_BOTH, 'oaaaoo'),
+ 'right-padding_single-byte' =>
+ array('ascii', 'aaa', 5, 'o', STR_PAD_RIGHT, 'aaaoo'),
+
+ // multi-byte
+ 'left-padding_multi-byte' =>
+ array('utf-8', 'äää', 5, 'ö', STR_PAD_LEFT, 'ööäää'),
+ 'center-padding_multi-byte' =>
+ array('utf-8', 'äää', 6, 'ö', STR_PAD_BOTH, 'öäääöö'),
+ 'right-padding_multi-byte' =>
+ array('utf-8', 'äää', 5, 'ö', STR_PAD_RIGHT, 'äääöö'),
+
+ // ZF-12186
+ 'input-longer-than-pad-length' =>
+ array('utf-8', 'äääöö', 2, 'ö', STR_PAD_RIGHT, 'äääöö'),
+ 'input-same-as-pad-length' =>
+ array('utf-8', 'äääöö', 5, 'ö', STR_PAD_RIGHT, 'äääöö'),
+ 'negative-pad-length' =>
+ array('utf-8', 'äääöö', -2, 'ö', STR_PAD_RIGHT, 'äääöö'),
+ );
+ }
+
+ /**
+ * @dataProvider strPadProvider
+ * @param string $encoding
+ * @param string $input
+ * @param integer $padLength
+ * @param string $padString
+ * @param integer $padType
+ * @param mixed $expected
+ *
+ * @group ZF-12186
+ */
+ public function testStrPad($encoding, $input, $padLength, $padString, $padType, $expected)
+ {
+ $wrapper = $this->getWrapper($encoding);
+ if (!$wrapper) {
+ $this->markTestSkipped("Encoding {$encoding} not supported");
+ }
+
+ $result = $wrapper->strPad($input, $padLength, $padString, $padType);
+ $this->assertSame($expected, $result);
+ }
+}
diff --git a/test/StringWrapper/IconvTest.php b/test/StringWrapper/IconvTest.php
new file mode 100644
index 000000000..ec3b0db24
--- /dev/null
+++ b/test/StringWrapper/IconvTest.php
@@ -0,0 +1,49 @@
+fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException');
+ } catch (Exception\ExtensionNotLoadedException $e) {
+ $this->markTestSkipped('Missing ext/iconv');
+ }
+ }
+
+ parent::setUp();
+ }
+
+ protected function getWrapper($encoding = null, $convertEncoding = null)
+ {
+ if ($encoding === null) {
+ $supportedEncodings = Iconv::getSupportedEncodings();
+ $encoding = array_shift($supportedEncodings);
+ }
+
+ if (!Iconv::isSupported($encoding, $convertEncoding)) {
+ return false;
+ }
+
+ $wrapper = new Iconv();
+ $wrapper->setEncoding($encoding, $convertEncoding);
+ return $wrapper;
+ }
+}
diff --git a/test/StringWrapper/IntlTest.php b/test/StringWrapper/IntlTest.php
new file mode 100644
index 000000000..d3092f60b
--- /dev/null
+++ b/test/StringWrapper/IntlTest.php
@@ -0,0 +1,49 @@
+fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException');
+ } catch (Exception\ExtensionNotLoadedException $e) {
+ $this->markTestSkipped('Missing ext/intl');
+ }
+ }
+
+ parent::setUp();
+ }
+
+ protected function getWrapper($encoding = null, $convertEncoding = null)
+ {
+ if ($encoding === null) {
+ $supportedEncodings = Intl::getSupportedEncodings();
+ $encoding = array_shift($supportedEncodings);
+ }
+
+ if (!Intl::isSupported($encoding, $convertEncoding)) {
+ return false;
+ }
+
+ $wrapper = new Intl();
+ $wrapper->setEncoding($encoding, $convertEncoding);
+ return $wrapper;
+ }
+}
diff --git a/test/StringWrapper/MbStringTest.php b/test/StringWrapper/MbStringTest.php
new file mode 100644
index 000000000..d024afaa6
--- /dev/null
+++ b/test/StringWrapper/MbStringTest.php
@@ -0,0 +1,49 @@
+fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException');
+ } catch (Exception\ExtensionNotLoadedException $e) {
+ $this->markTestSkipped('Missing ext/mbstring');
+ }
+ }
+
+ parent::setUp();
+ }
+
+ protected function getWrapper($encoding = null, $convertEncoding = null)
+ {
+ if ($encoding === null) {
+ $supportedEncodings = MbString::getSupportedEncodings();
+ $encoding = array_shift($supportedEncodings);
+ }
+
+ if (!MbString::isSupported($encoding, $convertEncoding)) {
+ return false;
+ }
+
+ $wrapper = new MbString();
+ $wrapper->setEncoding($encoding, $convertEncoding);
+ return $wrapper;
+ }
+}
diff --git a/test/StringWrapper/NativeTest.php b/test/StringWrapper/NativeTest.php
new file mode 100644
index 000000000..b54e41daa
--- /dev/null
+++ b/test/StringWrapper/NativeTest.php
@@ -0,0 +1,34 @@
+setEncoding($encoding, $convertEncoding);
+ return $wrapper;
+ }
+}
diff --git a/test/TestAsset/ArraySerializable.php b/test/TestAsset/ArraySerializable.php
new file mode 100644
index 000000000..96f1e74f9
--- /dev/null
+++ b/test/TestAsset/ArraySerializable.php
@@ -0,0 +1,53 @@
+data = array(
+ "foo" => "bar",
+ "bar" => "foo",
+ "blubb" => "baz",
+ "quo" => "blubb"
+ );
+ }
+
+ /**
+ * Exchange internal values from provided array
+ *
+ * @param array $array
+ * @return void
+ */
+ public function exchangeArray(array $array)
+ {
+ $this->data = $array;
+ }
+
+ /**
+ * Return an array representation of the object
+ *
+ * @return array
+ */
+ public function getArrayCopy()
+ {
+ return $this->data;
+ }
+}
diff --git a/test/TestAsset/ClassMethodsFilterProviderInterface.php b/test/TestAsset/ClassMethodsFilterProviderInterface.php
new file mode 100644
index 000000000..b24b8210a
--- /dev/null
+++ b/test/TestAsset/ClassMethodsFilterProviderInterface.php
@@ -0,0 +1,70 @@
+addFilter("get", new GetFilter());
+ $excludes = new FilterComposite();
+ $excludes->addFilter(
+ "servicemanager",
+ new MethodMatchFilter("getServiceManager"),
+ FilterComposite::CONDITION_AND
+ );
+ $excludes->addFilter(
+ "eventmanager",
+ new MethodMatchFilter("getEventManager"),
+ FilterComposite::CONDITION_AND
+ );
+ $filterComposite->addFilter("excludes", $excludes, FilterComposite::CONDITION_AND);
+
+ return $filterComposite;
+ }
+}
diff --git a/test/TestAsset/ClassMethodsInvalidParameter.php b/test/TestAsset/ClassMethodsInvalidParameter.php
new file mode 100644
index 000000000..cf9338865
--- /dev/null
+++ b/test/TestAsset/ClassMethodsInvalidParameter.php
@@ -0,0 +1,43 @@
+filterComposite = new FilterComposite();
+ }
+
+ public function testValidationAdd()
+ {
+ $this->assertTrue($this->filterComposite->filter("foo"));
+ $this->filterComposite->addFilter("has",
+ function($property) {
+ return false;
+ }
+ );
+ $this->assertFalse($this->filterComposite->filter("foo"));
+ }
+
+ public function testValidationRemove()
+ {
+ $this->filterComposite->addFilter("has",
+ function($property) {
+ return false;
+ }
+ );
+ $this->assertFalse($this->filterComposite->filter("foo"));
+ $this->filterComposite->removeFilter("has");
+ $this->assertTrue($this->filterComposite->filter("foo"));
+ }
+
+ public function testValidationHas()
+ {
+ $this->filterComposite->addFilter("has",
+ function($property) {
+ return false;
+ }
+ );
+ $this->assertFalse($this->filterComposite->filter("foo"));
+ $this->assertTrue($this->filterComposite->hasFilter("has"));
+ }
+
+ public function testComplexValidation()
+ {
+ $this->filterComposite->addFilter("has", new \Zend\Stdlib\Hydrator\Filter\HasFilter());
+ $this->filterComposite->addFilter("get", new \Zend\Stdlib\Hydrator\Filter\GetFilter());
+ $this->filterComposite->addFilter("is", new \Zend\Stdlib\Hydrator\Filter\IsFilter());
+
+ $this->filterComposite->addFilter("exclude",
+ function($property) {
+ $method = substr($property, strpos($property, '::'));
+
+ if ($method === 'getServiceLocator') {
+ return false;
+ }
+
+ return true;
+ }, FilterComposite::CONDITION_AND
+ );
+
+ $this->assertTrue($this->filterComposite->filter('getFooBar'));
+ $this->assertFalse($this->filterComposite->filter('getServiceLocator'));
+ }
+
+ public function testConstructorInjection()
+ {
+ $andCondition = array(
+ 'servicelocator' => function($property) {
+ if($property === 'getServiceLocator') {
+ return false;
+ }
+ return true;
+ },
+ 'foobar' => function($property) {
+ if($property === 'getFooBar') {
+ return false;
+ }
+ return true;
+ }
+ );
+ $orCondition = array(
+ 'has' => new \Zend\Stdlib\Hydrator\Filter\HasFilter(),
+ 'get' => new \Zend\Stdlib\Hydrator\Filter\GetFilter()
+ );
+ $filterComposite = new FilterComposite($orCondition, $andCondition);
+
+ $this->assertFalse($filterComposite->filter('getFooBar'));
+ $this->assertFalse($filterComposite->filter('geTFooBar'));
+ $this->assertFalse($filterComposite->filter('getServiceLocator'));
+ $this->assertTrue($filterComposite->filter('getFoo'));
+ $this->assertTrue($filterComposite->filter('hasFoo'));
+ }
+
+ public function testWithOnlyAndFiltersAdded()
+ {
+ $filter = new FilterComposite();
+ $filter->addFilter("foobarbaz", function($property) {
+ return true;
+ }, FilterComposite::CONDITION_AND);
+ $filter->addFilter("foobar", function($property) {
+ return true;
+ }, FilterComposite::CONDITION_AND);
+ $this->assertTrue($filter->filter("foo"));
+ }
+
+ public function testWithOnlyOrFiltersAdded()
+ {
+ $filter = new FilterComposite();
+ $filter->addFilter("foobarbaz", function($property) {
+ return true;
+ });
+ $filter->addFilter("foobar", function($property) {
+ return false;
+ });
+ $this->assertTrue($filter->filter("foo"));
+ }
+
+ public function testWithComplexCompositeAdded()
+ {
+ $filter1 = new FilterComposite();
+ $filter1->addFilter("foobarbaz", function($property) {
+ return true;
+ });
+ $filter1->addFilter("foobar", function($property) {
+ return false;
+ });
+ $filter2 = new FilterComposite();
+ $filter2->addFilter("bar", function($property) {
+ return true;
+ }, FilterComposite::CONDITION_AND);
+ $filter2->addFilter("barblubb", function($property) {
+ return true;
+ }, FilterComposite::CONDITION_AND);
+ $this->assertTrue($filter1->filter("foo"));
+ $this->assertTrue($filter2->filter("foo"));
+ $filter1->addFilter("bar", $filter2);
+ $this->assertTrue($filter1->filter("blubb"));
+
+ $filter1->addFilter("blubb", function($property) { return false; }, FilterComposite::CONDITION_AND);
+ $this->assertFalse($filter1->filter("test"));
+ }
+
+ /**
+ * @expectedException Zend\Stdlib\Exception\InvalidArgumentException
+ * @expectedExceptionMessage The value of test should be either a callable
+ * or an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface
+ */
+ public function testInvalidParameterConstructorInjection()
+ {
+ $andCondition = array('foo' => 'bar');
+ $orCondition = array('test' => 'blubb');
+
+ new FilterComposite($orCondition, $andCondition);
+ }
+
+ /**
+ * @expectedException Zend\Stdlib\Exception\InvalidArgumentException
+ * @expectedExceptionMessage The value of foo should be either a callable
+ * or an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface
+ */
+ public function testInvalidFilterInjection()
+ {
+ $this->filterComposite->addFilter('foo', 'bar');
+ }
+}
diff --git a/test/TestAsset/HydratorClosureStrategyEntity.php b/test/TestAsset/HydratorClosureStrategyEntity.php
new file mode 100644
index 000000000..bceaebb6b
--- /dev/null
+++ b/test/TestAsset/HydratorClosureStrategyEntity.php
@@ -0,0 +1,24 @@
+field1 = $field1;
+ $this->field2 = $field2;
+ }
+}
diff --git a/test/TestAsset/ObjectProperty.php b/test/TestAsset/ObjectProperty.php
new file mode 100644
index 000000000..6f412078a
--- /dev/null
+++ b/test/TestAsset/ObjectProperty.php
@@ -0,0 +1,34 @@
+foo = "bar";
+ $this->bar = "foo";
+ $this->blubb = "baz";
+ $this->quo = "blubb";
+ }
+
+}
diff --git a/test/TestAsset/ReflectionFilter.php b/test/TestAsset/ReflectionFilter.php
new file mode 100644
index 000000000..e74bb058e
--- /dev/null
+++ b/test/TestAsset/ReflectionFilter.php
@@ -0,0 +1,34 @@
+foo = "bar";
+ $this->bar = "foo";
+ $this->blubb = "baz";
+ $this->quo = "blubb";
+ }
+
+}