From bd5e18934bd41df352f75462fffa86f4739b016e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michae=CC=88l=20Gallego?= Date: Sun, 1 Jul 2012 18:40:59 +0200 Subject: [PATCH 01/75] Resolve bug --- src/Hydrator/ClassMethods.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index cbe4e1973..fbc415314 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -123,6 +123,7 @@ public function hydrate(array $data, $object) $letter = substr(array_shift($letters), 1, 1); return ucfirst($letter); }; + foreach ($data as $property => $value) { if (!$this->useCamelCase) { $property = preg_replace_callback('/(_[a-z])/', $transform, $property); From 9c25e6d060e007d065268fd33ae0479478061fd6 Mon Sep 17 00:00:00 2001 From: prolic Date: Mon, 9 Jul 2012 14:17:09 +0200 Subject: [PATCH 02/75] isSubclassOf uses case-insensitive classnames --- src/SubClass.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SubClass.php b/src/SubClass.php index 3befc5797..fd2393af5 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -26,9 +26,11 @@ public static function isSubclassOf($object, $type) if (is_object($object)) { $object = get_class($object); } + $type = strtolower($type); + $object = strtolower($object); if (!array_key_exists($object, self::$cache)) { self::$cache[$object] = class_parents($object, true) + class_implements($object, true); } return (isset(self::$cache[$object][$type])); } -} \ No newline at end of file +} From 6a6b17111c886465f7fc717eb252b6f340b65f53 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Mon, 9 Jul 2012 16:19:42 +0200 Subject: [PATCH 03/75] [CS][Library] Set File Header http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards#CodingStandards-Files The following script replaces the content between PHP open tag and namespace declaration. for COMPONENT in $(ls -d *) do for FILE in $(find $COMPONENT -name "*.php") do BLOCK="\/\*\*\n \* Zend Framework \(http:\/\/framework\.zend\.com\/\)\n \*\n \* \@link http:\/\/github\.com\/zendframework\/zf2 for the canonical source repository\n \* \@copyright Copyright \(c\) 2005-2012 Zend Technologies USA Inc\. \(http:\/\/www\.zend\.com\)\n \* \@license http:\/\/framework\.zend\.com\/license\/new-bsd New BSD License\n \* \@package Zend_$COMPONENT\n \*\/" perl -0777 -i -pe "s/(<\?php(\s*.*)*\nn)/ Date: Mon, 9 Jul 2012 16:34:21 +0200 Subject: [PATCH 04/75] [CS][test] Remove @copyright & @license for fl in $(find . -name "*.php"); do mv $fl $fl.old; sed '/@copyright/d' $fl.old > $fl; rm -f $fl.old; done; for fl in $(find . -name "*.php"); do mv $fl $fl.old; sed '/@license/d' $fl.old > $fl; rm -f $fl.old; done; --- test/ArrayUtilsTest.php | 2 -- test/CallbackHandlerTest.php | 4 ---- test/GlobTest.php | 2 -- test/HydratorTest.php | 4 ---- test/PriorityQueueTest.php | 4 ---- test/SplPriorityQueueTest.php | 4 ---- test/SplQueueTest.php | 4 ---- test/SplStackTest.php | 4 ---- test/TestAsset/ClassMethodsCamelCase.php | 2 +- test/TestAsset/ClassMethodsCamelCaseMissing.php | 2 +- test/TestAsset/ClassMethodsUnderscore.php | 2 +- test/TestAsset/Reflection.php | 2 +- 12 files changed, 4 insertions(+), 32 deletions(-) diff --git a/test/ArrayUtilsTest.php b/test/ArrayUtilsTest.php index 01c73e5f6..faf167179 100644 --- a/test/ArrayUtilsTest.php +++ b/test/ArrayUtilsTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ diff --git a/test/CallbackHandlerTest.php b/test/CallbackHandlerTest.php index c30507dfe..7b47ac80e 100644 --- a/test/CallbackHandlerTest.php +++ b/test/CallbackHandlerTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,8 +27,6 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ class CallbackHandlerTest extends \PHPUnit_Framework_TestCase { diff --git a/test/GlobTest.php b/test/GlobTest.php index 0ea85c51d..8c4bf5391 100644 --- a/test/GlobTest.php +++ b/test/GlobTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 85efb43c8..e1b5a7e4c 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -34,8 +32,6 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ class HydratorTest extends \PHPUnit_Framework_TestCase { diff --git a/test/PriorityQueueTest.php b/test/PriorityQueueTest.php index 678445314..91ba43ca3 100644 --- a/test/PriorityQueueTest.php +++ b/test/PriorityQueueTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace ZendTest\Stdlib; @@ -29,8 +27,6 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ class PriorityQueueTest extends \PHPUnit_Framework_TestCase { diff --git a/test/SplPriorityQueueTest.php b/test/SplPriorityQueueTest.php index fe8a987ff..fb65029d5 100644 --- a/test/SplPriorityQueueTest.php +++ b/test/SplPriorityQueueTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,8 +27,6 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ class SplPriorityQueueTest extends \PHPUnit_Framework_TestCase { diff --git a/test/SplQueueTest.php b/test/SplQueueTest.php index 7412a68e0..3cdb07d02 100644 --- a/test/SplQueueTest.php +++ b/test/SplQueueTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,8 +27,6 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ class SplQueueTest extends \PHPUnit_Framework_TestCase { diff --git a/test/SplStackTest.php b/test/SplStackTest.php index 3fbb6a842..89ea6079d 100644 --- a/test/SplStackTest.php +++ b/test/SplStackTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Stdlib * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id:$ */ @@ -29,8 +27,6 @@ * @package Zend_Stdlib * @subpackage UnitTests * @group Zend_Stdlib - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ class SplStackTest extends \PHPUnit_Framework_TestCase { diff --git a/test/TestAsset/ClassMethodsCamelCase.php b/test/TestAsset/ClassMethodsCamelCase.php index 2e9fc6ce6..fecb775c8 100644 --- a/test/TestAsset/ClassMethodsCamelCase.php +++ b/test/TestAsset/ClassMethodsCamelCase.php @@ -29,4 +29,4 @@ public function setFooBarBaz($value) $this->fooBarBaz = $value; return $this; } -} \ No newline at end of file +} diff --git a/test/TestAsset/ClassMethodsCamelCaseMissing.php b/test/TestAsset/ClassMethodsCamelCaseMissing.php index 03ffb4ee4..321f1d2a9 100644 --- a/test/TestAsset/ClassMethodsCamelCaseMissing.php +++ b/test/TestAsset/ClassMethodsCamelCaseMissing.php @@ -33,4 +33,4 @@ public function setFooBarBaz($value) return $this; } */ -} \ No newline at end of file +} diff --git a/test/TestAsset/ClassMethodsUnderscore.php b/test/TestAsset/ClassMethodsUnderscore.php index 35c4c0baa..7683a9a6f 100644 --- a/test/TestAsset/ClassMethodsUnderscore.php +++ b/test/TestAsset/ClassMethodsUnderscore.php @@ -29,4 +29,4 @@ public function setFooBarBaz($value) $this->foo_bar_baz = $value; return $this; } -} \ No newline at end of file +} diff --git a/test/TestAsset/Reflection.php b/test/TestAsset/Reflection.php index 9d23e285b..150fdcfe3 100644 --- a/test/TestAsset/Reflection.php +++ b/test/TestAsset/Reflection.php @@ -19,4 +19,4 @@ public function getFooBarBaz() { return $this->fooBarBaz; } -} \ No newline at end of file +} From 0a517319d35b616372d86adab353a5cacb4fc3e1 Mon Sep 17 00:00:00 2001 From: prolic Date: Mon, 9 Jul 2012 17:30:22 +0200 Subject: [PATCH 05/75] cache for isSubclassOf uses strtolower --- src/SubClass.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/SubClass.php b/src/SubClass.php index fd2393af5..9e7f1fbcd 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -24,13 +24,16 @@ public static function isSubclassOf($object, $type) return is_subclass_of($object, $type); } if (is_object($object)) { - $object = get_class($object); + $className = get_class($object); + } else { + $className = $object; } - $type = strtolower($type); - $object = strtolower($object); - if (!array_key_exists($object, self::$cache)) { - self::$cache[$object] = class_parents($object, true) + class_implements($object, true); + if (!array_key_exists(strtolower($className), self::$cache)) { + $parents = class_parents($className, true) + class_implements($className, true); + foreach ($parents as $parent) { + self::$cache[strtolower($className)] = strtolower($parent); + } } - return (isset(self::$cache[$object][$type])); + return (isset(self::$cache[strtolower($className)][strtolower($type)])); } } From 29193f05d4c5916cd4bfa54540a742ebcbe7f344 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Mon, 9 Jul 2012 16:41:27 +0200 Subject: [PATCH 06/75] [CS][Tests] Set File Header http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards#CodingStandards-Files The following script replaces the content between PHP open tag and namespace declaration. for COMPONENT in $(ls -d *) do for FILE in $(find $COMPONENT -name "*.php") do BLOCK="\/\*\*\n \* Zend Framework \(http:\/\/framework\.zend\.com\/\)\n \*\n \* \@link http:\/\/github\.com\/zendframework\/zf2 for the canonical source repository\n \* \@copyright Copyright \(c\) 2005-2012 Zend Technologies USA Inc\. \(http:\/\/www\.zend\.com\)\n \* \@license http:\/\/framework\.zend\.com\/license\/new-bsd New BSD License\n \* \@package Zend_$COMPONENT\n \*\/" perl -0777 -i -pe "s/(<\?php(\s*.*)*\nn)/ Date: Mon, 9 Jul 2012 23:58:44 +0200 Subject: [PATCH 07/75] fixed isSubclassOf method --- src/SubClass.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/SubClass.php b/src/SubClass.php index 9e7f1fbcd..c5be501f5 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -5,11 +5,6 @@ abstract class SubClass { - /** - * @var array - */ - protected static $cache = array(); - /** * Checks if the object has this class as one of its parents * @@ -28,12 +23,13 @@ public static function isSubclassOf($object, $type) } else { $className = $object; } - if (!array_key_exists(strtolower($className), self::$cache)) { - $parents = class_parents($className, true) + class_implements($className, true); - foreach ($parents as $parent) { - self::$cache[strtolower($className)] = strtolower($parent); - } + static $isSubclassFuncCache = null; // null as unset, array when set + if ($isSubclassFuncCache === null) { + $isSubclassFuncCache = array(); + } + if (!array_key_exists($className, $isSubclassFuncCache)) { + $isSubclassFuncCache[$className] = class_parents($className, true) + class_implements($className, true); } - return (isset(self::$cache[strtolower($className)][strtolower($type)])); + return (isset($isSubclassFuncCache[$className][$type])); } } From 87ea1a2182c5c7e67f8fceb4e8be5410b2f29087 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 00:21:07 +0200 Subject: [PATCH 08/75] readded case insensitive behaviour --- src/SubClass.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/SubClass.php b/src/SubClass.php index c5be501f5..38a526a65 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -28,8 +28,14 @@ public static function isSubclassOf($object, $type) $isSubclassFuncCache = array(); } if (!array_key_exists($className, $isSubclassFuncCache)) { - $isSubclassFuncCache[$className] = class_parents($className, true) + class_implements($className, true); + $parents = class_parents($className, true) + class_implements($className, true); + $caseInsensitiveParents = array(); + foreach ($parents as $parent) { + $caseInsensitiveParent = strtolower($parent); + $caseInsensitiveParents[$caseInsensitiveParent] = $caseInsensitiveParent; + } + $isSubclassFuncCache[strtolower($className)] = $caseInsensitiveParents; } - return (isset($isSubclassFuncCache[$className][$type])); + return (isset($isSubclassFuncCache[strtolower($className)][strtolower($type)])); } } From 8bbad0e5450c36c2126c9bcb77588ae5843b173e Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 9 Jul 2012 16:46:59 -0500 Subject: [PATCH 09/75] [zen-49] Correct import statements across framework - Ran a script that would create multiple import statements out of multi-line import statements, and which would sort all import statements in alphabetic order. Script is at https://gist.github.com/3079222 and was run by dropping into the library/Zend folder and typing (in zsh) "for file in **/*.php;do php /path/to/replace-uses.php $file; done" --- src/DispatchableInterface.php | 2 +- src/Hydrator/Reflection.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DispatchableInterface.php b/src/DispatchableInterface.php index 2d450ea63..33b0d1980 100644 --- a/src/DispatchableInterface.php +++ b/src/DispatchableInterface.php @@ -10,8 +10,8 @@ namespace Zend\Stdlib; -use Zend\Stdlib\ResponseInterface as Response; use Zend\Stdlib\RequestInterface as Request; +use Zend\Stdlib\ResponseInterface as Response; interface DispatchableInterface { diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php index f92fde0f1..8851b4691 100644 --- a/src/Hydrator/Reflection.php +++ b/src/Hydrator/Reflection.php @@ -11,8 +11,8 @@ namespace Zend\Stdlib\Hydrator; use ReflectionClass; -use Zend\Stdlib\Hydrator\HydratorInterface; use Zend\Stdlib\Exception; +use Zend\Stdlib\Hydrator\HydratorInterface; class Reflection implements HydratorInterface { From 99109c418373c6ae93570581b8027b5460ea46d5 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 10:02:59 +0200 Subject: [PATCH 10/75] added tests, added file header --- src/SubClass.php | 17 ++++++++++ test/SubClassTest.php | 50 ++++++++++++++++++++++++++++++ test/TestAsset/DummySubclasses.php | 16 ++++++++++ 3 files changed, 83 insertions(+) create mode 100644 test/SubClassTest.php create mode 100644 test/TestAsset/DummySubclasses.php diff --git a/src/SubClass.php b/src/SubClass.php index 38a526a65..720603b1f 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -1,7 +1,22 @@ =')) { + $this->markTestSkipped('Test is only for PHP Versions smaller then 5.3.7'); + } + require_once 'TestAsset/DummySubclasses.php'; + } + + public function testIsSubclassOf() + { + $test1 = SubClass::isSubclassOf('ZendTest\Stdlib\TestAsset\ChildClass', 'ZendTest\Stdlib\TestAsset\TestInterface'); + $test2 = SubClass::isSubclassOf('ZendTest\Stdlib\TestAsset\ParentClass', 'ZendTest\Stdlib\TestAsset\TestInterface'); + $this->assertTrue($test1); + $this->assertTrue($test2); + } + + public function testIsSubclassOfStripsTralingNamespaceSeparator() + { + $test = SubClass::isSubclassOf('\ZendTest\Stdlib\TestAsset\ChildClass', '\ZendTest\Stdlib\TestAsset\TestInterface'); + $this->assertTrue($test); + } + + public function testIsSubclassOfIsCaseInsensitve() + { + $test = SubClass::isSubclassOf('ZendTest\Stdlib\TestAsset\chiLdCLAss', 'ZendTest\Stdlib\TestAsset\testinterface'); + $this->assertTrue($test); + } + + public function testIsSubclassOfObjectToClassNameConversion() + { + $test = SubClass::isSubclassOf(new TestAsset\ChildClass(), 'ZendTest\Stdlib\TestAsset\testinterface'); + $this->assertTrue($test); + } +} \ No newline at end of file diff --git a/test/TestAsset/DummySubclasses.php b/test/TestAsset/DummySubclasses.php new file mode 100644 index 000000000..99fc86831 --- /dev/null +++ b/test/TestAsset/DummySubclasses.php @@ -0,0 +1,16 @@ + Date: Tue, 10 Jul 2012 18:37:25 +0200 Subject: [PATCH 11/75] improved performance (Reflection is case insensitive and much faster) --- src/SubClass.php | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/SubClass.php b/src/SubClass.php index 720603b1f..6b32a8fc1 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -10,6 +10,8 @@ namespace Zend\Stdlib; +use ReflectionClass; + /** * @see https://bugs.php.net/bug.php?id=53727 * @@ -38,21 +40,10 @@ public static function isSubclassOf($object, $type) } else { $className = $object; } - $className = ltrim($className, '\\'); - $type = ltrim($type, '\\'); - static $isSubclassFuncCache = null; // null as unset, array when set - if ($isSubclassFuncCache === null) { - $isSubclassFuncCache = array(); - } - if (!array_key_exists($className, $isSubclassFuncCache)) { - $parents = class_parents($className, true) + class_implements($className, true); - $caseInsensitiveParents = array(); - foreach ($parents as $parent) { - $caseInsensitiveParent = strtolower($parent); - $caseInsensitiveParents[$caseInsensitiveParent] = $caseInsensitiveParent; - } - $isSubclassFuncCache[strtolower($className)] = $caseInsensitiveParents; + if (is_subclass_of($className, $type)) { + return true; } - return (isset($isSubclassFuncCache[strtolower($className)][strtolower($type)])); + $r = new ReflectionClass($className); + return $r->implementsInterface($type); } } From 0b10a79cc024e1dfd031cb863a73e394f67f53f0 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 19:26:57 +0200 Subject: [PATCH 12/75] return early, if object is given --- src/SubClass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SubClass.php b/src/SubClass.php index 6b32a8fc1..70a711894 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -36,7 +36,7 @@ public static function isSubclassOf($object, $type) return is_subclass_of($object, $type); } if (is_object($object)) { - $className = get_class($object); + return ($object instanceof $type); } else { $className = $object; } From 86401e41c0c181d0558822c55a04577884975dd6 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 20:03:38 +0200 Subject: [PATCH 13/75] fix: added class_exists call for --- src/SubClass.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SubClass.php b/src/SubClass.php index 70a711894..85d5ca37c 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -43,7 +43,10 @@ public static function isSubclassOf($object, $type) if (is_subclass_of($className, $type)) { return true; } - $r = new ReflectionClass($className); + if (!class_exists($type)) { + return false; + } + $r = new ReflectionClass($object); return $r->implementsInterface($type); } } From 2750cd94e3eeb04e3d5968d92526dec8d29eb2ad Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 20:04:37 +0200 Subject: [PATCH 14/75] small fix --- src/SubClass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SubClass.php b/src/SubClass.php index 85d5ca37c..dff17ae0b 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -46,7 +46,7 @@ public static function isSubclassOf($object, $type) if (!class_exists($type)) { return false; } - $r = new ReflectionClass($object); + $r = new ReflectionClass($className); return $r->implementsInterface($type); } } From cb7ed992a3ef11bfb1d48ac0b98520cbe8f729e1 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 21:27:04 +0200 Subject: [PATCH 15/75] changed class_exists with interface_exists sorry, seams I need more sleep :-) --- src/SubClass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SubClass.php b/src/SubClass.php index dff17ae0b..9ba3536ef 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -43,7 +43,7 @@ public static function isSubclassOf($object, $type) if (is_subclass_of($className, $type)) { return true; } - if (!class_exists($type)) { + if (!interface_exists($type)) { return false; } $r = new ReflectionClass($className); From 6a723c66770a1081a75698a56739e19d5afdeb05 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 21:40:17 +0200 Subject: [PATCH 16/75] deal only with <-> comparisons, not <-> comparisons --- src/SubClass.php | 11 +++-------- test/SubClassTest.php | 6 ------ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/SubClass.php b/src/SubClass.php index 9ba3536ef..929e72c50 100644 --- a/src/SubClass.php +++ b/src/SubClass.php @@ -27,18 +27,13 @@ abstract class SubClass * * @see https://bugs.php.net/bug.php?id=53727 * - * @param object|string $object + * @param string $className * @param string $type */ - public static function isSubclassOf($object, $type) + public static function isSubclassOf($className, $type) { if (version_compare(PHP_VERSION, '5.3.7', '>=')) { - return is_subclass_of($object, $type); - } - if (is_object($object)) { - return ($object instanceof $type); - } else { - $className = $object; + return is_subclass_of($className, $type); } if (is_subclass_of($className, $type)) { return true; diff --git a/test/SubClassTest.php b/test/SubClassTest.php index 4b8fe92fb..939131972 100644 --- a/test/SubClassTest.php +++ b/test/SubClassTest.php @@ -41,10 +41,4 @@ public function testIsSubclassOfIsCaseInsensitve() $test = SubClass::isSubclassOf('ZendTest\Stdlib\TestAsset\chiLdCLAss', 'ZendTest\Stdlib\TestAsset\testinterface'); $this->assertTrue($test); } - - public function testIsSubclassOfObjectToClassNameConversion() - { - $test = SubClass::isSubclassOf(new TestAsset\ChildClass(), 'ZendTest\Stdlib\TestAsset\testinterface'); - $this->assertTrue($test); - } } \ No newline at end of file From 0e033d4f9bf08dbda4c83f70f93ba78ddc15d3c9 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 21:48:22 +0200 Subject: [PATCH 17/75] removed old test cases, that are not neccessary any more --- test/SubClassTest.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/test/SubClassTest.php b/test/SubClassTest.php index 939131972..3384a5602 100644 --- a/test/SubClassTest.php +++ b/test/SubClassTest.php @@ -30,15 +30,4 @@ public function testIsSubclassOf() $this->assertTrue($test2); } - public function testIsSubclassOfStripsTralingNamespaceSeparator() - { - $test = SubClass::isSubclassOf('\ZendTest\Stdlib\TestAsset\ChildClass', '\ZendTest\Stdlib\TestAsset\TestInterface'); - $this->assertTrue($test); - } - - public function testIsSubclassOfIsCaseInsensitve() - { - $test = SubClass::isSubclassOf('ZendTest\Stdlib\TestAsset\chiLdCLAss', 'ZendTest\Stdlib\TestAsset\testinterface'); - $this->assertTrue($test); - } -} \ No newline at end of file +} From f912824a112c47598a2dadc02e456c9d825832d1 Mon Sep 17 00:00:00 2001 From: prolic Date: Tue, 10 Jul 2012 21:51:33 +0200 Subject: [PATCH 18/75] enabled SubClass tests for all php versions --- test/SubClassTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/SubClassTest.php b/test/SubClassTest.php index 3384a5602..91fa4e334 100644 --- a/test/SubClassTest.php +++ b/test/SubClassTest.php @@ -16,9 +16,6 @@ class SubClassTest extends \PHPUnit_Framework_TestCase { protected function setUp() { - if (version_compare(PHP_VERSION, '5.3.7', '>=')) { - $this->markTestSkipped('Test is only for PHP Versions smaller then 5.3.7'); - } require_once 'TestAsset/DummySubclasses.php'; } From 9b8b3d0ee6ebc2d84bbe0a683179c5399b12291e Mon Sep 17 00:00:00 2001 From: Maks3w Date: Wed, 11 Jul 2012 22:09:11 +0200 Subject: [PATCH 19/75] [zen-46] Replace use statements in documentation and tests --- test/ArrayUtilsTest.php | 10 +++++----- test/ErrorHandlerTest.php | 4 ++-- test/GlobTest.php | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/ArrayUtilsTest.php b/test/ArrayUtilsTest.php index 041619404..5f62911ef 100644 --- a/test/ArrayUtilsTest.php +++ b/test/ArrayUtilsTest.php @@ -10,11 +10,11 @@ namespace ZendTest\Stdlib; -use PHPUnit_Framework_TestCase as TestCase, - stdClass, - \ArrayObject, - Zend\Stdlib\ArrayUtils, - Zend\Config\Config; +use PHPUnit_Framework_TestCase as TestCase; +use stdClass; +use \ArrayObject; +use Zend\Stdlib\ArrayUtils; +use Zend\Config\Config; class ArrayUtilsTest extends TestCase { diff --git a/test/ErrorHandlerTest.php b/test/ErrorHandlerTest.php index 79f90f333..f1613d4e1 100644 --- a/test/ErrorHandlerTest.php +++ b/test/ErrorHandlerTest.php @@ -10,8 +10,8 @@ namespace ZendTest\Stdlib; -use PHPUnit_Framework_TestCase as TestCase, - Zend\Stdlib\ErrorHandler; +use PHPUnit_Framework_TestCase as TestCase; +use Zend\Stdlib\ErrorHandler; class ErrorHandlerTest extends TestCase { diff --git a/test/GlobTest.php b/test/GlobTest.php index 32827f84e..3a88a4df3 100644 --- a/test/GlobTest.php +++ b/test/GlobTest.php @@ -10,8 +10,8 @@ namespace ZendTest\Stdlib; -use PHPUnit_Framework_TestCase as TestCase, - Zend\Stdlib\Glob; +use PHPUnit_Framework_TestCase as TestCase; +use Zend\Stdlib\Glob; class GlobTest extends TestCase { From d01cf3a1c9088391ca0e9fab7b5d2d0285e154dc Mon Sep 17 00:00:00 2001 From: Maks3w Date: Wed, 11 Jul 2012 22:11:34 +0200 Subject: [PATCH 20/75] Remove global prefix in use statements --- test/ArrayUtilsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ArrayUtilsTest.php b/test/ArrayUtilsTest.php index 5f62911ef..15333bb1d 100644 --- a/test/ArrayUtilsTest.php +++ b/test/ArrayUtilsTest.php @@ -12,7 +12,7 @@ use PHPUnit_Framework_TestCase as TestCase; use stdClass; -use \ArrayObject; +use ArrayObject; use Zend\Stdlib\ArrayUtils; use Zend\Config\Config; From 509f72e70b8a510b1ec724aa9daec1dea4937a41 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 11 Jul 2012 17:26:04 -0500 Subject: [PATCH 21/75] Remove Zend\Stdlib\SubClass The main reason for this class was to work around changes in PHP between versions 5.3.3 and 5.3.7 regarding how is_subclass_of() works. In the earlier versions, it was buggy. In 5.3.7 and up, the bugs are fixed, and the solution is very fast. There are very few places in the framework where an is_subclass_of() test makes sense, and those are typically only with classes responsible for creating other classes -- factories, primarily. As such, the number of places where this will be of use is minimal, and can be maintained. The main goal is to have a consistent, performant way to do the check when required, and one which will work with case sensitive contexts. The solution by @prolic in zendframework/zf2#1807 is good; we just don't need to abstract this, particularly as we'll be able to remove this entirely in ZF3. Additionally, abstracting it gives additional dependencies for those components needing it, and in cases like autoloaders, DI, and the service manager, the extra dependency is undesirable as these should stand alone. The code has been duplicated into each class requiring the lookup (I put the check into AbstractPluginManager, as it's not unlikely other plugin managers may need this). --- test/SubClassTest.php | 30 ------------------------------ test/TestAsset/DummySubclasses.php | 16 ---------------- 2 files changed, 46 deletions(-) delete mode 100644 test/SubClassTest.php delete mode 100644 test/TestAsset/DummySubclasses.php diff --git a/test/SubClassTest.php b/test/SubClassTest.php deleted file mode 100644 index 91fa4e334..000000000 --- a/test/SubClassTest.php +++ /dev/null @@ -1,30 +0,0 @@ -assertTrue($test1); - $this->assertTrue($test2); - } - -} diff --git a/test/TestAsset/DummySubclasses.php b/test/TestAsset/DummySubclasses.php deleted file mode 100644 index 99fc86831..000000000 --- a/test/TestAsset/DummySubclasses.php +++ /dev/null @@ -1,16 +0,0 @@ - Date: Thu, 12 Jul 2012 21:11:36 +0200 Subject: [PATCH 22/75] [PSR-2] fixers=braces,elseif,short_tag,php_closing_tag,trailing_spaces,linefeed Applied php-cs-fixer --fixers=braces,elseif,short_tag,php_closing_tag,trailing_spaces,linefeed --- src/ArraySerializableInterface.php | 6 +-- src/ArrayStack.php | 4 +- src/ArrayUtils.php | 16 +++---- src/CallbackHandler.php | 34 +++++++------- src/Glob.php | 44 +++++++++---------- src/Hydrator/ArraySerializable.php | 16 +++---- src/Hydrator/ClassMethods.php | 28 ++++++------ src/Hydrator/HydratorInterface.php | 10 ++--- src/Hydrator/ObjectProperty.php | 10 ++--- src/Hydrator/Reflection.php | 2 +- src/Message.php | 20 ++++----- src/Parameters.php | 24 +++++----- src/ParametersInterface.php | 6 +-- src/SplPriorityQueue.php | 14 +++--- src/SplQueue.php | 6 +-- src/SplStack.php | 6 +-- test/GlobTest.php | 2 +- test/HydratorTest.php | 6 +-- test/MessageTest.php | 16 +++---- test/OptionsTest.php | 14 +++--- test/SplPriorityQueueTest.php | 6 +-- test/TestAsset/ClassMethodsCamelCase.php | 10 ++--- .../ClassMethodsCamelCaseMissing.php | 12 ++--- test/TestAsset/ClassMethodsUnderscore.php | 10 ++--- test/TestAsset/TestOptions.php | 6 +-- 25 files changed, 163 insertions(+), 165 deletions(-) diff --git a/src/ArraySerializableInterface.php b/src/ArraySerializableInterface.php index 5dfbe229c..20dd4633c 100644 --- a/src/ArraySerializableInterface.php +++ b/src/ArraySerializableInterface.php @@ -18,15 +18,15 @@ interface ArraySerializableInterface { /** * Exchange internal values from provided array - * - * @param array $array + * + * @param array $array * @return void */ public function exchangeArray(array $array); /** * Return an array representation of the object - * + * * @return array */ public function getArrayCopy(); diff --git a/src/ArrayStack.php b/src/ArrayStack.php index 4b691cf0e..013ff262d 100644 --- a/src/ArrayStack.php +++ b/src/ArrayStack.php @@ -24,9 +24,9 @@ class ArrayStack extends ArrayObject /** * Retrieve iterator * - * Retrieve an array copy of the object, reverse its order, and return an + * Retrieve an array copy of the object, reverse its order, and return an * ArrayIterator with that reversed array. - * + * * @return ArrayIterator */ public function getIterator() diff --git a/src/ArrayUtils.php b/src/ArrayUtils.php index a06919606..866b784f6 100644 --- a/src/ArrayUtils.php +++ b/src/ArrayUtils.php @@ -33,7 +33,7 @@ public static function hasStringKeys($value, $allowEmpty = false) { if (!is_array($value)) { return false; - } + } if (!$value) { return $allowEmpty; @@ -53,7 +53,7 @@ public static function hasIntegerKeys($value, $allowEmpty = false) { if (!is_array($value)) { return false; - } + } if (!$value) { return $allowEmpty; @@ -80,8 +80,8 @@ public static function hasNumericKeys($value, $allowEmpty = false) { if (!is_array($value)) { return false; - } - + } + if (!$value) { return $allowEmpty; } @@ -113,8 +113,8 @@ public static function isList($value, $allowEmpty = false) { if (!is_array($value)) { return false; - } - + } + if (!$value) { return $allowEmpty; } @@ -155,8 +155,8 @@ public static function isHashTable($value, $allowEmpty = false) { if (!is_array($value)) { return false; - } - + } + if (!$value) { return $allowEmpty; } diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index e8543838a..edce4ff4a 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -39,9 +39,9 @@ class CallbackHandler /** * Constructor - * + * * @param string $event Event to which slot is subscribed - * @param string|array|object $callback PHP callback + * @param string|array|object $callback PHP callback * @param array $options Options used by the callback handler (e.g., priority) * @return void */ @@ -54,14 +54,14 @@ public function __construct($callback, array $metadata = array()) /** * Registers the callback provided in the constructor * - * If you have pecl/weakref {@see http://pecl.php.net/weakref} installed, + * If you have pecl/weakref {@see http://pecl.php.net/weakref} installed, * this method provides additional behavior. * - * If a callback is a functor, or an array callback composing an object + * If a callback is a functor, or an array callback composing an object * instance, this method will pass the object to a WeakRef instance prior * to registering the callback. - * - * @param callback $callback + * + * @param callback $callback * @return void */ protected function registerCallback($callback) @@ -93,7 +93,7 @@ protected function registerCallback($callback) list($target, $method) = $callback; - // If we have an array callback, and the first argument is not an + // If we have an array callback, and the first argument is not an // object, register as-is if (!is_object($target)) { $this->callback = $callback; @@ -108,7 +108,7 @@ protected function registerCallback($callback) /** * Retrieve registered callback - * + * * @return Callback */ public function getCallback() @@ -130,7 +130,7 @@ public function getCallback() return $callback; } - // Array callback with WeakRef object -- retrieve the object first, and + // Array callback with WeakRef object -- retrieve the object first, and // then return list($target, $method) = $callback; if ($target instanceof WeakRef) { @@ -143,7 +143,7 @@ public function getCallback() /** * Invoke handler - * + * * @param array $args Arguments to pass to callback * @return mixed */ @@ -162,7 +162,7 @@ public function call(array $args = array()) $this->validateStringCallbackFor54($callback); } - // Minor performance tweak; use call_user_func() until > 3 arguments + // Minor performance tweak; use call_user_func() until > 3 arguments // reached switch (count($args)) { case 0: @@ -197,7 +197,7 @@ public function call(array $args = array()) /** * Invoke as functor - * + * * @return mixed */ public function __invoke() @@ -207,7 +207,7 @@ public function __invoke() /** * Get all callback metadata - * + * * @return array */ public function getMetadata() @@ -217,8 +217,8 @@ public function getMetadata() /** * Retrieve a single metadatum - * - * @param string $name + * + * @param string $name * @return mixed */ public function getMetadatum($name) @@ -233,8 +233,8 @@ public function getMetadatum($name) * Validate a static method call * * Validates that a static method call in PHP 5.4 will actually work - * - * @param string $callback + * + * @param string $callback * @return true * @throws Exception\InvalidCallbackException if invalid */ diff --git a/src/Glob.php b/src/Glob.php index bfd0f7a13..e97019853 100644 --- a/src/Glob.php +++ b/src/Glob.php @@ -29,10 +29,10 @@ abstract class Glob const GLOB_ONLYDIR = 0x20; const GLOB_ERR = 0x30; /**#@-*/ - + /** * Find pathnames matching a pattern. - * + * * @see http://docs.php.net/glob * @param string $pattern * @param integer $flags @@ -47,10 +47,10 @@ public static function glob($pattern, $flags, $forceFallback = false) return self::systemGlob($pattern, $flags); } } - + /** * Use the glob function provided by the system. - * + * * @param string $pattern * @param integer $flags * @return array|false @@ -81,10 +81,10 @@ protected static function systemGlob($pattern, $flags) return glob($pattern, $globFlags); } - + /** * Expand braces manually, then use the system glob. - * + * * @param string $pattern * @param integer $flags * @return array|false @@ -94,26 +94,26 @@ protected static function fallbackGlob($pattern, $flags) if (!$flags & self::GLOB_BRACE) { return self::systemGlob($pattern, $flags); } - + $flags &= ~self::GLOB_BRACE; $length = strlen($pattern); $paths = array(); - + if ($flags & self::GLOB_NOESCAPE) { $begin = strpos($pattern, '{'); } else { $begin = 0; - + while (true) { if ($begin === $length) { $begin = false; break; - } else if ($pattern[$begin] === '\\' && ($begin + 1) < $length) { + } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) { $begin++; - } else if ($pattern[$begin] === '{') { + } elseif ($pattern[$begin] === '{') { break; } - + $begin++; } } @@ -121,7 +121,7 @@ protected static function fallbackGlob($pattern, $flags) if ($begin === false) { return self::systemGlob($pattern, $flags); } - + $next = self::nextBraceSub($pattern, $begin + 1, $flags); if ($next === null) { @@ -140,7 +140,7 @@ protected static function fallbackGlob($pattern, $flags) $p = $begin + 1; - while (true) { + while (true) { $subPattern = substr($pattern, 0, $begin) . substr($pattern, $p, $next - $p) . substr($pattern, $rest + 1); @@ -150,7 +150,7 @@ protected static function fallbackGlob($pattern, $flags) if ($result) { $paths = array_merge($paths, $result); } - + if ($pattern[$next] === '}') { break; } @@ -158,17 +158,17 @@ protected static function fallbackGlob($pattern, $flags) $p = $next + 1; $next = self::nextBraceSub($pattern, $p, $flags); } - + return array_unique($paths); } - + /** * Find the end of the sub-pattern in a brace expression. - * + * * @param string $pattern * @param integer $begin * @param integer $flags - * @return integer|null + * @return integer|null */ protected static function nextBraceSub($pattern, $begin, $flags) { @@ -181,12 +181,12 @@ protected static function nextBraceSub($pattern, $begin, $flags) if (++$current === $length) { break; } - + $current++; - } else { + } else { if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) { break; - } else if ($pattern[$current++] === '{') { + } elseif ($pattern[$current++] === '{') { $depth++; } } diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index cc281a085..41dd7ab61 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -21,10 +21,10 @@ class ArraySerializable implements HydratorInterface { /** * Extract values from the provided object - * + * * Extracts values via the object's getArrayCopy() method. - * - * @param object $object + * + * @param object $object * @return array * @throws Exception\BadMethodCallException for an $object not implementing getArrayCopy() */ @@ -42,11 +42,11 @@ public function extract($object) /** * Hydrate an object * - * Hydrates an object by passing $data to either its exchangeArray() or + * Hydrates an object by passing $data to either its exchangeArray() or * populate() method. - * - * @param array $data - * @param object $object + * + * @param array $data + * @param object $object * @return object * @throws Exception\BadMethodCallException for an $object not implementing exchangeArray() or populate() */ @@ -54,7 +54,7 @@ public function hydrate(array $data, $object) { if (is_callable(array($object, 'exchangeArray'))) { $object->exchangeArray($data); - } else if (is_callable(array($object, 'populate'))) { + } elseif (is_callable(array($object, 'populate'))) { $object->populate($data); } else { throw new Exception\BadMethodCallException(sprintf( diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index f642bbc8a..136aa5725 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -24,22 +24,22 @@ class ClassMethods implements HydratorInterface * @var boolean */ protected $underscoreSeparatedKeys; - + /** * Define if extract values will use camel case or name with underscore - * @param boolean $underscoreSeparatedKeys + * @param boolean $underscoreSeparatedKeys */ public function __construct($underscoreSeparatedKeys = true) { $this->underscoreSeparatedKeys = $underscoreSeparatedKeys; } - + /** * Extract values from an object with class methods * * Extracts the getter/setter of the given $object. - * - * @param object $object + * + * @param object $object * @return array * @throws Exception\BadMethodCallException for a non-object $object */ @@ -51,9 +51,8 @@ public function extract($object) __METHOD__ )); } - - $transform = function($letters) - { + + $transform = function($letters) { $letter = array_shift($letters); return '_' . strtolower($letter); }; @@ -75,7 +74,7 @@ public function extract($object) $attributes[$attribute] = $object->$method(); } } - + return $attributes; } @@ -83,9 +82,9 @@ public function extract($object) * Hydrate an object by populating getter/setter methods * * 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 */ @@ -97,9 +96,8 @@ public function hydrate(array $data, $object) __METHOD__ )); } - - $transform = function($letters) - { + + $transform = function($letters) { $letter = substr(array_shift($letters), 1, 1); return ucfirst($letter); }; diff --git a/src/Hydrator/HydratorInterface.php b/src/Hydrator/HydratorInterface.php index 84774f8b4..d014b3fdc 100644 --- a/src/Hydrator/HydratorInterface.php +++ b/src/Hydrator/HydratorInterface.php @@ -19,17 +19,17 @@ interface HydratorInterface { /** * Extract values from an object - * - * @param object $object + * + * @param object $object * @return array */ public function extract($object); /** * Hydrate $object with the provided $data. - * - * @param array $data - * @param object $object + * + * @param array $data + * @param object $object * @return object */ public function hydrate(array $data, $object); diff --git a/src/Hydrator/ObjectProperty.php b/src/Hydrator/ObjectProperty.php index e2c8c1067..c78ea76e8 100644 --- a/src/Hydrator/ObjectProperty.php +++ b/src/Hydrator/ObjectProperty.php @@ -23,8 +23,8 @@ class ObjectProperty implements HydratorInterface * Extract values from an object * * Extracts the accessible non-static properties of the given $object. - * - * @param object $object + * + * @param object $object * @return array * @throws Exception\BadMethodCallException for a non-object $object */ @@ -44,9 +44,9 @@ public function extract($object) * Hydrate an object by populating public properties * * Hydrates an object by setting public properties 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 */ diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php index 8851b4691..36181c095 100644 --- a/src/Hydrator/Reflection.php +++ b/src/Hydrator/Reflection.php @@ -68,7 +68,7 @@ protected static function getReflProperties($input) { if (is_object($input)) { $input = get_class($input); - } else if (!is_string($input)) { + } elseif (!is_string($input)) { throw new Exception\InvalidArgumentException('Input must be a string or an object.'); } diff --git a/src/Message.php b/src/Message.php index 2c68547f1..e5e8f088a 100644 --- a/src/Message.php +++ b/src/Message.php @@ -25,13 +25,13 @@ class Message implements MessageInterface protected $content = ''; /** - * Set message metadata + * Set message metadata * - * Non-destructive setting of message metadata; always adds to the metadata, never overwrites + * Non-destructive setting of message metadata; always adds to the metadata, never overwrites * the entire metadata container. - * - * @param string|int|array|Traversable $spec - * @param mixed $value + * + * @param string|int|array|Traversable $spec + * @param mixed $value * @return Message */ public function setMetadata($spec, $value = null) @@ -54,8 +54,8 @@ public function setMetadata($spec, $value = null) /** * Retrieve all metadata or a single metadatum as specified by key - * - * @param null|string|int $key + * + * @param null|string|int $key * @param null|mixed $default * @return mixed */ @@ -78,8 +78,8 @@ public function getMetadata($key = null, $default = null) /** * Set message content - * - * @param mixed $value + * + * @param mixed $value * @return Message */ public function setContent($value) @@ -90,7 +90,7 @@ public function setContent($value) /** * Get message content - * + * * @return mixed */ public function getContent() diff --git a/src/Parameters.php b/src/Parameters.php index 3fa8c3a1a..de67fe7b8 100644 --- a/src/Parameters.php +++ b/src/Parameters.php @@ -19,8 +19,8 @@ class Parameters extends ArrayObject implements ParametersInterface * * Enforces that we have an array, and enforces parameter access to array * elements. - * - * @param array $values + * + * @param array $values * @return void */ public function __construct(array $values = null) @@ -33,8 +33,8 @@ public function __construct(array $values = null) /** * Populate from native PHP array - * - * @param array $values + * + * @param array $values * @return void */ public function fromArray(array $values) @@ -44,8 +44,8 @@ public function fromArray(array $values) /** * Populate from query string - * - * @param string $string + * + * @param string $string * @return void */ public function fromString($string) @@ -57,7 +57,7 @@ public function fromString($string) /** * Serialize to native PHP array - * + * * @return array */ public function toArray() @@ -67,7 +67,7 @@ public function toArray() /** * Serialize to query string - * + * * @return string */ public function toString() @@ -79,8 +79,8 @@ public function toString() * Retrieve by key * * Returns null if the key does not exist. - * - * @param string $name + * + * @param string $name * @return mixed */ public function offsetGet($name) @@ -90,7 +90,7 @@ public function offsetGet($name) } return null; } - + /** * @param string $name * @param mixed $default optional default value @@ -103,7 +103,7 @@ public function get($name, $default = null) } return $default; } - + /** * @param string $name * @param mixed $value diff --git a/src/ParametersInterface.php b/src/ParametersInterface.php index f9fc539f4..42d309540 100644 --- a/src/ParametersInterface.php +++ b/src/ParametersInterface.php @@ -15,7 +15,7 @@ use Serializable; use Traversable; -/* +/* * Basically, an ArrayObject. You could simply define something like: * class QueryParams extends ArrayObject implements Parameters {} * and have 90% of the functionality @@ -35,8 +35,8 @@ public function toArray(); /* Allow serialization to query format; e.g., for PUT or POST requests */ public function toString(); - + public function get($name, $default = null); - + public function set($name, $value); } diff --git a/src/SplPriorityQueue.php b/src/SplPriorityQueue.php index 92799c1a1..a960d72a3 100644 --- a/src/SplPriorityQueue.php +++ b/src/SplPriorityQueue.php @@ -31,11 +31,11 @@ class SplPriorityQueue extends \SplPriorityQueue implements Serializable /** * Insert a value with a given priority * - * Utilizes {@var $serial} to ensure that values of equal priority are + * Utilizes {@var $serial} to ensure that values of equal priority are * emitted in the same order in which they are inserted. - * - * @param mixed $datum - * @param mixed $priority + * + * @param mixed $datum + * @param mixed $priority * @return void */ public function insert($datum, $priority) @@ -50,7 +50,7 @@ public function insert($datum, $priority) * Serialize to an array * * Array will be priority => data pairs - * + * * @return array */ public function toArray() @@ -79,7 +79,7 @@ public function toArray() /** * Serialize - * + * * @return string */ public function serialize() @@ -102,7 +102,7 @@ public function serialize() /** * Deserialize - * + * * @param string $data * @return void */ diff --git a/src/SplQueue.php b/src/SplQueue.php index ff59a5f8b..e753201d8 100644 --- a/src/SplQueue.php +++ b/src/SplQueue.php @@ -22,7 +22,7 @@ class SplQueue extends \SplQueue implements Serializable { /** * Return an array representing the queue - * + * * @return array */ public function toArray() @@ -36,7 +36,7 @@ public function toArray() /** * Serialize - * + * * @return string */ public function serialize() @@ -46,7 +46,7 @@ public function serialize() /** * Unserialize - * + * * @param string $data * @return void */ diff --git a/src/SplStack.php b/src/SplStack.php index 199502fa9..be3c76a42 100644 --- a/src/SplStack.php +++ b/src/SplStack.php @@ -22,7 +22,7 @@ class SplStack extends \SplStack implements Serializable { /** * Serialize to an array representing the stack - * + * * @return array */ public function toArray() @@ -36,7 +36,7 @@ public function toArray() /** * Serialize - * + * * @return string */ public function serialize() @@ -46,7 +46,7 @@ public function serialize() /** * Unserialize - * + * * @param string $data * @return void */ diff --git a/test/GlobTest.php b/test/GlobTest.php index 3a88a4df3..8a8728b71 100644 --- a/test/GlobTest.php +++ b/test/GlobTest.php @@ -20,7 +20,7 @@ public function testFallback() if (!defined('GLOB_BRACE')) { $this->markTestSkipped('GLOB_BRACE not available'); } - + $this->assertEquals( glob(__DIR__ . '/_files/{alph,bet}a', GLOB_BRACE), Glob::glob(__DIR__ . '/_files/{alph,bet}a', Glob::GLOB_BRACE, true) diff --git a/test/HydratorTest.php b/test/HydratorTest.php index a98bb3d15..10fae389e 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -53,7 +53,7 @@ public function setUp() $this->classMethodsUnderscore = new ClassMethodsUnderscore(); $this->reflection = new ReflectionAsset; } - + public function testInitiateValues() { $this->assertEquals($this->classMethodsCamelCase->getFooBar(), '1'); @@ -92,7 +92,7 @@ public function testHydratorClassMethodsCamelCase() $this->assertEquals($test->getFooBar(), 'foo'); $this->assertEquals($test->getFooBarBaz(), 'bar'); } - + public function testHydratorClassMethodsCamelCaseWithSetterMissing() { $hydrator = new ClassMethods(false); @@ -106,7 +106,7 @@ public function testHydratorClassMethodsCamelCaseWithSetterMissing() $this->assertEquals($test->getFooBar(), 'foo'); $this->assertEquals($test->getFooBarBaz(), '2'); } - + public function testHydratorClassMethodsUnderscore() { $hydrator = new ClassMethods(true); diff --git a/test/MessageTest.php b/test/MessageTest.php index 9371e54ef..9f81add04 100644 --- a/test/MessageTest.php +++ b/test/MessageTest.php @@ -21,7 +21,7 @@ public function testMessageCanSetAndGetContent() $this->assertInstanceOf('Zend\Stdlib\Message', $ret); $this->assertEquals('I can set content', $message->getContent()); } - + public function testMessageCanSetAndGetMetadataKeyAsString() { $message = new Message(); @@ -30,7 +30,7 @@ public function testMessageCanSetAndGetMetadataKeyAsString() $this->assertEquals('bar', $message->getMetadata('foo')); $this->assertEquals(array('foo' => 'bar'), $message->getMetadata()); } - + public function testMessageCanSetAndGetMetadataKeyAsArray() { $message = new Message(); @@ -38,29 +38,29 @@ public function testMessageCanSetAndGetMetadataKeyAsArray() $this->assertInstanceOf('Zend\Stdlib\Message', $ret); $this->assertEquals('bar', $message->getMetadata('foo')); } - + public function testMessageGetMetadataWillUseDefaultValueIfNoneExist() { $message = new Message(); $this->assertEquals('bar', $message->getMetadata('foo', 'bar')); } - + public function testMessageThrowsExceptionOnInvalidKeyForMetadataSet() { $message = new Message(); - + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); $message->setMetadata(new \stdClass()); } - + public function testMessageThrowsExceptionOnInvalidKeyForMetadataGet() { $message = new Message(); - + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); $message->getMetadata(new \stdClass()); } - + public function testMessageToStringWorks() { $message = new Message(); diff --git a/test/OptionsTest.php b/test/OptionsTest.php index 39d40a953..50f5f1932 100644 --- a/test/OptionsTest.php +++ b/test/OptionsTest.php @@ -20,18 +20,18 @@ class OptionsTest extends \PHPUnit_Framework_TestCase public function testConstructionWithArray() { $options = new TestOptions(array('test_field' => 1)); - + $this->assertEquals(1, $options->test_field); } - + public function testConstructionWithTraversable() { $config = new ArrayObject(array('test_field' => 1)); $options = new TestOptions($config); - + $this->assertEquals(1, $options->test_field); } - + public function testConstructionWithNull() { try { @@ -40,14 +40,14 @@ public function testConstructionWithNull() $this->fail("Unexpected InvalidArgumentException raised"); } } - + public function testUnsetting() { $options = new TestOptions(array('test_field' => 1)); - + $this->assertEquals(true, isset($options->test_field)); unset($options->testField); $this->assertEquals(false, isset($options->test_field)); - + } } diff --git a/test/SplPriorityQueueTest.php b/test/SplPriorityQueueTest.php index ccf2c5e58..40a3c4ea6 100644 --- a/test/SplPriorityQueueTest.php +++ b/test/SplPriorityQueueTest.php @@ -66,9 +66,9 @@ public function testSerializationAndDeserializationShouldMaintainState() public function testCanRetrieveQueueAsArray() { $expected = array( - 'bar', - 'foo', - 'baz', + 'bar', + 'foo', + 'baz', 'bat', ); $test = $this->queue->toArray(); diff --git a/test/TestAsset/ClassMethodsCamelCase.php b/test/TestAsset/ClassMethodsCamelCase.php index bb1afcc80..4371637ca 100644 --- a/test/TestAsset/ClassMethodsCamelCase.php +++ b/test/TestAsset/ClassMethodsCamelCase.php @@ -13,25 +13,25 @@ class ClassMethodsCamelCase { protected $fooBar = '1'; - + protected $fooBarBaz = '2'; - + public function getFooBar() { return $this->fooBar; } - + public function setFooBar($value) { $this->fooBar = $value; return $this; } - + public function getFooBarBaz() { return $this->fooBarBaz; } - + public function setFooBarBaz($value) { $this->fooBarBaz = $value; diff --git a/test/TestAsset/ClassMethodsCamelCaseMissing.php b/test/TestAsset/ClassMethodsCamelCaseMissing.php index 11851e461..7ad333e26 100644 --- a/test/TestAsset/ClassMethodsCamelCaseMissing.php +++ b/test/TestAsset/ClassMethodsCamelCaseMissing.php @@ -13,28 +13,28 @@ class ClassMethodsCamelCaseMissing { protected $fooBar = '1'; - + protected $fooBarBaz = '2'; - + public function getFooBar() { return $this->fooBar; } - + public function setFooBar($value) { $this->fooBar = $value; return $this; } - + public function getFooBarBaz() { return $this->fooBarBaz; } - + /* * comment to detection verification - * + * public function setFooBarBaz($value) { $this->fooBarBaz = $value; diff --git a/test/TestAsset/ClassMethodsUnderscore.php b/test/TestAsset/ClassMethodsUnderscore.php index e42baea6b..47d5cf1bb 100644 --- a/test/TestAsset/ClassMethodsUnderscore.php +++ b/test/TestAsset/ClassMethodsUnderscore.php @@ -13,25 +13,25 @@ class ClassMethodsUnderscore { protected $foo_bar = '1'; - + protected $foo_bar_baz = '2'; - + public function getFooBar() { return $this->foo_bar; } - + public function setFooBar($value) { $this->foo_bar = $value; return $this; } - + public function getFooBarBaz() { return $this->foo_bar_baz; } - + public function setFooBarBaz($value) { $this->foo_bar_baz = $value; diff --git a/test/TestAsset/TestOptions.php b/test/TestAsset/TestOptions.php index 51a6024c5..a2fbe9842 100644 --- a/test/TestAsset/TestOptions.php +++ b/test/TestAsset/TestOptions.php @@ -18,12 +18,12 @@ class TestOptions extends AbstractOptions { protected $testField; - - public function setTestField($value) + + public function setTestField($value) { $this->testField = $value; } - + public function getTestField() { return $this->testField; From d590df4f130dc1861529bfa921c65dcb37d5bbda Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Fri, 13 Jul 2012 12:37:49 -0700 Subject: [PATCH 23/75] Simplify strictMode to just a property @weierophinney made a strong point that the extending classes will probably just set this property themselves, thus it probably doesn't need to be able to be set from a public scope. --- src/AbstractOptions.php | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index c132a47b8..3ad8c0a4b 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -31,11 +31,8 @@ abstract class AbstractOptions implements ParameterObjectInterface * @return AbstractOptions * @throws Exception\InvalidArgumentException */ - public function __construct($options = null, $strict = null) + public function __construct($options = null) { - if (null !== $strict) { - $this->enableStrictMode($strict); - } if (null !== $options) { $this->setFromArray($options); } @@ -59,20 +56,6 @@ public function setFromArray($options) } } - /** - * With strict mode on, an exception will be thrown if there are values in - * an array with no matching setting in the options class. When off, the - * extra values will simply be ignored. - * - * @param bool $strict - * @return AbstractOptions - */ - public function enableStrictMode($strict) - { - $this->__strictMode__ = $strict; - return $this; - } - /** * @param string $key name of option with underscore * @return string name of setter method From 0331787022bb0fb94494d372c94bd1b77bdcbcfe Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Sat, 14 Jul 2012 01:44:07 -0700 Subject: [PATCH 24/75] Move toArray() to Stdlib\AbstractOptions Also added a specific exception for the __strictMode__ key. --- src/AbstractOptions.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 3ad8c0a4b..9ae85b586 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -56,6 +56,26 @@ public function setFromArray($options) } } + /** + * Cast to array + * + * @return array + */ + public function toArray() + { + $array = array(); + $transform = function($letters) { + $letter = array_shift($letters); + return '_' . strtolower($letter); + }; + foreach ($this as $key => $value) { + if ($key === '__strictMode__') continue; + $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key); + $array[$normalizedKey] = $value; + } + return $array; + } + /** * @param string $key name of option with underscore * @return string name of setter method From 405e321f4e604e8c59b26d3b89e3acb31e499cb6 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Sat, 14 Jul 2012 01:45:18 -0700 Subject: [PATCH 25/75] Performance optimization in AbstractOptions Suggested by @denixport See https://github.com/zendframework/zf2/pull/1883#issuecomment-6981173 --- src/AbstractOptions.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 9ae85b586..405ebd565 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -83,10 +83,8 @@ public function toArray() */ protected function assembleSetterNameFromKey($key) { - $parts = explode('_', $key); - $parts = array_map('ucfirst', $parts); - $setter = 'set' . implode('', $parts); - return $setter; + + return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); } /** @@ -96,10 +94,7 @@ protected function assembleSetterNameFromKey($key) */ protected function assembleGetterNameFromKey($key) { - $parts = explode('_', $key); - $parts = array_map('ucfirst', $parts); - $getter = 'get' . implode('', $parts); - return $getter; + return 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); } /** From 2f92b715f21550f8c54e2a7e5e4cbac96c02bdba Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Sat, 14 Jul 2012 01:59:48 -0700 Subject: [PATCH 26/75] Remove extra blank line --- src/AbstractOptions.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 405ebd565..d953d9e7e 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -83,7 +83,6 @@ public function toArray() */ protected function assembleSetterNameFromKey($key) { - return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); } From 37bee4faa861a6851e9da3670d16dadd09815593 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Mon, 16 Jul 2012 01:53:17 -0700 Subject: [PATCH 27/75] Removed assemble getter/setter in AbstractOptions --- src/AbstractOptions.php | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index d953d9e7e..6a3ba6534 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -76,26 +76,6 @@ public function toArray() return $array; } - /** - * @param string $key name of option with underscore - * @return string name of setter method - * @throws Exception\BadMethodCallException if setter method is undefined - */ - protected function assembleSetterNameFromKey($key) - { - return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); - } - - /** - * @param string $key name of option with underscore - * @return string name of getter method - * @throws Exception\BadMethodCallException if getter method is undefined - */ - protected function assembleGetterNameFromKey($key) - { - return 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); - } - /** * @see ParameterObject::__set() * @param string $key @@ -104,7 +84,7 @@ protected function assembleGetterNameFromKey($key) */ public function __set($key, $value) { - $setter = $this->assembleSetterNameFromKey($key); + $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); if ($this->__strictMode__ && !method_exists($this, $setter)) { throw new Exception\BadMethodCallException( 'The option "' . $key . '" does not ' @@ -122,7 +102,7 @@ public function __set($key, $value) */ public function __get($key) { - $getter = $this->assembleGetterNameFromKey($key); + $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); if (!method_exists($this, $getter)) { throw new Exception\BadMethodCallException( 'The option "' . $key . '" does not ' From 9ca3d05d7cead22493ff8b455baef1d7c3676630 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Mon, 16 Jul 2012 02:38:12 -0700 Subject: [PATCH 28/75] AbstractOptions ignore no setter if strict mode is off --- src/AbstractOptions.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 6a3ba6534..b0c074146 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -91,6 +91,8 @@ public function __set($key, $value) . 'have a matching ' . $setter . ' setter method ' . 'which must be defined' ); + } elseif (!$this->__strictMode__ && !method_exists($this, $setter)) { + return; } $this->{$setter}($value); } From ff9db10d3c811952d9657ec50f129e7457faea38 Mon Sep 17 00:00:00 2001 From: Artur Bodera Date: Mon, 16 Jul 2012 15:18:41 +0200 Subject: [PATCH 29/75] Fix method signatures, change "callback" to "callable". A callable array or a string is referred to as "callable" in PHP 5 (http://php.net/manual/en/language.oop5.typehinting.php) --- src/CallbackHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index edce4ff4a..d3a254162 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -61,7 +61,7 @@ public function __construct($callback, array $metadata = array()) * instance, this method will pass the object to a WeakRef instance prior * to registering the callback. * - * @param callback $callback + * @param callable $callback * @return void */ protected function registerCallback($callback) @@ -109,7 +109,7 @@ protected function registerCallback($callback) /** * Retrieve registered callback * - * @return Callback + * @return callable */ public function getCallback() { From 194560e52185f81684c18f87602f6aa5049c1af3 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Mon, 16 Jul 2012 08:03:22 -0700 Subject: [PATCH 30/75] Add unit test for AbstractOptions strictMode --- test/OptionsTest.php | 18 +++++++++++++- test/TestAsset/TestOptionsNoStrict.php | 33 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 test/TestAsset/TestOptionsNoStrict.php diff --git a/test/OptionsTest.php b/test/OptionsTest.php index 50f5f1932..a834bde93 100644 --- a/test/OptionsTest.php +++ b/test/OptionsTest.php @@ -12,6 +12,7 @@ use ArrayObject; use ZendTest\Stdlib\TestAsset\TestOptions; +use ZendTest\Stdlib\TestAsset\TestOptionsNoStrict; use ZendTest\Stdlib\TestAsset\TestTraversable; use Zend\Stdlib\Exception\InvalidArgumentException; @@ -32,6 +33,22 @@ public function testConstructionWithTraversable() $this->assertEquals(1, $options->test_field); } + public function testInvalidFieldThrowsException() + { + $this->setExpectedException('BadMethodCallException'); + $options = new TestOptions(array('foo' => 'bar')); + } + + public function testNonStrictOptionsDoesNotThrowException() + { + try { + $options = new TestOptionsNoStrict(array('foo' => 'bar')); + } catch (\Exception $e) { + $this->fail('Nonstrict options should not throw an exception'); + } + } + + public function testConstructionWithNull() { try { @@ -48,6 +65,5 @@ public function testUnsetting() $this->assertEquals(true, isset($options->test_field)); unset($options->testField); $this->assertEquals(false, isset($options->test_field)); - } } diff --git a/test/TestAsset/TestOptionsNoStrict.php b/test/TestAsset/TestOptionsNoStrict.php new file mode 100644 index 000000000..cd1a557ba --- /dev/null +++ b/test/TestAsset/TestOptionsNoStrict.php @@ -0,0 +1,33 @@ +testField = $value; + } + + public function getTestField() + { + return $this->testField; + } +} From da4036618d28a39587d984226fb1de172d3053a9 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Fri, 20 Jul 2012 05:05:22 -0700 Subject: [PATCH 31/75] Add Stdlib\Glob unit test Makes sure the bitwise stuff in Glob is correct -- if an invalid flag is passed to the system glob(), it will return false. This shouldn't happen; it should return an empty array if there are no matches and proper flags have been passed. --- test/GlobTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/GlobTest.php b/test/GlobTest.php index 8a8728b71..8a4e39c88 100644 --- a/test/GlobTest.php +++ b/test/GlobTest.php @@ -26,4 +26,10 @@ public function testFallback() Glob::glob(__DIR__ . '/_files/{alph,bet}a', Glob::GLOB_BRACE, true) ); } + + public function testNonMatchingGlobReturnsArray() + { + $result = Glob::glob('/some/path/{,*.}{this,orthis}.php', Glob::GLOB_BRACE); + $this->assertEquals(array(), $result); + } } From 370cf4d5bfeef0ecc94eda727c4a4f67bf32cf99 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Fri, 20 Jul 2012 05:13:43 -0700 Subject: [PATCH 32/75] Better assertion on GlobTest @DASPRiD suggested this... JUST in case that path exists. :rollseyes: To be fair, his point abou the assertion matching the test name at least makes some sense; so here it is. --- test/GlobTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/GlobTest.php b/test/GlobTest.php index 8a4e39c88..6eca47add 100644 --- a/test/GlobTest.php +++ b/test/GlobTest.php @@ -30,6 +30,6 @@ public function testFallback() public function testNonMatchingGlobReturnsArray() { $result = Glob::glob('/some/path/{,*.}{this,orthis}.php', Glob::GLOB_BRACE); - $this->assertEquals(array(), $result); + $this->assertInternalType('array', $result); } } From 8ebaa1419e318b9f85916bcdca441462b47f227d Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 22 Jul 2012 14:48:27 +0200 Subject: [PATCH 33/75] Changed to old behavior for calls with more then 3 arguments. --- src/CallbackHandler.php | 6 ++++-- test/CallbackHandlerTest.php | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index 7c8e7b2b9..216d47422 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -167,17 +167,19 @@ public function call(array $args = array()) $this->isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); } + $argCount = count($args); + if ($this->isPhp54 && is_string($callback)) { $result = $this->validateStringCallbackFor54($callback); - if ($result !== true) { + if ($result !== true && $argCount <= 3) { $callback = $result; } } // Minor performance tweak; use call_user_func() until > 3 arguments // reached - switch (count($args)) { + switch ($argCount) { case 0: if ($this->isPhp54) { return $callback(); diff --git a/test/CallbackHandlerTest.php b/test/CallbackHandlerTest.php index 1765de98b..80c671f72 100644 --- a/test/CallbackHandlerTest.php +++ b/test/CallbackHandlerTest.php @@ -130,6 +130,23 @@ public function testStringStaticCallbackForPhp54() $this->assertSame('staticHandler', $result); } + public function testStringStaticCallbackForPhp54WithMoreThan4Args() + { + if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::staticHandler'); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $result = $handler->call(array(1, 2, 3, 4)); + restore_error_handler(); + $this->assertFalse($error); + $this->assertSame('staticHandler', $result); + } + public function testCallbackToClassImplementingOverloadingButNotInvocableShouldRaiseException() { $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); From 903c72ce05d55dbdc1f157711f71eb21ff566608 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 22 Jul 2012 15:41:45 +0200 Subject: [PATCH 34/75] Added minor performance improvement for static string callbacks --- src/CallbackHandler.php | 5 ++++- test/CallbackHandlerTest.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index 216d47422..a374541aa 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -173,7 +173,10 @@ public function call(array $args = array()) $result = $this->validateStringCallbackFor54($callback); if ($result !== true && $argCount <= 3) { - $callback = $result; + $callback = $result; + // Minor performance tweak, if the callback gets called more + // then once + $this->callback = $result; } } diff --git a/test/CallbackHandlerTest.php b/test/CallbackHandlerTest.php index 80c671f72..124be3a90 100644 --- a/test/CallbackHandlerTest.php +++ b/test/CallbackHandlerTest.php @@ -130,7 +130,7 @@ public function testStringStaticCallbackForPhp54() $this->assertSame('staticHandler', $result); } - public function testStringStaticCallbackForPhp54WithMoreThan4Args() + public function testStringStaticCallbackForPhp54WithMoreThan3Args() { if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) { $this->markTestSkipped('Requires PHP 5.4'); From dbd9c06ddd65633c508fdae3c81bb1dbb240fc68 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 23 Jul 2012 00:37:50 +0200 Subject: [PATCH 35/75] typo fix --- src/CallbackHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index a374541aa..55fd82ed9 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -162,7 +162,7 @@ public function call(array $args = array()) return null; } - // Minor performance tweak, if the callback gets called more the once + // Minor performance tweak, if the callback gets called more than once if (!isset($this->isPhp54)) { $this->isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); } @@ -175,7 +175,7 @@ public function call(array $args = array()) if ($result !== true && $argCount <= 3) { $callback = $result; // Minor performance tweak, if the callback gets called more - // then once + // than once $this->callback = $result; } } From 67e5c3519179f0755068ec2c35ab5f9ab80d772e Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 23 Jul 2012 14:51:04 +0200 Subject: [PATCH 36/75] isPhp54 is now static. --- src/CallbackHandler.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index 55fd82ed9..9dfa14960 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -41,7 +41,7 @@ class CallbackHandler * PHP version is greater as 5.4rc1? * @var boolean */ - protected $isPhp54; + protected static $isPhp54; /** * Constructor @@ -163,13 +163,13 @@ public function call(array $args = array()) } // Minor performance tweak, if the callback gets called more than once - if (!isset($this->isPhp54)) { - $this->isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); + if (!isset(self::$isPhp54)) { + self::$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); } $argCount = count($args); - if ($this->isPhp54 && is_string($callback)) { + if (self::$isPhp54 && is_string($callback)) { $result = $this->validateStringCallbackFor54($callback); if ($result !== true && $argCount <= 3) { @@ -184,19 +184,19 @@ public function call(array $args = array()) // reached switch ($argCount) { case 0: - if ($this->isPhp54) { + if (self::$isPhp54) { return $callback(); } return call_user_func($callback); case 1: - if ($this->isPhp54) { + if (self::$isPhp54) { return $callback(array_shift($args)); } return call_user_func($callback, array_shift($args)); case 2: $arg1 = array_shift($args); $arg2 = array_shift($args); - if ($this->isPhp54) { + if (self::$isPhp54) { return $callback($arg1, $arg2); } return call_user_func($callback, $arg1, $arg2); @@ -204,7 +204,7 @@ public function call(array $args = array()) $arg1 = array_shift($args); $arg2 = array_shift($args); $arg3 = array_shift($args); - if ($this->isPhp54) { + if (self::$isPhp54) { return $callback($arg1, $arg2, $arg3); } return call_user_func($callback, $arg1, $arg2, $arg3); From d6a00a6b5dbaf4e389e6e9fefe9b8f11c05888eb Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Sun, 29 Jul 2012 18:50:34 -0700 Subject: [PATCH 37/75] Simplify SplPriorityQueue::serialize() $queue = new \Zend\Stdlib\SplPriorityQueue; for ($i=0; $i<100; $i++) { $queue->insert('hello'.$i, $i); } // Before $time = microtime(true); for ($i=0; $i<1000; $i++) { $serialized = $queue->serialize(); } echo (microtime(true) - $time); // 0.75588607788086 // After $time = microtime(true); for ($i=0; $i<1000; $i++) { $serialized = $queue->serialize(); } echo (microtime(true) - $time); // 0.28470015525818 --- src/SplPriorityQueue.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/SplPriorityQueue.php b/src/SplPriorityQueue.php index 0b035db65..690b6f6c4 100644 --- a/src/SplPriorityQueue.php +++ b/src/SplPriorityQueue.php @@ -63,6 +63,7 @@ public function toArray() return $array; } + /** * Serialize * @@ -70,17 +71,12 @@ public function toArray() */ public function serialize() { - $data = array(); - $this->setExtractFlags(self::EXTR_BOTH); - while ($this->valid()) { - $data[] = $this->current(); - $this->next(); - } - $this->setExtractFlags(self::EXTR_DATA); + $clone = clone $this; + $clone->setExtractFlags(self::EXTR_BOTH); - // Iterating through a priority queue removes items - foreach ($data as $item) { - $this->insert($item['data'], $item['priority']); + $data = array(); + foreach ($clone as $item) { + $data[] = $item; } return serialize($data); From f9d040fed4ffb860f567e4e07cc7af39a245cdc3 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:20:31 +0200 Subject: [PATCH 38/75] Made the hydrating and extracting of values more generic. --- src/Hydrator/AbstractHydrator.php | 18 +++++++++++++++++ src/Hydrator/ArraySerializable.php | 32 ++++++++++-------------------- src/Hydrator/ObjectProperty.php | 15 ++++---------- src/Hydrator/Reflection.php | 15 +++----------- 4 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index aeaf039b0..3b1247ae8 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -41,4 +41,22 @@ public function registerStrategy($name, StrategyInterface $strategy) { $this->strategies[$name] = $strategy; } + + public function extractValue($name, $value) + { + if ($this->hasStrategy($name)) { + $strategy = $this->getStrategy($name); + $value = $strategy->extract($value); + } + return $value; + } + + public function hydrateValue($name, $value) + { + if ($this->hasStrategy($name)) { + $strategy = $this->getStrategy($name); + $value = $strategy->hydrate($value); + } + return $value; + } } diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index 84ecf226d..3f2bee9b3 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -36,19 +36,12 @@ public function extract($object) __METHOD__ )); } - $data = $object->getArrayCopy(); - - $result = array(); - foreach ($data as $name => $value) { - if ($this->hasStrategy($name)) { - $strategy = $this->getStrategy($name); - $value = $strategy->extract($value); - } - - $result[$name] = $value; - } - return $result; + $data = $object->getArrayCopy(); + array_walk($data, function(&$value, $name) { + $value = $this->extractValue($name, $value); + }); + return $data; } /** @@ -64,19 +57,14 @@ public function extract($object) */ public function hydrate(array $data, $object) { - $hydrationData = array(); - foreach ($data as $name => $value) { - if ($this->hasStrategy($name)) { - $strategy = $this->getStrategy($name); - $value = $strategy->hydrate($value); - } - $hydrationData[$name] = $value; - } + array_walk($data, function(&$value, $name) { + $value = $this->hydrateValue($name, $value); + }); if (is_callable(array($object, 'exchangeArray'))) { - $object->exchangeArray($hydrationData); + $object->exchangeArray($data); } elseif (is_callable(array($object, 'populate'))) { - $object->populate($hydrationData); + $object->populate($data); } else { throw new Exception\BadMethodCallException(sprintf( '%s expects the provided object to implement exchangeArray() or populate()', diff --git a/src/Hydrator/ObjectProperty.php b/src/Hydrator/ObjectProperty.php index 52a2999e2..283b56aea 100644 --- a/src/Hydrator/ObjectProperty.php +++ b/src/Hydrator/ObjectProperty.php @@ -38,12 +38,9 @@ public function extract($object) } $data = get_object_vars($object); - foreach ($data as $name => $value) { - if ($this->hasStrategy($name)) { - $strategy = $this->getStrategy($name); - $data[$name] = $strategy->extract($value); - } - } + array_walk($data, function(&$value, $name) { + $value = $this->extractValue($name, $value); + }); return $data; } @@ -66,11 +63,7 @@ public function hydrate(array $data, $object) )); } foreach ($data as $property => $value) { - if ($this->hasStrategy($property)) { - $strategy = $this->getStrategy($property); - $value = $strategy->hydrate($value); - } - $object->$property = $value; + $object->$property = $this->hydrateValue($property, $value); } return $object; } diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php index a9c5fc9e7..98588f6bb 100644 --- a/src/Hydrator/Reflection.php +++ b/src/Hydrator/Reflection.php @@ -33,14 +33,9 @@ public function extract($object) $result = array(); foreach(self::getReflProperties($object) as $property) { $propertyName = $property->getName(); - $value = $property->getValue($object); - - if ($this->hasStrategy($propertyName)) { - $strategy = $this->getStrategy($propertyName); - $value = $strategy->extract($value); - } - $result[$propertyName] = $value; + $value = $property->getValue($object); + $result[$propertyName] = $this->extractValue($propertyName, $value); } return $result; @@ -58,11 +53,7 @@ public function hydrate(array $data, $object) $reflProperties = self::getReflProperties($object); foreach($data as $key => $value) { if (isset($reflProperties[$key])) { - if ($this->hasStrategy($key)) { - $strategy = $this->getStrategy($key); - $value = $strategy->hydrate($value); - } - $reflProperties[$key]->setValue($object, $value); + $reflProperties[$key]->setValue($object, $this->hydrateValue($key, $value)); } } return $object; From 4cc1eb3955b9bceb6974973957b0832b672ab79f Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:34:14 +0200 Subject: [PATCH 39/75] Fixes for the CS --- src/Hydrator/ArraySerializable.php | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index 3f2bee9b3..d736741e0 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -19,6 +19,7 @@ */ class ArraySerializable extends AbstractHydrator { + /** * Extract values from the provided object * @@ -32,15 +33,14 @@ public function extract($object) { if (!is_callable(array($object, 'getArrayCopy'))) { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided object to implement getArrayCopy()', - __METHOD__ + '%s expects the provided object to implement getArrayCopy()', __METHOD__ )); } - + $data = $object->getArrayCopy(); - array_walk($data, function(&$value, $name) { - $value = $this->extractValue($name, $value); - }); + array_walk($data, function(&$value, $name) { + $value = $this->extractValue($name, $value); + }); return $data; } @@ -57,18 +57,17 @@ public function extract($object) */ public function hydrate(array $data, $object) { - array_walk($data, function(&$value, $name) { - $value = $this->hydrateValue($name, $value); - }); - + array_walk($data, function(&$value, $name) { + $value = $this->hydrateValue($name, $value); + }); + if (is_callable(array($object, 'exchangeArray'))) { $object->exchangeArray($data); } elseif (is_callable(array($object, 'populate'))) { $object->populate($data); } else { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided object to implement exchangeArray() or populate()', - __METHOD__ + '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__ )); } return $object; From 830fda761a63f159d9ca6e34e37dcd10be15782d Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:34:57 +0200 Subject: [PATCH 40/75] Forgot to add the extraction for ClassMethods --- src/Hydrator/ClassMethods.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index e6139f2ef..ca29edaa9 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -71,15 +71,7 @@ public function extract($object) if ($this->underscoreSeparatedKeys) { $attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute); } - - $value = $object->$method(); - - if ($this->hasStrategy($attribute)) { - $strategy = $this->getStrategy($attribute); - $value = $strategy->extract($value); - } - - $attributes[$attribute] = $value; + $attributes[$attribute] = $this->extractValue($attribute, $object->$method()); } } From 4107c8920a17b4fc2d07bb0b45ded6abacfe80f8 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:35:19 +0200 Subject: [PATCH 41/75] Fixes for the CS --- src/Hydrator/ClassMethods.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index ca29edaa9..26d326fc1 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -48,8 +48,7 @@ public function extract($object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided $object to be a PHP object)', - __METHOD__ + '%s expects the provided $object to be a PHP object)', __METHOD__ )); } @@ -59,11 +58,11 @@ public function extract($object) }; $attributes = array(); $methods = get_class_methods($object); - foreach($methods as $method) { - if(preg_match('/^get[A-Z]\w*/', $method)) { + foreach ($methods as $method) { + if (preg_match('/^get[A-Z]\w*/', $method)) { // setter verification $setter = preg_replace('/^get/', 'set', $method); - if(!in_array($setter, $methods)) { + if (!in_array($setter, $methods)) { continue; } $attribute = substr($method, 3); @@ -92,8 +91,7 @@ public function hydrate(array $data, $object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided $object to be a PHP object)', - __METHOD__ + '%s expects the provided $object to be a PHP object)', __METHOD__ )); } @@ -112,7 +110,7 @@ public function hydrate(array $data, $object) $strategy = $this->getStrategy($property); $value = $strategy->hydrate($value); } - + $object->$method($value); } } From c34ae1f96970fd39c5b694eda856d472ed5e7052 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:37:40 +0200 Subject: [PATCH 42/75] Updated the ClassMethods hydrator --- src/Hydrator/ClassMethods.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index 26d326fc1..42cce880e 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -106,10 +106,7 @@ public function hydrate(array $data, $object) } $method = 'set' . ucfirst($property); if (method_exists($object, $method)) { - if ($this->hasStrategy($property)) { - $strategy = $this->getStrategy($property); - $value = $strategy->hydrate($value); - } + $value = $this->hydrateValue($property, $value); $object->$method($value); } From 3ef1bfcf1080842f01b846c4c2e05a19e3dface8 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:42:01 +0200 Subject: [PATCH 43/75] Changed the array with an ArrayObject --- src/Hydrator/AbstractHydrator.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 3b1247ae8..2343ccf59 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -10,7 +10,7 @@ namespace Zend\Stdlib\Hydrator; -use Zend\Stdlib\Exception; +use ArrayObject; use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; /** @@ -20,11 +20,19 @@ */ abstract class AbstractHydrator implements HydratorInterface { + /** + * The list with strategies that this hydrator has. + * + * @var ArrayObject + */ protected $strategies; - + + /** + * Initializes a new instance of this class. + */ public function __construct() { - $this->strategies = array(); + $this->strategies = new ArrayObject(); } public function getStrategy($name) From 95b392777d79ebe24319c987dc4030649b201a4c Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:50:37 +0200 Subject: [PATCH 44/75] Updated the HydratorInterface and added docblocks --- src/Hydrator/AbstractHydrator.php | 48 ++++++++++++++++++++- src/Hydrator/HydratorInterface.php | 33 ++++++++++++++ src/Hydrator/Strategy/StrategyInterface.php | 6 +-- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 2343ccf59..9dd9cabc7 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -35,21 +35,60 @@ public function __construct() $this->strategies = new ArrayObject(); } + /** + * Gets the strategy with the given name. + * + * @param string $name The name of the strategy to get. + * @return StrategyInterface + */ public function getStrategy($name) { return $this->strategies[$name]; } + /** + * Checks if the strategy with the given name exists. + * + * @param string $name The name of the strategy to check for. + * @return bool + */ public function hasStrategy($name) { return array_key_exists($name, $this->strategies); } - public function registerStrategy($name, StrategyInterface $strategy) + /** + * Adds the given strategy under the given name. + * + * @param string $name The name of the strategy to register. + * @param StrategyInterface $strategy The strategy to register. + * @return HydratorInterface + */ + public function addStrategy($name, StrategyInterface $strategy) { $this->strategies[$name] = $strategy; + return $this; } + /** + * Removes the strategy with the given name. + * + * @param string $name The name of the strategy to remove. + * @return HydratorInterface + */ + public function removeStrategy($name) + { + unset($this->strategies[$name]); + return $this; + } + + /** + * Converts a value for extraction. If no strategy exists the plain value is returned. + * + * @param string $name The name of the strategy to use. + * @param mixed $value The value that should be converted. + * @return mixed + */ public function extractValue($name, $value) { if ($this->hasStrategy($name)) { @@ -59,6 +98,13 @@ public function extractValue($name, $value) return $value; } + /** + * Converts a value for hydration. If no strategy exists the plain value is returned. + * + * @param string $name The name of the strategy to use. + * @param mixed $value The value that should be converted. + * @return mixed + */ public function hydrateValue($name, $value) { if ($this->hasStrategy($name)) { diff --git a/src/Hydrator/HydratorInterface.php b/src/Hydrator/HydratorInterface.php index d014b3fdc..488255121 100644 --- a/src/Hydrator/HydratorInterface.php +++ b/src/Hydrator/HydratorInterface.php @@ -17,6 +17,15 @@ */ interface HydratorInterface { + /** + * Adds the given strategy under the given name. + * + * @param string $name The name of the strategy to register. + * @param StrategyInterface $strategy The strategy to register. + * @return HydratorInterface + */ + public function addStrategy($name, StrategyInterface $strategy); + /** * Extract values from an object * @@ -25,6 +34,22 @@ interface HydratorInterface */ public function extract($object); + /** + * Gets the strategy with the given name. + * + * @param string $name The name of the strategy to get. + * @return StrategyInterface + */ + public function getStrategy($name); + + /** + * Checks if the strategy with the given name exists. + * + * @param string $name The name of the strategy to check for. + * @return bool + */ + public function hasStrategy($name); + /** * Hydrate $object with the provided $data. * @@ -33,4 +58,12 @@ public function extract($object); * @return object */ public function hydrate(array $data, $object); + + /** + * Removes the strategy with the given name. + * + * @param string $name The name of the strategy to remove. + * @return HydratorInterface + */ + public function removeStrategy($name); } diff --git a/src/Hydrator/Strategy/StrategyInterface.php b/src/Hydrator/Strategy/StrategyInterface.php index c901b21d7..7f8fe8df4 100644 --- a/src/Hydrator/Strategy/StrategyInterface.php +++ b/src/Hydrator/Strategy/StrategyInterface.php @@ -23,13 +23,13 @@ interface StrategyInterface * @param mixed $value The original value. * @return mixed Returns the value that should be extracted. */ - public function extract($value); - + public function extract($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); + public function hydrate($value); } From ce72b1c9593c87144b3439af6c233b267b28692f Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:51:52 +0200 Subject: [PATCH 45/75] Added a use statement to prevent PHP errors --- src/Hydrator/HydratorInterface.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Hydrator/HydratorInterface.php b/src/Hydrator/HydratorInterface.php index 488255121..68df7a8c5 100644 --- a/src/Hydrator/HydratorInterface.php +++ b/src/Hydrator/HydratorInterface.php @@ -10,6 +10,8 @@ namespace Zend\Stdlib\Hydrator; +use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; + /** * @category Zend * @package Zend_Stdlib From 5e13efb558649408a8e5df93416bdf09f8b2ff13 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:53:24 +0200 Subject: [PATCH 46/75] Added indentation... Netbeans' code formatting sucks --- src/Hydrator/ArraySerializable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index d736741e0..7b4054604 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -33,7 +33,7 @@ public function extract($object) { if (!is_callable(array($object, 'getArrayCopy'))) { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided object to implement getArrayCopy()', __METHOD__ + '%s expects the provided object to implement getArrayCopy()', __METHOD__ )); } From f3880604a44f1e4cdddb997902635fd208c04fc6 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:55:49 +0200 Subject: [PATCH 47/75] Netbeans' code formatting sucks --- src/Hydrator/ObjectProperty.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Hydrator/ObjectProperty.php b/src/Hydrator/ObjectProperty.php index 283b56aea..14cf9e5f6 100644 --- a/src/Hydrator/ObjectProperty.php +++ b/src/Hydrator/ObjectProperty.php @@ -32,15 +32,14 @@ public function extract($object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided $object to be a PHP object)', - __METHOD__ + '%s expects the provided $object to be a PHP object)', __METHOD__ )); } $data = get_object_vars($object); - array_walk($data, function(&$value, $name) { - $value = $this->extractValue($name, $value); - }); + array_walk($data, function(&$value, $name) { + $value = $this->extractValue($name, $value); + }); return $data; } @@ -58,8 +57,7 @@ public function hydrate(array $data, $object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided $object to be a PHP object)', - __METHOD__ + '%s expects the provided $object to be a PHP object)', __METHOD__ )); } foreach ($data as $property => $value) { From 24fe5ef79dd748ff814c29e845351564bbf8d898 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:56:47 +0200 Subject: [PATCH 48/75] Netbeans' code formatting sucks --- src/Hydrator/Strategy/DefaultStrategy.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Hydrator/Strategy/DefaultStrategy.php b/src/Hydrator/Strategy/DefaultStrategy.php index 5653003a6..efd17e1d3 100644 --- a/src/Hydrator/Strategy/DefaultStrategy.php +++ b/src/Hydrator/Strategy/DefaultStrategy.php @@ -23,18 +23,18 @@ class DefaultStrategy implements StrategyInterface * @param mixed $value The original value. * @return mixed Returns the value that should be extracted. */ - public function extract($value) + public function extract($value) { return $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) + public function hydrate($value) { return $value; } From f91196e7d0c48ef81ea0a92020eb50b3df02b9ea Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 10:59:22 +0200 Subject: [PATCH 49/75] Netbeans' code formatting sucks --- src/Hydrator/ArraySerializable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index 7b4054604..9c8650787 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -67,7 +67,7 @@ public function hydrate(array $data, $object) $object->populate($data); } else { throw new Exception\BadMethodCallException(sprintf( - '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__ + '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__ )); } return $object; From 6f658cfe808781abb81dd7d8651c0e6534ada4dd Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 15:41:53 +0200 Subject: [PATCH 50/75] Created a StrategyEnabledInterface which allows the creation of hydrators without implementing strategies. --- src/Hydrator/AbstractHydrator.php | 3 +- src/Hydrator/HydratorInterface.php | 35 --------------- src/Hydrator/StrategyEnabledInterface.php | 54 +++++++++++++++++++++++ 3 files changed, 56 insertions(+), 36 deletions(-) create mode 100644 src/Hydrator/StrategyEnabledInterface.php diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 9dd9cabc7..6d19ebb8c 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -11,6 +11,7 @@ namespace Zend\Stdlib\Hydrator; use ArrayObject; +use Zend\Stdlib\Hydrator\StrategyEnabledInterface; use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; /** @@ -18,7 +19,7 @@ * @package Zend_Stdlib * @subpackage Hydrator */ -abstract class AbstractHydrator implements HydratorInterface +abstract class AbstractHydrator implements HydratorInterface, StrategyEnabledInterface { /** * The list with strategies that this hydrator has. diff --git a/src/Hydrator/HydratorInterface.php b/src/Hydrator/HydratorInterface.php index 68df7a8c5..d014b3fdc 100644 --- a/src/Hydrator/HydratorInterface.php +++ b/src/Hydrator/HydratorInterface.php @@ -10,8 +10,6 @@ namespace Zend\Stdlib\Hydrator; -use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; - /** * @category Zend * @package Zend_Stdlib @@ -19,15 +17,6 @@ */ interface HydratorInterface { - /** - * Adds the given strategy under the given name. - * - * @param string $name The name of the strategy to register. - * @param StrategyInterface $strategy The strategy to register. - * @return HydratorInterface - */ - public function addStrategy($name, StrategyInterface $strategy); - /** * Extract values from an object * @@ -36,22 +25,6 @@ public function addStrategy($name, StrategyInterface $strategy); */ public function extract($object); - /** - * Gets the strategy with the given name. - * - * @param string $name The name of the strategy to get. - * @return StrategyInterface - */ - public function getStrategy($name); - - /** - * Checks if the strategy with the given name exists. - * - * @param string $name The name of the strategy to check for. - * @return bool - */ - public function hasStrategy($name); - /** * Hydrate $object with the provided $data. * @@ -60,12 +33,4 @@ public function hasStrategy($name); * @return object */ public function hydrate(array $data, $object); - - /** - * Removes the strategy with the given name. - * - * @param string $name The name of the strategy to remove. - * @return HydratorInterface - */ - public function removeStrategy($name); } diff --git a/src/Hydrator/StrategyEnabledInterface.php b/src/Hydrator/StrategyEnabledInterface.php new file mode 100644 index 000000000..faff0abb8 --- /dev/null +++ b/src/Hydrator/StrategyEnabledInterface.php @@ -0,0 +1,54 @@ + Date: Wed, 1 Aug 2012 18:14:22 +0200 Subject: [PATCH 51/75] Added tests for the hydrator strategy --- test/HydratorStrategyTest.php | 109 +++++++++++++++++++++ test/TestAsset/HydratorStrategy.php | 64 ++++++++++++ test/TestAsset/HydratorStrategyEntityA.php | 75 ++++++++++++++ test/TestAsset/HydratorStrategyEntityB.php | 47 +++++++++ 4 files changed, 295 insertions(+) create mode 100644 test/HydratorStrategyTest.php create mode 100644 test/TestAsset/HydratorStrategy.php create mode 100644 test/TestAsset/HydratorStrategyEntityA.php create mode 100644 test/TestAsset/HydratorStrategyEntityB.php diff --git a/test/HydratorStrategyTest.php b/test/HydratorStrategyTest.php new file mode 100644 index 000000000..85316d43e --- /dev/null +++ b/test/HydratorStrategyTest.php @@ -0,0 +1,109 @@ +hydrator = new ClassMethods(); + } + + public function testAddingStrategy() + { + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + + $this->hydrator->addStrategy('myStrategy', new HydratorStrategy()); + + $this->assertAttributeCount(1, 'strategies', $this->hydrator); + } + + public function testCheckStrategyEmpty() + { + $this->assertFalse($this->hydrator->hasStrategy('myStrategy')); + } + + public function testCheckStrategyNotEmpty() + { + $this->hydrator->addStrategy('myStrategy', new HydratorStrategy()); + + $this->assertTrue($this->hydrator->hasStrategy('myStrategy')); + } + + public function testRemovingStrategy() + { + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + + $this->hydrator->addStrategy('myStrategy', new HydratorStrategy()); + $this->assertAttributeCount(1, 'strategies', $this->hydrator); + + $this->hydrator->removeStrategy('myStrategy'); + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + } + + public function testRetrieveStrategy() + { + $strategy = new HydratorStrategy(); + $this->hydrator->addStrategy('myStrategy', $strategy); + + $this->assertEquals($strategy, $this->hydrator->getStrategy('myStrategy')); + } + + public function testExtractingObjects() + { + $this->hydrator->addStrategy('entities', new HydratorStrategy()); + + $entityA = new HydratorStrategyEntityA(); + $entityA->addEntity(new HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new HydratorStrategyEntityB(222, 'BBB')); + + $attributes = $this->hydrator->extract($entityA); + + $this->assertContains(111, $attributes['entities']); + $this->assertContains(222, $attributes['entities']); + } + + public function testHydratingObjects() + { + $this->hydrator->addStrategy('entities', new HydratorStrategy()); + + $entityA = new HydratorStrategyEntityA(); + $entityA->addEntity(new HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new HydratorStrategyEntityB(222, 'BBB')); + + $attributes = $this->hydrator->extract($entityA); + $attributes['entities'][] = 333; + + $this->hydrator->hydrate($attributes, $entityA); + $entities = $entityA->getEntities(); + + $this->assertCount(3, $entities); + } +} diff --git a/test/TestAsset/HydratorStrategy.php b/test/TestAsset/HydratorStrategy.php new file mode 100644 index 000000000..ba222ff59 --- /dev/null +++ b/test/TestAsset/HydratorStrategy.php @@ -0,0 +1,64 @@ +simulatedStorageDevice = array(); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(111, 'AAA'); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(222, 'BBB'); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(333, 'CCC'); + } + + public function extract($value) + { + $result = array(); + foreach ($value as $instance) { + $result[] = $instance->getField1(); + } + return $result; + } + + public function hydrate($value) + { + $result = $value; + if (is_array($value)) { + $result = array(); + foreach ($value as $field1) { + $result[] = $this->findEntity($field1); + } + } + return $result; + } + + private function findEntity($field1) + { + $result = null; + foreach ($this->simulatedStorageDevice as $entity) { + if ($entity->getField1() == $field1) { + $result = $entity; + break; + } + } + return $result; + } +} diff --git a/test/TestAsset/HydratorStrategyEntityA.php b/test/TestAsset/HydratorStrategyEntityA.php new file mode 100644 index 000000000..8af71a0e7 --- /dev/null +++ b/test/TestAsset/HydratorStrategyEntityA.php @@ -0,0 +1,75 @@ +entities = array(); + } + + public function addEntity(HydratorStrategyEntityB $entity) + { + $this->entities[] = $entity; + } + + public function getEntities() + { + return $this->entities; + } + + public function setEntities($entities) + { + $this->entities = $entities; + } + + public function getInputFilter() + { + if (!$this->inputFilter) { + $input = new Input(); + $input->setName('entities'); + $input->setRequired(false); + + $this->inputFilter = new InputFilter(); + $this->inputFilter->add($input); + } + + return $this->inputFilter; + } + + public function setInputFilter(InputFilterInterface $inputFilter) + { + $this->inputFilter = $inputFilter; + } + + // Add the getArrayCopy method so we can test the ArraySerializable hydrator: + public function getArrayCopy() + { + return get_object_vars($this); + } + + // Add the populate method so we can test the ArraySerializable hydrator: + public function populate($data) + { + foreach ($data as $name => $value) { + $this->$name = $value; + } + } +} \ No newline at end of file diff --git a/test/TestAsset/HydratorStrategyEntityB.php b/test/TestAsset/HydratorStrategyEntityB.php new file mode 100644 index 000000000..9aae0a4c1 --- /dev/null +++ b/test/TestAsset/HydratorStrategyEntityB.php @@ -0,0 +1,47 @@ +field1 = $field1; + $this->field2 = $field2; + } + + public function getField1() + { + return $this->field1; + } + + public function getField2() + { + return $this->field2; + } + + public function setField1($value) + { + $this->field1 = $value; + return $this; + } + + public function setField2($value) + { + $this->field2 = $value; + return $this; + } +} \ No newline at end of file From debdd75aae2913d72f17540c16f6277a0491d18a Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 18:16:57 +0200 Subject: [PATCH 52/75] Added new lines to the end of the files. --- test/TestAsset/HydratorStrategyEntityA.php | 2 +- test/TestAsset/HydratorStrategyEntityB.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TestAsset/HydratorStrategyEntityA.php b/test/TestAsset/HydratorStrategyEntityA.php index 8af71a0e7..988cfa99a 100644 --- a/test/TestAsset/HydratorStrategyEntityA.php +++ b/test/TestAsset/HydratorStrategyEntityA.php @@ -72,4 +72,4 @@ public function populate($data) $this->$name = $value; } } -} \ No newline at end of file +} diff --git a/test/TestAsset/HydratorStrategyEntityB.php b/test/TestAsset/HydratorStrategyEntityB.php index 9aae0a4c1..273cb481d 100644 --- a/test/TestAsset/HydratorStrategyEntityB.php +++ b/test/TestAsset/HydratorStrategyEntityB.php @@ -44,4 +44,4 @@ public function setField2($value) $this->field2 = $value; return $this; } -} \ No newline at end of file +} From 7bdd8b8d6d4181d6f30ffbfe2898edf759959060 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 1 Aug 2012 12:00:27 -0500 Subject: [PATCH 53/75] [zendframework/zf2#2072] Fix for 5.3 - Defined a number of closures that relied on the current method context. Unfortunately, this does not work in 5.3 unless you import the current object ($self = $this; use ($self) in the closure declaration). - Renamed HydratorStrategyTest to remove naming conflicts --- src/Hydrator/ArraySerializable.php | 10 +++-- src/Hydrator/ObjectProperty.php | 5 ++- test/HydratorStrategyTest.php | 59 ++++++++++++++---------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index 9c8650787..3b6cb18e2 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -37,9 +37,10 @@ public function extract($object) )); } + $self = $this; $data = $object->getArrayCopy(); - array_walk($data, function(&$value, $name) { - $value = $this->extractValue($name, $value); + array_walk($data, function(&$value, $name) use ($self) { + $value = $self->extractValue($name, $value); }); return $data; } @@ -57,8 +58,9 @@ public function extract($object) */ public function hydrate(array $data, $object) { - array_walk($data, function(&$value, $name) { - $value = $this->hydrateValue($name, $value); + $self = $this; + array_walk($data, function(&$value, $name) use ($self) { + $value = $self->hydrateValue($name, $value); }); if (is_callable(array($object, 'exchangeArray'))) { diff --git a/src/Hydrator/ObjectProperty.php b/src/Hydrator/ObjectProperty.php index 14cf9e5f6..2416de8a5 100644 --- a/src/Hydrator/ObjectProperty.php +++ b/src/Hydrator/ObjectProperty.php @@ -36,9 +36,10 @@ public function extract($object) )); } + $self = $this; $data = get_object_vars($object); - array_walk($data, function(&$value, $name) { - $value = $this->extractValue($name, $value); + array_walk($data, function(&$value, $name) use ($self) { + $value = $self->extractValue($name, $value); }); return $data; } diff --git a/test/HydratorStrategyTest.php b/test/HydratorStrategyTest.php index 85316d43e..5a4c14dba 100644 --- a/test/HydratorStrategyTest.php +++ b/test/HydratorStrategyTest.php @@ -12,9 +12,6 @@ use Zend\Stdlib\Hydrator\HydratorInterface; use Zend\Stdlib\Hydrator\ClassMethods; -use ZendTest\StdLib\TestAsset\HydratorStrategy; -use ZendTest\StdLib\TestAsset\HydratorStrategyEntityA; -use ZendTest\StdLib\TestAsset\HydratorStrategyEntityB; /** * @category Zend @@ -22,15 +19,15 @@ * @subpackage UnitTests * @group Zend_Stdlib */ -class HydratorTest extends \PHPUnit_Framework_TestCase +class HydratorStrategyTest extends \PHPUnit_Framework_TestCase { /** * The hydrator that is used during testing. - * + * * @var HydratorInterface */ private $hydrator; - + public function setUp() { $this->hydrator = new ClassMethods(); @@ -39,9 +36,9 @@ public function setUp() public function testAddingStrategy() { $this->assertAttributeCount(0, 'strategies', $this->hydrator); - - $this->hydrator->addStrategy('myStrategy', new HydratorStrategy()); - + + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + $this->assertAttributeCount(1, 'strategies', $this->hydrator); } @@ -52,58 +49,58 @@ public function testCheckStrategyEmpty() public function testCheckStrategyNotEmpty() { - $this->hydrator->addStrategy('myStrategy', new HydratorStrategy()); - + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + $this->assertTrue($this->hydrator->hasStrategy('myStrategy')); } public function testRemovingStrategy() { $this->assertAttributeCount(0, 'strategies', $this->hydrator); - - $this->hydrator->addStrategy('myStrategy', new HydratorStrategy()); + + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); $this->assertAttributeCount(1, 'strategies', $this->hydrator); - + $this->hydrator->removeStrategy('myStrategy'); $this->assertAttributeCount(0, 'strategies', $this->hydrator); } public function testRetrieveStrategy() { - $strategy = new HydratorStrategy(); + $strategy = new TestAsset\HydratorStrategy(); $this->hydrator->addStrategy('myStrategy', $strategy); - + $this->assertEquals($strategy, $this->hydrator->getStrategy('myStrategy')); } public function testExtractingObjects() { - $this->hydrator->addStrategy('entities', new HydratorStrategy()); - - $entityA = new HydratorStrategyEntityA(); - $entityA->addEntity(new HydratorStrategyEntityB(111, 'AAA')); - $entityA->addEntity(new HydratorStrategyEntityB(222, 'BBB')); - + $this->hydrator->addStrategy('entities', new TestAsset\HydratorStrategy()); + + $entityA = new TestAsset\HydratorStrategyEntityA(); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(222, 'BBB')); + $attributes = $this->hydrator->extract($entityA); - + $this->assertContains(111, $attributes['entities']); $this->assertContains(222, $attributes['entities']); } public function testHydratingObjects() { - $this->hydrator->addStrategy('entities', new HydratorStrategy()); - - $entityA = new HydratorStrategyEntityA(); - $entityA->addEntity(new HydratorStrategyEntityB(111, 'AAA')); - $entityA->addEntity(new HydratorStrategyEntityB(222, 'BBB')); - + $this->hydrator->addStrategy('entities', new TestAsset\HydratorStrategy()); + + $entityA = new TestAsset\HydratorStrategyEntityA(); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(222, 'BBB')); + $attributes = $this->hydrator->extract($entityA); $attributes['entities'][] = 333; - + $this->hydrator->hydrate($attributes, $entityA); $entities = $entityA->getEntities(); - + $this->assertCount(3, $entities); } } From a22bdcbbcda084958f513d34537323cf0fa0ece7 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 1 Aug 2012 12:03:16 -0500 Subject: [PATCH 54/75] [zendframework/zf2#2072] CS fixes - trailing whitespace --- src/Hydrator/AbstractHydrator.php | 28 ++++++++++----------- src/Hydrator/Reflection.php | 2 +- src/Hydrator/Strategy/DefaultStrategy.php | 4 +-- src/Hydrator/Strategy/StrategyInterface.php | 4 +-- src/Hydrator/StrategyEnabledInterface.php | 8 +++--- test/TestAsset/HydratorStrategy.php | 10 ++++---- test/TestAsset/HydratorStrategyEntityA.php | 6 ++--- test/TestAsset/HydratorStrategyEntityB.php | 10 ++++---- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 6d19ebb8c..4b320f18f 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -23,22 +23,22 @@ abstract class AbstractHydrator implements HydratorInterface, StrategyEnabledInt { /** * The list with strategies that this hydrator has. - * + * * @var ArrayObject */ protected $strategies; /** - * Initializes a new instance of this class. + * Initializes a new instance of this class. */ public function __construct() { $this->strategies = new ArrayObject(); } - + /** * Gets the strategy with the given name. - * + * * @param string $name The name of the strategy to get. * @return StrategyInterface */ @@ -46,10 +46,10 @@ public function getStrategy($name) { return $this->strategies[$name]; } - + /** * Checks if the strategy with the given name exists. - * + * * @param string $name The name of the strategy to check for. * @return bool */ @@ -57,10 +57,10 @@ public function hasStrategy($name) { return array_key_exists($name, $this->strategies); } - + /** * Adds the given strategy under the given name. - * + * * @param string $name The name of the strategy to register. * @param StrategyInterface $strategy The strategy to register. * @return HydratorInterface @@ -70,10 +70,10 @@ public function addStrategy($name, StrategyInterface $strategy) $this->strategies[$name] = $strategy; return $this; } - + /** * Removes the strategy with the given name. - * + * * @param string $name The name of the strategy to remove. * @return HydratorInterface */ @@ -82,10 +82,10 @@ public function removeStrategy($name) unset($this->strategies[$name]); return $this; } - + /** * Converts a value for extraction. If no strategy exists the plain value is returned. - * + * * @param string $name The name of the strategy to use. * @param mixed $value The value that should be converted. * @return mixed @@ -98,10 +98,10 @@ public function extractValue($name, $value) } return $value; } - + /** * Converts a value for hydration. If no strategy exists the plain value is returned. - * + * * @param string $name The name of the strategy to use. * @param mixed $value The value that should be converted. * @return mixed diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php index 98588f6bb..22ff5569c 100644 --- a/src/Hydrator/Reflection.php +++ b/src/Hydrator/Reflection.php @@ -33,7 +33,7 @@ public function extract($object) $result = array(); foreach(self::getReflProperties($object) as $property) { $propertyName = $property->getName(); - + $value = $property->getValue($object); $result[$propertyName] = $this->extractValue($propertyName, $value); } diff --git a/src/Hydrator/Strategy/DefaultStrategy.php b/src/Hydrator/Strategy/DefaultStrategy.php index efd17e1d3..0bdc2e761 100644 --- a/src/Hydrator/Strategy/DefaultStrategy.php +++ b/src/Hydrator/Strategy/DefaultStrategy.php @@ -19,7 +19,7 @@ class DefaultStrategy implements StrategyInterface { /** * 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. */ @@ -30,7 +30,7 @@ public function extract($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. */ diff --git a/src/Hydrator/Strategy/StrategyInterface.php b/src/Hydrator/Strategy/StrategyInterface.php index 7f8fe8df4..56d576247 100644 --- a/src/Hydrator/Strategy/StrategyInterface.php +++ b/src/Hydrator/Strategy/StrategyInterface.php @@ -19,7 +19,7 @@ interface StrategyInterface { /** * 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. */ @@ -27,7 +27,7 @@ public function extract($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. */ diff --git a/src/Hydrator/StrategyEnabledInterface.php b/src/Hydrator/StrategyEnabledInterface.php index faff0abb8..413b48fe8 100644 --- a/src/Hydrator/StrategyEnabledInterface.php +++ b/src/Hydrator/StrategyEnabledInterface.php @@ -21,7 +21,7 @@ interface StrategyEnabledInterface { /** * Adds the given strategy under the given name. - * + * * @param string $name The name of the strategy to register. * @param StrategyInterface $strategy The strategy to register. * @return HydratorInterface @@ -30,7 +30,7 @@ public function addStrategy($name, StrategyInterface $strategy); /** * Gets the strategy with the given name. - * + * * @param string $name The name of the strategy to get. * @return StrategyInterface */ @@ -38,7 +38,7 @@ public function getStrategy($name); /** * Checks if the strategy with the given name exists. - * + * * @param string $name The name of the strategy to check for. * @return bool */ @@ -46,7 +46,7 @@ public function hasStrategy($name); /** * Removes the strategy with the given name. - * + * * @param string $name The name of the strategy to remove. * @return HydratorInterface */ diff --git a/test/TestAsset/HydratorStrategy.php b/test/TestAsset/HydratorStrategy.php index ba222ff59..abb7bf47e 100644 --- a/test/TestAsset/HydratorStrategy.php +++ b/test/TestAsset/HydratorStrategy.php @@ -16,11 +16,11 @@ class HydratorStrategy extends DefaultStrategy { /** * A simulated storage device which is just an array with Car objects. - * + * * @var array */ private $simulatedStorageDevice; - + public function __construct() { $this->simulatedStorageDevice = array(); @@ -28,7 +28,7 @@ public function __construct() $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(222, 'BBB'); $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(333, 'CCC'); } - + public function extract($value) { $result = array(); @@ -37,7 +37,7 @@ public function extract($value) } return $result; } - + public function hydrate($value) { $result = $value; @@ -49,7 +49,7 @@ public function hydrate($value) } return $result; } - + private function findEntity($field1) { $result = null; diff --git a/test/TestAsset/HydratorStrategyEntityA.php b/test/TestAsset/HydratorStrategyEntityA.php index 988cfa99a..641d44473 100644 --- a/test/TestAsset/HydratorStrategyEntityA.php +++ b/test/TestAsset/HydratorStrategyEntityA.php @@ -19,7 +19,7 @@ class HydratorStrategyEntityA implements InputFilterAwareInterface { public $entities; // public to make testing easier! private $inputFilter; // used to test forms - + public function __construct() { $this->entities = array(); @@ -46,14 +46,14 @@ public function getInputFilter() $input = new Input(); $input->setName('entities'); $input->setRequired(false); - + $this->inputFilter = new InputFilter(); $this->inputFilter->add($input); } return $this->inputFilter; } - + public function setInputFilter(InputFilterInterface $inputFilter) { $this->inputFilter = $inputFilter; diff --git a/test/TestAsset/HydratorStrategyEntityB.php b/test/TestAsset/HydratorStrategyEntityB.php index 273cb481d..e3be42ae1 100644 --- a/test/TestAsset/HydratorStrategyEntityB.php +++ b/test/TestAsset/HydratorStrategyEntityB.php @@ -16,29 +16,29 @@ class HydratorStrategyEntityB { private $field1; private $field2; - + public function __construct($field1, $field2) { $this->field1 = $field1; $this->field2 = $field2; } - + public function getField1() { return $this->field1; } - + public function getField2() { return $this->field2; } - + public function setField1($value) { $this->field1 = $value; return $this; } - + public function setField2($value) { $this->field2 = $value; From 3c253e8dff437a1e76f00897dde0ebda9bcc1311 Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Fri, 3 Aug 2012 02:19:04 +0000 Subject: [PATCH 55/75] Fixed typos --- src/AbstractOptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index b0c074146..251bfd0c3 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -20,7 +20,7 @@ abstract class AbstractOptions implements ParameterObjectInterface { /** * We use the __ prefix to avoid collisions with properties in - * user-implmentations. + * user-implementations. * * @var bool */ From cd3886bda62e39973716533374099c5500b9613c Mon Sep 17 00:00:00 2001 From: Artur Bodera Date: Wed, 8 Aug 2012 20:18:29 +0200 Subject: [PATCH 56/75] Fix phpdocs - wrong variable names. --- src/CallbackHandler.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index 841d4311d..f321731f9 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -52,9 +52,9 @@ class CallbackHandler /** * Constructor * - * @param string $event Event to which slot is subscribed - * @param string|array|object $callable PHP callback - * @param array $options Options used by the callable handler (e.g., priority) + * @param string $event Event to which slot is subscribed + * @param string|array|object|callable $callback PHP callback + * @param array $options Options used by the callable handler (e.g., priority) * @return void */ public function __construct($callback, array $metadata = array()) @@ -73,7 +73,7 @@ public function __construct($callback, array $metadata = array()) * instance, this method will pass the object to a WeakRef instance prior * to registering the callback. * - * @param callable $callable + * @param callable $callback * @return void */ protected function registerCallback($callback) @@ -262,7 +262,7 @@ public function getMetadatum($name) * * Validates that a static method call in PHP 5.4 will actually work * - * @param string $callable + * @param string $callback * @return true|array * @throws Exception\InvalidCallbackException if invalid */ From d3ffe881f876272969eb5828ad558ef6783dda82 Mon Sep 17 00:00:00 2001 From: Artur Bodera Date: Wed, 8 Aug 2012 20:26:41 +0200 Subject: [PATCH 57/75] More hand made fixes to last commits, phpdoc cleanup. --- src/CallbackHandler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index f321731f9..fed74fc73 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -27,7 +27,7 @@ class CallbackHandler { /** - * @var string|array PHP callable to invoke + * @var string|array|callable PHP callback to invoke */ protected $callback; @@ -54,7 +54,7 @@ class CallbackHandler * * @param string $event Event to which slot is subscribed * @param string|array|object|callable $callback PHP callback - * @param array $options Options used by the callable handler (e.g., priority) + * @param array $options Options used by the callback handler (e.g., priority) * @return void */ public function __construct($callback, array $metadata = array()) @@ -160,7 +160,7 @@ public function getCallback() /** * Invoke handler * - * @param array $args Arguments to pass to callable + * @param array $args Arguments to pass to callback * @return mixed */ public function call(array $args = array()) From 91b0e10c95889873d9ee717a1056a5121f943f29 Mon Sep 17 00:00:00 2001 From: RWOverdijk Date: Thu, 9 Aug 2012 09:24:56 +0200 Subject: [PATCH 58/75] Spaces added --- src/AbstractOptions.php | 2 +- test/OptionsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 251bfd0c3..594cc41d0 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -135,7 +135,7 @@ public function __unset($key) { try { $this->__set($key, null); - } catch(\InvalidArgumentException $e) { + } catch (\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException( 'The class property $' . $key . ' cannot be unset as' . ' NULL is an invalid value for it', diff --git a/test/OptionsTest.php b/test/OptionsTest.php index a834bde93..718e9d991 100644 --- a/test/OptionsTest.php +++ b/test/OptionsTest.php @@ -53,7 +53,7 @@ public function testConstructionWithNull() { try { $options = new TestOptions(null); - } catch(InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $this->fail("Unexpected InvalidArgumentException raised"); } } From 4b8f42a3ded4df25360173cd6bb73c6e33a8f4ef Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Thu, 30 Aug 2012 12:20:35 +0200 Subject: [PATCH 59/75] add unit tests add unit tests for has support --- test/HydratorTest.php | 22 +++++++++++++++++++ test/TestAsset/ClassMethodsCamelCase.php | 26 +++++++++++++++++++++++ test/TestAsset/ClassMethodsUnderscore.php | 26 +++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 62913ce5a..30615e116 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -60,10 +60,14 @@ public function testInitiateValues() $this->assertEquals($this->classMethodsCamelCase->getFooBarBaz(), '2'); $this->assertEquals($this->classMethodsCamelCase->getIsFoo(), true); $this->assertEquals($this->classMethodsCamelCase->isBar(), true); + $this->assertEquals($this->classMethodsCamelCase->getHasFoo(), true); + $this->assertEquals($this->classMethodsCamelCase->hasBar(), true); $this->assertEquals($this->classMethodsUnderscore->getFooBar(), '1'); $this->assertEquals($this->classMethodsUnderscore->getFooBarBaz(), '2'); $this->assertEquals($this->classMethodsUnderscore->getIsFoo(), true); $this->assertEquals($this->classMethodsUnderscore->isBar(), true); + $this->assertEquals($this->classMethodsUnderscore->getHasFoo(), true); + $this->assertEquals($this->classMethodsUnderscore->hasBar(), true); } public function testHydratorReflection() @@ -95,12 +99,18 @@ public function testHydratorClassMethodsCamelCase() $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); $test = $hydrator->hydrate( array( 'fooBar' => 'foo', 'fooBarBaz' => 'bar', 'isFoo' => false, 'isBar' => false, + 'hasFoo' => false, + 'hasBar' => false, ), $this->classMethodsCamelCase ); @@ -109,6 +119,8 @@ public function testHydratorClassMethodsCamelCase() $this->assertEquals($test->getFooBarBaz(), 'bar'); $this->assertEquals($test->getIsFoo(), false); $this->assertEquals($test->isBar(), false); + $this->assertEquals($test->getHasFoo(), false); + $this->assertEquals($test->hasBar(), false); } public function testHydratorClassMethodsCamelCaseWithSetterMissing() @@ -139,12 +151,20 @@ public function testHydratorClassMethodsUnderscore() $this->assertTrue(isset($datas['is_bar'])); $this->assertFalse(isset($datas['isBar'])); $this->assertEquals($datas['is_bar'], true); + $this->assertTrue(isset($datas['has_foo'])); + $this->assertFalse(isset($datas['hasFoo'])); + $this->assertEquals($datas['has_foo'], true); + $this->assertTrue(isset($datas['has_bar'])); + $this->assertFalse(isset($datas['hasBar'])); + $this->assertEquals($datas['has_bar'], true); $test = $hydrator->hydrate( array( 'foo_bar' => 'foo', 'foo_bar_baz' => 'bar', 'is_foo' => false, 'is_bar' => false, + 'has_foo' => false, + 'has_bar' => false, ), $this->classMethodsUnderscore ); @@ -153,6 +173,8 @@ public function testHydratorClassMethodsUnderscore() $this->assertEquals($test->getFooBarBaz(), 'bar'); $this->assertEquals($test->getIsFoo(), false); $this->assertEquals($test->isBar(), false); + $this->assertEquals($test->getHasFoo(), false); + $this->assertEquals($test->hasBar(), false); } public function testHydratorClassMethodsIgnoresInvalidValues() diff --git a/test/TestAsset/ClassMethodsCamelCase.php b/test/TestAsset/ClassMethodsCamelCase.php index 545a142f9..c00948847 100644 --- a/test/TestAsset/ClassMethodsCamelCase.php +++ b/test/TestAsset/ClassMethodsCamelCase.php @@ -20,6 +20,10 @@ class ClassMethodsCamelCase protected $isBar = true; + protected $hasFoo = true; + + protected $hasBar = true; + public function getFooBar() { return $this->fooBar; @@ -63,4 +67,26 @@ public function setIsBar($value) $this->isBar = $value; return $this; } + + public function getHasFoo() + { + return $this->hasFoo; + } + + public function setHasFoo($value) + { + $this->hasFoo = $value; + return $this; + } + + public function hasBar() + { + return $this->hasBar; + } + + public function setHasBar($value) + { + $this->hasBar = $value; + return $this; + } } diff --git a/test/TestAsset/ClassMethodsUnderscore.php b/test/TestAsset/ClassMethodsUnderscore.php index b30b458de..4ed1766fa 100644 --- a/test/TestAsset/ClassMethodsUnderscore.php +++ b/test/TestAsset/ClassMethodsUnderscore.php @@ -20,6 +20,10 @@ class ClassMethodsUnderscore protected $is_bar = true; + protected $has_foo = true; + + protected $has_bar = true; + public function getFooBar() { return $this->foo_bar; @@ -63,4 +67,26 @@ public function setIsBar($value) $this->is_bar = $value; return $this; } + + public function getHasFoo() + { + return $this->has_foo; + } + + public function setHasFoo($value) + { + $this->has_foo = $value; + return $this; + } + + public function hasBar() + { + return $this->has_bar; + } + + public function setHasBar($value) + { + $this->has_bar = $value; + return $this; + } } From 4c923be8357dc14a22f9cba8a08d0945f2621ce4 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 30 Aug 2012 15:10:41 -0500 Subject: [PATCH 60/75] [zendframework/zf2#2268] CS fixes - Trailing whitespace --- test/TestAsset/ClassMethodsCamelCase.php | 2 +- test/TestAsset/ClassMethodsUnderscore.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TestAsset/ClassMethodsCamelCase.php b/test/TestAsset/ClassMethodsCamelCase.php index c00948847..50ccd4ec6 100644 --- a/test/TestAsset/ClassMethodsCamelCase.php +++ b/test/TestAsset/ClassMethodsCamelCase.php @@ -67,7 +67,7 @@ public function setIsBar($value) $this->isBar = $value; return $this; } - + public function getHasFoo() { return $this->hasFoo; diff --git a/test/TestAsset/ClassMethodsUnderscore.php b/test/TestAsset/ClassMethodsUnderscore.php index 4ed1766fa..a51883805 100644 --- a/test/TestAsset/ClassMethodsUnderscore.php +++ b/test/TestAsset/ClassMethodsUnderscore.php @@ -67,7 +67,7 @@ public function setIsBar($value) $this->is_bar = $value; return $this; } - + public function getHasFoo() { return $this->has_foo; From f3afe2b7a0ff5c9c0d276316b47f0d32bb3461a9 Mon Sep 17 00:00:00 2001 From: Michel Hunziker Date: Fri, 31 Aug 2012 10:57:14 +0200 Subject: [PATCH 61/75] More phpDoc updates to match php code --- src/Hydrator/Reflection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php index be3d90d47..55d098050 100644 --- a/src/Hydrator/Reflection.php +++ b/src/Hydrator/Reflection.php @@ -64,7 +64,8 @@ public function hydrate(array $data, $object) * class has not been loaded. * * @static - * @param string|object $object + * @param string|object $input + * @throws Exception\InvalidArgumentException * @return array */ protected static function getReflProperties($input) From 6235867f2b132f28f680cb28a4e5cd8e4dd54f90 Mon Sep 17 00:00:00 2001 From: Michel Hunziker Date: Fri, 31 Aug 2012 17:30:38 +0200 Subject: [PATCH 62/75] Add missing @throws annotations --- src/AbstractOptions.php | 3 +++ src/ArrayUtils.php | 1 + src/CallbackHandler.php | 1 + src/Message.php | 2 ++ 4 files changed, 7 insertions(+) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 594cc41d0..86e69c3d5 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -40,6 +40,7 @@ public function __construct($options = null) /** * @param array|Traversable $options + * @throws Exception\InvalidArgumentException * @return void */ public function setFromArray($options) @@ -80,6 +81,7 @@ public function toArray() * @see ParameterObject::__set() * @param string $key * @param mixed $value + * @throws Exception\BadMethodCallException * @return void */ public function __set($key, $value) @@ -100,6 +102,7 @@ public function __set($key, $value) /** * @see ParameterObject::__get() * @param string $key + * @throws Exception\BadMethodCallException * @return mixed */ public function __get($key) diff --git a/src/ArrayUtils.php b/src/ArrayUtils.php index 866b784f6..1ec57dabd 100644 --- a/src/ArrayUtils.php +++ b/src/ArrayUtils.php @@ -172,6 +172,7 @@ public static function isHashTable($value, $allowEmpty = false) * * @param array|Traversable $iterator The array or Traversable object to convert * @param bool $recursive Recursively check all nested structures + * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object * @return array */ public static function iteratorToArray($iterator, $recursive = true) diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php index fe4309bb5..7e1f19df7 100644 --- a/src/CallbackHandler.php +++ b/src/CallbackHandler.php @@ -72,6 +72,7 @@ public function __construct($callback, array $metadata = array()) * to registering the callback. * * @param callable $callback + * @throws Exception\InvalidCallbackException * @return void */ protected function registerCallback($callback) diff --git a/src/Message.php b/src/Message.php index e5e8f088a..f8ec758ab 100644 --- a/src/Message.php +++ b/src/Message.php @@ -32,6 +32,7 @@ class Message implements MessageInterface * * @param string|int|array|Traversable $spec * @param mixed $value + * @throws Exception\InvalidArgumentException * @return Message */ public function setMetadata($spec, $value = null) @@ -57,6 +58,7 @@ public function setMetadata($spec, $value = null) * * @param null|string|int $key * @param null|mixed $default + * @throws Exception\InvalidArgumentException * @return mixed */ public function getMetadata($key = null, $default = null) From 17d9eedaba1de2a16099eb356372e6b5535cfa5d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 31 Aug 2012 14:44:59 -0500 Subject: [PATCH 63/75] [zendframework/zf2#2284][ZF2-507] Updated README - Notice about Date header --- .coveralls.yml | 3 + .gitattributes | 6 + .gitignore | 14 + .php_cs | 43 ++ .travis.yml | 35 ++ CONTRIBUTING.md | 229 +++++++++++ LICENSE.txt | 27 ++ README.md | 15 + composer.json | 45 +++ phpunit.xml.dist | 34 ++ phpunit.xml.travis | 34 ++ src/AbstractOptions.php | 147 +++++++ src/ArraySerializableInterface.php | 33 ++ src/ArrayStack.php | 37 ++ src/ArrayUtils.php | 248 ++++++++++++ src/CallbackHandler.php | 303 +++++++++++++++ src/DispatchableInterface.php | 19 + src/ErrorHandler.php | 107 +++++ src/Exception/BadMethodCallException.php | 21 + src/Exception/DomainException.php | 15 + src/Exception/ExceptionInterface.php | 15 + src/Exception/InvalidArgumentException.php | 15 + src/Exception/InvalidCallbackException.php | 21 + src/Exception/LogicException.php | 21 + src/Glob.php | 197 ++++++++++ src/Hydrator/AbstractHydrator.php | 117 ++++++ src/Hydrator/ArraySerializable.php | 77 ++++ src/Hydrator/ClassMethods.php | 124 ++++++ src/Hydrator/HydratorInterface.php | 36 ++ src/Hydrator/ObjectProperty.php | 69 ++++ src/Hydrator/Reflection.php | 90 +++++ src/Hydrator/Strategy/DefaultStrategy.php | 41 ++ src/Hydrator/Strategy/StrategyInterface.php | 35 ++ src/Hydrator/StrategyEnabledInterface.php | 54 +++ src/Message.php | 118 ++++++ src/MessageInterface.php | 21 + src/ParameterObjectInterface.php | 43 ++ src/Parameters.php | 116 ++++++ src/ParametersInterface.php | 42 ++ src/PriorityQueue.php | 302 +++++++++++++++ src/Request.php | 16 + src/RequestInterface.php | 15 + src/Response.php | 16 + src/ResponseInterface.php | 16 + src/SplPriorityQueue.php | 97 +++++ src/SplQueue.php | 59 +++ src/SplStack.php | 59 +++ test/ArrayUtilsTest.php | 366 ++++++++++++++++++ test/CallbackHandlerTest.php | 175 +++++++++ test/ErrorHandlerTest.php | 90 +++++ test/GlobTest.php | 35 ++ test/HydratorStrategyTest.php | 106 +++++ test/HydratorTest.php | 205 ++++++++++ test/MessageTest.php | 72 ++++ test/OptionsTest.php | 69 ++++ test/ParametersTest.php | 66 ++++ test/PriorityQueueTest.php | 155 ++++++++ test/SignalHandlers/InstanceMethod.php | 24 ++ test/SignalHandlers/Invokable.php | 19 + test/SignalHandlers/ObjectCallback.php | 21 + test/SignalHandlers/Overloadable.php | 19 + test/SplPriorityQueueTest.php | 77 ++++ test/SplQueueTest.php | 54 +++ test/SplStackTest.php | 56 +++ test/TestAsset/ClassMethodsCamelCase.php | 92 +++++ .../ClassMethodsCamelCaseMissing.php | 44 +++ test/TestAsset/ClassMethodsUnderscore.php | 92 +++++ test/TestAsset/HydratorStrategy.php | 64 +++ test/TestAsset/HydratorStrategyEntityA.php | 75 ++++ test/TestAsset/HydratorStrategyEntityB.php | 47 +++ test/TestAsset/Reflection.php | 30 ++ test/TestAsset/TestOptions.php | 31 ++ test/TestAsset/TestOptionsNoStrict.php | 33 ++ test/_files/alpha | 0 test/_files/beta | 0 test/_files/delta | 0 test/_files/gamma | 0 test/bootstrap.php | 34 ++ 78 files changed, 5398 insertions(+) create mode 100644 .coveralls.yml create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .php_cs create mode 100644 .travis.yml create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 phpunit.xml.travis create mode 100644 src/AbstractOptions.php create mode 100644 src/ArraySerializableInterface.php create mode 100644 src/ArrayStack.php create mode 100644 src/ArrayUtils.php create mode 100644 src/CallbackHandler.php create mode 100644 src/DispatchableInterface.php create mode 100644 src/ErrorHandler.php create mode 100644 src/Exception/BadMethodCallException.php create mode 100644 src/Exception/DomainException.php create mode 100644 src/Exception/ExceptionInterface.php create mode 100644 src/Exception/InvalidArgumentException.php create mode 100644 src/Exception/InvalidCallbackException.php create mode 100644 src/Exception/LogicException.php create mode 100644 src/Glob.php create mode 100644 src/Hydrator/AbstractHydrator.php create mode 100644 src/Hydrator/ArraySerializable.php create mode 100644 src/Hydrator/ClassMethods.php create mode 100644 src/Hydrator/HydratorInterface.php create mode 100644 src/Hydrator/ObjectProperty.php create mode 100644 src/Hydrator/Reflection.php create mode 100644 src/Hydrator/Strategy/DefaultStrategy.php create mode 100644 src/Hydrator/Strategy/StrategyInterface.php create mode 100644 src/Hydrator/StrategyEnabledInterface.php create mode 100644 src/Message.php create mode 100644 src/MessageInterface.php create mode 100644 src/ParameterObjectInterface.php create mode 100644 src/Parameters.php create mode 100644 src/ParametersInterface.php create mode 100644 src/PriorityQueue.php create mode 100644 src/Request.php create mode 100644 src/RequestInterface.php create mode 100644 src/Response.php create mode 100644 src/ResponseInterface.php create mode 100644 src/SplPriorityQueue.php create mode 100644 src/SplQueue.php create mode 100644 src/SplStack.php create mode 100644 test/ArrayUtilsTest.php create mode 100644 test/CallbackHandlerTest.php create mode 100644 test/ErrorHandlerTest.php create mode 100644 test/GlobTest.php create mode 100644 test/HydratorStrategyTest.php create mode 100644 test/HydratorTest.php create mode 100644 test/MessageTest.php create mode 100644 test/OptionsTest.php create mode 100644 test/ParametersTest.php create mode 100644 test/PriorityQueueTest.php create mode 100644 test/SignalHandlers/InstanceMethod.php create mode 100644 test/SignalHandlers/Invokable.php create mode 100644 test/SignalHandlers/ObjectCallback.php create mode 100644 test/SignalHandlers/Overloadable.php create mode 100644 test/SplPriorityQueueTest.php create mode 100644 test/SplQueueTest.php create mode 100644 test/SplStackTest.php create mode 100644 test/TestAsset/ClassMethodsCamelCase.php create mode 100644 test/TestAsset/ClassMethodsCamelCaseMissing.php create mode 100644 test/TestAsset/ClassMethodsUnderscore.php create mode 100644 test/TestAsset/HydratorStrategy.php create mode 100644 test/TestAsset/HydratorStrategyEntityA.php create mode 100644 test/TestAsset/HydratorStrategyEntityB.php create mode 100644 test/TestAsset/Reflection.php create mode 100644 test/TestAsset/TestOptions.php create mode 100644 test/TestAsset/TestOptionsNoStrict.php create mode 100644 test/_files/alpha create mode 100644 test/_files/beta create mode 100644 test/_files/delta create mode 100644 test/_files/gamma create mode 100644 test/bootstrap.php diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 000000000..53bda829c --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,3 @@ +coverage_clover: clover.xml +json_path: coveralls-upload.json +src_dir: src diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..85dc9a8c8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +/test export-ignore +/vendor export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.travis.yml export-ignore +.php_cs export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4cac0a218 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.buildpath +.DS_Store +.idea +.project +.settings/ +.*.sw* +.*.un~ +nbproject +tmp/ + +clover.xml +coveralls-upload.json +phpunit.xml +vendor diff --git a/.php_cs b/.php_cs new file mode 100644 index 000000000..bf4b799f3 --- /dev/null +++ b/.php_cs @@ -0,0 +1,43 @@ +notPath('TestAsset') + ->notPath('_files') + ->filter(function (SplFileInfo $file) { + if (strstr($file->getPath(), 'compatibility')) { + return false; + } + }); +$config = Symfony\CS\Config\Config::create(); +$config->level(null); +$config->fixers( + array( + 'braces', + 'duplicate_semicolon', + 'elseif', + 'empty_return', + 'encoding', + 'eof_ending', + 'function_call_space', + 'function_declaration', + 'indentation', + 'join_function', + 'line_after_namespace', + 'linefeed', + 'lowercase_keywords', + 'parenthesis', + 'multiple_use', + 'method_argument_space', + 'object_operator', + 'php_closing_tag', + 'psr0', + 'remove_lines_between_uses', + 'short_tag', + 'standardize_not_equal', + 'trailing_spaces', + 'unused_use', + 'visibility', + 'whitespacy_lines', + ) +); +$config->finder($finder); +return $config; diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..fe909ecb1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +sudo: false + +language: php + +matrix: + fast_finish: true + include: + - php: 5.5 + - php: 5.6 + env: + - EXECUTE_TEST_COVERALLS=true + - EXECUTE_CS_CHECK=true + - php: 7 + - php: hhvm + allow_failures: + - php: 7 + - php: hhvm + +notifications: + irc: "irc.freenode.org#zftalk.dev" + email: false + +before_install: + - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi + +install: + - composer install --no-interaction --prefer-source + +script: + - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit -c phpunit.xml.travis --coverage-clover clover.xml ; fi + - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit -c phpunit.xml.travis ; fi + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run --config-file=.php_cs ; fi + +after_script: + - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/coveralls ; fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..b87ecf039 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,229 @@ +# CONTRIBUTING + +## RESOURCES + +If you wish to contribute to Zend Framework, please be sure to +read/subscribe to the following resources: + + - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) + - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) + - ZF Contributor's mailing list: + Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html + Subscribe: zf-contributors-subscribe@lists.zend.com + - ZF Contributor's IRC channel: + #zftalk.dev on Freenode.net + +If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-stdlib/issues/new). + +## Reporting Potential Security Issues + +If you have encountered a potential security vulnerability, please **DO NOT** report it on the public +issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. +We will work with you to verify the vulnerability and patch it as soon as possible. + +When reporting issues, please provide the following information: + +- Component(s) affected +- A description indicating how to reproduce the issue +- A summary of the security vulnerability and impact + +We request that you contact us via the email address above and give the project +contributors a chance to resolve the vulnerability and issue a new release prior +to any public exposure; this helps protect users and provides them with a chance +to upgrade and/or update in order to protect their applications. + +For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). + +## RUNNING TESTS + +> ### Note: testing versions prior to 2.4 +> +> This component originates with Zend Framework 2. During the lifetime of ZF2, +> testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no +> changes were necessary. However, due to the migration, tests may not run on +> versions < 2.4. As such, you may need to change the PHPUnit dependency if +> attempting a fix on such a version. + +To run tests: + +- Clone the repository: + + ```console + $ git clone git@github.com:zendframework/zend-stdlib.git + $ cd + ``` + +- Install dependencies via composer: + + ```console + $ curl -sS https://getcomposer.org/installer | php -- + $ ./composer.phar install + ``` + + If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ + +- Run the tests via `phpunit` and the provided PHPUnit config, like in this example: + + ```console + $ ./vendor/bin/phpunit + ``` + +You can turn on conditional tests with the phpunit.xml file. +To do so: + + - Copy `phpunit.xml.dist` file to `phpunit.xml` + - Edit `phpunit.xml` to enable any specific functionality you + want to test, as well as to provide test values to utilize. + +## Running Coding Standards Checks + +This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding +standards checks, and provides configuration for our selected checks. +`php-cs-fixer` is installed by default via Composer. + +To run checks only: + +```console +$ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs +``` + +To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` +flag: + +```console +$ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs +``` + +If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure +they pass, and make sure you add and commit the changes after verification. + +## Recommended Workflow for Contributions + +Your first step is to establish a public repository from which we can +pull your work into the master repository. We recommend using +[GitHub](https://github.com), as that is where the component is already hosted. + +1. Setup a [GitHub account](http://github.com/), if you haven't yet +2. Fork the repository (http://github.com/zendframework/zend-stdlib) +3. Clone the canonical repository locally and enter it. + + ```console + $ git clone git://github.com:zendframework/zend-stdlib.git + $ cd zend-stdlib + ``` + +4. Add a remote to your fork; substitute your GitHub username in the command + below. + + ```console + $ git remote add {username} git@github.com:{username}/zend-stdlib.git + $ git fetch {username} + ``` + +### Keeping Up-to-Date + +Periodically, you should update your fork or personal repository to +match the canonical ZF repository. Assuming you have setup your local repository +per the instructions above, you can do the following: + + +```console +$ git checkout master +$ git fetch origin +$ git rebase origin/master +# OPTIONALLY, to keep your remote up-to-date - +$ git push {username} master:master +``` + +If you're tracking other branches -- for example, the "develop" branch, where +new feature development occurs -- you'll want to do the same operations for that +branch; simply substitute "develop" for "master". + +### Working on a patch + +We recommend you do each new feature or bugfix in a new branch. This simplifies +the task of code review as well as the task of merging your changes into the +canonical repository. + +A typical workflow will then consist of the following: + +1. Create a new local branch based off either your master or develop branch. +2. Switch to your new local branch. (This step can be combined with the + previous step with the use of `git checkout -b`.) +3. Do some work, commit, repeat as necessary. +4. Push the local branch to your remote repository. +5. Send a pull request. + +The mechanics of this process are actually quite trivial. Below, we will +create a branch for fixing an issue in the tracker. + +```console +$ git checkout -b hotfix/9295 +Switched to a new branch 'hotfix/9295' +``` + +... do some work ... + + +```console +$ git commit +``` + +... write your log message ... + + +```console +$ git push {username} hotfix/9295:hotfix/9295 +Counting objects: 38, done. +Delta compression using up to 2 threads. +Compression objects: 100% (18/18), done. +Writing objects: 100% (20/20), 8.19KiB, done. +Total 20 (delta 12), reused 0 (delta 0) +To ssh://git@github.com/{username}/zend-stdlib.git + b5583aa..4f51698 HEAD -> master +``` + +To send a pull request, you have two options. + +If using GitHub, you can do the pull request from there. Navigate to +your repository, select the branch you just created, and then select the +"Pull Request" button in the upper right. Select the user/organization +"zendframework" as the recipient. + +If using your own repository - or even if using GitHub - you can use `git +format-patch` to create a patchset for us to apply; in fact, this is +**recommended** for security-related patches. If you use `format-patch`, please +send the patches as attachments to: + +- zf-devteam@zend.com for patches without security implications +- zf-security@zend.com for security patches + +#### What branch to issue the pull request against? + +Which branch should you issue a pull request against? + +- For fixes against the stable release, issue the pull request against the + "master" branch. +- For new features, or fixes that introduce new elements to the public API (such + as new public methods or properties), issue the pull request against the + "develop" branch. + +### Branch Cleanup + +As you might imagine, if you are a frequent contributor, you'll start to +get a ton of branches both locally and on your remote. + +Once you know that your changes have been accepted to the master +repository, we suggest doing some cleanup of these branches. + +- Local branch cleanup + + ```console + $ git branch -d + ``` + +- Remote branch removal + + ```console + $ git push {username} : + ``` diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..6eab5aa14 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2005-2015, Zend Technologies USA, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Zend Technologies USA, Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 000000000..c065e86e3 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# zend-stdlib + +`Zend\Stdlib` is a set of components that implements general purpose utility +class for different scopes like: + +- array utilities functions; +- hydrators; +- json serialazible interfaces; +- general messaging systems; +- strin wrappers; +- etc + + +- File issues at https://github.com/zendframework/zend-stdlib/issues +- Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-stdlib diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..478ef0e41 --- /dev/null +++ b/composer.json @@ -0,0 +1,45 @@ +{ + "name": "zendframework/zend-stdlib", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "stdlib" + ], + "homepage": "https://github.com/zendframework/zend-stdlib", + "autoload": { + "psr-4": { + "Zend\\Stdlib": "src/" + } + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "zendframework/zend-eventmanager": "self.version", + "zendframework/zend-serializer": "self.version", + "zendframework/zend-servicemanager": "self.version", + "zendframework/zend-filter": "self.version", + "fabpot/php-cs-fixer": "1.7.*", + "satooshi/php-coveralls": "dev-master", + "phpunit/PHPUnit": "~4.0" + }, + "suggest": { + "zendframework/zend-eventmanager": "To support aggregate hydrator usage", + "zendframework/zend-serializer": "Zend\\Serializer component", + "zendframework/zend-servicemanager": "To support hydrator plugin manager usage", + "zendframework/zend-filter": "To support naming strategy hydrator usage", + "pecl-weakref": "Implementation of weak references for Stdlib\\CallbackHandler" + }, + "extra": { + "branch-alias": { + "dev-master": "2.4-dev", + "dev-develop": "2.5-dev" + } + }, + "autoload-dev": { + "psr-4": { + "ZendTest\\Stdlib\\": "test/" + } + } +} \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 000000000..2d77d4b78 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,34 @@ + + + + + ./test/ + + + + + + disable + + + + + + ./src + + + + + + + + + + + diff --git a/phpunit.xml.travis b/phpunit.xml.travis new file mode 100644 index 000000000..2d77d4b78 --- /dev/null +++ b/phpunit.xml.travis @@ -0,0 +1,34 @@ + + + + + ./test/ + + + + + + disable + + + + + + ./src + + + + + + + + + + + diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php new file mode 100644 index 000000000..594cc41d0 --- /dev/null +++ b/src/AbstractOptions.php @@ -0,0 +1,147 @@ +setFromArray($options); + } + } + + /** + * @param array|Traversable $options + * @return void + */ + public function setFromArray($options) + { + if (!is_array($options) && !$options instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Parameter provided to %s must be an array or Traversable', + __METHOD__ + )); + } + + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + } + + /** + * Cast to array + * + * @return array + */ + public function toArray() + { + $array = array(); + $transform = function($letters) { + $letter = array_shift($letters); + return '_' . strtolower($letter); + }; + foreach ($this as $key => $value) { + if ($key === '__strictMode__') continue; + $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key); + $array[$normalizedKey] = $value; + } + return $array; + } + + /** + * @see ParameterObject::__set() + * @param string $key + * @param mixed $value + * @return void + */ + public function __set($key, $value) + { + $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); + if ($this->__strictMode__ && !method_exists($this, $setter)) { + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $setter . ' setter method ' + . 'which must be defined' + ); + } elseif (!$this->__strictMode__ && !method_exists($this, $setter)) { + return; + } + $this->{$setter}($value); + } + + /** + * @see ParameterObject::__get() + * @param string $key + * @return mixed + */ + public function __get($key) + { + $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); + if (!method_exists($this, $getter)) { + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $getter . ' getter method ' + . 'which must be defined' + ); + } + return $this->{$getter}(); + } + + /** + * @see ParameterObject::__isset() + * @param string $key + * @return boolean + */ + public function __isset($key) + { + return null !== $this->__get($key); + } + + /** + * @see ParameterObject::__unset() + * @param string $key + * @return void + * @throws Exception\InvalidArgumentException + */ + public function __unset($key) + { + try { + $this->__set($key, null); + } catch (\InvalidArgumentException $e) { + throw new Exception\InvalidArgumentException( + 'The class property $' . $key . ' cannot be unset as' + . ' NULL is an invalid value for it', + 0, + $e + ); + } + } +} diff --git a/src/ArraySerializableInterface.php b/src/ArraySerializableInterface.php new file mode 100644 index 000000000..20dd4633c --- /dev/null +++ b/src/ArraySerializableInterface.php @@ -0,0 +1,33 @@ +getArrayCopy(); + return new ArrayIterator(array_reverse($array)); + } +} diff --git a/src/ArrayUtils.php b/src/ArrayUtils.php new file mode 100644 index 000000000..866b784f6 --- /dev/null +++ b/src/ArrayUtils.php @@ -0,0 +1,248 @@ + 0; + } + + /** + * Test whether an array contains one or more integer keys + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasIntegerKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_int')) > 0; + } + + /** + * Test whether an array contains one or more numeric keys. + * + * A numeric key can be one of the following: + * - an integer 1, + * - a string with a number '20' + * - a string with negative number: '-1000' + * - a float: 2.2120, -78.150999 + * - a string with float: '4000.99999', '-10.10' + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasNumericKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_numeric')) > 0; + } + + /** + * Test whether an array is a list + * + * A list is a collection of values assigned to continuous integer keys + * starting at 0 and ending at count() - 1. + * + * For example: + * + * $list = array( 'a','b','c','d' ); + * $list = array( + * 0 => 'foo', + * 1 => 'bar', + * 2 => array( 'foo' => 'baz' ), + * ); + * + * + * @param mixed $value + * @param bool $allowEmpty Is an empty list a valid list? + * @return bool + */ + public static function isList($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return (array_values($value) === $value); + } + + /** + * Test whether an array is a hash table. + * + * An array is a hash table if: + * + * 1. Contains one or more non-integer keys, or + * 2. Integer keys are non-continuous or misaligned (not starting with 0) + * + * For example: + * + * $hash = array( + * 'foo' => 15, + * 'bar' => false, + * ); + * $hash = array( + * 1995 => 'Birth of PHP', + * 2009 => 'PHP 5.3.0', + * 2012 => 'PHP 5.4.0', + * ); + * $hash = array( + * 'formElement, + * 'options' => array( 'debug' => true ), + * ); + * + * + * @param mixed $value + * @param bool $allowEmpty Is an empty array() a valid hash table? + * @return bool + */ + public static function isHashTable($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return (array_values($value) !== $value); + } + + /** + * Convert an iterator to an array. + * + * Converts an iterator to an array. The $recursive flag, on by default, + * hints whether or not you want to do so recursively. + * + * @param array|Traversable $iterator The array or Traversable object to convert + * @param bool $recursive Recursively check all nested structures + * @return array + */ + public static function iteratorToArray($iterator, $recursive = true) + { + if (!is_array($iterator) && !$iterator instanceof Traversable) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object'); + } + + if (!$recursive) { + if (is_array($iterator)) { + return $iterator; + } + + return iterator_to_array($iterator); + } + + if (method_exists($iterator, 'toArray')) { + return $iterator->toArray(); + } + + $array = array(); + foreach ($iterator as $key => $value) { + if (is_scalar($value)) { + $array[$key] = $value; + continue; + } + + if ($value instanceof Traversable) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + if (is_array($value)) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + $array[$key] = $value; + } + + return $array; + } + + /** + * Merge two arrays together. + * + * If an integer key exists in both arrays, the value from the second array + * will be appended the the first array. If both values are arrays, they + * are merged together, else the value of the second array overwrites the + * one of the first array. + * + * @param array $a + * @param array $b + * @return array + */ + public static function merge(array $a, array $b) + { + foreach ($b as $key => $value) { + if (array_key_exists($key, $a)) { + if (is_int($key)) { + $a[] = $value; + } elseif (is_array($value) && is_array($a[$key])) { + $a[$key] = self::merge($a[$key], $value); + } else { + $a[$key] = $value; + } + } else { + $a[$key] = $value; + } + } + + return $a; + } +} diff --git a/src/CallbackHandler.php b/src/CallbackHandler.php new file mode 100644 index 000000000..bf9c47e89 --- /dev/null +++ b/src/CallbackHandler.php @@ -0,0 +1,303 @@ +metadata = $metadata; + $this->registerCallback($callback); + } + + /** + * Registers the callback provided in the constructor + * + * If you have pecl/weakref {@see http://pecl.php.net/weakref} installed, + * this method provides additional behavior. + * + * If a callback is a functor, or an array callback composing an object + * instance, this method will pass the object to a WeakRef instance prior + * to registering the callback. + * + * @param callable $callback + * @return void + */ + protected function registerCallback($callback) + { + if (!is_callable($callback)) { + throw new Exception\InvalidCallbackException('Invalid callback provided; not callable'); + } + + if (null === self::$hasWeakRefExtension) { + self::$hasWeakRefExtension = class_exists('WeakRef'); + } + + // If pecl/weakref is not installed, simply store the callback and return + if (!self::$hasWeakRefExtension) { + $this->callback = $callback; + return; + } + + // If WeakRef exists, we want to use it. + + // If we have a non-closure object, pass it to WeakRef, and then + // register it. + if (is_object($callback) && !$callback instanceof Closure) { + $this->callback = new WeakRef($callback); + return; + } + + // If we have a string or closure, register as-is + if (!is_array($callback)) { + $this->callback = $callback; + return; + } + + list($target, $method) = $callback; + + // If we have an array callback, and the first argument is not an + // object, register as-is + if (!is_object($target)) { + $this->callback = $callback; + return; + } + + // We have an array callback with an object as the first argument; + // pass it to WeakRef, and then register the new callback + $target = new WeakRef($target); + $this->callback = array($target, $method); + } + + /** + * Retrieve registered callback + * + * @return callable + */ + public function getCallback() + { + $callback = $this->callback; + + // String callbacks -- simply return + if (is_string($callback)) { + return $callback; + } + + // WeakRef callbacks -- pull it out of the object and return it + if ($callback instanceof WeakRef) { + return $callback->get(); + } + + // Non-WeakRef object callback -- return it + if (is_object($callback)) { + return $callback; + } + + // Array callback with WeakRef object -- retrieve the object first, and + // then return + list($target, $method) = $callback; + if ($target instanceof WeakRef) { + return array($target->get(), $method); + } + + // Otherwise, return it + return $callback; + } + + /** + * Invoke handler + * + * @param array $args Arguments to pass to callback + * @return mixed + */ + public function call(array $args = array()) + { + $callback = $this->getCallback(); + + // WeakRef object will return null if the real object was disposed + if (null === $callback) { + return null; + } + + // Minor performance tweak, if the callback gets called more than once + if (!isset(self::$isPhp54)) { + self::$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); + } + + $argCount = count($args); + + if (self::$isPhp54 && is_string($callback)) { + $result = $this->validateStringCallbackFor54($callback); + + if ($result !== true && $argCount <= 3) { + $callback = $result; + // Minor performance tweak, if the callback gets called more + // than once + $this->callback = $result; + } + } + + // Minor performance tweak; use call_user_func() until > 3 arguments + // reached + switch ($argCount) { + case 0: + if (self::$isPhp54) { + return $callback(); + } + return call_user_func($callback); + case 1: + if (self::$isPhp54) { + return $callback(array_shift($args)); + } + return call_user_func($callback, array_shift($args)); + case 2: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + if (self::$isPhp54) { + return $callback($arg1, $arg2); + } + return call_user_func($callback, $arg1, $arg2); + case 3: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + $arg3 = array_shift($args); + if (self::$isPhp54) { + return $callback($arg1, $arg2, $arg3); + } + return call_user_func($callback, $arg1, $arg2, $arg3); + default: + return call_user_func_array($callback, $args); + } + } + + /** + * Invoke as functor + * + * @return mixed + */ + public function __invoke() + { + return $this->call(func_get_args()); + } + + /** + * Get all callback metadata + * + * @return array + */ + public function getMetadata() + { + return $this->metadata; + } + + /** + * Retrieve a single metadatum + * + * @param string $name + * @return mixed + */ + public function getMetadatum($name) + { + if (array_key_exists($name, $this->metadata)) { + return $this->metadata[$name]; + } + return null; + } + + /** + * Validate a static method call + * + * Validates that a static method call in PHP 5.4 will actually work + * + * @param string $callback + * @return true|array + * @throws Exception\InvalidCallbackException if invalid + */ + protected function validateStringCallbackFor54($callback) + { + if (!strstr($callback, '::')) { + return true; + } + + list($class, $method) = explode('::', $callback, 2); + + if (!class_exists($class)) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a class that does not exist', + $callback + )); + } + + $r = new ReflectionClass($class); + if (!$r->hasMethod($method)) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that does not exist', + $callback + )); + } + $m = $r->getMethod($method); + if (!$m->isStatic()) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that is not static', + $callback + )); + } + + // returning a non boolean value may not be nice for a validate method, + // but that allows the usage of a static string callback without using + // the call_user_func function. + return array($class, $method); + } +} diff --git a/src/DispatchableInterface.php b/src/DispatchableInterface.php new file mode 100644 index 000000000..33b0d1980 --- /dev/null +++ b/src/DispatchableInterface.php @@ -0,0 +1,19 @@ + GLOB_MARK, + self::GLOB_NOSORT => GLOB_NOSORT, + self::GLOB_NOCHECK => GLOB_NOCHECK, + self::GLOB_NOESCAPE => GLOB_NOESCAPE, + self::GLOB_BRACE => GLOB_BRACE, + self::GLOB_ONLYDIR => GLOB_ONLYDIR, + self::GLOB_ERR => GLOB_ERR, + ); + + $globFlags = 0; + + foreach ($flagMap as $internalFlag => $globFlag) { + if ($flags & $internalFlag) { + $globFlags |= $globFlag; + } + } + } else { + $globFlags = 0; + } + + return glob($pattern, $globFlags); + } + + /** + * Expand braces manually, then use the system glob. + * + * @param string $pattern + * @param integer $flags + * @return array|false + */ + protected static function fallbackGlob($pattern, $flags) + { + if (!$flags & self::GLOB_BRACE) { + return self::systemGlob($pattern, $flags); + } + + $flags &= ~self::GLOB_BRACE; + $length = strlen($pattern); + $paths = array(); + + if ($flags & self::GLOB_NOESCAPE) { + $begin = strpos($pattern, '{'); + } else { + $begin = 0; + + while (true) { + if ($begin === $length) { + $begin = false; + break; + } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) { + $begin++; + } elseif ($pattern[$begin] === '{') { + break; + } + + $begin++; + } + } + + if ($begin === false) { + return self::systemGlob($pattern, $flags); + } + + $next = self::nextBraceSub($pattern, $begin + 1, $flags); + + if ($next === null) { + return self::systemGlob($pattern, $flags); + } + + $rest = $next; + + while ($pattern[$rest] !== '}') { + $rest = self::nextBraceSub($pattern, $rest + 1, $flags); + + if ($rest === null) { + return self::systemGlob($pattern, $flags); + } + } + + $p = $begin + 1; + + while (true) { + $subPattern = substr($pattern, 0, $begin) + . substr($pattern, $p, $next - $p) + . substr($pattern, $rest + 1); + + $result = self::fallbackGlob($subPattern, $flags | self::GLOB_BRACE); + + if ($result) { + $paths = array_merge($paths, $result); + } + + if ($pattern[$next] === '}') { + break; + } + + $p = $next + 1; + $next = self::nextBraceSub($pattern, $p, $flags); + } + + return array_unique($paths); + } + + /** + * Find the end of the sub-pattern in a brace expression. + * + * @param string $pattern + * @param integer $begin + * @param integer $flags + * @return integer|null + */ + protected static function nextBraceSub($pattern, $begin, $flags) + { + $length = strlen($pattern); + $depth = 0; + $current = $begin; + + while ($current < $length) { + if (!$flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') { + if (++$current === $length) { + break; + } + + $current++; + } else { + if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) { + break; + } elseif ($pattern[$current++] === '{') { + $depth++; + } + } + } + + return ($current < $length ? $current : null); + } +} diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php new file mode 100644 index 000000000..4b320f18f --- /dev/null +++ b/src/Hydrator/AbstractHydrator.php @@ -0,0 +1,117 @@ +strategies = new ArrayObject(); + } + + /** + * Gets the strategy with the given name. + * + * @param string $name The name of the strategy to get. + * @return StrategyInterface + */ + public function getStrategy($name) + { + return $this->strategies[$name]; + } + + /** + * Checks if the strategy with the given name exists. + * + * @param string $name The name of the strategy to check for. + * @return bool + */ + public function hasStrategy($name) + { + return array_key_exists($name, $this->strategies); + } + + /** + * Adds the given strategy under the given name. + * + * @param string $name The name of the strategy to register. + * @param StrategyInterface $strategy The strategy to register. + * @return HydratorInterface + */ + public function addStrategy($name, StrategyInterface $strategy) + { + $this->strategies[$name] = $strategy; + return $this; + } + + /** + * Removes the strategy with the given name. + * + * @param string $name The name of the strategy to remove. + * @return HydratorInterface + */ + public function removeStrategy($name) + { + unset($this->strategies[$name]); + return $this; + } + + /** + * Converts a value for extraction. If no strategy exists the plain value is returned. + * + * @param string $name The name of the strategy to use. + * @param mixed $value The value that should be converted. + * @return mixed + */ + public function extractValue($name, $value) + { + if ($this->hasStrategy($name)) { + $strategy = $this->getStrategy($name); + $value = $strategy->extract($value); + } + return $value; + } + + /** + * Converts a value for hydration. If no strategy exists the plain value is returned. + * + * @param string $name The name of the strategy to use. + * @param mixed $value The value that should be converted. + * @return mixed + */ + public function hydrateValue($name, $value) + { + if ($this->hasStrategy($name)) { + $strategy = $this->getStrategy($name); + $value = $strategy->hydrate($value); + } + return $value; + } +} diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php new file mode 100644 index 000000000..3b6cb18e2 --- /dev/null +++ b/src/Hydrator/ArraySerializable.php @@ -0,0 +1,77 @@ +getArrayCopy(); + array_walk($data, function(&$value, $name) use ($self) { + $value = $self->extractValue($name, $value); + }); + return $data; + } + + /** + * Hydrate an object + * + * Hydrates an object by passing $data to either its exchangeArray() or + * populate() method. + * + * @param array $data + * @param object $object + * @return object + * @throws Exception\BadMethodCallException for an $object not implementing exchangeArray() or populate() + */ + public function hydrate(array $data, $object) + { + $self = $this; + array_walk($data, function(&$value, $name) use ($self) { + $value = $self->hydrateValue($name, $value); + }); + + if (is_callable(array($object, 'exchangeArray'))) { + $object->exchangeArray($data); + } elseif (is_callable(array($object, 'populate'))) { + $object->populate($data); + } else { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__ + )); + } + return $object; + } +} diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php new file mode 100644 index 000000000..d48082987 --- /dev/null +++ b/src/Hydrator/ClassMethods.php @@ -0,0 +1,124 @@ +underscoreSeparatedKeys = $underscoreSeparatedKeys; + } + + /** + * Extract values from an object with class methods + * + * Extracts the getter/setter of the given $object. + * + * @param object $object + * @return array + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function extract($object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + + $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)) { + continue; + } + if (preg_match('/^get/', $method)) { + // setter verification + $setter = preg_replace('/^get/', 'set', $method); + $attribute = substr($method, 3); + $attribute = lcfirst($attribute); + } else { + // setter verification + $setter = 'set' . ucfirst($method); + $attribute = $method; + } + if (!in_array($setter, $methods)) { + continue; + } + if ($this->underscoreSeparatedKeys) { + $attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute); + } + $attributes[$attribute] = $this->extractValue($attribute, $object->$method()); + } + + return $attributes; + } + + /** + * Hydrate an object by populating getter/setter methods + * + * Hydrates an object by getter/setter methods of the object. + * + * @param array $data + * @param object $object + * @return object + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function hydrate(array $data, $object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + + $transform = function($letters) { + $letter = substr(array_shift($letters), 1, 1); + return ucfirst($letter); + }; + + foreach ($data as $property => $value) { + if ($this->underscoreSeparatedKeys) { + $property = preg_replace_callback('/(_[a-z])/', $transform, $property); + } + $method = 'set' . ucfirst($property); + if (method_exists($object, $method)) { + $value = $this->hydrateValue($property, $value); + + $object->$method($value); + } + } + return $object; + } +} diff --git a/src/Hydrator/HydratorInterface.php b/src/Hydrator/HydratorInterface.php new file mode 100644 index 000000000..d014b3fdc --- /dev/null +++ b/src/Hydrator/HydratorInterface.php @@ -0,0 +1,36 @@ +extractValue($name, $value); + }); + return $data; + } + + /** + * Hydrate an object by populating public properties + * + * Hydrates an object by setting public properties of the object. + * + * @param array $data + * @param object $object + * @return object + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function hydrate(array $data, $object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + foreach ($data as $property => $value) { + $object->$property = $this->hydrateValue($property, $value); + } + return $object; + } +} diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php new file mode 100644 index 000000000..be3d90d47 --- /dev/null +++ b/src/Hydrator/Reflection.php @@ -0,0 +1,90 @@ +getName(); + + $value = $property->getValue($object); + $result[$propertyName] = $this->extractValue($propertyName, $value); + } + + return $result; + } + + /** + * Hydrate $object with the provided $data. + * + * @param array $data + * @param object $object + * @return object + */ + public function hydrate(array $data, $object) + { + $reflProperties = self::getReflProperties($object); + foreach ($data as $key => $value) { + if (isset($reflProperties[$key])) { + $reflProperties[$key]->setValue($object, $this->hydrateValue($key, $value)); + } + } + return $object; + } + + /** + * Get a reflection properties from in-memory cache and lazy-load if + * class has not been loaded. + * + * @static + * @param string|object $object + * @return array + */ + protected static function getReflProperties($input) + { + if (is_object($input)) { + $input = get_class($input); + } elseif (!is_string($input)) { + throw new Exception\InvalidArgumentException('Input must be a string or an object.'); + } + + if (!isset(self::$reflProperties[$input])) { + $reflClass = new ReflectionClass($input); + $reflProperties = $reflClass->getProperties(); + + foreach ($reflProperties as $key => $property) { + $property->setAccessible(true); + self::$reflProperties[$input][$property->getName()] = $property; + } + } + + return self::$reflProperties[$input]; + } +} diff --git a/src/Hydrator/Strategy/DefaultStrategy.php b/src/Hydrator/Strategy/DefaultStrategy.php new file mode 100644 index 000000000..0bdc2e761 --- /dev/null +++ b/src/Hydrator/Strategy/DefaultStrategy.php @@ -0,0 +1,41 @@ +metadata[$spec] = $value; + return $this; + } + if (!is_array($spec) && !$spec instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expected a string, array, or Traversable argument in first position; received "%s"', + (is_object($spec) ? get_class($spec) : gettype($spec)) + )); + } + foreach ($spec as $key => $value) { + $this->metadata[$key] = $value; + } + return $this; + } + + /** + * Retrieve all metadata or a single metadatum as specified by key + * + * @param null|string|int $key + * @param null|mixed $default + * @return mixed + */ + public function getMetadata($key = null, $default = null) + { + if (null === $key) { + return $this->metadata; + } + + if (!is_scalar($key)) { + throw new Exception\InvalidArgumentException('Non-scalar argument provided for key'); + } + + if (array_key_exists($key, $this->metadata)) { + return $this->metadata[$key]; + } + + return $default; + } + + /** + * Set message content + * + * @param mixed $value + * @return Message + */ + public function setContent($value) + { + $this->content = $value; + return $this; + } + + /** + * Get message content + * + * @return mixed + */ + public function getContent() + { + return $this->content; + } + + /** + * @return string + */ + public function toString() + { + $request = ''; + foreach ($this->getMetadata() as $key => $value) { + $request .= sprintf( + "%s: %s\r\n", + (string) $key, + (string) $value + ); + } + $request .= "\r\n" . $this->getContent(); + return $request; + } + +} diff --git a/src/MessageInterface.php b/src/MessageInterface.php new file mode 100644 index 000000000..067ce262f --- /dev/null +++ b/src/MessageInterface.php @@ -0,0 +1,21 @@ +exchangeArray($values); + } + + /** + * Populate from query string + * + * @param string $string + * @return void + */ + public function fromString($string) + { + $array = array(); + parse_str($string, $array); + $this->fromArray($array); + } + + /** + * Serialize to native PHP array + * + * @return array + */ + public function toArray() + { + return $this->getArrayCopy(); + } + + /** + * Serialize to query string + * + * @return string + */ + public function toString() + { + return http_build_query($this); + } + + /** + * Retrieve by key + * + * Returns null if the key does not exist. + * + * @param string $name + * @return mixed + */ + public function offsetGet($name) + { + if (isset($this[$name])) { + return parent::offsetGet($name); + } + return null; + } + + /** + * @param string $name + * @param mixed $default optional default value + * @return mixed + */ + public function get($name, $default = null) + { + if (isset($this[$name])) { + return parent::offsetGet($name); + } + return $default; + } + + /** + * @param string $name + * @param mixed $value + * @return $this + */ + public function set($name, $value) + { + $this[$name] = $value; + return $this; + } +} diff --git a/src/ParametersInterface.php b/src/ParametersInterface.php new file mode 100644 index 000000000..42d309540 --- /dev/null +++ b/src/ParametersInterface.php @@ -0,0 +1,42 @@ +items[] = array( + 'data' => $data, + 'priority' => $priority, + ); + $this->getQueue()->insert($data, $priority); + return $this; + } + + /** + * Remove an item from the queue + * + * This is different than {@link extract()}; its purpose is to dequeue an + * item. + * + * This operation is potentially expensive, as it requires + * re-initialization and re-population of the inner queue. + * + * Note: this removes the first item matching the provided item found. If + * the same item has been added multiple times, it will not remove other + * instances. + * + * @param mixed $datum + * @return boolean False if the item was not found, true otherwise. + */ + public function remove($datum) + { + $found = false; + foreach ($this->items as $key => $item) { + if ($item['data'] === $datum) { + $found = true; + break; + } + } + if ($found) { + unset($this->items[$key]); + $this->queue = null; + $queue = $this->getQueue(); + foreach ($this->items as $item) { + $queue->insert($item['data'], $item['priority']); + } + return true; + } + return false; + } + + /** + * Is the queue empty? + * + * @return bool + */ + public function isEmpty() + { + return (0 === $this->count()); + } + + /** + * How many items are in the queue? + * + * @return int + */ + public function count() + { + return count($this->items); + } + + /** + * Peek at the top node in the queue, based on priority. + * + * @return mixed + */ + public function top() + { + return $this->getIterator()->top(); + } + + /** + * Extract a node from the inner queue and sift up + * + * @return mixed + */ + public function extract() + { + return $this->getQueue()->extract(); + } + + /** + * Retrieve the inner iterator + * + * SplPriorityQueue acts as a heap, which typically implies that as items + * are iterated, they are also removed. This does not work for situations + * where the queue may be iterated multiple times. As such, this class + * aggregates the values, and also injects an SplPriorityQueue. This method + * retrieves the inner queue object, and clones it for purposes of + * iteration. + * + * @return SplPriorityQueue + */ + public function getIterator() + { + $queue = $this->getQueue(); + return clone $queue; + } + + /** + * Serialize the data structure + * + * @return string + */ + public function serialize() + { + return serialize($this->items); + } + + /** + * Unserialize a string into a PriorityQueue object + * + * Serialization format is compatible with {@link Zend\Stdlib\SplPriorityQueue} + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->insert($item['data'], $item['priority']); + } + } + + /** + * Serialize to an array + * + * By default, returns only the item data, and in the order registered (not + * sorted). You may provide one of the EXTR_* flags as an argument, allowing + * the ability to return priorities or both data and priority. + * + * @param int $flag + * @return array + */ + public function toArray($flag = self::EXTR_DATA) + { + switch ($flag) { + case self::EXTR_BOTH: + return $this->items; + break; + case self::EXTR_PRIORITY: + return array_map(function($item) { + return $item['priority']; + }, $this->items); + case self::EXTR_DATA: + default: + return array_map(function($item) { + return $item['data']; + }, $this->items); + } + } + + /** + * Specify the internal queue class + * + * Please see {@link getIterator()} for details on the necessity of an + * internal queue class. The class provided should extend SplPriorityQueue. + * + * @param string $class + * @return PriorityQueue + */ + public function setInternalQueueClass($class) + { + $this->queueClass = (string) $class; + return $this; + } + + /** + * Does the queue contain the given datum? + * + * @param mixed $datum + * @return bool + */ + public function contains($datum) + { + foreach ($this->items as $item) { + if ($item['data'] === $datum) { + return true; + } + } + return false; + } + + /** + * Does the queue have an item with the given priority? + * + * @param int $priority + * @return bool + */ + public function hasPriority($priority) + { + foreach ($this->items as $item) { + if ($item['priority'] === $priority) { + return true; + } + } + return false; + } + + /** + * Get the inner priority queue instance + * + * @return SplPriorityQueue + */ + protected function getQueue() + { + if (null === $this->queue) { + $this->queue = new $this->queueClass(); + if (!$this->queue instanceof \SplPriorityQueue) { + throw new \DomainException(sprintf( + 'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"', + get_class($this->queue) + )); + } + } + return $this->queue; + } + + /** + * Add support for deep cloning + * + * @return void + */ + public function __clone() + { + if (null !== $this->queue) { + $this->queue = clone $this->queue; + } + } +} diff --git a/src/Request.php b/src/Request.php new file mode 100644 index 000000000..b445e8a54 --- /dev/null +++ b/src/Request.php @@ -0,0 +1,16 @@ +serial--); + } + parent::insert($datum, $priority); + } + + + /** + * Serialize to an array + * + * Array will be priority => data pairs + * + * @return array + */ + public function toArray() + { + $array = array(); + foreach (clone $this as $item) { + $array[] = $item; + } + return $array; + } + + + /** + * Serialize + * + * @return string + */ + public function serialize() + { + $clone = clone $this; + $clone->setExtractFlags(self::EXTR_BOTH); + + $data = array(); + foreach ($clone as $item) { + $data[] = $item; + } + + return serialize($data); + } + + /** + * Deserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->insert($item['data'], $item['priority']); + } + } +} diff --git a/src/SplQueue.php b/src/SplQueue.php new file mode 100644 index 000000000..e753201d8 --- /dev/null +++ b/src/SplQueue.php @@ -0,0 +1,59 @@ +toArray()); + } + + /** + * Unserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->push($item); + } + } +} diff --git a/src/SplStack.php b/src/SplStack.php new file mode 100644 index 000000000..be3c76a42 --- /dev/null +++ b/src/SplStack.php @@ -0,0 +1,59 @@ +toArray()); + } + + /** + * Unserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->unshift($item); + } + } +} diff --git a/test/ArrayUtilsTest.php b/test/ArrayUtilsTest.php new file mode 100644 index 000000000..15333bb1d --- /dev/null +++ b/test/ArrayUtilsTest.php @@ -0,0 +1,366 @@ + 'bar' + )), + array(array( + '15', + 'foo' => 'bar', + 'baz' => array('baz') + )), + array(array( + 0 => false, + 2 => null + )), + array(array( + -100 => 'foo', + 100 => 'bar' + )), + array(array( + 1 => 0 + )), + ); + } + + public static function validLists() + { + return array( + array(array(null)), + array(array(true)), + array(array(false)), + array(array(0)), + array(array(-0.9999)), + array(array('string')), + array(array(new stdClass)), + array(array( + 0 => 'foo', + 1 => 'bar', + 2 => false, + 3 => null, + 4 => array(), + 5 => new stdClass() + )) + ); + } + + public static function validArraysWithStringKeys() + { + return array( + array(array( + 'foo' => 'bar', + )), + array(array( + 'bar', + 'foo' => 'bar', + 'baz', + )), + ); + } + + public static function validArraysWithNumericKeys() + { + return array( + array(array( + 'foo', + 'bar' + )), + array(array( + '0' => 'foo', + '1' => 'bar', + )), + array(array( + 'bar', + '1' => 'bar', + 3 => 'baz' + )), + array(array( + -10000 => null, + '-10000' => null, + )), + array(array( + '-00000.00009' => 'foo' + )), + array(array( + 1 => 0 + )), + ); + } + + public static function validArraysWithIntegerKeys() + { + return array( + array(array( + 'foo', + 'bar,' + )), + array(array( + 100 => 'foo', + 200 => 'bar' + )), + array(array( + -100 => 'foo', + 0 => 'bar', + 100 => 'baz' + )), + array(array( + 'foo', + 'bar', + 1000 => 'baz' + )), + ); + } + + public static function invalidArrays() + { + return array( + array(new stdClass()), + array(15), + array('foo'), + array(new ArrayObject()), + ); + } + + public static function mergeArrays() + { + return array( + 'merge-integer-and-string keys' => array( + array( + 'foo', + 3 => 'bar', + 'baz' => 'baz' + ), + array( + 'baz', + ), + array( + 0 => 'foo', + 3 => 'bar', + 'baz' => 'baz', + 4 => 'baz' + ) + ), + 'merge-arrays-recursively' => array( + array( + 'foo' => array( + 'baz' + ) + ), + array( + 'foo' => array( + 'baz' + ) + ), + array( + 'foo' => array( + 0 => 'baz', + 1 => 'baz' + ) + ) + ), + 'replace-string-keys' => array( + array( + 'foo' => 'bar', + 'bar' => array() + ), + array( + 'foo' => 'baz', + 'bar' => 'bat' + ), + array( + 'foo' => 'baz', + 'bar' => 'bat' + ) + ), + ); + } + + public static function validIterators() + { + return array( + array(array( + 'foo' => 'bar', + ), array( + 'foo' => 'bar', + )), + array(new Config(array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), + array(new ArrayObject(array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), + ); + } + + public static function invalidIterators() + { + return array( + array(null), + array(true), + array(false), + array(0), + array(1), + array(0.0), + array(1.0), + array('string'), + array(new stdClass), + ); + } + + /** + * @dataProvider validArraysWithStringKeys + */ + public function testValidArraysWithStringKeys($test) + { + $this->assertTrue(ArrayUtils::hasStringKeys($test)); + } + + /** + * @dataProvider validArraysWithIntegerKeys + */ + public function testValidArraysWithIntegerKeys($test) + { + $this->assertTrue(ArrayUtils::hasIntegerKeys($test)); + } + + /** + * @dataProvider validArraysWithNumericKeys + */ + public function testValidArraysWithNumericKeys($test) + { + $this->assertTrue(ArrayUtils::hasNumericKeys($test)); + } + + /** + * @dataProvider invalidArrays + */ + public function testInvalidArraysAlwaysReturnFalse($test) + { + $this->assertFalse(ArrayUtils::hasStringKeys($test, False)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, False)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, False)); + $this->assertFalse(ArrayUtils::isList($test, False)); + $this->assertFalse(ArrayUtils::isHashTable($test, False)); + + $this->assertFalse(ArrayUtils::hasStringKeys($test, false)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, false)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, false)); + $this->assertFalse(ArrayUtils::isList($test, false)); + $this->assertFalse(ArrayUtils::isHashTable($test, false)); + } + + /** + * @dataProvider validLists + */ + public function testLists($test) + { + $this->assertTrue(ArrayUtils::isList($test)); + $this->assertTrue(ArrayUtils::hasIntegerKeys($test)); + $this->assertTrue(ArrayUtils::hasNumericKeys($test)); + $this->assertFalse(ArrayUtils::hasStringKeys($test)); + $this->assertFalse(ArrayUtils::isHashTable($test)); + } + + /** + * @dataProvider validHashTables + */ + public function testHashTables($test) + { + $this->assertTrue(ArrayUtils::isHashTable($test)); + $this->assertFalse(ArrayUtils::isList($test)); + } + + public function testEmptyArrayReturnsTrue() + { + $test = array(); + $this->assertTrue(ArrayUtils::hasStringKeys($test, true)); + $this->assertTrue(ArrayUtils::hasIntegerKeys($test, true)); + $this->assertTrue(ArrayUtils::hasNumericKeys($test, true)); + $this->assertTrue(ArrayUtils::isList($test, true)); + $this->assertTrue(ArrayUtils::isHashTable($test, true)); + } + + public function testEmptyArrayReturnsFalse() + { + $test = array(); + $this->assertFalse(ArrayUtils::hasStringKeys($test, false)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, false)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, false)); + $this->assertFalse(ArrayUtils::isList($test, false)); + $this->assertFalse(ArrayUtils::isHashTable($test, false)); + } + + /** + * @dataProvider mergeArrays + */ + public function testMerge($a, $b, $expected) + { + $this->assertEquals($expected, ArrayUtils::merge($a, $b)); + } + + /** + * @dataProvider validIterators + */ + public function testValidIteratorsReturnArrayRepresentation($test, $expected) + { + $result = ArrayUtils::iteratorToArray($test); + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider invalidIterators + */ + public function testInvalidIteratorsRaiseInvalidArgumentException($test) + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $this->assertFalse(ArrayUtils::iteratorToArray($test)); + } +} diff --git a/test/CallbackHandlerTest.php b/test/CallbackHandlerTest.php new file mode 100644 index 000000000..124be3a90 --- /dev/null +++ b/test/CallbackHandlerTest.php @@ -0,0 +1,175 @@ +args)) { + unset($this->args); + } + } + + public function testCallbackShouldStoreMetadata() + { + $handler = new CallbackHandler('rand', array('event' => 'foo')); + $this->assertEquals('foo', $handler->getMetadatum('event')); + $this->assertEquals(array('event' => 'foo'), $handler->getMetadata()); + } + + public function testCallbackShouldBeStringIfNoHandlerPassedToConstructor() + { + $handler = new CallbackHandler('rand'); + $this->assertSame('rand', $handler->getCallback()); + } + + public function testCallbackShouldBeArrayIfHandlerPassedToConstructor() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); + $this->assertSame(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'), $handler->getCallback()); + } + + public function testCallShouldInvokeCallbackWithSuppliedArguments() + { + $handler = new CallbackHandler(array( $this, 'handleCall' )); + $args = array('foo', 'bar', 'baz'); + $handler->call($args); + $this->assertSame($args, $this->args); + } + + public function testPassingInvalidCallbackShouldRaiseInvalidCallbackExceptionDuringInstantiation() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('boguscallback'); + } + + public function testCallShouldReturnTheReturnValueOfTheCallback() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); + if (!is_callable(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'))) { + echo "\nClass exists? " . var_export(class_exists('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback'), 1) . "\n"; + echo "Include path: " . get_include_path() . "\n"; + } + $this->assertEquals('bar', $handler->call(array())); + } + + public function testStringCallbackResolvingToClassDefiningInvokeNameShouldRaiseException() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\Invokable'); + } + + public function testStringCallbackReferringToClassWithoutDefinedInvokeShouldRaiseException() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $class = new SignalHandlers\InstanceMethod(); + $handler = new CallbackHandler($class); + } + + public function testCallbackConsistingOfStringContextWithNonStaticMethodShouldNotRaiseExceptionButWillRaiseEStrict() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod', 'handler')); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $handler->call(); + restore_error_handler(); + $this->assertTrue($error); + } + + public function testStringCallbackConsistingOfNonStaticMethodShouldRaiseException() + { + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::handler'); + + if (version_compare(PHP_VERSION, '5.4.0rc1', '>=')) { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler->call(); + } else { + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $handler->call(); + restore_error_handler(); + $this->assertTrue($error); + } + } + + public function testStringStaticCallbackForPhp54() + { + if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::staticHandler'); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $result = $handler->call(); + restore_error_handler(); + $this->assertFalse($error); + $this->assertSame('staticHandler', $result); + } + + public function testStringStaticCallbackForPhp54WithMoreThan3Args() + { + if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::staticHandler'); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $result = $handler->call(array(1, 2, 3, 4)); + restore_error_handler(); + $this->assertFalse($error); + $this->assertSame('staticHandler', $result); + } + + public function testCallbackToClassImplementingOverloadingButNotInvocableShouldRaiseException() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('foo', array( 'ZendTest\\Stdlib\\SignalHandlers\\Overloadable', 'foo' )); + } + + public function testClosureCallbackShouldBeInvokedByCall() + { + $handler = new CallbackHandler(function () { + return 'foo'; + }); + $this->assertEquals('foo', $handler->call()); + } + + public function testHandlerShouldBeInvocable() + { + $handler = new CallbackHandler(array($this, 'handleCall')); + $handler('foo', 'bar'); + $this->assertEquals(array('foo', 'bar'), $this->args); + } + + public function handleCall() + { + $this->args = func_get_args(); + } +} diff --git a/test/ErrorHandlerTest.php b/test/ErrorHandlerTest.php new file mode 100644 index 000000000..f1613d4e1 --- /dev/null +++ b/test/ErrorHandlerTest.php @@ -0,0 +1,90 @@ +assertFalse(ErrorHandler::started()); + + ErrorHandler::start(); + $this->assertTrue(ErrorHandler::started()); + + ErrorHandler::stop(); + $this->assertFalse(ErrorHandler::started()); + } + + public function testStartThrowsLogicException() + { + ErrorHandler::start(); + + $this->setExpectedException('Zend\Stdlib\Exception\LogicException'); + ErrorHandler::start(); + } + + public function testStopThrowsLogicException() + { + $this->setExpectedException('Zend\Stdlib\Exception\LogicException'); + ErrorHandler::stop(); + } + + public function testReturnCatchedError() + { + ErrorHandler::start(); + strpos(); // Invalid argument list + $err = ErrorHandler::stop(); + + $this->assertInstanceOf('ErrorException', $err); + } + + public function testThrowCatchedError() + { + ErrorHandler::start(); + strpos(); // Invalid argument list + + $this->setExpectedException('ErrorException'); + ErrorHandler::stop(true); + } + + public function testAddErrors() + { + ErrorHandler::start(); + ErrorHandler::addError(1, 'test-msg1', 'test-file1', 100); + ErrorHandler::addError(2, 'test-msg2', 'test-file2', 200); + $err = ErrorHandler::stop(); + + $this->assertInstanceOf('ErrorException', $err); + $this->assertEquals('test-file2', $err->getFile()); + $this->assertEquals('test-msg2', $err->getMessage()); + $this->assertEquals(200, $err->getLine()); + $this->assertEquals(0, $err->getCode()); + $this->assertEquals(2, $err->getSeverity()); + + $previous = $err->getPrevious(); + $this->assertInstanceOf('ErrorException', $previous); + $this->assertEquals('test-file1', $previous->getFile()); + $this->assertEquals('test-msg1', $previous->getMessage()); + $this->assertEquals(100, $previous->getLine()); + $this->assertEquals(0, $previous->getCode()); + $this->assertEquals(1, $previous->getSeverity()); + } +} diff --git a/test/GlobTest.php b/test/GlobTest.php new file mode 100644 index 000000000..6eca47add --- /dev/null +++ b/test/GlobTest.php @@ -0,0 +1,35 @@ +markTestSkipped('GLOB_BRACE not available'); + } + + $this->assertEquals( + glob(__DIR__ . '/_files/{alph,bet}a', GLOB_BRACE), + Glob::glob(__DIR__ . '/_files/{alph,bet}a', Glob::GLOB_BRACE, true) + ); + } + + public function testNonMatchingGlobReturnsArray() + { + $result = Glob::glob('/some/path/{,*.}{this,orthis}.php', Glob::GLOB_BRACE); + $this->assertInternalType('array', $result); + } +} diff --git a/test/HydratorStrategyTest.php b/test/HydratorStrategyTest.php new file mode 100644 index 000000000..5a4c14dba --- /dev/null +++ b/test/HydratorStrategyTest.php @@ -0,0 +1,106 @@ +hydrator = new ClassMethods(); + } + + public function testAddingStrategy() + { + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + + $this->assertAttributeCount(1, 'strategies', $this->hydrator); + } + + public function testCheckStrategyEmpty() + { + $this->assertFalse($this->hydrator->hasStrategy('myStrategy')); + } + + public function testCheckStrategyNotEmpty() + { + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + + $this->assertTrue($this->hydrator->hasStrategy('myStrategy')); + } + + public function testRemovingStrategy() + { + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + $this->assertAttributeCount(1, 'strategies', $this->hydrator); + + $this->hydrator->removeStrategy('myStrategy'); + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + } + + public function testRetrieveStrategy() + { + $strategy = new TestAsset\HydratorStrategy(); + $this->hydrator->addStrategy('myStrategy', $strategy); + + $this->assertEquals($strategy, $this->hydrator->getStrategy('myStrategy')); + } + + public function testExtractingObjects() + { + $this->hydrator->addStrategy('entities', new TestAsset\HydratorStrategy()); + + $entityA = new TestAsset\HydratorStrategyEntityA(); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(222, 'BBB')); + + $attributes = $this->hydrator->extract($entityA); + + $this->assertContains(111, $attributes['entities']); + $this->assertContains(222, $attributes['entities']); + } + + public function testHydratingObjects() + { + $this->hydrator->addStrategy('entities', new TestAsset\HydratorStrategy()); + + $entityA = new TestAsset\HydratorStrategyEntityA(); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(222, 'BBB')); + + $attributes = $this->hydrator->extract($entityA); + $attributes['entities'][] = 333; + + $this->hydrator->hydrate($attributes, $entityA); + $entities = $entityA->getEntities(); + + $this->assertCount(3, $entities); + } +} diff --git a/test/HydratorTest.php b/test/HydratorTest.php new file mode 100644 index 000000000..30615e116 --- /dev/null +++ b/test/HydratorTest.php @@ -0,0 +1,205 @@ +classMethodsCamelCase = new ClassMethodsCamelCase(); + $this->classMethodsCamelCaseMissing = new ClassMethodsCamelCaseMissing(); + $this->classMethodsUnderscore = new ClassMethodsUnderscore(); + $this->reflection = new ReflectionAsset; + } + + public function testInitiateValues() + { + $this->assertEquals($this->classMethodsCamelCase->getFooBar(), '1'); + $this->assertEquals($this->classMethodsCamelCase->getFooBarBaz(), '2'); + $this->assertEquals($this->classMethodsCamelCase->getIsFoo(), true); + $this->assertEquals($this->classMethodsCamelCase->isBar(), true); + $this->assertEquals($this->classMethodsCamelCase->getHasFoo(), true); + $this->assertEquals($this->classMethodsCamelCase->hasBar(), true); + $this->assertEquals($this->classMethodsUnderscore->getFooBar(), '1'); + $this->assertEquals($this->classMethodsUnderscore->getFooBarBaz(), '2'); + $this->assertEquals($this->classMethodsUnderscore->getIsFoo(), true); + $this->assertEquals($this->classMethodsUnderscore->isBar(), true); + $this->assertEquals($this->classMethodsUnderscore->getHasFoo(), true); + $this->assertEquals($this->classMethodsUnderscore->hasBar(), true); + } + + public function testHydratorReflection() + { + $hydrator = new Reflection; + $datas = $hydrator->extract($this->reflection); + $this->assertTrue(isset($datas['foo'])); + $this->assertEquals($datas['foo'], '1'); + $this->assertTrue(isset($datas['fooBar'])); + $this->assertEquals($datas['fooBar'], '2'); + $this->assertTrue(isset($datas['fooBarBaz'])); + $this->assertEquals($datas['fooBarBaz'], '3'); + + $test = $hydrator->hydrate(array('foo' => 'foo', 'fooBar' => 'bar', 'fooBarBaz' => 'baz'), $this->reflection); + $this->assertEquals($test->foo, 'foo'); + $this->assertEquals($test->getFooBar(), 'bar'); + $this->assertEquals($test->getFooBarBaz(), 'baz'); + } + + public function testHydratorClassMethodsCamelCase() + { + $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); + $test = $hydrator->hydrate( + array( + 'fooBar' => 'foo', + 'fooBarBaz' => 'bar', + 'isFoo' => false, + 'isBar' => false, + 'hasFoo' => false, + 'hasBar' => false, + ), + $this->classMethodsCamelCase + ); + $this->assertSame($this->classMethodsCamelCase, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), 'bar'); + $this->assertEquals($test->getIsFoo(), false); + $this->assertEquals($test->isBar(), false); + $this->assertEquals($test->getHasFoo(), false); + $this->assertEquals($test->hasBar(), false); + } + + public function testHydratorClassMethodsCamelCaseWithSetterMissing() + { + $hydrator = new ClassMethods(false); + $datas = $hydrator->extract($this->classMethodsCamelCaseMissing); + $this->assertTrue(isset($datas['fooBar'])); + $this->assertEquals($datas['fooBar'], '1'); + $this->assertFalse(isset($datas['fooBarBaz'])); + $this->assertFalse(isset($datas['foo_bar'])); + $test = $hydrator->hydrate(array('fooBar' => 'foo'), $this->classMethodsCamelCaseMissing); + $this->assertSame($this->classMethodsCamelCaseMissing, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), '2'); + } + + public function testHydratorClassMethodsUnderscore() + { + $hydrator = new ClassMethods(true); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertTrue(isset($datas['foo_bar'])); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertTrue(isset($datas['foo_bar_baz'])); + $this->assertFalse(isset($datas['fooBar'])); + $this->assertTrue(isset($datas['is_foo'])); + $this->assertFalse(isset($datas['isFoo'])); + $this->assertEquals($datas['is_foo'], true); + $this->assertTrue(isset($datas['is_bar'])); + $this->assertFalse(isset($datas['isBar'])); + $this->assertEquals($datas['is_bar'], true); + $this->assertTrue(isset($datas['has_foo'])); + $this->assertFalse(isset($datas['hasFoo'])); + $this->assertEquals($datas['has_foo'], true); + $this->assertTrue(isset($datas['has_bar'])); + $this->assertFalse(isset($datas['hasBar'])); + $this->assertEquals($datas['has_bar'], true); + $test = $hydrator->hydrate( + array( + 'foo_bar' => 'foo', + 'foo_bar_baz' => 'bar', + 'is_foo' => false, + 'is_bar' => false, + 'has_foo' => false, + 'has_bar' => false, + ), + $this->classMethodsUnderscore + ); + $this->assertSame($this->classMethodsUnderscore, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), 'bar'); + $this->assertEquals($test->getIsFoo(), false); + $this->assertEquals($test->isBar(), false); + $this->assertEquals($test->getHasFoo(), false); + $this->assertEquals($test->hasBar(), false); + } + + public function testHydratorClassMethodsIgnoresInvalidValues() + { + $hydrator = new ClassMethods(true); + $data = array( + 'foo_bar' => '1', + 'foo_bar_baz' => '2', + 'invalid' => 'value' + ); + $test = $hydrator->hydrate($data, $this->classMethodsUnderscore); + $this->assertSame($this->classMethodsUnderscore, $test); + } + + public function testHydratorClassMethodsDefaultBehaviorIsConvertUnderscoreToCamelCase() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertTrue(isset($datas['foo_bar'])); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertTrue(isset($datas['foo_bar_baz'])); + $this->assertFalse(isset($datas['fooBar'])); + $test = $hydrator->hydrate(array('foo_bar' => 'foo', 'foo_bar_baz' => 'bar'), $this->classMethodsUnderscore); + $this->assertSame($this->classMethodsUnderscore, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), 'bar'); + } +} diff --git a/test/MessageTest.php b/test/MessageTest.php new file mode 100644 index 000000000..9f81add04 --- /dev/null +++ b/test/MessageTest.php @@ -0,0 +1,72 @@ +setContent('I can set content'); + $this->assertInstanceOf('Zend\Stdlib\Message', $ret); + $this->assertEquals('I can set content', $message->getContent()); + } + + public function testMessageCanSetAndGetMetadataKeyAsString() + { + $message = new Message(); + $ret = $message->setMetadata('foo', 'bar'); + $this->assertInstanceOf('Zend\Stdlib\Message', $ret); + $this->assertEquals('bar', $message->getMetadata('foo')); + $this->assertEquals(array('foo' => 'bar'), $message->getMetadata()); + } + + public function testMessageCanSetAndGetMetadataKeyAsArray() + { + $message = new Message(); + $ret = $message->setMetadata(array('foo' => 'bar')); + $this->assertInstanceOf('Zend\Stdlib\Message', $ret); + $this->assertEquals('bar', $message->getMetadata('foo')); + } + + public function testMessageGetMetadataWillUseDefaultValueIfNoneExist() + { + $message = new Message(); + $this->assertEquals('bar', $message->getMetadata('foo', 'bar')); + } + + public function testMessageThrowsExceptionOnInvalidKeyForMetadataSet() + { + $message = new Message(); + + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $message->setMetadata(new \stdClass()); + } + + public function testMessageThrowsExceptionOnInvalidKeyForMetadataGet() + { + $message = new Message(); + + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $message->getMetadata(new \stdClass()); + } + + public function testMessageToStringWorks() + { + $message = new Message(); + $message->setMetadata(array('Foo' => 'bar', 'One' => 'Two')); + $message->setContent('This is my content'); + $expected = "Foo: bar\r\nOne: Two\r\n\r\nThis is my content"; + $this->assertEquals($expected, $message->toString()); + } +} diff --git a/test/OptionsTest.php b/test/OptionsTest.php new file mode 100644 index 000000000..718e9d991 --- /dev/null +++ b/test/OptionsTest.php @@ -0,0 +1,69 @@ + 1)); + + $this->assertEquals(1, $options->test_field); + } + + public function testConstructionWithTraversable() + { + $config = new ArrayObject(array('test_field' => 1)); + $options = new TestOptions($config); + + $this->assertEquals(1, $options->test_field); + } + + public function testInvalidFieldThrowsException() + { + $this->setExpectedException('BadMethodCallException'); + $options = new TestOptions(array('foo' => 'bar')); + } + + public function testNonStrictOptionsDoesNotThrowException() + { + try { + $options = new TestOptionsNoStrict(array('foo' => 'bar')); + } catch (\Exception $e) { + $this->fail('Nonstrict options should not throw an exception'); + } + } + + + public function testConstructionWithNull() + { + try { + $options = new TestOptions(null); + } catch (InvalidArgumentException $e) { + $this->fail("Unexpected InvalidArgumentException raised"); + } + } + + public function testUnsetting() + { + $options = new TestOptions(array('test_field' => 1)); + + $this->assertEquals(true, isset($options->test_field)); + unset($options->testField); + $this->assertEquals(false, isset($options->test_field)); + } +} diff --git a/test/ParametersTest.php b/test/ParametersTest.php new file mode 100644 index 000000000..5ebba9b14 --- /dev/null +++ b/test/ParametersTest.php @@ -0,0 +1,66 @@ +assertInstanceOf('Zend\Stdlib\ParametersInterface', $parameters); + $this->assertInstanceOf('ArrayObject', $parameters); + $this->assertInstanceOf('ArrayAccess', $parameters); + $this->assertInstanceOf('Countable', $parameters); + $this->assertInstanceOf('Serializable', $parameters); + $this->assertInstanceOf('Traversable', $parameters); + } + + public function testParametersPersistNameAndValues() + { + $parameters = new Parameters(array('foo' => 'bar')); + $this->assertEquals('bar', $parameters['foo']); + $this->assertEquals('bar', $parameters->foo); + $parameters->offsetSet('baz', 5); + $this->assertEquals(5, $parameters->baz); + + $parameters->fromArray(array('bar' => 'foo')); + $this->assertEquals('foo', $parameters->bar); + + $parameters->fromString('bar=foo&five=5'); + $this->assertEquals('foo', $parameters->bar); + $this->assertEquals('5', $parameters->five); + $this->assertEquals(array('bar' => 'foo', 'five' => '5'), $parameters->toArray()); + $this->assertEquals('bar=foo&five=5', $parameters->toString()); + + $parameters->fromArray(array()); + $parameters->set('foof', 'barf'); + $this->assertEquals('barf', $parameters->get('foof')); + $this->assertEquals('barf', $parameters->foof); + + } + + public function testParametersOffsetgetReturnsNullIfNonexistentKeyIsProvided() + { + $parameters = new Parameters; + $this->assertNull($parameters->foo); + } + + public function testParametersGetReturnsDefaultValueIfNonExistent() + { + $parameters = new Parameters(); + + $this->assertEquals(5, $parameters->get('nonExistentProp', 5)); + } + +} diff --git a/test/PriorityQueueTest.php b/test/PriorityQueueTest.php new file mode 100644 index 000000000..47373fa04 --- /dev/null +++ b/test/PriorityQueueTest.php @@ -0,0 +1,155 @@ +queue = new PriorityQueue(); + $this->queue->insert('foo', 3); + $this->queue->insert('bar', 4); + $this->queue->insert('baz', 2); + $this->queue->insert('bat', 1); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->queue); + $unserialized = unserialize($s); + $count = count($this->queue); + $this->assertSame($count, count($unserialized), 'Expected count ' . $count . '; received ' . count($unserialized)); + + $expected = array(); + foreach ($this->queue as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test, 'Expected: ' . var_export($expected, 1) . "\nReceived:" . var_export($test, 1)); + } + + public function testRetrievingQueueAsArrayReturnsDataOnlyByDefault() + { + $expected = array( + 'foo', + 'bar', + 'baz', + 'bat', + ); + $test = $this->queue->toArray(); + $this->assertSame($expected, $test, var_export($test, 1)); + } + + public function testCanCastToArrayOfPrioritiesOnly() + { + $expected = array( + 3, + 4, + 2, + 1, + ); + $test = $this->queue->toArray(PriorityQueue::EXTR_PRIORITY); + $this->assertSame($expected, $test, var_export($test, 1)); + } + + public function testCanCastToArrayOfDataPriorityPairs() + { + $expected = array( + array('data' => 'foo', 'priority' => 3), + array('data' => 'bar', 'priority' => 4), + array('data' => 'baz', 'priority' => 2), + array('data' => 'bat', 'priority' => 1), + ); + $test = $this->queue->toArray(PriorityQueue::EXTR_BOTH); + $this->assertSame($expected, $test, var_export($test, 1)); + } + + public function testCanIterateMultipleTimesAndReceiveSameResults() + { + $expected = array('bar', 'foo', 'baz', 'bat'); + + for ($i = 1; $i < 3; $i++) { + $test = array(); + foreach ($this->queue as $item) { + $test[] = $item; + } + $this->assertEquals($expected, $test, 'Failed at iteration ' . $i); + } + } + + public function testCanRemoveItemFromQueue() + { + $this->queue->remove('baz'); + $expected = array('bar', 'foo', 'bat'); + $test = array(); + foreach ($this->queue as $item) { + $test[] = $item; + } + $this->assertEquals($expected, $test); + } + + public function testCanTestForExistenceOfItemInQueue() + { + $this->assertTrue($this->queue->contains('foo')); + $this->assertFalse($this->queue->contains('foobar')); + } + + public function testCanTestForExistenceOfPriorityInQueue() + { + $this->assertTrue($this->queue->hasPriority(3)); + $this->assertFalse($this->queue->hasPriority(1000)); + } + + public function testCloningAlsoClonesQueue() + { + $foo = new \stdClass(); + $foo->name = 'bar'; + + $queue = new PriorityQueue(); + $queue->insert($foo, 1); + $queue->insert($foo, 2); + + $queueClone = clone $queue; + + while (!$queue->isEmpty()) { + $this->assertSame($foo, $queue->top()); + $queue->remove($queue->top()); + } + + $this->assertTrue($queue->isEmpty()); + $this->assertFalse($queueClone->isEmpty()); + $this->assertEquals(2, $queueClone->count()); + + while (!$queueClone->isEmpty()) { + $this->assertSame($foo, $queueClone->top()); + $queueClone->remove($queueClone->top()); + } + + $this->assertTrue($queueClone->isEmpty()); + } +} diff --git a/test/SignalHandlers/InstanceMethod.php b/test/SignalHandlers/InstanceMethod.php new file mode 100644 index 000000000..af7d905ff --- /dev/null +++ b/test/SignalHandlers/InstanceMethod.php @@ -0,0 +1,24 @@ +queue = new SplPriorityQueue(); + $this->queue->insert('foo', 3); + $this->queue->insert('bar', 4); + $this->queue->insert('baz', 2); + $this->queue->insert('bat', 1); + } + + public function testMaintainsInsertOrderForDataOfEqualPriority() + { + $queue = new SplPriorityQueue(); + $queue->insert('foo', 1000); + $queue->insert('bar', 1000); + $queue->insert('baz', 1000); + $queue->insert('bat', 1000); + + $expected = array('foo', 'bar', 'baz', 'bat'); + $test = array(); + foreach ($queue as $datum) { + $test[] = $datum; + } + $this->assertEquals($expected, $test); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->queue); + $unserialized = unserialize($s); + $count = count($this->queue); + $this->assertSame($count, count($unserialized), 'Expected count ' . $count . '; received ' . count($unserialized)); + + $expected = array(); + foreach ($this->queue as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test, 'Expected: ' . var_export($expected, 1) . "\nReceived:" . var_export($test, 1)); + } + + public function testCanRetrieveQueueAsArray() + { + $expected = array( + 'bar', + 'foo', + 'baz', + 'bat', + ); + $test = $this->queue->toArray(); + $this->assertSame($expected, $test, var_export($test, 1)); + } +} diff --git a/test/SplQueueTest.php b/test/SplQueueTest.php new file mode 100644 index 000000000..5eb3af1ac --- /dev/null +++ b/test/SplQueueTest.php @@ -0,0 +1,54 @@ +queue = new SplQueue(); + $this->queue->push('foo'); + $this->queue->push('bar'); + $this->queue->push('baz'); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->queue); + $unserialized = unserialize($s); + $count = count($this->queue); + $this->assertSame($count, count($unserialized)); + + $expected = array(); + foreach ($this->queue as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test); + } + + public function testCanRetrieveQueueAsArray() + { + $expected = array('foo', 'bar', 'baz'); + $this->assertSame($expected, $this->queue->toArray()); + } +} diff --git a/test/SplStackTest.php b/test/SplStackTest.php new file mode 100644 index 000000000..18c2ea0db --- /dev/null +++ b/test/SplStackTest.php @@ -0,0 +1,56 @@ +stack = new SplStack(); + $this->stack->push('foo'); + $this->stack->push('bar'); + $this->stack->push('baz'); + $this->stack->push('bat'); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->stack); + $unserialized = unserialize($s); + $count = count($this->stack); + $this->assertSame($count, count($unserialized)); + + $expected = array(); + foreach ($this->stack as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test); + } + + public function testCanRetrieveQueueAsArray() + { + $expected = array('bat', 'baz', 'bar', 'foo'); + $test = $this->stack->toArray(); + $this->assertSame($expected, $test, var_export($test, 1)); + } +} diff --git a/test/TestAsset/ClassMethodsCamelCase.php b/test/TestAsset/ClassMethodsCamelCase.php new file mode 100644 index 000000000..50ccd4ec6 --- /dev/null +++ b/test/TestAsset/ClassMethodsCamelCase.php @@ -0,0 +1,92 @@ +fooBar; + } + + public function setFooBar($value) + { + $this->fooBar = $value; + return $this; + } + + public function getFooBarBaz() + { + return $this->fooBarBaz; + } + + public function setFooBarBaz($value) + { + $this->fooBarBaz = $value; + return $this; + } + + public function getIsFoo() + { + return $this->isFoo; + } + + public function setIsFoo($value) + { + $this->isFoo = $value; + return $this; + } + + public function isBar() + { + return $this->isBar; + } + + public function setIsBar($value) + { + $this->isBar = $value; + return $this; + } + + public function getHasFoo() + { + return $this->hasFoo; + } + + public function setHasFoo($value) + { + $this->hasFoo = $value; + return $this; + } + + public function hasBar() + { + return $this->hasBar; + } + + public function setHasBar($value) + { + $this->hasBar = $value; + return $this; + } +} diff --git a/test/TestAsset/ClassMethodsCamelCaseMissing.php b/test/TestAsset/ClassMethodsCamelCaseMissing.php new file mode 100644 index 000000000..7ad333e26 --- /dev/null +++ b/test/TestAsset/ClassMethodsCamelCaseMissing.php @@ -0,0 +1,44 @@ +fooBar; + } + + public function setFooBar($value) + { + $this->fooBar = $value; + return $this; + } + + public function getFooBarBaz() + { + return $this->fooBarBaz; + } + + /* + * comment to detection verification + * + public function setFooBarBaz($value) + { + $this->fooBarBaz = $value; + return $this; + } + */ +} diff --git a/test/TestAsset/ClassMethodsUnderscore.php b/test/TestAsset/ClassMethodsUnderscore.php new file mode 100644 index 000000000..a51883805 --- /dev/null +++ b/test/TestAsset/ClassMethodsUnderscore.php @@ -0,0 +1,92 @@ +foo_bar; + } + + public function setFooBar($value) + { + $this->foo_bar = $value; + return $this; + } + + public function getFooBarBaz() + { + return $this->foo_bar_baz; + } + + public function setFooBarBaz($value) + { + $this->foo_bar_baz = $value; + return $this; + } + + public function getIsFoo() + { + return $this->is_foo; + } + + public function setIsFoo($value) + { + $this->is_foo = $value; + return $this; + } + + public function isBar() + { + return $this->is_bar; + } + + public function setIsBar($value) + { + $this->is_bar = $value; + return $this; + } + + public function getHasFoo() + { + return $this->has_foo; + } + + public function setHasFoo($value) + { + $this->has_foo = $value; + return $this; + } + + public function hasBar() + { + return $this->has_bar; + } + + public function setHasBar($value) + { + $this->has_bar = $value; + return $this; + } +} diff --git a/test/TestAsset/HydratorStrategy.php b/test/TestAsset/HydratorStrategy.php new file mode 100644 index 000000000..abb7bf47e --- /dev/null +++ b/test/TestAsset/HydratorStrategy.php @@ -0,0 +1,64 @@ +simulatedStorageDevice = array(); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(111, 'AAA'); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(222, 'BBB'); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(333, 'CCC'); + } + + public function extract($value) + { + $result = array(); + foreach ($value as $instance) { + $result[] = $instance->getField1(); + } + return $result; + } + + public function hydrate($value) + { + $result = $value; + if (is_array($value)) { + $result = array(); + foreach ($value as $field1) { + $result[] = $this->findEntity($field1); + } + } + return $result; + } + + private function findEntity($field1) + { + $result = null; + foreach ($this->simulatedStorageDevice as $entity) { + if ($entity->getField1() == $field1) { + $result = $entity; + break; + } + } + return $result; + } +} diff --git a/test/TestAsset/HydratorStrategyEntityA.php b/test/TestAsset/HydratorStrategyEntityA.php new file mode 100644 index 000000000..641d44473 --- /dev/null +++ b/test/TestAsset/HydratorStrategyEntityA.php @@ -0,0 +1,75 @@ +entities = array(); + } + + public function addEntity(HydratorStrategyEntityB $entity) + { + $this->entities[] = $entity; + } + + public function getEntities() + { + return $this->entities; + } + + public function setEntities($entities) + { + $this->entities = $entities; + } + + public function getInputFilter() + { + if (!$this->inputFilter) { + $input = new Input(); + $input->setName('entities'); + $input->setRequired(false); + + $this->inputFilter = new InputFilter(); + $this->inputFilter->add($input); + } + + return $this->inputFilter; + } + + public function setInputFilter(InputFilterInterface $inputFilter) + { + $this->inputFilter = $inputFilter; + } + + // Add the getArrayCopy method so we can test the ArraySerializable hydrator: + public function getArrayCopy() + { + return get_object_vars($this); + } + + // Add the populate method so we can test the ArraySerializable hydrator: + public function populate($data) + { + foreach ($data as $name => $value) { + $this->$name = $value; + } + } +} diff --git a/test/TestAsset/HydratorStrategyEntityB.php b/test/TestAsset/HydratorStrategyEntityB.php new file mode 100644 index 000000000..e3be42ae1 --- /dev/null +++ b/test/TestAsset/HydratorStrategyEntityB.php @@ -0,0 +1,47 @@ +field1 = $field1; + $this->field2 = $field2; + } + + public function getField1() + { + return $this->field1; + } + + public function getField2() + { + return $this->field2; + } + + public function setField1($value) + { + $this->field1 = $value; + return $this; + } + + public function setField2($value) + { + $this->field2 = $value; + return $this; + } +} diff --git a/test/TestAsset/Reflection.php b/test/TestAsset/Reflection.php new file mode 100644 index 000000000..97ddc1b12 --- /dev/null +++ b/test/TestAsset/Reflection.php @@ -0,0 +1,30 @@ +fooBar; + } + + public function getFooBarBaz() + { + return $this->fooBarBaz; + } +} diff --git a/test/TestAsset/TestOptions.php b/test/TestAsset/TestOptions.php new file mode 100644 index 000000000..a2fbe9842 --- /dev/null +++ b/test/TestAsset/TestOptions.php @@ -0,0 +1,31 @@ +testField = $value; + } + + public function getTestField() + { + return $this->testField; + } +} diff --git a/test/TestAsset/TestOptionsNoStrict.php b/test/TestAsset/TestOptionsNoStrict.php new file mode 100644 index 000000000..cd1a557ba --- /dev/null +++ b/test/TestAsset/TestOptionsNoStrict.php @@ -0,0 +1,33 @@ +testField = $value; + } + + public function getTestField() + { + return $this->testField; + } +} diff --git a/test/_files/alpha b/test/_files/alpha new file mode 100644 index 000000000..e69de29bb diff --git a/test/_files/beta b/test/_files/beta new file mode 100644 index 000000000..e69de29bb diff --git a/test/_files/delta b/test/_files/delta new file mode 100644 index 000000000..e69de29bb diff --git a/test/_files/gamma b/test/_files/gamma new file mode 100644 index 000000000..e69de29bb diff --git a/test/bootstrap.php b/test/bootstrap.php new file mode 100644 index 000000000..570bf9e43 --- /dev/null +++ b/test/bootstrap.php @@ -0,0 +1,34 @@ + Date: Sat, 1 Sep 2012 22:09:27 +0200 Subject: [PATCH 64/75] Add more missing @throws annotations --- src/PriorityQueue.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PriorityQueue.php b/src/PriorityQueue.php index 372233f09..ecb8fbd31 100644 --- a/src/PriorityQueue.php +++ b/src/PriorityQueue.php @@ -272,6 +272,7 @@ public function hasPriority($priority) /** * Get the inner priority queue instance * + * @throws \DomainException * @return SplPriorityQueue */ protected function getQueue() From f585310079b066826f41bc81c7253350b661671c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 26 Sep 2012 19:14:36 +0200 Subject: [PATCH 65/75] Simplfy code --- src/Hydrator/ClassMethods.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index af5e43a57..f6280076b 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -63,12 +63,13 @@ public function extract($object) if (!preg_match('/^(get|has|is)[A-Z]\w*/', $method)) { continue; } + + $attribute = $method; if (preg_match('/^get/', $method)) { $attribute = substr($method, 3); $attribute = lcfirst($attribute); - } else { - $attribute = $method; } + if ($this->underscoreSeparatedKeys) { $attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute); } From 45d3f59d6ffcf89fae2bfd205fbe62ec2631efa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 26 Sep 2012 22:36:42 +0200 Subject: [PATCH 66/75] Toto --- src/Hydrator/ClassMethods.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index f6280076b..ad565f88d 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -63,7 +63,7 @@ public function extract($object) if (!preg_match('/^(get|has|is)[A-Z]\w*/', $method)) { continue; } - + $attribute = $method; if (preg_match('/^get/', $method)) { $attribute = substr($method, 3); From 1063833c6d0be04e1b6b0cbeb368355854770fe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Thu, 27 Sep 2012 11:03:15 +0200 Subject: [PATCH 67/75] Updated tests --- test/HydratorTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 1e4432e54..b44fca5f0 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -188,4 +188,19 @@ public function testHydratorClassMethodsDefaultBehaviorIsConvertUnderscoreToCame $this->assertEquals($test->getFooBar(), 'foo'); $this->assertEquals($test->getFooBarBaz(), 'bar'); } + + public function testHydratorClassMethodsCamelCaseWithSetterMissing() + { + $hydrator = new ClassMethods(false); + + $datas = $hydrator->extract($this->classMethodsCamelCaseMissing); + $this->assertTrue(isset($datas['fooBar'])); + $this->assertEquals($datas['fooBar'], '1'); + $this->assertTrue(isset($datas['fooBarBaz'])); + $this->assertFalse(isset($datas['foo_bar'])); + $test = $hydrator->hydrate(array('fooBar' => 'foo', 'fooBarBaz' => 1), $this->classMethodsCamelCaseMissing); + $this->assertSame($this->classMethodsCamelCaseMissing, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), '2'); + } } From fe89de66749b4ef59443a43428da1d249697c30d Mon Sep 17 00:00:00 2001 From: Martin Meredith Date: Fri, 5 Oct 2012 15:19:37 +0100 Subject: [PATCH 68/75] Remove unused Uses --- test/OptionsTest.php | 1 - test/PriorityQueueTest.php | 1 - test/TestAsset/HydratorStrategyEntityB.php | 1 - 3 files changed, 3 deletions(-) diff --git a/test/OptionsTest.php b/test/OptionsTest.php index 718e9d991..bf226e7ec 100644 --- a/test/OptionsTest.php +++ b/test/OptionsTest.php @@ -13,7 +13,6 @@ use ArrayObject; use ZendTest\Stdlib\TestAsset\TestOptions; use ZendTest\Stdlib\TestAsset\TestOptionsNoStrict; -use ZendTest\Stdlib\TestAsset\TestTraversable; use Zend\Stdlib\Exception\InvalidArgumentException; class OptionsTest extends \PHPUnit_Framework_TestCase diff --git a/test/PriorityQueueTest.php b/test/PriorityQueueTest.php index 47373fa04..6c5ce77b2 100644 --- a/test/PriorityQueueTest.php +++ b/test/PriorityQueueTest.php @@ -11,7 +11,6 @@ namespace ZendTest\Stdlib; use Zend\Stdlib\PriorityQueue; -use SplPriorityQueue; /** * @category Zend diff --git a/test/TestAsset/HydratorStrategyEntityB.php b/test/TestAsset/HydratorStrategyEntityB.php index e3be42ae1..d31f8c73c 100644 --- a/test/TestAsset/HydratorStrategyEntityB.php +++ b/test/TestAsset/HydratorStrategyEntityB.php @@ -10,7 +10,6 @@ namespace ZendTest\Stdlib\TestAsset; -use Zend\InputFilter\InputFilterAwareInterface; class HydratorStrategyEntityB { From 97f0f4c6966697f8b8aaab843803f29d3f9e1e02 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 25 Dec 2012 02:22:58 +0700 Subject: [PATCH 69/75] remove trailing_spaces --- src/Glob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Glob.php b/src/Glob.php index cda6d0a17..b01d38d80 100644 --- a/src/Glob.php +++ b/src/Glob.php @@ -44,7 +44,7 @@ public static function glob($pattern, $flags, $forceFallback = false) if (!defined('GLOB_BRACE') || $forceFallback) { return static::fallbackGlob($pattern, $flags); } - + return static::systemGlob($pattern, $flags); } From 1d0e607d53cafff968c7a34582e586e1e5f89e2c Mon Sep 17 00:00:00 2001 From: ingo Date: Sat, 5 Jan 2013 04:53:31 +0100 Subject: [PATCH 70/75] Added tests --- test/HydratorTest.php | 4 +++ .../ClassMethodsInvalidParameter.php | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/test/HydratorTest.php b/test/HydratorTest.php index f8cddf9ce..7717099cc 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -215,5 +215,9 @@ public function testHydratorClassMethodsWithServiceManager() { $hydrator = new ClassMethods(false); $datas = $hydrator->extract($this->classMethodsInvalidParameter); + + $this->assertTrue($datas['hasBar']); + $this->assertEquals('Bar', $datas['foo']); + $this->assertFalse($datas['isBla']); } } diff --git a/test/TestAsset/ClassMethodsInvalidParameter.php b/test/TestAsset/ClassMethodsInvalidParameter.php index 471577373..cf9338865 100644 --- a/test/TestAsset/ClassMethodsInvalidParameter.php +++ b/test/TestAsset/ClassMethodsInvalidParameter.php @@ -15,4 +15,29 @@ public function hasAlias($alias) { return $alias; } + + public function getTest($foo) + { + return $foo; + } + + public function isTest($bar) + { + return $bar; + } + + public function hasBar() + { + return true; + } + + public function getFoo() + { + return "Bar"; + } + + public function isBla() + { + return false; + } } From dc54cde6dc3376f49d0cceb46c8a4ad1cb3bfc07 Mon Sep 17 00:00:00 2001 From: David Kidd Date: Wed, 9 Jan 2013 09:38:04 -0500 Subject: [PATCH 71/75] Refactored Zend\Stdlib\DateTime::createISO8601Date to Zend\Stdlib\DateTime::createFromISO8601, updated documentation --- src/DateTime.php | 6 ++++-- test/DateTimeTest.php | 7 +++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/DateTime.php b/src/DateTime.php index 397793899..ba388e135 100644 --- a/src/DateTime.php +++ b/src/DateTime.php @@ -23,13 +23,15 @@ class DateTime extends \DateTime { /** - * Creates a DateTime object from a string and (optional) timezone. + * The DateTime::ISO8601 constant used by php's native DateTime object does + * not allow for fractions of a second. This function better handles ISO8601 + * formatted date strings. * * @param string $time * @param DateTimeZone $timezone * @return mixed */ - public static function createISO8601Date($time, DateTimeZone $timezone = null){ + public static function createFromISO8601($time, DateTimeZone $timezone = null){ $format = self::ISO8601; if (isset($time[19]) && $time[19] === '.') { $format = 'Y-m-d\TH:i:s.uO'; diff --git a/test/DateTimeTest.php b/test/DateTimeTest.php index a401ecc91..e981f948e 100644 --- a/test/DateTimeTest.php +++ b/test/DateTimeTest.php @@ -5,7 +5,7 @@ * @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_Feed + * @package Zend_Stdlib */ namespace ZendTest\Stdlib; @@ -27,7 +27,7 @@ public function testCreatesIS08601WithoutFractionalSeconds() { $time = '2009-03-07T08:03:50Z'; - $date = DateTime::createISO8601Date($time); + $date = DateTime::createFromISO8601($time); $this->assertEquals( \DateTime::createFromFormat(\DateTime::ISO8601, $time), $date); } @@ -36,11 +36,10 @@ public function testCreatesIS08601WithFractionalSeconds() { $time = '2009-03-07T08:03:50.012Z'; - $date = DateTime::createISO8601Date($time); + $date = DateTime::createFromISO8601($time); $standard = \DateTime::createFromFormat('Y-m-d\TH:i:s.uO', $time); $this->assertEquals( $standard, $date); } - } \ No newline at end of file From 7d1820b470f05145c6cb5b3125dcb5ab47fcb556 Mon Sep 17 00:00:00 2001 From: David Kidd Date: Wed, 9 Jan 2013 10:49:44 -0500 Subject: [PATCH 72/75] Fixed annotation of ZendTest\DateTimeTest --- test/DateTimeTest.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/DateTimeTest.php b/test/DateTimeTest.php index e981f948e..5929da034 100644 --- a/test/DateTimeTest.php +++ b/test/DateTimeTest.php @@ -13,13 +13,12 @@ use Zend\Stdlib\DateTime; /** -* @category Zend -* @package Zend_Feed -* @subpackage UnitTests -* @group Zend_Feed -* @group Zend_Feed_Reader -*/ -class AtomTest extends \PHPUnit_Framework_TestCase + * @category Zend + * @package Zend_Stdlib + * @subpackage UnitTests + * @group Zend_Stdlib + */ +class DateTimeTest extends \PHPUnit_Framework_TestCase { public $dateTime; From 45016f956c4d9868daf4b9dd3b28fccfc718e1ae Mon Sep 17 00:00:00 2001 From: David Kidd Date: Wed, 9 Jan 2013 12:47:41 -0500 Subject: [PATCH 73/75] Ran php-cs-fixer on Zend\Stdlib\DateTime.php and ZendTest\Stdlib\DateTimeTest.php --- src/DateTime.php | 22 ++++++++++++---------- test/DateTimeTest.php | 16 ++++++++-------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/DateTime.php b/src/DateTime.php index ba388e135..a3d8a651d 100644 --- a/src/DateTime.php +++ b/src/DateTime.php @@ -20,27 +20,29 @@ * @category Zend * @package Zend_Stdlib */ -class DateTime extends \DateTime { - +class DateTime extends \DateTime +{ /** * The DateTime::ISO8601 constant used by php's native DateTime object does * not allow for fractions of a second. This function better handles ISO8601 * formatted date strings. - * - * @param string $time - * @param DateTimeZone $timezone + * + * @param string $time + * @param DateTimeZone $timezone * @return mixed */ - public static function createFromISO8601($time, DateTimeZone $timezone = null){ + public static function createFromISO8601($time, DateTimeZone $timezone = null) + { $format = self::ISO8601; if (isset($time[19]) && $time[19] === '.') { $format = 'Y-m-d\TH:i:s.uO'; } - - if( $timezone !== null ) + + if ($timezone !== null) { return self::createFromFormat($format, $time, $timezone); + } return self::createFromFormat($format, $time); } - -} \ No newline at end of file + +} diff --git a/test/DateTimeTest.php b/test/DateTimeTest.php index 5929da034..45d4f8909 100644 --- a/test/DateTimeTest.php +++ b/test/DateTimeTest.php @@ -21,24 +21,24 @@ class DateTimeTest extends \PHPUnit_Framework_TestCase { public $dateTime; - + public function testCreatesIS08601WithoutFractionalSeconds() { $time = '2009-03-07T08:03:50Z'; - + $date = DateTime::createFromISO8601($time); - + $this->assertEquals( \DateTime::createFromFormat(\DateTime::ISO8601, $time), $date); } - + public function testCreatesIS08601WithFractionalSeconds() { $time = '2009-03-07T08:03:50.012Z'; - + $date = DateTime::createFromISO8601($time); - + $standard = \DateTime::createFromFormat('Y-m-d\TH:i:s.uO', $time); - + $this->assertEquals( $standard, $date); } -} \ No newline at end of file +} From d33133a5e30be0a8ba38843411216e84b219b80a Mon Sep 17 00:00:00 2001 From: Maks3w Date: Wed, 9 Jan 2013 20:53:45 +0100 Subject: [PATCH 74/75] [zendframework/zf2#3375] Update copyright year --- src/DateTime.php | 2 +- test/DateTimeTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DateTime.php b/src/DateTime.php index a3d8a651d..032fc94ff 100644 --- a/src/DateTime.php +++ b/src/DateTime.php @@ -3,7 +3,7 @@ * 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) + * @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 */ diff --git a/test/DateTimeTest.php b/test/DateTimeTest.php index 45d4f8909..f6c2e0553 100644 --- a/test/DateTimeTest.php +++ b/test/DateTimeTest.php @@ -3,7 +3,7 @@ * 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) + * @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 */ From a385e2a8dae6ab96ac8976cd9c3a02ecad233822 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 14 Jan 2013 10:41:22 -0600 Subject: [PATCH 75/75] [zendframework/zf2#3352] Import ReflectionMethod --- src/Hydrator/ClassMethods.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index b756d9e38..0f3dea2e2 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -10,6 +10,7 @@ namespace Zend\Stdlib\Hydrator; +use ReflectionMethod; use Zend\Stdlib\Exception; /** @@ -64,7 +65,7 @@ public function extract($object) continue; } - $reflectionMethod = new \ReflectionMethod(get_class($object) . '::' . $method); + $reflectionMethod = new ReflectionMethod(get_class($object) . '::' . $method); if ($reflectionMethod->getNumberOfParameters() > 0) { continue; }