Skip to content
Browse files

Added filter possibility

  • Loading branch information...
1 parent c21f78c commit 0e9664a92ab97eff1f37f0aa7ec46ac4d230787c @iwalz committed Jan 6, 2013
View
76 library/Zend/Stdlib/Hydrator/ClassMethods.php
@@ -10,7 +10,11 @@
namespace Zend\Stdlib\Hydrator;
-use Zend\Stdlib\Exception;
+use Zend\Stdlib\Exception,
+ Zend\Stdlib\Hydrator\Filter\FilterComposite,
+ Zend\Stdlib\Hydrator\Filter\IsFilter,
+ Zend\Stdlib\Hydrator\Filter\GetFilter,
+ Zend\Stdlib\Hydrator\Filter\HasFilter;
/**
* @category Zend
@@ -26,13 +30,24 @@ class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface
protected $underscoreSeparatedKeys = true;
/**
+ * Composite to filter the methods, that need to be hydrated
+ * @var Filter\FilterComposite
+ */
+ protected $filterComposite;
+
+ /**
* Define if extract values will use camel case or name with underscore
* @param boolean|array $underscoreSeparatedKeys
*/
public function __construct($underscoreSeparatedKeys = true)
{
parent::__construct();
$this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys);
+
+ $this->filterComposite = new FilterComposite();
+ $this->filterComposite->addFilter("is", new IsFilter());
+ $this->filterComposite->addFilter("has", new HasFilter());
+ $this->filterComposite->addFilter("get", new GetFilter());
}
/**
@@ -63,6 +78,7 @@ public function setOptions($options)
public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys)
{
$this->underscoreSeparatedKeys = $underscoreSeparatedKeys;
+
return $this;
}
@@ -72,6 +88,7 @@ public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys)
public function getUnderscoreSeparatedKeys()
{
return $this->underscoreSeparatedKeys;
+
}
/**
@@ -99,7 +116,11 @@ public function extract($object)
$methods = get_class_methods($object);
foreach ($methods as $method) {
- if (!preg_match('/^(get|has|is)[A-Z]\w*/', $method)) {
+ if (
+ !$this->filterComposite->filter(
+ get_class($object) . '::' . $method
+ )
+ ) {
continue;
}
@@ -154,4 +175,55 @@ public function hydrate(array $data, $object)
}
return $object;
}
+
+ /**
+ * Add a new filter to take care of what needs to be hydrated.
+ * To exclude e.g. the method getServiceLocator:
+ *
+ * <code>
+ * $composite->addFilter("servicelocator",
+ * function($property) {
+ * list($class, $method) = explode('::', $property);
+ * if ($method === 'getServiceLocator') {
+ * return false;
+ * }
+ * return true;
+ * }, FilterComposite::CONDITION_AND
+ * );
+ * </code>
+ *
+ * @param string $name Index in the composite
+ * @param callable|Zend\Stdlib\Hydrator\Filter\FilterInterface $filter
+ * @param int $condition
+ */
+ public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR)
+ {
+ $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
+ *
+ * <code>
+ * $filterComposite->removeFilter('has');
+ * </code>
+ *
+ * @param $name
+ */
+ public function removeFilter($name)
+ {
+ $this->filterComposite->removeFilter($name);
+ }
}
View
159 library/Zend/Stdlib/Hydrator/Filter/FilterComposite.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+namespace Zend\Stdlib\Hydrator\Filter;
+
+/**
+ * @category Zend
+ * @package Zend_Stdlib
+ * @subpackage Hydrator
+ */
+class FilterComposite implements FilterInterface
+{
+ /**
+ * @var \ArrayObject
+ */
+ protected $orFilter;
+ /**
+ * @var \ArrayObject
+ */
+ protected $andFilter;
+
+ /**
+ * Constant to add with "or" conditition
+ */
+ const CONDITION_OR = 1;
+ /**
+ * Constant to add with "and" conditition
+ */
+ const CONDITION_AND = 2;
+
+ /**
+ * Define default Filter
+ */
+ public function __construct($orFilter = array(), $andFilter = array())
+ {
+ $this->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'
+ * <code>
+ * $composite->addFilter('exclude',
+ * function($method) {
+ * if (preg_match('/^getService/', $method) {
+ * return false;
+ * }
+ * return true;
+ * }, FilterComposite::CONDITION_AND
+ * );
+ * </code>
+ *
+ * @param string $name
+ * @param callable|FilterInterface $filter
+ * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND
+ */
+ public function addFilter($name, $filter, $condition = self::CONDITION_OR)
+ {
+ if (
+ is_callable($filter) ||
+ $filter instanceof FilterInterface
+ ) {
+ if ($condition === self::CONDITION_OR) {
+ $this->orFilter[$name] = $filter;
+ }
+ if ($condition === self::CONDITION_AND) {
+ $this->andFilter[$name] = $filter;
+ }
+ }
+ }
+
+ /**
+ * Remove a filter from the composition
+ *
+ * @param $name string Identifier for the filter
+ */
+ public function removeFilter($name)
+ {
+ if( isset($this->orFilter[$name])) {
+ unset($this->orFilter[$name]);
+ }
+
+ if( isset($this->andFilter[$name])) {
+ unset($this->andFilter[$name]);
+ }
+ }
+
+ /**
+ * 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)
+ {
+ // return true if no filters are registered
+ if (
+ count($this->orFilter) === 0 &&
+ count($this->andFilter) === 0
+ ) {
+ return true;
+ }
+
+ // Check if 1 from the or filters return true
+ $returnValue = false;
+ foreach($this->orFilter as $filter) {
+ if (is_callable($filter)) {
+ if( $filter($property) === true)
+ {
+ $returnValue = true;
+ break;
+ }
+ } 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;
+ }
+ } else {
+ if( $filter->filter($property) === false) {
+ return false;
+ }
+ }
+ }
+
+ return $returnValue;
+ }
+}
View
20 library/Zend/Stdlib/Hydrator/Filter/FilterInterface.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+namespace Zend\Stdlib\Hydrator\Filter;
+
+/**
+ * @category Zend
+ * @package Zend_Stdlib
+ * @subpackage Hydrator
+ */
+interface FilterInterface
+{
+ public function filter($property);
+}
View
33 library/Zend/Stdlib/Hydrator/Filter/GetFilter.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+namespace Zend\Stdlib\Hydrator\Filter;
+
+/**
+ * @category Zend
+ * @package Zend_Stdlib
+ * @subpackage Hydrator
+ */
+class GetFilter implements FilterInterface
+{
+ public function filter($property)
+ {
+ $pos = strpos($property, '::');
+ if ($pos !== false) {
+ $pos += 2;
+ } else {
+ $pos = 0;
+ }
+
+ if (substr($property, $pos, 3) === 'get') {
+ return true;
+ }
+ return false;
+ }
+}
View
33 library/Zend/Stdlib/Hydrator/Filter/HasFilter.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+namespace Zend\Stdlib\Hydrator\Filter;
+
+/**
+ * @category Zend
+ * @package Zend_Stdlib
+ * @subpackage Hydrator
+ */
+class HasFilter implements FilterInterface
+{
+ public function filter($property)
+ {
+ $pos = strpos($property, '::');
+ if ($pos !== false) {
+ $pos += 2;
+ } else {
+ $pos = 0;
+ }
+
+ if (substr($property, $pos, 3) === 'has') {
+ return true;
+ }
+ return false;
+ }
+}
View
33 library/Zend/Stdlib/Hydrator/Filter/IsFilter.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+namespace Zend\Stdlib\Hydrator\Filter;
+
+/**
+ * @category Zend
+ * @package Zend_Stdlib
+ * @subpackage Hydrator
+ */
+class IsFilter implements FilterInterface
+{
+ public function filter($property)
+ {
+ $pos = strpos($property, '::');
+ if ($pos !== false) {
+ $pos += 2;
+ } else {
+ $pos = 0;
+ }
+
+ if (substr($property, $pos, 2) === 'is') {
+ return true;
+ }
+ return false;
+ }
+}
View
55 tests/ZendTest/Stdlib/FilterTest.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+
+namespace ZendTest\Stdlib;
+
+use Zend\Stdlib\Hydrator\Filter\HasFilter,
+ Zend\Stdlib\Hydrator\Filter\IsFilter,
+ Zend\Stdlib\Hydrator\Filter\GetFilter;
+
+class ValidationTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasValidation()
+ {
+ $hasValidation = new HasFilter();
+ $this->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'));
+ }
+
+}
View
45 tests/ZendTest/Stdlib/HydratorTest.php
@@ -12,6 +12,7 @@
use Zend\Stdlib\Hydrator\ClassMethods;
use Zend\Stdlib\Hydrator\Reflection;
+use Zend\Stdlib\Hydrator\Filter\FilterComposite;
use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCase;
use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore;
use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing;
@@ -248,4 +249,48 @@ 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 testHydratorClassMethodsWithCostumFilter()
+ {
+ $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']));
+ }
}
View
79 tests/ZendTest/Stdlib/TestAsset/FilterCompositeTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Service
+ */
+
+namespace ZendTest\Stdlib;
+
+use Zend\Stdlib\Hydrator\Filter\FilterComposite;
+
+class ValidationCompositeTest extends \PHPUnit_Framework_TestCase
+{
+ protected $validatorComposite;
+
+ public function setUp()
+ {
+ $this->validatorComposite = new FilterComposite();
+ }
+
+ public function testValidationAdd()
+ {
+ $this->assertTrue($this->validatorComposite->filter("foo"));
+ $this->validatorComposite->addFilter("has",
+ function($property) {
+ return false;
+ }
+ );
+ $this->assertFalse($this->validatorComposite->filter("foo"));
+ }
+
+ public function testValidationRemove()
+ {
+ $this->validatorComposite->addFilter("has",
+ function($property) {
+ return false;
+ }
+ );
+ $this->assertFalse($this->validatorComposite->filter("foo"));
+ $this->validatorComposite->removeFilter("has");
+ $this->assertTrue($this->validatorComposite->filter("foo"));
+ }
+
+ public function testValidationHas()
+ {
+ $this->validatorComposite->addFilter("has",
+ function($property) {
+ return false;
+ }
+ );
+ $this->assertFalse($this->validatorComposite->filter("foo"));
+ $this->assertTrue($this->validatorComposite->hasFilter("has"));
+ }
+
+ public function testComplexValidation()
+ {
+ $this->validatorComposite->addFilter("has", new \Zend\Stdlib\Hydrator\Filter\HasFilter());
+ $this->validatorComposite->addFilter("get", new \Zend\Stdlib\Hydrator\Filter\GetFilter());
+ $this->validatorComposite->addFilter("is", new \Zend\Stdlib\Hydrator\Filter\IsFilter());
+
+ $this->validatorComposite->addFilter("exclude",
+ function($property) {
+ $method = substr($property, strpos($property, '::'));
+
+ if ($method === 'getServiceLocator') {
+ return false;
+ }
+
+ return true;
+ }, FilterComposite::CONDITION_AND
+ );
+
+ $this->assertTrue($this->validatorComposite->filter('getFooBar'));
+ $this->assertFalse($this->validatorComposite->filter('getServiceLocator'));
+ }
+}

0 comments on commit 0e9664a

Please sign in to comment.
Something went wrong with that request. Please try again.