From c7c559127c7217fc1bd8d521cfbad07f11f9f851 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 2 Aug 2012 06:19:09 +0200 Subject: [PATCH 001/126] Added module class map cache ability. - ModuleAutoloader uses now Exception\InvalidArgumentException instead of the built-in InvalidArgumentException --- library/Zend/Loader/ModuleAutoloader.php | 34 ++++- .../ModuleManager/Listener/ConfigListener.php | 22 +-- .../Listener/DefaultListenerAggregate.php | 4 +- .../Listener/ListenerOptions.php | 64 ++++++++ .../Listener/ModuleLoaderListener.php | 140 ++++++++++++++++++ tests/Zend/Loader/ModuleAutoloaderTest.php | 12 ++ tests/Zend/Loader/_files/BarModule/Module.php | 15 ++ tests/Zend/Loader/_files/PharModuleMap.phar | Bin 0 -> 6824 bytes tests/Zend/Loader/_files/_buildPhars.php | 1 + .../Listener/ModuleLoaderListenerTest.php | 96 ++++++++++++ 10 files changed, 367 insertions(+), 21 deletions(-) create mode 100644 library/Zend/ModuleManager/Listener/ModuleLoaderListener.php create mode 100644 tests/Zend/Loader/_files/BarModule/Module.php create mode 100644 tests/Zend/Loader/_files/PharModuleMap.phar create mode 100644 tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php diff --git a/library/Zend/Loader/ModuleAutoloader.php b/library/Zend/Loader/ModuleAutoloader.php index 0ce4db807df..9e7eecc7a0c 100644 --- a/library/Zend/Loader/ModuleAutoloader.php +++ b/library/Zend/Loader/ModuleAutoloader.php @@ -94,6 +94,29 @@ public function setOptions($options) return $this; } + /** + * Retrieves the class map for all loaded modules. + * + * @return array + */ + public function getModuleClassMap() + { + return $this->moduleClassMap; + } + + /** + * Sets the class map used to speed up the module autoloading. + * + * @param array $classmap + * @return ModuleLoader + */ + public function setModuleClassMap(array $classmap) + { + $this->moduleClassMap = $classmap; + + return $this; + } + /** * Autoload a class * @@ -109,6 +132,11 @@ public function autoload($class) return false; } + if (isset($this->moduleClassMap[$class])) { + require_once $this->moduleClassMap[$class]; + return $class; + } + $moduleName = substr($class, 0, -7); if (isset($this->explicitPaths[$moduleName])) { $classLoaded = $this->loadModuleFromDir($this->explicitPaths[$moduleName], $class); @@ -268,7 +296,8 @@ public function unregister() public function registerPaths($paths) { if (!is_array($paths) && !$paths instanceof Traversable) { - throw new \InvalidArgumentException( + require_once __DIR__ . '/Exception/InvalidArgumentException.php'; + throw new Exception\InvalidArgumentException( 'Parameter to \\Zend\\Loader\\ModuleAutoloader\'s ' . 'registerPaths method must be an array or ' . 'implement the \\Traversable interface' @@ -296,7 +325,8 @@ public function registerPaths($paths) public function registerPath($path, $moduleName = false) { if (!is_string($path)) { - throw new \InvalidArgumentException(sprintf( + require_once __DIR__ . '/Exception/InvalidArgumentException.php'; + throw new Exception\InvalidArgumentException(sprintf( 'Invalid path provided; must be a string, received %s', gettype($path) )); diff --git a/library/Zend/ModuleManager/Listener/ConfigListener.php b/library/Zend/ModuleManager/Listener/ConfigListener.php index 392861dd6ba..116ae1b600f 100644 --- a/library/Zend/ModuleManager/Listener/ConfigListener.php +++ b/library/Zend/ModuleManager/Listener/ConfigListener.php @@ -171,8 +171,12 @@ public function onLoadModulesPost(ModuleEvent $e) } // If enabled, update the config cache - if ($this->getOptions()->getConfigCacheEnabled()) { - $this->updateCache(); + if ( + $this->getOptions()->getConfigCacheEnabled() + && false === $this->skipConfig + ) { + $configFile = $this->getOptions()->getConfigCacheFile(); + $this->writeArrayToFile($configFile, $this->getMergedConfig(false)); } return $this; @@ -386,18 +390,4 @@ protected function getCachedConfig() { return include $this->getOptions()->getConfigCacheFile(); } - - /** - * @return ConfigListener - */ - protected function updateCache() - { - if (($this->getOptions()->getConfigCacheEnabled()) - && (false === $this->skipConfig) - ) { - $configFile = $this->getOptions()->getConfigCacheFile(); - $this->writeArrayToFile($configFile, $this->getMergedConfig(false)); - } - return $this; - } } diff --git a/library/Zend/ModuleManager/Listener/DefaultListenerAggregate.php b/library/Zend/ModuleManager/Listener/DefaultListenerAggregate.php index 0404c3e34d3..f63a2bd78ee 100644 --- a/library/Zend/ModuleManager/Listener/DefaultListenerAggregate.php +++ b/library/Zend/ModuleManager/Listener/DefaultListenerAggregate.php @@ -12,7 +12,6 @@ use Zend\EventManager\EventManagerInterface; use Zend\EventManager\ListenerAggregateInterface; -use Zend\Loader\ModuleAutoloader; use Zend\ModuleManager\ModuleEvent; use Zend\Stdlib\CallbackHandler; @@ -47,10 +46,9 @@ public function attach(EventManagerInterface $events) $options = $this->getOptions(); $configListener = $this->getConfigListener(); $locatorRegistrationListener = new LocatorRegistrationListener($options); - $moduleAutoloader = new ModuleAutoloader($options->getModulePaths()); // High priority, we assume module autoloading (for FooNamespace\Module classes) should be available before anything else - $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($moduleAutoloader, 'register'), 9000); + $this->listeners[] = $events->attach(new ModuleLoaderListener($options)); $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE_RESOLVE, new ModuleResolverListener); // High priority, because most other loadModule listeners will assume the module's classes are available via autoloading $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE, new AutoloaderListener($options), 9000); diff --git a/library/Zend/ModuleManager/Listener/ListenerOptions.php b/library/Zend/ModuleManager/Listener/ListenerOptions.php index 761fbb8bd41..96c44d95b93 100644 --- a/library/Zend/ModuleManager/Listener/ListenerOptions.php +++ b/library/Zend/ModuleManager/Listener/ListenerOptions.php @@ -57,6 +57,16 @@ class ListenerOptions extends AbstractOptions */ protected $cacheDir; + /** + * @var string + */ + protected $moduleMapCacheEnabled = false; + + /** + * @var string + */ + protected $moduleMapCacheKey; + /** * Get an array of paths where modules reside * @@ -261,6 +271,60 @@ public function setCacheDir($cacheDir) return $this; } + /** + * Check if the module class map cache is enabled + * + * @return bool + */ + public function getModuleMapCacheEnabled() + { + return $this->moduleMapCacheEnabled; + } + + /** + * Set if the module class map cache should be enabled or not + * + * @param bool $enabled + * @return ListenerOptions + */ + public function setModuleMapCacheEnabled($enabled) + { + $this->moduleMapCacheEnabled = (bool) $enabled; + return $this; + } + + /** + * Get key used to create the cache file name + * + * @return string + */ + public function getModuleMapCacheKey() + { + return (string) $this->moduleMapCacheKey; + } + + /** + * Set key used to create the cache file name + * + * @param string $moduleMapCacheKey the value to be set + * @return ListenerOptions + */ + public function setModuleMapCacheKey($moduleMapCacheKey) + { + $this->moduleMapCacheKey = $moduleMapCacheKey; + return $this; + } + + /** + * Get the path to the module class map cache + * + * @return string + */ + public function getModuleMapCacheFile() + { + return $this->getCacheDir() . '/module-classmap-cache.'.$this->getModuleMapCacheKey().'.php'; + } + /** * Normalize a path for insertion in the stack * diff --git a/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php b/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php new file mode 100644 index 00000000000..495c978c459 --- /dev/null +++ b/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php @@ -0,0 +1,140 @@ +generateCache = $this->options->getModuleMapCacheEnabled(); + $this->moduleLoader = new ModuleAutoloader($this->options->getModulePaths()); + + if ($this->hasCachedClassMap()) { + $this->generateCache = false; + $this->moduleLoader->setModuleClassMap($this->getCachedConfig()); + } + } + + /** + * Attach one or more listeners + * + * @param EventManagerInterface $events + * @return LocatorRegistrationListener + */ + public function attach(EventManagerInterface $events) + { + $this->listeners[] = $events->attach( + ModuleEvent::EVENT_LOAD_MODULES, + array($this->moduleLoader, 'register'), + 9000 + ); + + if ($this->generateCache) { + $this->listeners[] = $events->attach( + ModuleEvent::EVENT_LOAD_MODULES_POST, + array($this, 'onLoadModulesPost') + ); + } + + return $this; + } + + /** + * Detach all previously attached listeners + * + * @param EventManagerInterface $events + * @return void + */ + public function detach(EventManagerInterface $events) + { + foreach ($this->listeners as $key => $listener) { + if ($events->detach($listener)) { + unset($this->listeners[$key]); + } + } + } + + /** + * @return bool + */ + protected function hasCachedClassMap() + { + if ( + $this->options->getModuleMapCacheEnabled() + && file_exists($this->options->getConfigCacheFile()) + ) { + return true; + } + + return false; + } + + /** + * @return array + */ + protected function getCachedConfig() + { + return include $this->options->getModuleMapCacheFile(); + } + + /** + * loadModulesPost + * + * Unregisters the ModuleLoader and generates the module class map cache. + * + * @param ModuleEvent $e + */ + public function onLoadModulesPost(ModuleEvent $event) + { + $this->moduleLoader->unregister(); + $this->writeArrayToFile( + $this->options->getModuleMapCacheFile(), + $this->moduleLoader->getModuleClassMap() + ); + } +} diff --git a/tests/Zend/Loader/ModuleAutoloaderTest.php b/tests/Zend/Loader/ModuleAutoloaderTest.php index ab50a563474..c6e6e7974de 100644 --- a/tests/Zend/Loader/ModuleAutoloaderTest.php +++ b/tests/Zend/Loader/ModuleAutoloaderTest.php @@ -197,4 +197,16 @@ public function testCanLoadModulesFromExplicitLocation() $this->assertTrue(class_exists('PharModuleExplicit\Module')); } + public function testCanLoadModulesFromClassMap() + { + $loader = new ModuleAutoloader(); + $loader->setModuleClassMap(array( + 'BarModule\Module' => __DIR__ . '/_files/BarModule/Module.php', + 'PharModuleMap\Module' => __DIR__ . '/_files/PharModuleMap.phar', + )); + $loader->register(); + + $this->assertTrue(class_exists('BarModule\Module')); + $this->assertTrue(class_exists('PharModuleMap\Module')); + } } diff --git a/tests/Zend/Loader/_files/BarModule/Module.php b/tests/Zend/Loader/_files/BarModule/Module.php new file mode 100644 index 00000000000..dfd18098c5f --- /dev/null +++ b/tests/Zend/Loader/_files/BarModule/Module.php @@ -0,0 +1,15 @@ +}qZ?|N)n z9 zgCw)qvwhZS7?vx(SvkMXTS?&fkwwI6YLZkkZ*5hPz1*uJ&#Q<*JgXw7Q6)LQ&a1eu zvr2*nSWCK8d50XU+$%Dc#2jBrW_rV^cy~t6F z;#u-=MG=-HktmPlri3a$@hKu%r6-=+f^sNCgsMarj|`rcpk`MU64^X!HGv${~;CoKaYY@^h{nVL-&XSp)8Ro>vc;ti}XJ3D{byo!g z_4xbf=}DYbbR*Hv&_K1M=rQix^HY1Z)0jCA6H+G|xoElNzG)^o9LN?EnA&XTr~ARS zXb=TFvP-_HXvh{dO)`ll+OlW@Ne5^W6bZ9l4~P9$d%MjZ?zGuSe91l5=V|CfJj#O` zYnfW>IF?7G%V;RAw_}kfJdra5wjhf^nA6BG9Yl_q8HnLlkv7PE`)1HP!c_ai%7Bx4 z#126TLQ)|k{j{UD>0m$hG_^vr*e+EbI@%rfXy*}o8|Un0yofxClDqSm)%K|I?Ef)h zdn7?$*k11E0pF)_y_8TyVr*&7y-DodNRfGapA0makgB10lDxrcCHWRugtQWZ8nRp~ zrHsG`rOS_|F@>piRt?q3$ik%JQHG|4NlM$RgQOFK-D?hS65eH{fmYf~&2!A7Sw5Fr zIz@8s5-{PD&%cwsm*b#yH zvw493`FP#G>Lj3IH@Nfv$O#~kzIZbF8Cuk|UJvNw?PUwJ4GtMt;umJw@VA}1%0LbPsL>5uvxEHo{ z4s0xrx;^nDC%vgpsfeV|BSNNT2yXq*B7E(|s08@pczE)({Y^)fxp_QlzsCX64KAcZ zPLD+&Q|#+ZqSs(_QKQvnNM;MktVT;eVRO zX_wsw{)81BhWQ!hZ_Y49Cjmx8lY+2VA#c~2R?Z^MJ+MsUR48e>ahRkWEyH8DR5@uT zgHrd1lBX#9&8|*vJ+3vadpo)Hlg?+|E$i6e@#MDiBMys`TP287HF{1AK z8SaICPPwurDiCFxAqzNt)YOF%u^MN06?3poCWB2C9R#nl0(;2ILZYU(5NVTdBOAsxzE&+y(eB zOkUE|l~vLxJp6GN55$%wi+qe$PorMR7vO8%G}<`j$-t@P0MV!uYAGWtwB9o`B~#Yq zJ~K(RC{{vjE72lh5^<@hHO@mdQ)^c#{V}dPnRWw?Zh)yMV103pgfAoAA<3~i1_7qQ z63CXfuLxSmNfU7A6XTd_XlkF!l@gQNqRNf-#8wYPMljZl7MPHySV))Z0alBmh8pw*d44pdB!}{nAYVTt zB}%90Tv{m^SalE=fJzsXbXhaGL5kLrRho?iXw=*+;}d=V3bA1gCQu2G06f{i)Ye=A zyOgBck8lAq1Ks-SRID)G0e<9x z1uwpBZBfQyoJZi;U{;z@Au5|&FuDstnmKw5srxAMp(RMK4okQSF-3zgW71i)j!~fq zr&GRG8{<~KKtn5>a$4t;*16j{_gd$?b&j_O#TB?@vV)DFG>SB=Y92i# zzFH8-tmZQw07*~P-zIfWNSztOSj;G}DpeiY61h!a>4=T0;`@4K>ppJK_UL_q#t6oj zP6QdRtmCRighrp<$WBDHjaMJkqX|WuE`=nXkH~dHAzITFt%fdRZW%udQOwwbGB$Q8 zVWbEpT69kkni`i&i+98XCZ`ZIo|9gbLY4qjySs#pf&!b;mgre)vI-Jv;S~T^$ge_j zijDfA&c_bkMN4R2dlQLQMoheekDNf_QAQI2s0%k=#tHo5qP|^RJfym9(4Z0zL|Nn` z6cK23dcCw7IEodFx>{>rEpYpHQ})6vPCG})W%Ulcrnj} zTH(#z%ig#eYnTcc(arD9uqsf(EQlwz^&9kj0tr)HO=701A2~o3WQ7yK^PC-|p@3Id zblJfo3jBz!jz|`5^BrmW*+ipEscQp7ny%m@HDMbCcsM>fJ?Z23mH|lY`Tj4Ar}ysN`x*ZKN`2x3e+K?9e<^BX^_PGBx=)`+e;ywF zodoc=M?Wnw!yw?4;f~B1{iY)2P8?uV_2NKMj1Qmw^Ur_$GXLV6FaLY~*MI-*_h0^e P^uXa?K+&rgCold7N1__B literal 0 HcmV?d00001 diff --git a/tests/Zend/Loader/_files/_buildPhars.php b/tests/Zend/Loader/_files/_buildPhars.php index c3318c23ef0..9b72f8fb032 100644 --- a/tests/Zend/Loader/_files/_buildPhars.php +++ b/tests/Zend/Loader/_files/_buildPhars.php @@ -4,6 +4,7 @@ // Executable // .phar buildModulePhar('PharModule'); +buildModulePhar('PharModuleMap'); // .phar.gz buildModulePhar('PharModuleGz', Phar::PHAR, Phar::GZ); // .phar.bz2 diff --git a/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php b/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php new file mode 100644 index 00000000000..ce0d1ea2728 --- /dev/null +++ b/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php @@ -0,0 +1,96 @@ +tmpdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zend_module_cache_dir'; + @mkdir($this->tmpdir); + + $this->moduleManager = new ModuleManager(array()); + $this->moduleManager->getEventManager()->attach('loadModule.resolve', new ModuleResolverListener, 1000); + } + + public function tearDown() + { + $file = glob($this->tmpdir . DIRECTORY_SEPARATOR . '*'); + @unlink($file[0]); // change this if there's ever > 1 file + @rmdir($this->tmpdir); + } + + public function testModuleLoaderListenerFunctionsAsAggregateListenerEnabledCache() + { + $options = new ListenerOptions(array( + 'cache_dir' => $this->tmpdir, + 'module_map_cache_enabled' => true, + 'module_map_cache_key' => 'foo', + )); + + $configListener = new ModuleLoaderListener($options); + + $moduleManager = $this->moduleManager; + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + + $configListener->attach($moduleManager->getEventManager()); + $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + } + + public function testModuleLoaderListenerFunctionsAsAggregateListenerDisabledCache() + { + $options = new ListenerOptions(array( + 'cache_dir' => $this->tmpdir, + )); + + $configListener = new ModuleLoaderListener($options); + + $moduleManager = $this->moduleManager; + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + + $configListener->attach($moduleManager->getEventManager()); + $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + } + + public function testModuleLoaderListenerFunctionsAsAggregateListenerHasCache() + { + $options = new ListenerOptions(array( + 'cache_dir' => $this->tmpdir, + 'module_map_cache_enabled' => true, + 'module_map_cache_key' => 'foo', + )); + + file_put_contents($options->getModuleMapCacheFile(), 'moduleManager; + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + + $configListener->attach($moduleManager->getEventManager()); + $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + } +} From 530017a3816cb045dea0bfb8917f9f2e849643e8 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 2 Aug 2012 06:21:57 +0200 Subject: [PATCH 002/126] Renamed callback method and fixed API docblock --- .../ModuleManager/Listener/LocatorRegistrationListener.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/Zend/ModuleManager/Listener/LocatorRegistrationListener.php b/library/Zend/ModuleManager/Listener/LocatorRegistrationListener.php index e57337c28f3..5620b791646 100644 --- a/library/Zend/ModuleManager/Listener/LocatorRegistrationListener.php +++ b/library/Zend/ModuleManager/Listener/LocatorRegistrationListener.php @@ -54,14 +54,14 @@ public function onLoadModule(ModuleEvent $e) } /** - * loadModulesPost + * loadModules * * Once all the modules are loaded, loop * * @param Event $e * @return void */ - public function onLoadModulesPost(Event $e) + public function onLoadModules(Event $e) { $moduleManager = $e->getTarget(); $events = $moduleManager->getEventManager()->getSharedManager(); @@ -117,7 +117,7 @@ public function onBootstrap(Event $e) public function attach(EventManagerInterface $events) { $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE, array($this, 'onLoadModule')); - $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($this, 'onLoadModulesPost'), -1000); + $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($this, 'onLoadModules'), -1000); return $this; } From 983101dda66e1c5f10ddbcc6c5ef10e0d9b7bb76 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 2 Aug 2012 06:41:13 +0200 Subject: [PATCH 003/126] Fixed error in the previous commit --- .../Listener/ModuleLoaderListener.php | 2 +- .../Listener/ModuleLoaderListenerTest.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php b/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php index 495c978c459..15bbdbf0e4d 100644 --- a/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php +++ b/library/Zend/ModuleManager/Listener/ModuleLoaderListener.php @@ -106,7 +106,7 @@ protected function hasCachedClassMap() { if ( $this->options->getModuleMapCacheEnabled() - && file_exists($this->options->getConfigCacheFile()) + && file_exists($this->options->getModuleMapCacheFile()) ) { return true; } diff --git a/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php b/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php index ce0d1ea2728..cc654093d0e 100644 --- a/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php +++ b/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php @@ -45,13 +45,13 @@ public function testModuleLoaderListenerFunctionsAsAggregateListenerEnabledCache 'module_map_cache_key' => 'foo', )); - $configListener = new ModuleLoaderListener($options); + $moduleLoaderListener = new ModuleLoaderListener($options); $moduleManager = $this->moduleManager; $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - $configListener->attach($moduleManager->getEventManager()); + $moduleLoaderListener->attach($moduleManager->getEventManager()); $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); } @@ -62,13 +62,13 @@ public function testModuleLoaderListenerFunctionsAsAggregateListenerDisabledCach 'cache_dir' => $this->tmpdir, )); - $configListener = new ModuleLoaderListener($options); + $moduleLoaderListener = new ModuleLoaderListener($options); $moduleManager = $this->moduleManager; $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - $configListener->attach($moduleManager->getEventManager()); + $moduleLoaderListener->attach($moduleManager->getEventManager()); $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); } @@ -77,20 +77,20 @@ public function testModuleLoaderListenerFunctionsAsAggregateListenerHasCache() { $options = new ListenerOptions(array( 'cache_dir' => $this->tmpdir, - 'module_map_cache_enabled' => true, 'module_map_cache_key' => 'foo', + 'module_map_cache_enabled' => true, )); file_put_contents($options->getModuleMapCacheFile(), 'moduleManager; $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - $configListener->attach($moduleManager->getEventManager()); + $moduleLoaderListener->attach($moduleManager->getEventManager()); $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); } } From 092fffdb2b8c985a5100582db405a2fdac14dd67 Mon Sep 17 00:00:00 2001 From: "marek.nos" Date: Thu, 2 Aug 2012 23:43:49 +0200 Subject: [PATCH 004/126] refresh() method in Redirect plugin --- .../Zend/Mvc/Controller/Plugin/Redirect.php | 36 ++++++++++++++++++- .../Mvc/Controller/Plugin/RedirectTest.php | 24 +++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Redirect.php b/library/Zend/Mvc/Controller/Plugin/Redirect.php index 3930f1128ef..97976e31ba6 100644 --- a/library/Zend/Mvc/Controller/Plugin/Redirect.php +++ b/library/Zend/Mvc/Controller/Plugin/Redirect.php @@ -28,6 +28,24 @@ class Redirect extends AbstractPlugin protected $response; protected $router; + /** + * Gets current route name + * + * @return string + */ + protected function getCurrentRoute () + { + return $this->getEvent()->getRouteMatch()->getMatchedRouteName(); + } + + /** + * Gets current route params + */ + protected function getCurrentRouteParams() + { + return $this->getEvent()->getRouteMatch()->getParams(); + } + /** * Generates a URL based on a route * @@ -38,8 +56,14 @@ class Redirect extends AbstractPlugin * @throws Exception\DomainException if composed controller does not implement InjectApplicationEventInterface, or * router cannot be found in controller event */ - public function toRoute($route, array $params = array(), array $options = array()) + public function toRoute($route = null, array $params = array(), array $options = array()) { + // Refresh if null provided + if (is_null($route)) { + $route = $this->getCurrentRoute(); + $params = array_merge($this->getCurrentRouteParams(), $params); + } + $response = $this->getResponse(); $router = $this->getRouter(); @@ -64,6 +88,16 @@ public function toUrl($url) return $response; } + /** + * Refresh to current route + * + * @return string + */ + public function refresh() + { + return $this->toRoute($this->getCurrentRoute(), $this->getCurrentRouteParams()); + } + /** * Get the router * diff --git a/tests/Zend/Mvc/Controller/Plugin/RedirectTest.php b/tests/Zend/Mvc/Controller/Plugin/RedirectTest.php index 732728afefb..c2546ecab59 100644 --- a/tests/Zend/Mvc/Controller/Plugin/RedirectTest.php +++ b/tests/Zend/Mvc/Controller/Plugin/RedirectTest.php @@ -12,10 +12,12 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Http\Response; +use Zend\Route\Request; use Zend\Mvc\Controller\Plugin\Redirect as RedirectPlugin; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\Http\Literal as LiteralRoute; use Zend\Mvc\Router\SimpleRouteStack; +use Zend\Mvc\Router\RouteMatch; use ZendTest\Mvc\Controller\TestAsset\SampleController; class RedirectTest extends TestCase @@ -32,9 +34,13 @@ public function setUp() ), ))); + $routeMatch = new RouteMatch(array()); + $routeMatch->setMatchedRouteName('home'); + $event = new MvcEvent(); $event->setRouter($router); $event->setResponse($this->response); + $event->setRouteMatch($routeMatch); $this->controller = new SampleController(); $this->controller->setEvent($event); @@ -95,4 +101,22 @@ public function testRedirectToRouteWithoutRouterInEventRaisesDomainException() $this->setExpectedException('Zend\Mvc\Exception\DomainException', 'event compose a router'); $plugin->toRoute('home'); } + + public function testPluginCanRefreshToRouteWhenProperlyConfigured() + { + $response = $this->plugin->refresh(); + $this->assertTrue($response->isRedirect()); + $headers = $response->getHeaders(); + $location = $headers->get('Location'); + $this->assertEquals('/', $location->getFieldValue()); + } + + public function testPluginCanRedirectToRouteWithNullWhenProperlyConfigured() + { + $response = $this->plugin->toRoute(); + $this->assertTrue($response->isRedirect()); + $headers = $response->getHeaders(); + $location = $headers->get('Location'); + $this->assertEquals('/', $location->getFieldValue()); + } } From 4a5b2ccd1690df5fd9341347f8101aefe5ab8348 Mon Sep 17 00:00:00 2001 From: Roy van Kaathoven Date: Fri, 3 Aug 2012 23:51:19 +0200 Subject: [PATCH 005/126] added class annotation scanner --- library/Zend/Code/Scanner/ClassScanner.php | 16 +++++++--- .../TestAsset/EntityWithAnnotations.php | 8 ++++- tests/Zend/Code/Scanner/ClassScannerTest.php | 29 ++++++++++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/library/Zend/Code/Scanner/ClassScanner.php b/library/Zend/Code/Scanner/ClassScanner.php index 000b6346bd0..3e8eef17edd 100644 --- a/library/Zend/Code/Scanner/ClassScanner.php +++ b/library/Zend/Code/Scanner/ClassScanner.php @@ -10,7 +10,7 @@ namespace Zend\Code\Scanner; -use Zend\Code\Annotation\AnnotationManager; +use Zend\Code\Annotation; use Zend\Code\Exception; use Zend\Code\NameInformation; @@ -107,9 +107,17 @@ public function __construct(array $classTokens, NameInformation $nameInformation $this->nameInformation = $nameInformation; } - public function getAnnotations() + /** + * @param Annotation\AnnotationManager $annotationManager + * @return Annotation\AnnotationCollection + */ + public function getAnnotations(Annotation\AnnotationManager $annotationManager) { - return array(); + if (($docComment = $this->getDocComment()) == '') { + return false; + } + + return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } public function getDocComment() @@ -678,4 +686,4 @@ protected function scan() return; } -} +} \ No newline at end of file diff --git a/tests/Zend/Code/Annotation/TestAsset/EntityWithAnnotations.php b/tests/Zend/Code/Annotation/TestAsset/EntityWithAnnotations.php index 4ed63fd024a..0472e5d6610 100644 --- a/tests/Zend/Code/Annotation/TestAsset/EntityWithAnnotations.php +++ b/tests/Zend/Code/Annotation/TestAsset/EntityWithAnnotations.php @@ -10,6 +10,12 @@ namespace ZendTest\Code\Annotation\TestAsset; +/** + * @Foo(first) + * @Bar(second) + * @Bar(third) + * @Bogus(does not exist) + */ class EntityWithAnnotations { /** @@ -19,4 +25,4 @@ class EntityWithAnnotations * @Bogus(does not exist) */ public $test; -} +} \ No newline at end of file diff --git a/tests/Zend/Code/Scanner/ClassScannerTest.php b/tests/Zend/Code/Scanner/ClassScannerTest.php index c0fdda8d791..0993f6b9abe 100644 --- a/tests/Zend/Code/Scanner/ClassScannerTest.php +++ b/tests/Zend/Code/Scanner/ClassScannerTest.php @@ -11,10 +11,24 @@ namespace ZendTest\Code\Scanner; use Zend\Code\Scanner\FileScanner; +use Zend\Code\Annotation; use PHPUnit_Framework_TestCase as TestCase; class ClassScannerTest extends TestCase { + protected $manager; + + public function setUp() + { + $this->manager = new Annotation\AnnotationManager(); + + $genericParser = new Annotation\Parser\GenericAnnotationParser(); + $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Foo'); + $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Bar'); + + $this->manager->attach($genericParser); + } + public function testClassScannerHasClassInformation() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); @@ -84,5 +98,18 @@ public function testClassScannerCanReturnLineNumbers() $this->assertEquals(11, $class->getLineStart()); $this->assertEquals(34, $class->getLineEnd()); } + + public function testClassScannerCanScanAnnotations() + { + $file = new FileScanner(__DIR__ . '/../Annotation/TestAsset/EntityWithAnnotations.php'); + $class = $file->getClass('ZendTest\Code\Annotation\TestAsset\EntityWithAnnotations'); + $annotations = $class->getAnnotations($this->manager); + + $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Foo')); + $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Bar')); -} + $this->assertEquals('first', $annotations[0]->content); + $this->assertEquals('second', $annotations[1]->content); + $this->assertEquals('third', $annotations[2]->content); + } +} \ No newline at end of file From 28af5b6237631fc7d7378acd7a1b33c569e1769a Mon Sep 17 00:00:00 2001 From: Roy van Kaathoven Date: Sat, 4 Aug 2012 00:03:20 +0200 Subject: [PATCH 006/126] fixed trailing spaces --- tests/Zend/Code/Scanner/ClassScannerTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Zend/Code/Scanner/ClassScannerTest.php b/tests/Zend/Code/Scanner/ClassScannerTest.php index 0993f6b9abe..b659fa43659 100644 --- a/tests/Zend/Code/Scanner/ClassScannerTest.php +++ b/tests/Zend/Code/Scanner/ClassScannerTest.php @@ -17,18 +17,18 @@ class ClassScannerTest extends TestCase { protected $manager; - + public function setUp() { $this->manager = new Annotation\AnnotationManager(); - + $genericParser = new Annotation\Parser\GenericAnnotationParser(); $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Foo'); $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Bar'); - + $this->manager->attach($genericParser); } - + public function testClassScannerHasClassInformation() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); @@ -98,13 +98,13 @@ public function testClassScannerCanReturnLineNumbers() $this->assertEquals(11, $class->getLineStart()); $this->assertEquals(34, $class->getLineEnd()); } - + public function testClassScannerCanScanAnnotations() { $file = new FileScanner(__DIR__ . '/../Annotation/TestAsset/EntityWithAnnotations.php'); $class = $file->getClass('ZendTest\Code\Annotation\TestAsset\EntityWithAnnotations'); $annotations = $class->getAnnotations($this->manager); - + $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Foo')); $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Bar')); From 5329b36a79a7a8e110b7ca5e80569b669f8f372c Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Fri, 27 Jul 2012 16:54:23 -0400 Subject: [PATCH 007/126] Added MongoDB session save handler --- library/Zend/Session/SaveHandler/MongoDB.php | 201 ++++++++++++++ .../Session/SaveHandler/MongoDBOptions.php | 260 ++++++++++++++++++ .../SaveHandler/MongoDBOptionsTest.php | 146 ++++++++++ .../Session/SaveHandler/MongoDBTest.php | 158 +++++++++++ 4 files changed, 765 insertions(+) create mode 100644 library/Zend/Session/SaveHandler/MongoDB.php create mode 100644 library/Zend/Session/SaveHandler/MongoDBOptions.php create mode 100644 tests/ZendTest/Session/SaveHandler/MongoDBOptionsTest.php create mode 100644 tests/ZendTest/Session/SaveHandler/MongoDBTest.php diff --git a/library/Zend/Session/SaveHandler/MongoDB.php b/library/Zend/Session/SaveHandler/MongoDB.php new file mode 100644 index 00000000000..578e06da1fd --- /dev/null +++ b/library/Zend/Session/SaveHandler/MongoDB.php @@ -0,0 +1,201 @@ +getDatabase())) { + throw new InvalidArgumentException('The database option cannot be emtpy'); + } + + if (null === ($collection = $options->getCollection())) { + throw new InvalidArgumentException('The collection option cannot be emtpy'); + } + + $this->mongoCollection = $mongo->selectCollection($database, $collection); + $this->options = $options; + } + + /** + * Open session + * + * @param string $savePath + * @param string $name + * @return boolean + */ + public function open($savePath, $name) + { + // Note: session save path is not used + $this->sessionName = $name; + $this->lifetime = ini_get('session.gc_maxlifetime'); + + return true; + } + + /** + * Close session + * + * @return boolean + */ + public function close() + { + return true; + } + + /** + * Read session data + * + * @param string $id + * @return string + */ + public function read($id) + { + $session = $this->mongoCollection->findOne(array( + '_id' => $id, + $this->options->getNameField() => $this->sessionName, + )); + + if (null !== $session) { + if ($session[$this->options->getModifiedField()] instanceof MongoDate && + $session[$this->options->getModifiedField()]->sec + + $session[$this->options->getLifetimeField()] > time()) { + return $session[$this->options->getDataField()]; + } + $this->destroy($id); + } + + return ''; + } + + /** + * Write session data + * + * @param string $id + * @param string $data + * @return boolean + */ + public function write($id, $data) + { + $saveOptions = array_replace( + $this->options->getSaveOptions(), + array('upsert' => true, 'multiple' => false) + ); + + $criteria = array( + '_id' => $id, + $this->options->getNameField() => $this->sessionName, + ); + + $newObj = array('$set' => array( + $this->options->getDataField() => (string) $data, + $this->options->getLifetimeField() => $this->lifetime, + $this->options->getModifiedField() => new MongoDate(), + )); + + /* Note: a MongoCursorException will be thrown if a record with this ID + * already exists with a different session name, since the upsert query + * cannot insert a new document with the same ID and new session name. + * This should only happen if ID's are not unique or if the session name + * is altered mid-process. + */ + $result = $this->mongoCollection->update($criteria, $newObj, $saveOptions); + + return (bool) (isset($result['ok']) ? $result['ok'] : $result); + } + + /** + * Destroy session + * + * @param string $id + * @return boolean + */ + public function destroy($id) + { + $result = $this->mongoCollection->remove(array( + '_id' => $id, + $this->options->getNameField() => $this->sessionName, + ), $this->options->getSaveOptions()); + + return (bool) (isset($result['ok']) ? $result['ok'] : $result); + } + + /** + * Garbage collection + * + * Note: MongoDB 2.2+ supports TTL collections, which may be used in place + * of this method by indexing with "modified" field with an + * "expireAfterSeconds" option. + * + * @see http://docs.mongodb.org/manual/tutorial/expire-data/ + * @param int $maxlifetime + * @return boolean + */ + public function gc($maxlifetime) + { + /* Note: unlike DbTableGateway, we do not use the lifetime field in + * each document. Doing so would require a $where query to work with the + * computed value (modified + lifetime) and be very inefficient. + */ + $result = $this->mongoCollection->remove(array( + $this->options->getModifiedField() => array('$lt' => new MongoDate(time() - $maxlifetime)), + ), $this->options->getSaveOptions()); + + return (bool) (isset($result['ok']) ? $result['ok'] : $result); + } +} diff --git a/library/Zend/Session/SaveHandler/MongoDBOptions.php b/library/Zend/Session/SaveHandler/MongoDBOptions.php new file mode 100644 index 00000000000..fccd89d4b8b --- /dev/null +++ b/library/Zend/Session/SaveHandler/MongoDBOptions.php @@ -0,0 +1,260 @@ + true); + + /** + * Name field + * + * @var string + */ + protected $nameField = 'name'; + + /** + * Data field + * + * @var string + */ + protected $dataField = 'data'; + + /** + * Lifetime field + * + * @var string + */ + protected $lifetimeField = 'lifetime'; + + /** + * Modified field + * + * @var string + */ + protected $modifiedField = 'modified'; + + /** + * Set database name + * + * @param string $database + * @return MongoDBOptions + * @throws Zend\Session\Exception\InvalidArgumentException + */ + public function setDatabase($database) + { + $database = (string) $database; + if (strlen($database) === 0) { + throw new InvalidArgumentException('$database must be a non-empty string'); + } + $this->database = $database; + return $this; + } + + /** + * Get database name + * + * @return string + */ + public function getDatabase() + { + return $this->database; + } + + /** + * Set collection name + * + * @param string $collection + * @return MongoDBOptions + * @throws Zend\Session\Exception\InvalidArgumentException + */ + public function setCollection($collection) + { + $collection = (string) $collection; + if (strlen($collection) === 0) { + throw new InvalidArgumentException('$collection must be a non-empty string'); + } + $this->collection = $collection; + return $this; + } + + /** + * Get collection name + * + * @return string + */ + public function getCollection() + { + return $this->collection; + } + + /** + * Set save options + * + * @see http://php.net/manual/en/mongocollection.save.php + * @param array $saveOptions + * @return MongoDBOptions + */ + public function setSaveOptions(array $saveOptions) + { + $this->saveOptions = $saveOptions; + return $this; + } + + /** + * Get save options + * + * @return string + */ + public function getSaveOptions() + { + return $this->saveOptions; + } + + /** + * Set name field + * + * @param string $nameField + * @return MongoDBOptions + * @throws Zend\Session\Exception\InvalidArgumentException + */ + public function setNameField($nameField) + { + $nameField = (string) $nameField; + if (strlen($nameField) === 0) { + throw new InvalidArgumentException('$nameField must be a non-empty string'); + } + $this->nameField = $nameField; + return $this; + } + + /** + * Get name field + * + * @return string + */ + public function getNameField() + { + return $this->nameField; + } + + /** + * Set data field + * + * @param string $dataField + * @return MongoDBOptions + * @throws Zend\Session\Exception\InvalidArgumentException + */ + public function setDataField($dataField) + { + $dataField = (string) $dataField; + if (strlen($dataField) === 0) { + throw new InvalidArgumentException('$dataField must be a non-empty string'); + } + $this->dataField = $dataField; + return $this; + } + + /** + * Get data field + * + * @return string + */ + public function getDataField() + { + return $this->dataField; + } + + /** + * Set lifetime field + * + * @param string $lifetimeField + * @return MongoDBOptions + * @throws Zend\Session\Exception\InvalidArgumentException + */ + public function setLifetimeField($lifetimeField) + { + $lifetimeField = (string) $lifetimeField; + if (strlen($lifetimeField) === 0) { + throw new InvalidArgumentException('$lifetimeField must be a non-empty string'); + } + $this->lifetimeField = $lifetimeField; + return $this; + } + + /** + * Get lifetime Field + * + * @return string + */ + public function getLifetimeField() + { + return $this->lifetimeField; + } + + /** + * Set Modified Field + * + * @param string $modifiedField + * @return MongoDBOptions + * @throws Zend\Session\Exception\InvalidArgumentException + */ + public function setModifiedField($modifiedField) + { + $modifiedField = (string) $modifiedField; + if (strlen($modifiedField) === 0) { + throw new InvalidArgumentException('$modifiedField must be a non-empty string'); + } + $this->modifiedField = $modifiedField; + return $this; + } + + /** + * Get modified Field + * + * @return string + */ + public function getModifiedField() + { + return $this->modifiedField; + } +} diff --git a/tests/ZendTest/Session/SaveHandler/MongoDBOptionsTest.php b/tests/ZendTest/Session/SaveHandler/MongoDBOptionsTest.php new file mode 100644 index 00000000000..ad603306b9d --- /dev/null +++ b/tests/ZendTest/Session/SaveHandler/MongoDBOptionsTest.php @@ -0,0 +1,146 @@ +assertNull($options->getDatabase()); + $this->assertNull($options->getCollection()); + $this->assertEquals(array('safe' => true), $options->getSaveOptions()); + $this->assertEquals('name', $options->getNameField()); + $this->assertEquals('data', $options->getDataField()); + $this->assertEquals('lifetime', $options->getLifetimeField()); + $this->assertEquals('modified', $options->getModifiedField()); + } + + public function testSetConstructor() + { + $options = new MongoDBOptions(array( + 'database' => 'testDatabase', + 'collection' => 'testCollection', + 'saveOptions' => array('safe' => 2), + 'nameField' => 'testName', + 'dataField' => 'testData', + 'lifetimeField' => 'testLifetime', + 'modifiedField' => 'testModified', + )); + + $this->assertEquals('testDatabase', $options->getDatabase()); + $this->assertEquals('testCollection', $options->getCollection()); + $this->assertEquals(array('safe' => 2), $options->getSaveOptions()); + $this->assertEquals('testName', $options->getNameField()); + $this->assertEquals('testData', $options->getDataField()); + $this->assertEquals('testLifetime', $options->getLifetimeField()); + $this->assertEquals('testModified', $options->getModifiedField()); + } + + public function testSetters() + { + $options = new MongoDBOptions(); + $options->setDatabase('testDatabase') + ->setCollection('testCollection') + ->setSaveOptions(array('safe' => 2)) + ->setNameField('testName') + ->setDataField('testData') + ->setLifetimeField('testLifetime') + ->setModifiedField('testModified'); + + $this->assertEquals('testDatabase', $options->getDatabase()); + $this->assertEquals('testCollection', $options->getCollection()); + $this->assertEquals(array('safe' => 2), $options->getSaveOptions()); + $this->assertEquals('testName', $options->getNameField()); + $this->assertEquals('testData', $options->getDataField()); + $this->assertEquals('testLifetime', $options->getLifetimeField()); + $this->assertEquals('testModified', $options->getModifiedField()); + } + + /** + * @expectedException Zend\Session\Exception\InvalidArgumentException + */ + public function testInvalidDatabase() + { + $options = new MongoDBOptions(array( + 'database' => null, + )); + } + + /** + * @expectedException Zend\Session\Exception\InvalidArgumentException + */ + public function testInvalidCollection() + { + $options = new MongoDBOptions(array( + 'collection' => null, + )); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function testInvalidSaveOptions() + { + $options = new MongoDBOptions(array( + 'saveOptions' => null, + )); + } + + /** + * @expectedException Zend\Session\Exception\InvalidArgumentException + */ + public function testInvalidNameField() + { + $options = new MongoDBOptions(array( + 'nameField' => null, + )); + } + + /** + * @expectedException Zend\Session\Exception\InvalidArgumentException + */ + public function testInvalidModifiedField() + { + $options = new MongoDBOptions(array( + 'modifiedField' => null, + )); + } + + /** + * @expectedException Zend\Session\Exception\InvalidArgumentException + */ + public function testInvalidLifetimeField() + { + $options = new MongoDBOptions(array( + 'lifetimeField' => null, + )); + } + + /** + * @expectedException Zend\Session\Exception\InvalidArgumentException + */ + public function testInvalidDataField() + { + $options = new MongoDBOptions(array( + 'dataField' => null, + )); + } +} diff --git a/tests/ZendTest/Session/SaveHandler/MongoDBTest.php b/tests/ZendTest/Session/SaveHandler/MongoDBTest.php new file mode 100644 index 00000000000..8a6bbf77182 --- /dev/null +++ b/tests/ZendTest/Session/SaveHandler/MongoDBTest.php @@ -0,0 +1,158 @@ +markTestSkipped('Zend\Session\SaveHandler\MongoDB tests are not enabled due to missing Mongo extension'); + } + + $this->options = new MongoDBOptions(array( + 'database' => 'zf2_tests', + 'collection' => 'sessions', + )); + + $this->mongo = new Mongo(); + $this->mongoCollection = $this->mongo->selectCollection($this->options->getDatabase(), $this->options->getCollection()); + } + + /** + * Tear-down operations performed after each test method + * + * @return void + */ + public function tearDown() + { + if ($this->mongoCollection) { + $this->mongoCollection->drop(); + } + } + + public function testReadWrite() + { + $saveHandler = new MongoDB($this->mongo, $this->options); + $this->assertTrue($saveHandler->open('savepath', 'sessionname')); + + $id = '242'; + $data = array('foo' => 'bar', 'bar' => array('foo' => 'bar')); + + $this->assertTrue($saveHandler->write($id, serialize($data))); + $this->assertEquals($data, unserialize($saveHandler->read($id))); + + $data = array('foo' => array(1, 2, 3)); + + $this->assertTrue($saveHandler->write($id, serialize($data))); + $this->assertEquals($data, unserialize($saveHandler->read($id))); + } + + public function testReadDestroysExpiredSession() + { + /* Note: due to the session save handler's open() method reading the + * "session.gc_maxlifetime" INI value directly, it's necessary to set + * that to simulate natural session expiration. + */ + $oldMaxlifetime = ini_get('session.gc_maxlifetime'); + ini_set('session.gc_maxlifetime', 0); + + $saveHandler = new MongoDB($this->mongo, $this->options); + $this->assertTrue($saveHandler->open('savepath', 'sessionname')); + + $id = '242'; + $data = array('foo' => 'bar'); + + $this->assertNull($this->mongoCollection->findOne(array('_id' => $id))); + + $this->assertTrue($saveHandler->write($id, serialize($data))); + $this->assertNotNull($this->mongoCollection->findOne(array('_id' => $id))); + $this->assertEquals('', $saveHandler->read($id)); + $this->assertNull($this->mongoCollection->findOne(array('_id' => $id))); + + ini_set('session.gc_maxlifetime', $oldMaxlifetime); + } + + public function testGarbageCollection() + { + $saveHandler = new MongoDB($this->mongo, $this->options); + $this->assertTrue($saveHandler->open('savepath', 'sessionname')); + + $data = array('foo' => 'bar'); + + $this->assertTrue($saveHandler->write(123, serialize($data))); + $this->assertTrue($saveHandler->write(456, serialize($data))); + $this->assertEquals(2, $this->mongoCollection->count()); + $saveHandler->gc(5); + $this->assertEquals(2, $this->mongoCollection->count()); + + /* Note: MongoDate uses micro-second precision, so even a maximum + * lifetime of zero would not match records that were just inserted. + * Use a negative number instead. + */ + $saveHandler->gc(-1); + $this->assertEquals(0, $this->mongoCollection->count()); + } + + /** + * @expectedException MongoCursorException + */ + public function testWriteExceptionEdgeCaseForChangedSessionName() + { + $saveHandler = new MongoDB($this->mongo, $this->options); + $this->assertTrue($saveHandler->open('savepath', 'sessionname')); + + $id = '242'; + $data = array('foo' => 'bar'); + + /* Note: a MongoCursorException will be thrown if a record with this ID + * already exists with a different session name, since the upsert query + * cannot insert a new document with the same ID and new session name. + * This should only happen if ID's are not unique or if the session name + * is altered mid-process. + */ + $saveHandler->write($id, serialize($data)); + $saveHandler->open('savepath', 'sessionname_changed'); + $saveHandler->write($id, serialize($data)); + } +} From 7e98e2519b83291c7e3a673e6aa42ed804534db8 Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:30:54 +0200 Subject: [PATCH 008/126] Add hydrator wildcard Add hydrator wildcard to add strategy for all extract/hydrate --- library/Zend/Stdlib/Hydrator/AbstractHydrator.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php index 4b320f18f18..44e77ba0da9 100644 --- a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php +++ b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php @@ -44,7 +44,10 @@ public function __construct() */ public function getStrategy($name) { - return $this->strategies[$name]; + if(isset($this->strategies[$name])) { + return $this->strategies[$name]; + } + return $this->strategies['*']; } /** @@ -55,7 +58,8 @@ public function getStrategy($name) */ public function hasStrategy($name) { - return array_key_exists($name, $this->strategies); + return array_key_exists($name, $this->strategies) + || array_key_exists('*', $this->strategies); } /** From dc754a3ec635e902994f76dea73fe9c431d20679 Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:31:54 +0200 Subject: [PATCH 009/126] Add hydrator strategy Add hydrator strategy with serializer --- .../Strategy/SerializableStrategy.php | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 library/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php diff --git a/library/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php b/library/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php new file mode 100644 index 00000000000..31804fb0330 --- /dev/null +++ b/library/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php @@ -0,0 +1,128 @@ +setSerializer($serializer); + if($serializerOptions) { + $this->setSerializerOptions($serializerOptions); + } + } + + /** + * Serialize the given value so that it can be extracted by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be extracted. + */ + public function extract($value) + { + $serializer = $this->getSerializer(); + return $serializer->serialize($value); + } + + /** + * Unserialize the given value so that it can be hydrated by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be hydrated. + */ + public function hydrate($value) + { + $serializer = $this->getSerializer(); + return $serializer->unserialize($value); + } + + /** + * Set serializer + * + * @param string|SerializerAdapter $serializer + * @return Serializer + */ + public function setSerializer($serializer) + { + if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) { + throw new InvalidArgumentException(sprintf( + '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; ' + . 'received "%s"', + __METHOD__, + (is_object($serializer) ? get_class($serializer) : gettype($serializer)) + )); + } + $this->serializer = $serializer; + return $this; + } + + /** + * Get serializer + * + * @return SerializerAdapter + */ + public function getSerializer() + { + if (is_string($this->serializer)) { + $options = $this->getSerializerOptions(); + $this->setSerializer(SerializerFactory::factory($this->serializer, $options)); + } elseif (null === $this->serializer) { + $this->setSerializer(SerializerFactory::getDefaultAdapter()); + } + + return $this->serializer; + } + + /** + * Set configuration options for instantiating a serializer adapter + * + * @param mixed $serializerOptions + * @return SerializableStrategy + */ + public function setSerializerOptions($serializerOptions) + { + $this->serializerOptions = $serializerOptions; + return $this; + } + + /** + * Get configuration options for instantiating a serializer adapter + * + * @return mixed + */ + public function getSerializerOptions() + { + return $this->serializerOptions; + } +} From e8e08e36477a8b05cb6c198f094714b0070f1951 Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:32:51 +0200 Subject: [PATCH 010/126] Add unit tests for wildcard Add unit tests for wirldcard --- tests/ZendTest/Stdlib/HydratorTest.php | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/ZendTest/Stdlib/HydratorTest.php b/tests/ZendTest/Stdlib/HydratorTest.php index 10fae389e83..34365083acf 100644 --- a/tests/ZendTest/Stdlib/HydratorTest.php +++ b/tests/ZendTest/Stdlib/HydratorTest.php @@ -16,6 +16,8 @@ use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing; use ZendTest\Stdlib\TestAsset\Reflection as ReflectionAsset; +use Zend\Stdlib\Hydrator\Strategy\DefaultStrategy; +use Zend\Stdlib\Hydrator\Strategy\SerializableStrategy; /** * @category Zend @@ -146,4 +148,37 @@ public function testHydratorClassMethodsDefaultBehaviorIsConvertUnderscoreToCame $this->assertEquals($test->getFooBar(), 'foo'); $this->assertEquals($test->getFooBarBaz(), 'bar'); } + + public function testRetrieveWildStrategyAndOther() + { + $hydrator = new ClassMethods(); + $hydrator->addStrategy('default', new DefaultStrategy()); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $default = $hydrator->getStrategy('default'); + $this->assertEquals(get_class($default), 'Zend\Stdlib\Hydrator\Strategy\DefaultStrategy'); + $serializable = $hydrator->getStrategy('*'); + $this->assertEquals(get_class($serializable), 'Zend\Stdlib\Hydrator\Strategy\SerializableStrategy'); + } + + public function testUseWildStrategyByDefault() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], 's:1:"1";'); + } + + public function testUseWildStrategyAndOther() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $hydrator->addStrategy('foo_bar', new DefaultStrategy()); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertEquals($datas['foo_bar_baz'], 's:1:"2";'); + } } From 441fc418260932a0e6a85f14b6d1f9dcd2c17112 Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:33:58 +0200 Subject: [PATCH 011/126] Add unit tests for serializable strategy Add unit tests for serializable strategy --- .../Strategy/SerializableStrategyTest.php | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php diff --git a/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php b/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php new file mode 100644 index 00000000000..1bd88c774a6 --- /dev/null +++ b/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php @@ -0,0 +1,53 @@ +setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $serializerStrategy = new SerializableStrategy(false); + } + + public function testUseBadSerilizerObject() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $this->assertEquals($serializer, $serializerStrategy->getSerializer()); + } + + public function testUseBadSerilizerString() + { + $serializerStrategy = new SerializableStrategy('phpserialize'); + $this->assertEquals('Zend\Serializer\Adapter\PhpSerialize', get_class($serializerStrategy->getSerializer())); + } + + public function testCanSerialize() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $serialized = $serializerStrategy->extract('foo'); + $this->assertEquals($serialized, 's:3:"foo";'); + } + + public function testCanUnserialize() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $serialized = $serializerStrategy->hydrate('s:3:"foo";'); + $this->assertEquals($serialized, 'foo'); + } +} \ No newline at end of file From 47ef0c410e39cd5b2a7b87bbedb5045ad3d4f196 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 8 Aug 2012 03:43:56 +0200 Subject: [PATCH 012/126] Adding factories to generate the abstract Di factories and initializers --- .../Service/AbstractPluginManagerFactory.php | 16 +++---- .../Mvc/Service/ControllerLoaderFactory.php | 8 +--- .../DiAbstractServiceFactoryFactory.php | 34 ++++++++++++++ library/Zend/Mvc/Service/DiFactory.php | 5 +-- .../Service/DiServiceInitializerFactory.php | 34 ++++++++++++++ .../DiStrictAbstractServiceFactoryFactory.php | 44 +++++++++++++++++++ .../Mvc/Service/ServiceListenerFactory.php | 43 +++++++++--------- 7 files changed, 145 insertions(+), 39 deletions(-) create mode 100644 library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php create mode 100644 library/Zend/Mvc/Service/DiServiceInitializerFactory.php create mode 100644 library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php diff --git a/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php b/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php index 6fada16abb8..723120528f3 100644 --- a/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php +++ b/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php @@ -30,23 +30,21 @@ abstract class AbstractPluginManagerFactory implements FactoryInterface * the PLUGIN_MANGER_CLASS constant. * * @param ServiceLocatorInterface $serviceLocator - * @return AbstractPluginManager + * @return \Zend\ServiceManager\AbstractPluginManager */ public function createService(ServiceLocatorInterface $serviceLocator) { $pluginManagerClass = static::PLUGIN_MANAGER_CLASS; + /* @var $plugins \Zend\ServiceManager\AbstractPluginManager */ $plugins = new $pluginManagerClass; $plugins->setServiceLocator($serviceLocator); - $configuration = $serviceLocator->get('Config'); + $configuration = $serviceLocator->get('Config'); + if (isset($configuration['di']) && $serviceLocator->has('Di')) { - $di = $serviceLocator->get('Di'); - $plugins->addAbstractFactory( - new DiAbstractServiceFactory($di, DiAbstractServiceFactory::USE_SL_BEFORE_DI) - ); - $plugins->addInitializer( - new DiServiceInitializer($di, $serviceLocator) - ); + $plugins->addAbstractFactory($serviceLocator->get('DiAbstractServiceFactory')); + $plugins->addInitializer($serviceLocator->get('DiServiceInitializer')); } + return $plugins; } } diff --git a/library/Zend/Mvc/Service/ControllerLoaderFactory.php b/library/Zend/Mvc/Service/ControllerLoaderFactory.php index be64bda0ad5..434271389fd 100644 --- a/library/Zend/Mvc/Service/ControllerLoaderFactory.php +++ b/library/Zend/Mvc/Service/ControllerLoaderFactory.php @@ -47,13 +47,7 @@ public function createService(ServiceLocatorInterface $serviceLocator) $config = $serviceLocator->get('Config'); if (isset($config['di']) && isset($config['di']['allowed_controllers']) && $serviceLocator->has('Di')) { - $diAbstractFactory = new DiStrictAbstractServiceFactory( - $serviceLocator->get('Di'), - DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI - ); - $diAbstractFactory->setAllowedServiceNames($config['di']['allowed_controllers']); - - $controllerLoader->addAbstractFactory($diAbstractFactory); + $controllerLoader->addAbstractFactory($serviceLocator->get('DiStrictAbstractServiceFactory')); } return $controllerLoader; diff --git a/library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php b/library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php new file mode 100644 index 00000000000..1d57754520f --- /dev/null +++ b/library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php @@ -0,0 +1,34 @@ +get('Di'), DiAbstractServiceFactory::USE_SL_BEFORE_DI); + } +} diff --git a/library/Zend/Mvc/Service/DiFactory.php b/library/Zend/Mvc/Service/DiFactory.php index 8c801713120..22a80d5dbcc 100644 --- a/library/Zend/Mvc/Service/DiFactory.php +++ b/library/Zend/Mvc/Service/DiFactory.php @@ -48,9 +48,8 @@ public function createService(ServiceLocatorInterface $serviceLocator) if ($serviceLocator instanceof ServiceManager) { /* @var $serviceLocator ServiceManager */ - $serviceLocator->addAbstractFactory( - new DiAbstractServiceFactory($di, DiAbstractServiceFactory::USE_SL_BEFORE_DI) - ); + //$serviceLocator->addAbstractFactory($serviceLocator->get('DiAbstractServiceFactory')); + //$serviceLocator->addInitializer($serviceLocator->get('DiServiceInitializer')); } return $di; diff --git a/library/Zend/Mvc/Service/DiServiceInitializerFactory.php b/library/Zend/Mvc/Service/DiServiceInitializerFactory.php new file mode 100644 index 00000000000..abe295450e2 --- /dev/null +++ b/library/Zend/Mvc/Service/DiServiceInitializerFactory.php @@ -0,0 +1,34 @@ +get('Di'), $serviceLocator); + } +} diff --git a/library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php b/library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php new file mode 100644 index 00000000000..6c1fd47e590 --- /dev/null +++ b/library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php @@ -0,0 +1,44 @@ +get('Di'), + DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI + ); + $config = $serviceLocator->get('Config'); + + if (isset($config['di']['allowed_controllers'])) { + $diAbstractFactory->setAllowedServiceNames($config['di']['allowed_controllers']); + } + + return $diAbstractFactory; + } +} diff --git a/library/Zend/Mvc/Service/ServiceListenerFactory.php b/library/Zend/Mvc/Service/ServiceListenerFactory.php index 6889d612320..2ae9e339e0f 100644 --- a/library/Zend/Mvc/Service/ServiceListenerFactory.php +++ b/library/Zend/Mvc/Service/ServiceListenerFactory.php @@ -45,26 +45,29 @@ class ServiceListenerFactory implements FactoryInterface 'RouteListener' => 'Zend\Mvc\RouteListener', ), 'factories' => array( - 'Application' => 'Zend\Mvc\Service\ApplicationFactory', - 'Config' => 'Zend\Mvc\Service\ConfigFactory', - 'ControllerLoader' => 'Zend\Mvc\Service\ControllerLoaderFactory', - 'ControllerPluginManager' => 'Zend\Mvc\Service\ControllerPluginManagerFactory', - 'ConsoleAdapter' => 'Zend\Mvc\Service\ConsoleAdapterFactory', - 'ConsoleRouter' => 'Zend\Mvc\Service\RouterFactory', - 'DependencyInjector' => 'Zend\Mvc\Service\DiFactory', - 'HttpRouter' => 'Zend\Mvc\Service\RouterFactory', - 'Request' => 'Zend\Mvc\Service\RequestFactory', - 'Response' => 'Zend\Mvc\Service\ResponseFactory', - 'Router' => 'Zend\Mvc\Service\RouterFactory', - 'ViewHelperManager' => 'Zend\Mvc\Service\ViewHelperManagerFactory', - 'ViewFeedRenderer' => 'Zend\Mvc\Service\ViewFeedRendererFactory', - 'ViewFeedStrategy' => 'Zend\Mvc\Service\ViewFeedStrategyFactory', - 'ViewJsonRenderer' => 'Zend\Mvc\Service\ViewJsonRendererFactory', - 'ViewJsonStrategy' => 'Zend\Mvc\Service\ViewJsonStrategyFactory', - 'ViewManager' => 'Zend\Mvc\Service\ViewManagerFactory', - 'ViewResolver' => 'Zend\Mvc\Service\ViewResolverFactory', - 'ViewTemplateMapResolver' => 'Zend\Mvc\Service\ViewTemplateMapResolverFactory', - 'ViewTemplatePathStack' => 'Zend\Mvc\Service\ViewTemplatePathStackFactory', + 'Application' => 'Zend\Mvc\Service\ApplicationFactory', + 'Config' => 'Zend\Mvc\Service\ConfigFactory', + 'ControllerLoader' => 'Zend\Mvc\Service\ControllerLoaderFactory', + 'ControllerPluginManager' => 'Zend\Mvc\Service\ControllerPluginManagerFactory', + 'ConsoleAdapter' => 'Zend\Mvc\Service\ConsoleAdapterFactory', + 'ConsoleRouter' => 'Zend\Mvc\Service\RouterFactory', + 'DependencyInjector' => 'Zend\Mvc\Service\DiFactory', + 'DiStrictAbstractServiceFactory' => 'Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory', + 'DiAbstractServiceFactory' => 'Zend\Mvc\Service\DiAbstractServiceFactoryFactory', + 'DiServiceInitializer' => 'Zend\Mvc\Service\DiServiceInitializerFactory', + 'HttpRouter' => 'Zend\Mvc\Service\RouterFactory', + 'Request' => 'Zend\Mvc\Service\RequestFactory', + 'Response' => 'Zend\Mvc\Service\ResponseFactory', + 'Router' => 'Zend\Mvc\Service\RouterFactory', + 'ViewHelperManager' => 'Zend\Mvc\Service\ViewHelperManagerFactory', + 'ViewFeedRenderer' => 'Zend\Mvc\Service\ViewFeedRendererFactory', + 'ViewFeedStrategy' => 'Zend\Mvc\Service\ViewFeedStrategyFactory', + 'ViewJsonRenderer' => 'Zend\Mvc\Service\ViewJsonRendererFactory', + 'ViewJsonStrategy' => 'Zend\Mvc\Service\ViewJsonStrategyFactory', + 'ViewManager' => 'Zend\Mvc\Service\ViewManagerFactory', + 'ViewResolver' => 'Zend\Mvc\Service\ViewResolverFactory', + 'ViewTemplateMapResolver' => 'Zend\Mvc\Service\ViewTemplateMapResolverFactory', + 'ViewTemplatePathStack' => 'Zend\Mvc\Service\ViewTemplatePathStackFactory', ), 'aliases' => array( 'Configuration' => 'Config', From e03f4f22b28e8894d8fce821ba7a5eb0ab3c37cc Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 8 Aug 2012 03:53:23 +0200 Subject: [PATCH 013/126] Fixing tests (missing factories) --- tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php b/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php index b4c3433e4d6..68ad2741d20 100644 --- a/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php +++ b/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php @@ -15,6 +15,9 @@ use Zend\Mvc\Service\ControllerLoaderFactory; use Zend\Mvc\Service\ControllerPluginManagerFactory; use Zend\Mvc\Service\DiFactory; +use Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory; +use Zend\Mvc\Service\DiAbstractServiceFactoryFactory; +use Zend\Mvc\Service\DiServiceInitializerFactory; use Zend\Mvc\Service\EventManagerFactory; use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; @@ -42,6 +45,9 @@ public function setUp() $this->services->setService('Config', $config); $this->services->setFactory('ControllerPluginBroker', new ControllerPluginManagerFactory()); $this->services->setFactory('Di', new DiFactory()); + $this->services->setFactory('DiStrictAbstractServiceFactory', new DiStrictAbstractServiceFactoryFactory()); + $this->services->setFactory('DiAbstractServiceFactory', new DiAbstractServiceFactoryFactory()); + $this->services->setFactory('DiServiceInitializer', new DiServiceInitializerFactory()); $this->services->setFactory('EventManager', new EventManagerFactory()); $this->services->setInvokableClass('SharedEventManager', 'Zend\EventManager\SharedEventManager'); } From eb27880943d60510045f213e9c3bbeeeaea9ec57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 15 Aug 2012 16:40:12 +0200 Subject: [PATCH 014/126] Add DateSelect and MonthSelect elements --- library/Zend/Form/Element/DateSelect.php | 236 +++++++++++++++ library/Zend/Form/Element/MonthSelect.php | 70 +++++ .../Zend/Form/View/Helper/FormDateSelect.php | 286 ++++++++++++++++++ library/Zend/Form/View/Helper/FormElement.php | 10 + .../Zend/Form/View/Helper/FormMonthSelect.php | 67 ++++ library/Zend/Form/View/HelperConfig.php | 2 + library/Zend/Validator/Regex.php | 2 +- .../ZendTest/Form/Element/DateSelectTest.php | 42 +++ .../ZendTest/Form/Element/MonthSelectTest.php | 42 +++ .../Form/View/Helper/FormDateSelectTest.php | 58 ++++ .../Form/View/Helper/FormMonthSelectTest.php | 58 ++++ 11 files changed, 872 insertions(+), 1 deletion(-) create mode 100644 library/Zend/Form/Element/DateSelect.php create mode 100644 library/Zend/Form/Element/MonthSelect.php create mode 100644 library/Zend/Form/View/Helper/FormDateSelect.php create mode 100644 library/Zend/Form/View/Helper/FormMonthSelect.php create mode 100644 tests/ZendTest/Form/Element/DateSelectTest.php create mode 100644 tests/ZendTest/Form/Element/MonthSelectTest.php create mode 100644 tests/ZendTest/Form/View/Helper/FormDateSelectTest.php create mode 100644 tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php new file mode 100644 index 00000000000..dd40d758e1f --- /dev/null +++ b/library/Zend/Form/Element/DateSelect.php @@ -0,0 +1,236 @@ +dayElement = new Select('day'); + $this->monthElement = new Select('month'); + $this->yearElement = new Select('year'); + + $this->maxYear = date('Y'); + $this->minYear = $this->maxYear - 100; + } + + /** + * Accepted options for DateSelect: + * - min_year: min year to use in the year select + * - max_year: max year to use in the year select + * + * @param array|\Traversable $options + * @return DateSelect + */ + public function setOptions($options) + { + parent::setOptions($options); + + if (isset($options['min_year'])) { + $this->setMinYear($options['min_year']); + } + + if (isset($options['max_year'])) { + $this->setMaxYear($options['max_year']); + } + + return $this; + } + + /** + * @return Select + */ + public function getDayElement() + { + return $this->dayElement; + } + + /** + * @return Select + */ + public function getMonthElement() + { + return $this->monthElement; + } + + /** + * @return Select + */ + public function getYearElement() + { + return $this->yearElement; + } + + /** + * @param int $minYear + * @return DateSelect + */ + public function setMinYear($minYear) + { + $this->minYear = $minYear; + return $this; + } + + /** + * @return int + */ + public function getMinYear() + { + return $this->minYear; + } + + /** + * @param int $maxYear + * @return DateSelect + */ + public function setMaxYear($maxYear) + { + $this->maxYear = $maxYear; + return $this; + } + + /** + * @return int + */ + public function getMaxYear() + { + return $this->maxYear; + } + + /** + * @param mixed $value + * @return void|\Zend\Form\Element + */ + public function setValue($value) + { + $this->dayElement->setValue($value['day']); + $this->monthElement->setValue($value['month']); + $this->yearElement->setValue($value['year']); + } + + /** + * Prepare the form element (mostly used for rendering purposes) + * + * @param Form $form + * @return mixed + */ + public function prepareElement(Form $form) + { + $name = $this->getName(); + + $this->dayElement->setName($name . '[day]'); + $this->monthElement->setName($name . '[month]'); + $this->yearElement->setName($name . '[year]'); + } + + /** + * Get validator + * + * @return ValidatorInterface + */ + protected function getValidator() + { + if (null === $this->validator) { + $this->validator = new DateValidator(array('format' => 'Y-n-j')); + } + + return $this->validator; + } + + /** + * Should return an array specification compatible with + * {@link Zend\InputFilter\Factory::createInput()}. + * + * @return array + */ + public function getInputSpecification() + { + return array( + 'name' => $this->getName(), + 'required' => false, + 'filters' => array( + array( + 'name' => 'Callback', + 'options' => array( + 'callback' => function($date) { + // Convert the date to a specific format + if (is_array($date)) { + $date = $date['year'] . '-' . $date['month'] . '-' . $date['day']; + } + + return $date; + } + ) + ) + ), + 'validators' => array( + $this->getValidator(), + ) + ); + } +} + diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php new file mode 100644 index 00000000000..939810fa9ec --- /dev/null +++ b/library/Zend/Form/Element/MonthSelect.php @@ -0,0 +1,70 @@ +monthElement->setValue($value['month']); + $this->yearElement->setValue($value['year']); + } + + /** + * Get validator + * + * @return ValidatorInterface + */ + protected function getValidator() + { + return new RegexValidator('/^[0-9]{4}\-(0?[1-9]|1[012])$/'); + } + + /** + * Should return an array specification compatible with + * {@link Zend\InputFilter\Factory::createInput()}. + * + * @return array + */ + public function getInputSpecification() + { + return array( + 'name' => $this->getName(), + 'required' => false, + 'filters' => array( + array( + 'name' => 'Callback', + 'options' => array( + 'callback' => function($date) { + // Convert the date to a specific format + if (is_array($date)) { + $date = $date['year'] . '-' . $date['month']; + } + + return $date; + } + ) + ) + ), + 'validators' => array( + $this->getValidator(), + ) + ); + } +} + diff --git a/library/Zend/Form/View/Helper/FormDateSelect.php b/library/Zend/Form/View/Helper/FormDateSelect.php new file mode 100644 index 00000000000..6f7a97f6736 --- /dev/null +++ b/library/Zend/Form/View/Helper/FormDateSelect.php @@ -0,0 +1,286 @@ +getName(); + if ($name === null || $name === '') { + throw new Exception\DomainException(sprintf( + '%s requires that the element has an assigned name; none discovered', + __METHOD__ + )); + } + + $selectHelper = $this->getSelectElementHelper(); + $pattern = $this->parsePattern(); + + $daysOptions = $this->getDaysOptions($pattern['day']); + $monthsOptions = $this->getMonthsOptions($pattern['month']); + $yearOptions = $this->getYearsOptions($element->getMinYear(), $element->getMaxYear()); + + $dayElement = $element->getDayElement()->setAttribute('options', $daysOptions); + $monthElement = $element->getMonthElement()->setAttribute('options', $monthsOptions); + $yearElement = $element->getYearElement()->setAttribute('options', $yearOptions); + + $markup = array(); + $markup[$pattern['day']] = $selectHelper->render($dayElement); + $markup[$pattern['month']] = $selectHelper->render($monthElement); + $markup[$pattern['year']] = $selectHelper->render($yearElement); + + $markup = sprintf( + '%s %s %s %s %s', + $markup[array_shift($pattern)], + array_shift($pattern), // Delimiter + $markup[array_shift($pattern)], + array_shift($pattern), // Delimiter + $markup[array_shift($pattern)] + ); + + return $markup; + } + + /** + * Invoke helper as function + * + * Proxies to {@link render()}. + * + * @param \Zend\Form\ElementInterface $element + * @param int $dateType + * @param null|string $locale + * @return FormDateSelect + */ + public function __invoke(ElementInterface $element = null, $dateType = IntlDateFormatter::LONG, $locale = null) + { + if (!$element) { + return $this; + } + + $this->setDateType($dateType); + + if ($locale !== null) { + $this->setLocale($locale); + } + + return $this->render($element); + } + + /** + * Parse the pattern + * + * @return array + */ + public function parsePattern() + { + $pattern = $this->getPattern(); + $pregResult = preg_split('/([ -,.\/]+)/', $pattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + $result = array(); + foreach ($pregResult as $value) { + if (stripos($value, 'd') !== false) { + $result['day'] = $value; + } elseif (stripos($value, 'm') !== false) { + $result['month'] = $value; + } elseif (stripos($value, 'y') !== false) { + $result['year'] = $value; + } else { + $result[] = $value; + } + } + + return $result; + } + + /** + * @return string + */ + public function getPattern() + { + if ($this->pattern === null) { + $intl = new IntlDateFormatter($this->getLocale(), $this->dateType, IntlDateFormatter::NONE); + $this->pattern = $intl->getPattern(); + } + + return $this->pattern; + } + + /** + * @param int $dateType + * @return FormDateSelect + */ + public function setDateType($dateType) + { + // The FULL format uses values that are not used + if ($dateType === IntlDateFormatter::FULL) { + $dateType = IntlDateFormatter::LONG; + } + + $this->dateType = $dateType; + + return $this; + } + + /** + * @return int + */ + public function getDateType() + { + return $this->dateType; + } + + /** + * @param string $locale + * @return FormDateSelect + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Create a key => value options for days + * + * @param string $pattern Pattern to use for days + * @return array + */ + public function getDaysOptions($pattern) + { + $formatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); + $date = new DateTime('1970-01-01'); + + $result = array(); + for ($day = 1; $day <= 31; $day++) { + $result[$day] = $formatter->format($date); + $date->modify('+1 day'); + } + + return $result; + } + + /** + * Create a key => value options for months + * + * @param string $pattern Pattern to use for months + * @return array + */ + public function getMonthsOptions($pattern) + { + $formatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); + $date = new DateTime('1970-01-01'); + + $result = array(); + for ($month = 1; $month <= 12; $month++) { + $result[$month] = $formatter->format($date); + $date->modify('+1 month'); + } + + return $result; + } + + /** + * Create a key => value options for years + * NOTE: we don't use a pattern for years, as years written as two digits can lead to hard to + * read date for users, so we only use four digits years + * + * @param int $minYear + * @param int $maxYear + * @return array + */ + public function getYearsOptions($minYear, $maxYear) + { + $result = array(); + for ($i = $maxYear; $i >= $minYear; --$i) { + $result[$i] = $i; + } + + return $result; + } + + /** + * Retrieve the FormSelect helper + * + * @return FormRow + */ + protected function getSelectElementHelper() + { + if ($this->selectHelper) { + return $this->selectHelper; + } + + if (method_exists($this->view, 'plugin')) { + $this->selectHelper = $this->view->plugin('formselect'); + } + + return $this->selectHelper; + } +} + diff --git a/library/Zend/Form/View/Helper/FormElement.php b/library/Zend/Form/View/Helper/FormElement.php index 3597f22ee50..f9ddad3157a 100644 --- a/library/Zend/Form/View/Helper/FormElement.php +++ b/library/Zend/Form/View/Helper/FormElement.php @@ -53,6 +53,16 @@ public function render(ElementInterface $element) return $helper($element); } + if ($element instanceof Element\MonthSelect) { + $helper = $renderer->plugin('form_month_select'); + return $helper($element); + } + + if ($element instanceof Element\DateSelect) { + $helper = $renderer->plugin('form_date_select'); + return $helper($element); + } + $type = $element->getAttribute('type'); $options = $element->getAttribute('options'); diff --git a/library/Zend/Form/View/Helper/FormMonthSelect.php b/library/Zend/Form/View/Helper/FormMonthSelect.php new file mode 100644 index 00000000000..afb8c274f5f --- /dev/null +++ b/library/Zend/Form/View/Helper/FormMonthSelect.php @@ -0,0 +1,67 @@ +getName(); + if ($name === null || $name === '') { + throw new Exception\DomainException(sprintf( + '%s requires that the element has an assigned name; none discovered', + __METHOD__ + )); + } + + $selectHelper = $this->getSelectElementHelper(); + $pattern = $this->parsePattern(); + + // The pattern always contains "day" part and the first separator, so we have to remove it + unset($pattern['day']); + unset($pattern[0]); + + $monthsOptions = $this->getMonthsOptions($pattern['month']); + $yearOptions = $this->getYearsOptions($element->getMinYear(), $element->getMaxYear()); + + $monthElement = $element->getMonthElement()->setAttribute('options', $monthsOptions); + $yearElement = $element->getYearElement()->setAttribute('options', $yearOptions); + + $markup = array(); + $markup[$pattern['month']] = $selectHelper->render($monthElement); + $markup[$pattern['year']] = $selectHelper->render($yearElement); + + $markup = sprintf( + '%s %s %s', + $markup[array_shift($pattern)], + array_shift($pattern), // Delimiter + $markup[array_shift($pattern)] + ); + + return $markup; + } +} + diff --git a/library/Zend/Form/View/HelperConfig.php b/library/Zend/Form/View/HelperConfig.php index fe6590d65ba..aeada7947d2 100644 --- a/library/Zend/Form/View/HelperConfig.php +++ b/library/Zend/Form/View/HelperConfig.php @@ -43,6 +43,7 @@ class HelperConfig implements ConfigInterface 'formdate' => 'Zend\Form\View\Helper\FormDate', 'formdatetime' => 'Zend\Form\View\Helper\FormDateTime', 'formdatetimelocal' => 'Zend\Form\View\Helper\FormDateTimeLocal', + 'formdateselect' => 'Zend\Form\View\Helper\FormDateSelect', 'formelement' => 'Zend\Form\View\Helper\FormElement', 'formelementerrors' => 'Zend\Form\View\Helper\FormElementErrors', 'formemail' => 'Zend\Form\View\Helper\FormEmail', @@ -52,6 +53,7 @@ class HelperConfig implements ConfigInterface 'forminput' => 'Zend\Form\View\Helper\FormInput', 'formlabel' => 'Zend\Form\View\Helper\FormLabel', 'formmonth' => 'Zend\Form\View\Helper\FormMonth', + 'formmonthselect' => 'Zend\Form\View\Helper\FormMonthSelect', 'formmulticheckbox' => 'Zend\Form\View\Helper\FormMultiCheckbox', 'formnumber' => 'Zend\Form\View\Helper\FormNumber', 'formpassword' => 'Zend\Form\View\Helper\FormPassword', diff --git a/library/Zend/Validator/Regex.php b/library/Zend/Validator/Regex.php index 010d7a429a1..03cd15011ea 100644 --- a/library/Zend/Validator/Regex.php +++ b/library/Zend/Validator/Regex.php @@ -118,7 +118,7 @@ public function isValid($value) $this->error(self::INVALID); return false; } - +var_dump($value); $this->setValue($value); $status = @preg_match($this->pattern, $value); diff --git a/tests/ZendTest/Form/Element/DateSelectTest.php b/tests/ZendTest/Form/Element/DateSelectTest.php new file mode 100644 index 00000000000..e18698d7a0c --- /dev/null +++ b/tests/ZendTest/Form/Element/DateSelectTest.php @@ -0,0 +1,42 @@ +getInputSpecification(); + $this->assertArrayHasKey('validators', $inputSpec); + $this->assertInternalType('array', $inputSpec['validators']); + + $expectedClasses = array( + 'Zend\Validator\Date' + ); + foreach ($inputSpec['validators'] as $validator) { + $class = get_class($validator); + $this->assertTrue(in_array($class, $expectedClasses), $class); + switch ($class) { + case 'Zend\Validator\Date': + $this->assertEquals('Y-n-j', $validator->getFormat()); + break; + default: + break; + } + } + } +} diff --git a/tests/ZendTest/Form/Element/MonthSelectTest.php b/tests/ZendTest/Form/Element/MonthSelectTest.php new file mode 100644 index 00000000000..f1c3d99c102 --- /dev/null +++ b/tests/ZendTest/Form/Element/MonthSelectTest.php @@ -0,0 +1,42 @@ +getInputSpecification(); + $this->assertArrayHasKey('validators', $inputSpec); + $this->assertInternalType('array', $inputSpec['validators']); + + $expectedClasses = array( + 'Zend\Validator\Regex' + ); + foreach ($inputSpec['validators'] as $validator) { + $class = get_class($validator); + $this->assertTrue(in_array($class, $expectedClasses), $class); + switch ($class) { + case 'Zend\Validator\Regex': + $this->assertEquals('/^[0-9]{4}\-(0?[1-9]|1[012])$/', $validator->getPattern()); + break; + default: + break; + } + } + } +} diff --git a/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php b/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php new file mode 100644 index 00000000000..cd590ad1b65 --- /dev/null +++ b/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php @@ -0,0 +1,58 @@ +helper = new FormDateSelectHelper(); + parent::setUp(); + } + + public function testRaisesExceptionWhenNameIsNotPresentInElement() + { + $element = new DateSelect(); + $this->setExpectedException('Zend\Form\Exception\DomainException', 'name'); + $this->helper->render($element); + } + + public function testGeneratesThreeSelectsWithElement() + { + $element = new DateSelect('foo'); + $markup = $this->helper->render($element); + $this->assertContains('assertContains('assertContains('assertSame($this->helper, $this->helper->__invoke()); + } +} diff --git a/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php b/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php new file mode 100644 index 00000000000..9babc9e4d85 --- /dev/null +++ b/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php @@ -0,0 +1,58 @@ +helper = new FormMonthSelectHelper(); + parent::setUp(); + } + + public function testRaisesExceptionWhenNameIsNotPresentInElement() + { + $element = new MonthSelect(); + $this->setExpectedException('Zend\Form\Exception\DomainException', 'name'); + $this->helper->render($element); + } + + public function testGeneratesTwoSelectsWithElement() + { + $element = new MonthSelect('foo'); + $markup = $this->helper->render($element); + $this->assertNotContains('assertContains('assertContains('assertSame($this->helper, $this->helper->__invoke()); + } +} From 056a5ba9b5793a58ab3842bf21fb2cca158e0b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 15 Aug 2012 17:35:22 +0200 Subject: [PATCH 015/126] Use more user-friendly format Y-m-d instead of Y-n-j --- library/Zend/Form/Element/DateSelect.php | 2 +- .../Zend/Form/View/Helper/FormDateSelect.php | 20 +++++++++++++------ library/Zend/Validator/Regex.php | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index dd40d758e1f..d3fc3c5afc5 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -195,7 +195,7 @@ public function prepareElement(Form $form) protected function getValidator() { if (null === $this->validator) { - $this->validator = new DateValidator(array('format' => 'Y-n-j')); + $this->validator = new DateValidator(array('format' => 'Y-m-d')); } return $this->validator; diff --git a/library/Zend/Form/View/Helper/FormDateSelect.php b/library/Zend/Form/View/Helper/FormDateSelect.php index 6f7a97f6736..ca0627ff045 100644 --- a/library/Zend/Form/View/Helper/FormDateSelect.php +++ b/library/Zend/Form/View/Helper/FormDateSelect.php @@ -214,12 +214,16 @@ public function getLocale() */ public function getDaysOptions($pattern) { - $formatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); - $date = new DateTime('1970-01-01'); + $keyFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'dd'); + $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); + $date = new DateTime('1970-01-01'); $result = array(); for ($day = 1; $day <= 31; $day++) { - $result[$day] = $formatter->format($date); + $key = $keyFormatter->format($date); + $value = $valueFormatter->format($date); + $result[$key] = $value; + $date->modify('+1 day'); } @@ -234,12 +238,16 @@ public function getDaysOptions($pattern) */ public function getMonthsOptions($pattern) { - $formatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); - $date = new DateTime('1970-01-01'); + $keyFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'MM'); + $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); + $date = new DateTime('1970-01-01'); $result = array(); for ($month = 1; $month <= 12; $month++) { - $result[$month] = $formatter->format($date); + $key = $keyFormatter->format($date); + $value = $valueFormatter->format($date); + $result[$key] = $value; + $date->modify('+1 month'); } diff --git a/library/Zend/Validator/Regex.php b/library/Zend/Validator/Regex.php index 03cd15011ea..010d7a429a1 100644 --- a/library/Zend/Validator/Regex.php +++ b/library/Zend/Validator/Regex.php @@ -118,7 +118,7 @@ public function isValid($value) $this->error(self::INVALID); return false; } -var_dump($value); + $this->setValue($value); $status = @preg_match($this->pattern, $value); From b201562c76c1f5dfbcde59509b68b6f725f19fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 15 Aug 2012 17:53:49 +0200 Subject: [PATCH 016/126] Fix test --- tests/ZendTest/Form/Element/DateSelectTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ZendTest/Form/Element/DateSelectTest.php b/tests/ZendTest/Form/Element/DateSelectTest.php index e18698d7a0c..dd87802c949 100644 --- a/tests/ZendTest/Form/Element/DateSelectTest.php +++ b/tests/ZendTest/Form/Element/DateSelectTest.php @@ -32,7 +32,7 @@ public function testProvidesInputSpecificationThatIncludesValidatorsBasedOnAttri $this->assertTrue(in_array($class, $expectedClasses), $class); switch ($class) { case 'Zend\Validator\Date': - $this->assertEquals('Y-n-j', $validator->getFormat()); + $this->assertEquals('Y-m-d', $validator->getFormat()); break; default: break; From feae790e1577950ff6c5c2955d3af5bea5514b41 Mon Sep 17 00:00:00 2001 From: Roy van Kaathoven Date: Fri, 3 Aug 2012 23:51:19 +0200 Subject: [PATCH 017/126] added class annotation scanner --- library/Zend/Code/Scanner/ClassScanner.php | 16 +++++++--- .../TestAsset/EntityWithAnnotations.php | 8 ++++- .../Code/Scanner/ClassScannerTest.php | 29 ++++++++++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/library/Zend/Code/Scanner/ClassScanner.php b/library/Zend/Code/Scanner/ClassScanner.php index 000b6346bd0..3e8eef17edd 100644 --- a/library/Zend/Code/Scanner/ClassScanner.php +++ b/library/Zend/Code/Scanner/ClassScanner.php @@ -10,7 +10,7 @@ namespace Zend\Code\Scanner; -use Zend\Code\Annotation\AnnotationManager; +use Zend\Code\Annotation; use Zend\Code\Exception; use Zend\Code\NameInformation; @@ -107,9 +107,17 @@ public function __construct(array $classTokens, NameInformation $nameInformation $this->nameInformation = $nameInformation; } - public function getAnnotations() + /** + * @param Annotation\AnnotationManager $annotationManager + * @return Annotation\AnnotationCollection + */ + public function getAnnotations(Annotation\AnnotationManager $annotationManager) { - return array(); + if (($docComment = $this->getDocComment()) == '') { + return false; + } + + return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } public function getDocComment() @@ -678,4 +686,4 @@ protected function scan() return; } -} +} \ No newline at end of file diff --git a/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php b/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php index 4ed63fd024a..0472e5d6610 100644 --- a/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php +++ b/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php @@ -10,6 +10,12 @@ namespace ZendTest\Code\Annotation\TestAsset; +/** + * @Foo(first) + * @Bar(second) + * @Bar(third) + * @Bogus(does not exist) + */ class EntityWithAnnotations { /** @@ -19,4 +25,4 @@ class EntityWithAnnotations * @Bogus(does not exist) */ public $test; -} +} \ No newline at end of file diff --git a/tests/ZendTest/Code/Scanner/ClassScannerTest.php b/tests/ZendTest/Code/Scanner/ClassScannerTest.php index c0fdda8d791..0993f6b9abe 100644 --- a/tests/ZendTest/Code/Scanner/ClassScannerTest.php +++ b/tests/ZendTest/Code/Scanner/ClassScannerTest.php @@ -11,10 +11,24 @@ namespace ZendTest\Code\Scanner; use Zend\Code\Scanner\FileScanner; +use Zend\Code\Annotation; use PHPUnit_Framework_TestCase as TestCase; class ClassScannerTest extends TestCase { + protected $manager; + + public function setUp() + { + $this->manager = new Annotation\AnnotationManager(); + + $genericParser = new Annotation\Parser\GenericAnnotationParser(); + $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Foo'); + $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Bar'); + + $this->manager->attach($genericParser); + } + public function testClassScannerHasClassInformation() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); @@ -84,5 +98,18 @@ public function testClassScannerCanReturnLineNumbers() $this->assertEquals(11, $class->getLineStart()); $this->assertEquals(34, $class->getLineEnd()); } + + public function testClassScannerCanScanAnnotations() + { + $file = new FileScanner(__DIR__ . '/../Annotation/TestAsset/EntityWithAnnotations.php'); + $class = $file->getClass('ZendTest\Code\Annotation\TestAsset\EntityWithAnnotations'); + $annotations = $class->getAnnotations($this->manager); + + $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Foo')); + $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Bar')); -} + $this->assertEquals('first', $annotations[0]->content); + $this->assertEquals('second', $annotations[1]->content); + $this->assertEquals('third', $annotations[2]->content); + } +} \ No newline at end of file From 43a401d832f3b88e6e7e08d08550b0db74354c2b Mon Sep 17 00:00:00 2001 From: Roy van Kaathoven Date: Sat, 4 Aug 2012 00:03:20 +0200 Subject: [PATCH 018/126] fixed trailing spaces --- tests/ZendTest/Code/Scanner/ClassScannerTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ZendTest/Code/Scanner/ClassScannerTest.php b/tests/ZendTest/Code/Scanner/ClassScannerTest.php index 0993f6b9abe..b659fa43659 100644 --- a/tests/ZendTest/Code/Scanner/ClassScannerTest.php +++ b/tests/ZendTest/Code/Scanner/ClassScannerTest.php @@ -17,18 +17,18 @@ class ClassScannerTest extends TestCase { protected $manager; - + public function setUp() { $this->manager = new Annotation\AnnotationManager(); - + $genericParser = new Annotation\Parser\GenericAnnotationParser(); $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Foo'); $genericParser->registerAnnotation('ZendTest\Code\Annotation\TestAsset\Bar'); - + $this->manager->attach($genericParser); } - + public function testClassScannerHasClassInformation() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); @@ -98,13 +98,13 @@ public function testClassScannerCanReturnLineNumbers() $this->assertEquals(11, $class->getLineStart()); $this->assertEquals(34, $class->getLineEnd()); } - + public function testClassScannerCanScanAnnotations() { $file = new FileScanner(__DIR__ . '/../Annotation/TestAsset/EntityWithAnnotations.php'); $class = $file->getClass('ZendTest\Code\Annotation\TestAsset\EntityWithAnnotations'); $annotations = $class->getAnnotations($this->manager); - + $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Foo')); $this->assertTrue($annotations->hasAnnotation('ZendTest\Code\Annotation\TestAsset\Bar')); From 59d8c0028cdaa37179f4c8d4e7f5fe1183c0a2e4 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 8 Aug 2012 03:43:56 +0200 Subject: [PATCH 019/126] Adding factories to generate the abstract Di factories and initializers --- .../Service/AbstractPluginManagerFactory.php | 16 +++---- .../Mvc/Service/ControllerLoaderFactory.php | 8 +--- .../DiAbstractServiceFactoryFactory.php | 34 ++++++++++++++ library/Zend/Mvc/Service/DiFactory.php | 5 +-- .../Service/DiServiceInitializerFactory.php | 34 ++++++++++++++ .../DiStrictAbstractServiceFactoryFactory.php | 44 +++++++++++++++++++ .../Mvc/Service/ServiceListenerFactory.php | 43 +++++++++--------- 7 files changed, 145 insertions(+), 39 deletions(-) create mode 100644 library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php create mode 100644 library/Zend/Mvc/Service/DiServiceInitializerFactory.php create mode 100644 library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php diff --git a/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php b/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php index 6fada16abb8..723120528f3 100644 --- a/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php +++ b/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php @@ -30,23 +30,21 @@ abstract class AbstractPluginManagerFactory implements FactoryInterface * the PLUGIN_MANGER_CLASS constant. * * @param ServiceLocatorInterface $serviceLocator - * @return AbstractPluginManager + * @return \Zend\ServiceManager\AbstractPluginManager */ public function createService(ServiceLocatorInterface $serviceLocator) { $pluginManagerClass = static::PLUGIN_MANAGER_CLASS; + /* @var $plugins \Zend\ServiceManager\AbstractPluginManager */ $plugins = new $pluginManagerClass; $plugins->setServiceLocator($serviceLocator); - $configuration = $serviceLocator->get('Config'); + $configuration = $serviceLocator->get('Config'); + if (isset($configuration['di']) && $serviceLocator->has('Di')) { - $di = $serviceLocator->get('Di'); - $plugins->addAbstractFactory( - new DiAbstractServiceFactory($di, DiAbstractServiceFactory::USE_SL_BEFORE_DI) - ); - $plugins->addInitializer( - new DiServiceInitializer($di, $serviceLocator) - ); + $plugins->addAbstractFactory($serviceLocator->get('DiAbstractServiceFactory')); + $plugins->addInitializer($serviceLocator->get('DiServiceInitializer')); } + return $plugins; } } diff --git a/library/Zend/Mvc/Service/ControllerLoaderFactory.php b/library/Zend/Mvc/Service/ControllerLoaderFactory.php index be64bda0ad5..434271389fd 100644 --- a/library/Zend/Mvc/Service/ControllerLoaderFactory.php +++ b/library/Zend/Mvc/Service/ControllerLoaderFactory.php @@ -47,13 +47,7 @@ public function createService(ServiceLocatorInterface $serviceLocator) $config = $serviceLocator->get('Config'); if (isset($config['di']) && isset($config['di']['allowed_controllers']) && $serviceLocator->has('Di')) { - $diAbstractFactory = new DiStrictAbstractServiceFactory( - $serviceLocator->get('Di'), - DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI - ); - $diAbstractFactory->setAllowedServiceNames($config['di']['allowed_controllers']); - - $controllerLoader->addAbstractFactory($diAbstractFactory); + $controllerLoader->addAbstractFactory($serviceLocator->get('DiStrictAbstractServiceFactory')); } return $controllerLoader; diff --git a/library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php b/library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php new file mode 100644 index 00000000000..1d57754520f --- /dev/null +++ b/library/Zend/Mvc/Service/DiAbstractServiceFactoryFactory.php @@ -0,0 +1,34 @@ +get('Di'), DiAbstractServiceFactory::USE_SL_BEFORE_DI); + } +} diff --git a/library/Zend/Mvc/Service/DiFactory.php b/library/Zend/Mvc/Service/DiFactory.php index 8c801713120..22a80d5dbcc 100644 --- a/library/Zend/Mvc/Service/DiFactory.php +++ b/library/Zend/Mvc/Service/DiFactory.php @@ -48,9 +48,8 @@ public function createService(ServiceLocatorInterface $serviceLocator) if ($serviceLocator instanceof ServiceManager) { /* @var $serviceLocator ServiceManager */ - $serviceLocator->addAbstractFactory( - new DiAbstractServiceFactory($di, DiAbstractServiceFactory::USE_SL_BEFORE_DI) - ); + //$serviceLocator->addAbstractFactory($serviceLocator->get('DiAbstractServiceFactory')); + //$serviceLocator->addInitializer($serviceLocator->get('DiServiceInitializer')); } return $di; diff --git a/library/Zend/Mvc/Service/DiServiceInitializerFactory.php b/library/Zend/Mvc/Service/DiServiceInitializerFactory.php new file mode 100644 index 00000000000..abe295450e2 --- /dev/null +++ b/library/Zend/Mvc/Service/DiServiceInitializerFactory.php @@ -0,0 +1,34 @@ +get('Di'), $serviceLocator); + } +} diff --git a/library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php b/library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php new file mode 100644 index 00000000000..6c1fd47e590 --- /dev/null +++ b/library/Zend/Mvc/Service/DiStrictAbstractServiceFactoryFactory.php @@ -0,0 +1,44 @@ +get('Di'), + DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI + ); + $config = $serviceLocator->get('Config'); + + if (isset($config['di']['allowed_controllers'])) { + $diAbstractFactory->setAllowedServiceNames($config['di']['allowed_controllers']); + } + + return $diAbstractFactory; + } +} diff --git a/library/Zend/Mvc/Service/ServiceListenerFactory.php b/library/Zend/Mvc/Service/ServiceListenerFactory.php index 6889d612320..2ae9e339e0f 100644 --- a/library/Zend/Mvc/Service/ServiceListenerFactory.php +++ b/library/Zend/Mvc/Service/ServiceListenerFactory.php @@ -45,26 +45,29 @@ class ServiceListenerFactory implements FactoryInterface 'RouteListener' => 'Zend\Mvc\RouteListener', ), 'factories' => array( - 'Application' => 'Zend\Mvc\Service\ApplicationFactory', - 'Config' => 'Zend\Mvc\Service\ConfigFactory', - 'ControllerLoader' => 'Zend\Mvc\Service\ControllerLoaderFactory', - 'ControllerPluginManager' => 'Zend\Mvc\Service\ControllerPluginManagerFactory', - 'ConsoleAdapter' => 'Zend\Mvc\Service\ConsoleAdapterFactory', - 'ConsoleRouter' => 'Zend\Mvc\Service\RouterFactory', - 'DependencyInjector' => 'Zend\Mvc\Service\DiFactory', - 'HttpRouter' => 'Zend\Mvc\Service\RouterFactory', - 'Request' => 'Zend\Mvc\Service\RequestFactory', - 'Response' => 'Zend\Mvc\Service\ResponseFactory', - 'Router' => 'Zend\Mvc\Service\RouterFactory', - 'ViewHelperManager' => 'Zend\Mvc\Service\ViewHelperManagerFactory', - 'ViewFeedRenderer' => 'Zend\Mvc\Service\ViewFeedRendererFactory', - 'ViewFeedStrategy' => 'Zend\Mvc\Service\ViewFeedStrategyFactory', - 'ViewJsonRenderer' => 'Zend\Mvc\Service\ViewJsonRendererFactory', - 'ViewJsonStrategy' => 'Zend\Mvc\Service\ViewJsonStrategyFactory', - 'ViewManager' => 'Zend\Mvc\Service\ViewManagerFactory', - 'ViewResolver' => 'Zend\Mvc\Service\ViewResolverFactory', - 'ViewTemplateMapResolver' => 'Zend\Mvc\Service\ViewTemplateMapResolverFactory', - 'ViewTemplatePathStack' => 'Zend\Mvc\Service\ViewTemplatePathStackFactory', + 'Application' => 'Zend\Mvc\Service\ApplicationFactory', + 'Config' => 'Zend\Mvc\Service\ConfigFactory', + 'ControllerLoader' => 'Zend\Mvc\Service\ControllerLoaderFactory', + 'ControllerPluginManager' => 'Zend\Mvc\Service\ControllerPluginManagerFactory', + 'ConsoleAdapter' => 'Zend\Mvc\Service\ConsoleAdapterFactory', + 'ConsoleRouter' => 'Zend\Mvc\Service\RouterFactory', + 'DependencyInjector' => 'Zend\Mvc\Service\DiFactory', + 'DiStrictAbstractServiceFactory' => 'Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory', + 'DiAbstractServiceFactory' => 'Zend\Mvc\Service\DiAbstractServiceFactoryFactory', + 'DiServiceInitializer' => 'Zend\Mvc\Service\DiServiceInitializerFactory', + 'HttpRouter' => 'Zend\Mvc\Service\RouterFactory', + 'Request' => 'Zend\Mvc\Service\RequestFactory', + 'Response' => 'Zend\Mvc\Service\ResponseFactory', + 'Router' => 'Zend\Mvc\Service\RouterFactory', + 'ViewHelperManager' => 'Zend\Mvc\Service\ViewHelperManagerFactory', + 'ViewFeedRenderer' => 'Zend\Mvc\Service\ViewFeedRendererFactory', + 'ViewFeedStrategy' => 'Zend\Mvc\Service\ViewFeedStrategyFactory', + 'ViewJsonRenderer' => 'Zend\Mvc\Service\ViewJsonRendererFactory', + 'ViewJsonStrategy' => 'Zend\Mvc\Service\ViewJsonStrategyFactory', + 'ViewManager' => 'Zend\Mvc\Service\ViewManagerFactory', + 'ViewResolver' => 'Zend\Mvc\Service\ViewResolverFactory', + 'ViewTemplateMapResolver' => 'Zend\Mvc\Service\ViewTemplateMapResolverFactory', + 'ViewTemplatePathStack' => 'Zend\Mvc\Service\ViewTemplatePathStackFactory', ), 'aliases' => array( 'Configuration' => 'Config', From c082164b915dee68ea4e64c49e9db9a6d7f400a5 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 8 Aug 2012 03:53:23 +0200 Subject: [PATCH 020/126] Fixing tests (missing factories) --- tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php b/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php index b4c3433e4d6..68ad2741d20 100644 --- a/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php +++ b/tests/ZendTest/Mvc/Service/ControllerLoaderFactoryTest.php @@ -15,6 +15,9 @@ use Zend\Mvc\Service\ControllerLoaderFactory; use Zend\Mvc\Service\ControllerPluginManagerFactory; use Zend\Mvc\Service\DiFactory; +use Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory; +use Zend\Mvc\Service\DiAbstractServiceFactoryFactory; +use Zend\Mvc\Service\DiServiceInitializerFactory; use Zend\Mvc\Service\EventManagerFactory; use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; @@ -42,6 +45,9 @@ public function setUp() $this->services->setService('Config', $config); $this->services->setFactory('ControllerPluginBroker', new ControllerPluginManagerFactory()); $this->services->setFactory('Di', new DiFactory()); + $this->services->setFactory('DiStrictAbstractServiceFactory', new DiStrictAbstractServiceFactoryFactory()); + $this->services->setFactory('DiAbstractServiceFactory', new DiAbstractServiceFactoryFactory()); + $this->services->setFactory('DiServiceInitializer', new DiServiceInitializerFactory()); $this->services->setFactory('EventManager', new EventManagerFactory()); $this->services->setInvokableClass('SharedEventManager', 'Zend\EventManager\SharedEventManager'); } From cc2dadaa6d9517aba481a3b1e4dd58cac77e4ea4 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 16 Aug 2012 21:29:02 +0200 Subject: [PATCH 021/126] Removing registration of abstract service factories within the DiFactory since it will only cause problems with cyclic dependencies --- .../Service/AbstractPluginManagerFactory.php | 1 - library/Zend/Mvc/Service/DiFactory.php | 13 +++------ tests/ZendTest/Mvc/Service/DiFactoryTest.php | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 tests/ZendTest/Mvc/Service/DiFactoryTest.php diff --git a/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php b/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php index 723120528f3..340a55b8d83 100644 --- a/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php +++ b/library/Zend/Mvc/Service/AbstractPluginManagerFactory.php @@ -11,7 +11,6 @@ namespace Zend\Mvc\Service; use Zend\ServiceManager\Di\DiAbstractServiceFactory; -use Zend\ServiceManager\Di\DiServiceInitializer; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; diff --git a/library/Zend/Mvc/Service/DiFactory.php b/library/Zend/Mvc/Service/DiFactory.php index 22a80d5dbcc..f208bfd4487 100644 --- a/library/Zend/Mvc/Service/DiFactory.php +++ b/library/Zend/Mvc/Service/DiFactory.php @@ -10,12 +10,10 @@ namespace Zend\Mvc\Service; -use Zend\Di\Config as DiConfig; +use Zend\Di\Config; use Zend\Di\Di; -use Zend\ServiceManager\Di\DiAbstractServiceFactory; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; -use Zend\ServiceManager\ServiceManager; /** * @category Zend @@ -43,13 +41,8 @@ public function createService(ServiceLocatorInterface $serviceLocator) $config = $serviceLocator->get('Config'); if (isset($config['di'])) { - $di->configure(new DiConfig($config['di'])); - } - - if ($serviceLocator instanceof ServiceManager) { - /* @var $serviceLocator ServiceManager */ - //$serviceLocator->addAbstractFactory($serviceLocator->get('DiAbstractServiceFactory')); - //$serviceLocator->addInitializer($serviceLocator->get('DiServiceInitializer')); + $config = new Config($config['di']); + $config->configure($di); } return $di; diff --git a/tests/ZendTest/Mvc/Service/DiFactoryTest.php b/tests/ZendTest/Mvc/Service/DiFactoryTest.php new file mode 100644 index 00000000000..c93baede574 --- /dev/null +++ b/tests/ZendTest/Mvc/Service/DiFactoryTest.php @@ -0,0 +1,27 @@ +setService('Config', array('di' => array(''))); + $serviceManager->setFactory('Di', new DiFactory()); + + $di = $serviceManager->get('Di'); + $this->assertInstanceOf('Zend\Di\Di', $di); + } +} From 5687065c49f456e7ae8f4015e9f9161b2d94f130 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 16 Aug 2012 23:24:33 +0200 Subject: [PATCH 022/126] Added msgpack serializer --- library/Zend/Serializer/Adapter/MsgPack.php | 91 +++++++++++ .../Zend/Serializer/AdapterPluginManager.php | 1 + .../Serializer/Adapter/MsgPackTest.php | 154 ++++++++++++++++++ 3 files changed, 246 insertions(+) create mode 100644 library/Zend/Serializer/Adapter/MsgPack.php create mode 100644 tests/ZendTest/Serializer/Adapter/MsgPackTest.php diff --git a/library/Zend/Serializer/Adapter/MsgPack.php b/library/Zend/Serializer/Adapter/MsgPack.php new file mode 100644 index 00000000000..ee81d4df136 --- /dev/null +++ b/library/Zend/Serializer/Adapter/MsgPack.php @@ -0,0 +1,91 @@ + 'Zend\Serializer\Adapter\IgBinary', 'json' => 'Zend\Serializer\Adapter\Json', + 'msgpack' => 'Zend\Serializer\Adapter\MsgPack', 'phpcode' => 'Zend\Serializer\Adapter\PhpCode', 'phpserialize' => 'Zend\Serializer\Adapter\PhpSerialize', 'pythonpickle' => 'Zend\Serializer\Adapter\PythonPickle', diff --git a/tests/ZendTest/Serializer/Adapter/MsgPackTest.php b/tests/ZendTest/Serializer/Adapter/MsgPackTest.php new file mode 100644 index 00000000000..90f0ee62220 --- /dev/null +++ b/tests/ZendTest/Serializer/Adapter/MsgPackTest.php @@ -0,0 +1,154 @@ +fail("Zend\\Serializer\\Adapter\\MsgPack needs missing ext/msgpack but did't throw exception"); + } catch (ExtensionNotLoadedException $e) {} + $this->markTestSkipped('Zend\\Serializer\\Adapter\\MsgPack needs ext/msgpack'); + } + $this->adapter = new Serializer\Adapter\MsgPack(); + } + + public function tearDown() + { + $this->adapter = null; + } + + public function testSerializeString() + { + $value = 'test'; + $expected = msgpack_serialize($value); + + $data = $this->adapter->serialize($value); + $this->assertEquals($expected, $data); + } + + public function testSerializeFalse() + { + $value = false; + $expected = msgpack_serialize($value); + + $data = $this->adapter->serialize($value); + $this->assertEquals($expected, $data); + } + + public function testSerializeNull() + { + $value = null; + $expected = msgpack_serialize($value); + + $data = $this->adapter->serialize($value); + $this->assertEquals($expected, $data); + } + + public function testSerializeNumeric() + { + $value = 100; + $expected = msgpack_serialize($value); + + $data = $this->adapter->serialize($value); + $this->assertEquals($expected, $data); + } + + public function testSerializeObject() + { + $value = new \stdClass(); + $expected = msgpack_serialize($value); + + $data = $this->adapter->serialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserializeString() + { + $expected = 'test'; + $value = msgpack_serialize($expected); + + $data = $this->adapter->unserialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserializeFalse() + { + $expected = false; + $value = msgpack_serialize($expected); + + $data = $this->adapter->unserialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserializeNull() + { + $expected = null; + $value = msgpack_serialize($expected); + + $data = $this->adapter->unserialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserializeNumeric() + { + $expected = 100; + $value = msgpack_serialize($expected); + + $data = $this->adapter->unserialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserializeObject() + { + $expected = new \stdClass(); + $value = msgpack_serialize($expected); + + $data = $this->adapter->unserialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserialize0() + { + $expected = 0; + $value = msgpack_serialize($expected); + + $data = $this->adapter->unserialize($value); + $this->assertEquals($expected, $data); + } + + public function testUnserialzeInvalid() + { + $value = "\0\1\r\n"; + $this->setExpectedException( + 'Zend\Serializer\Exception\RuntimeException', + 'Unserialization failed' + ); + $this->adapter->unserialize($value); + } +} \ No newline at end of file From 4818c4b419c7d36a118a13c8922d599be48a57ae Mon Sep 17 00:00:00 2001 From: Shahar Evron Date: Tue, 21 Aug 2012 19:14:37 +0300 Subject: [PATCH 023/126] allowing users to check if a scheme is registered in the factory --- library/Zend/Uri/UriFactory.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/Zend/Uri/UriFactory.php b/library/Zend/Uri/UriFactory.php index 6871e3e1527..5e8490374e6 100644 --- a/library/Zend/Uri/UriFactory.php +++ b/library/Zend/Uri/UriFactory.php @@ -66,6 +66,23 @@ public static function unregisterScheme($scheme) } } + /** + * Get the class name for a registered scheme + * + * If provided scheme is not registered, will return NULL + * + * @param string $scheme + * @return string|null + */ + public static function getRegisteredSchemeClass($scheme) + { + if (isset(static::$schemeClasses[$scheme])) { + return static::$schemeClasses[$scheme]; + } else { + return null; + } + } + /** * Create a URI from a string * From 7748ba2f2ffb3b46e6ec93899ba661dcec6b937f Mon Sep 17 00:00:00 2001 From: Shahar Evron Date: Tue, 21 Aug 2012 19:20:36 +0300 Subject: [PATCH 024/126] adding the UriNormalize filter + relevant unit tests --- library/Zend/Filter/UriNormalize.php | 134 +++++++++++++++++++++ tests/ZendTest/Filter/UriNormalizeTest.php | 56 +++++++++ 2 files changed, 190 insertions(+) create mode 100644 library/Zend/Filter/UriNormalize.php create mode 100644 tests/ZendTest/Filter/UriNormalizeTest.php diff --git a/library/Zend/Filter/UriNormalize.php b/library/Zend/Filter/UriNormalize.php new file mode 100644 index 00000000000..a35bfe0a668 --- /dev/null +++ b/library/Zend/Filter/UriNormalize.php @@ -0,0 +1,134 @@ +setOptions($options); + } + + /** + * Set the default scheme to use when parsing scheme-less URIs + * + * The scheme used when parsing URIs may affect the specific object used to + * normalize the URI and thus may affect the resulting normalize URI. + * + * @param string $defaultScheme + * @return \Zend\Filter\UriNormalize + */ + public function setDefaultScheme($defaultScheme) + { + $this->defaultScheme = $defaultScheme; + return $this; + } + + /** + * Set a URI scheme to enforce on schemeless URIs + * + * This allows forcing input values such as 'www.example.com/foo' into + * 'http://www.example.com/foo'. + * + * This should be used with caution, as a standard-compliant URI parser + * would regard 'www.example.com' in the above input URI to be the path and + * not host part of the URI. While this option can assist in solving + * real-world user mishaps, it may yield unexpected results at times. + * + * @param string $enforcedScheme + * @return \Zend\Filter\UriNormalize + */ + public function setEnforcedScheme($enforcedScheme) + { + $this->enforcedScheme = $enforcedScheme; + return $this; + } + + /** + * Filter the URL by normalizing it and applying a default scheme if set + * + * @param string $value + * @return string + */ + public function filter($value) + { + $defaultScheme = $this->defaultScheme ?: $this->enforcedScheme; + + // Reset default scheme if it is not a known scheme + if (! UriFactory::getRegisteredSchemeClass($defaultScheme)) { + $defaultScheme = null; + } + + try { + $uri = UriFactory::factory($value, $defaultScheme); + if ($this->enforcedScheme && (! $uri->getScheme())) { + $this->enforceScheme($uri); + } + + } catch (UriException $ex) { + // We are unable to parse / enfore scheme with the given config and input + return $value; + } + + $uri->normalize(); + + if (! $uri->isValid()) { + return $value; + } + + return $uri->toString(); + } + + /** + * Enforce the defined scheme on the URI + * + * This will also adjust the host and path parts of the URI as expected in + * the case of scheme-less network URIs + * + * @param Uri $uri + */ + protected function enforceScheme(Uri $uri) + { + $path = $uri->getPath(); + if (strpos($path, '/') !== false) { + list($host, $path) = explode('/', $path, 2); + $path = '/' . $path; + } else { + $host = $path; + $path = ''; + } + + // We have nothing to do if we have no host + if (! $host) return; + + $uri->setScheme($this->enforcedScheme) + ->setHost($host) + ->setPath($path); + } +} diff --git a/tests/ZendTest/Filter/UriNormalizeTest.php b/tests/ZendTest/Filter/UriNormalizeTest.php new file mode 100644 index 00000000000..8e3d02edd3c --- /dev/null +++ b/tests/ZendTest/Filter/UriNormalizeTest.php @@ -0,0 +1,56 @@ +filter($url); + $this->assertEquals($expected, $result); + } + + public function testDefaultSchemeAffectsNormalization() + { + $this->markTestIncomplete(); + } + + /** + * @dataProvider enforcedSchemeTestcaseProvider + */ + public function testEnforcedScheme($scheme, $input, $expected) + { + $filter = new UriNormalize(array('enforcedScheme' => $scheme)); + $result = $filter->filter($input); + $this->assertEquals($expected, $result); + } + + static public function abnormalUriProvider() + { + return array( + array('http://www.example.com', 'http://www.example.com/'), + array('hTTp://www.example.com/ space', 'http://www.example.com/%20space'), + array('file:///www.example.com/foo/bar', 'file:///www.example.com/foo/bar'), // this should not be affected + array('file:///home/shahar/secret/../../otherguy/secret', 'file:///home/otherguy/secret'), + array('https://www.example.com:443/hasport', 'https://www.example.com/hasport'), + array('/foo/bar?q=%711', '/foo/bar?q=q1'), // no scheme enforced + ); + } + + static public function enforcedSchemeTestcaseProvider() + { + return array( + array('ftp', 'http://www.example.com', 'http://www.example.com/'), // no effect - this one has a scheme + array('mailto', 'mailto:shahar@example.com', 'mailto:shahar@example.com'), + array('http', 'www.example.com/foo/bar?q=q', 'http://www.example.com/foo/bar?q=q'), + array('ftp', 'www.example.com/path/to/file.ext', 'ftp://www.example.com/path/to/file.ext'), + array('http', '/just/a/path', '/just/a/path') // cannot be enforced, no host + ); + } +} From b1f9ff628519700a2fb07adb3b724b55192adeba Mon Sep 17 00:00:00 2001 From: Shahar Evron Date: Tue, 21 Aug 2012 19:22:25 +0300 Subject: [PATCH 025/126] adding the urinormalize filter to the filter plugin manager --- library/Zend/Filter/FilterPluginManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Zend/Filter/FilterPluginManager.php b/library/Zend/Filter/FilterPluginManager.php index d7ea9b55078..0f58a4e3a4d 100644 --- a/library/Zend/Filter/FilterPluginManager.php +++ b/library/Zend/Filter/FilterPluginManager.php @@ -68,6 +68,7 @@ class FilterPluginManager extends AbstractPluginManager 'stringtrim' => 'Zend\Filter\StringTrim', 'stripnewlines' => 'Zend\Filter\StripNewlines', 'striptags' => 'Zend\Filter\StripTags', + 'urinormalize' => 'Zend\Filter\UriNormalize', 'wordcamelcasetodash' => 'Zend\Filter\Word\CamelCaseToDash', 'wordcamelcasetoseparator' => 'Zend\Filter\Word\CamelCaseToSeparator', 'wordcamelcasetounderscore' => 'Zend\Filter\Word\CamelCaseToUnderscore', From 09b5907ad00647d420d12e70874377a34735db3d Mon Sep 17 00:00:00 2001 From: Shahar Evron Date: Tue, 21 Aug 2012 21:36:11 +0300 Subject: [PATCH 026/126] CS fixes --- library/Zend/Filter/UriNormalize.php | 36 ++++++++++++++++------ tests/ZendTest/Filter/UriNormalizeTest.php | 18 +++++++++-- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/library/Zend/Filter/UriNormalize.php b/library/Zend/Filter/UriNormalize.php index a35bfe0a668..082c37a89cb 100644 --- a/library/Zend/Filter/UriNormalize.php +++ b/library/Zend/Filter/UriNormalize.php @@ -1,13 +1,25 @@ setOptions($options); + if ($options) { + $this->setOptions($options); + } } /** @@ -81,13 +95,13 @@ public function filter($value) $defaultScheme = $this->defaultScheme ?: $this->enforcedScheme; // Reset default scheme if it is not a known scheme - if (! UriFactory::getRegisteredSchemeClass($defaultScheme)) { + if (!UriFactory::getRegisteredSchemeClass($defaultScheme)) { $defaultScheme = null; } try { $uri = UriFactory::factory($value, $defaultScheme); - if ($this->enforcedScheme && (! $uri->getScheme())) { + if ($this->enforcedScheme && (!$uri->getScheme())) { $this->enforceScheme($uri); } @@ -98,7 +112,7 @@ public function filter($value) $uri->normalize(); - if (! $uri->isValid()) { + if (!$uri->isValid()) { return $value; } @@ -125,7 +139,9 @@ protected function enforceScheme(Uri $uri) } // We have nothing to do if we have no host - if (! $host) return; + if (!$host) { + return; + } $uri->setScheme($this->enforcedScheme) ->setHost($host) diff --git a/tests/ZendTest/Filter/UriNormalizeTest.php b/tests/ZendTest/Filter/UriNormalizeTest.php index 8e3d02edd3c..f0d42e36c28 100644 --- a/tests/ZendTest/Filter/UriNormalizeTest.php +++ b/tests/ZendTest/Filter/UriNormalizeTest.php @@ -1,9 +1,23 @@ assertEquals($expected, $result); } - static public function abnormalUriProvider() + public static function abnormalUriProvider() { return array( array('http://www.example.com', 'http://www.example.com/'), @@ -43,7 +57,7 @@ static public function abnormalUriProvider() ); } - static public function enforcedSchemeTestcaseProvider() + public static function enforcedSchemeTestcaseProvider() { return array( array('ftp', 'http://www.example.com', 'http://www.example.com/'), // no effect - this one has a scheme From d9a085488fa93e4754b137a8229fd9fcb569b959 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 1 Aug 2012 23:03:45 +0200 Subject: [PATCH 027/126] Added a ChromePhp logger. --- library/Zend/Log/Formatter/ChromePhp.php | 51 +++++++++ library/Zend/Log/Writer/ChromePhp.php | 105 ++++++++++++++++++ .../Log/Writer/ChromePhp/ChromePhpBridge.php | 71 ++++++++++++ .../Writer/ChromePhp/ChromePhpInterface.php | 54 +++++++++ 4 files changed, 281 insertions(+) create mode 100644 library/Zend/Log/Formatter/ChromePhp.php create mode 100644 library/Zend/Log/Writer/ChromePhp.php create mode 100644 library/Zend/Log/Writer/ChromePhp/ChromePhpBridge.php create mode 100644 library/Zend/Log/Writer/ChromePhp/ChromePhpInterface.php diff --git a/library/Zend/Log/Formatter/ChromePhp.php b/library/Zend/Log/Formatter/ChromePhp.php new file mode 100644 index 00000000000..158f5b09fa8 --- /dev/null +++ b/library/Zend/Log/Formatter/ChromePhp.php @@ -0,0 +1,51 @@ +chromephp = $instance === null ? $this->getChromePhp() : $instance; + $this->formatter = new ChromePhpFormatter(); + } + + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + protected function doWrite(array $event) + { + $line = $this->formatter->format($event); + + switch ($event['priority']) { + case Logger::EMERG: + case Logger::ALERT: + case Logger::CRIT: + case Logger::ERR: + $this->chromephp->error($line); + break; + case Logger::WARN: + $this->chromephp->warn($line); + break; + case Logger::NOTICE: + case Logger::INFO: + $this->chromephp->info($line); + break; + case Logger::DEBUG: + $this->chromephp->trace($line); + break; + default: + $this->chromephp->log($line); + break; + } + } + + /** + * Gets the ChromePhpInterface instance that is used for logging. + * + * @return ChromePhpInterface + */ + public function getChromePhp() + { + // Remember: class names in strings are absolute; thus the class_exists + // here references the canonical name for the ChromePhp class + if (!$this->chromephp instanceof ChromePhpInterface + && class_exists('ChromePhp') + ) { + $this->setChromePhp(new ChromePhpBridge()); + } + return $this->chromephp; + } + + /** + * Sets the ChromePhpInterface instance that is used for logging. + * + * @param ChromePhpInterface $instance The instance to set. + * @return ChromePhp + */ + public function setChromePhp(ChromePhpInterface $instance) + { + $this->chromephp = $instance; + return $this; + } +} diff --git a/library/Zend/Log/Writer/ChromePhp/ChromePhpBridge.php b/library/Zend/Log/Writer/ChromePhp/ChromePhpBridge.php new file mode 100644 index 00000000000..d6a97655d64 --- /dev/null +++ b/library/Zend/Log/Writer/ChromePhp/ChromePhpBridge.php @@ -0,0 +1,71 @@ + Date: Thu, 2 Aug 2012 18:42:00 +0200 Subject: [PATCH 028/126] Added tests for ChromePhp --- tests/Zend/Log/TestAsset/MockChromePhp.php | 46 +++++++++++ tests/Zend/Log/Writer/ChromePhpTest.php | 91 ++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 tests/Zend/Log/TestAsset/MockChromePhp.php create mode 100644 tests/Zend/Log/Writer/ChromePhpTest.php diff --git a/tests/Zend/Log/TestAsset/MockChromePhp.php b/tests/Zend/Log/TestAsset/MockChromePhp.php new file mode 100644 index 00000000000..41b4933f5c9 --- /dev/null +++ b/tests/Zend/Log/TestAsset/MockChromePhp.php @@ -0,0 +1,46 @@ +enabled = $enabled; + } + + public function getEnabled() + { + return $this->enabled; + } + + public function error($line) + { + $this->calls['error'][] = $line; + } + + public function warn($line) + { + $this->calls['warn'][] = $line; + } + + public function info($line) + { + $this->calls['info'][] = $line; + } + + public function trace($line) + { + $this->calls['trace'][] = $line; + } + + public function log($line) + { + $this->calls['log'][] = $line; + } +} diff --git a/tests/Zend/Log/Writer/ChromePhpTest.php b/tests/Zend/Log/Writer/ChromePhpTest.php new file mode 100644 index 00000000000..6225f0581bd --- /dev/null +++ b/tests/Zend/Log/Writer/ChromePhpTest.php @@ -0,0 +1,91 @@ +firephp = new MockFirePhp(); + + } + /** + * Test get FirePhp + */ + public function testGetFirePhp() + { + $writer = new FirePhp($this->firephp); + $this->assertTrue($writer->getFirePhp() instanceof FirePhpInterface); + } + /** + * Test set firephp + */ + public function testSetFirePhp() + { + $writer = new FirePhp($this->firephp); + $firephp2 = new MockFirePhp(); + + $writer->setFirePhp($firephp2); + $this->assertTrue($writer->getFirePhp() instanceof FirePhpInterface); + $this->assertEquals($firephp2, $writer->getFirePhp()); + } + /** + * Test write + */ + public function testWrite() + { + $writer = new FirePhp($this->firephp); + $writer->write(array( + 'message' => 'my msg', + 'priority' => Logger::DEBUG + )); + $this->assertEquals('my msg', $this->firephp->calls['trace'][0]); + } + /** + * Test write with FirePhp disabled + */ + public function testWriteDisabled() + { + $firephp = new MockFirePhp(false); + $writer = new FirePhp($firephp); + $writer->write(array( + 'message' => 'my msg', + 'priority' => Logger::DEBUG + )); + $this->assertTrue(empty($this->firephp->calls)); + } +} From 8036b52726fe6df14313a0815e8effe02e3e420b Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Thu, 2 Aug 2012 18:42:30 +0200 Subject: [PATCH 029/126] Added tests for ChromePhp --- tests/Zend/Log/TestAsset/MockChromePhp.php | 4 +- tests/Zend/Log/Writer/ChromePhpTest.php | 56 ++++++++++------------ 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/tests/Zend/Log/TestAsset/MockChromePhp.php b/tests/Zend/Log/TestAsset/MockChromePhp.php index 41b4933f5c9..814bedfe586 100644 --- a/tests/Zend/Log/TestAsset/MockChromePhp.php +++ b/tests/Zend/Log/TestAsset/MockChromePhp.php @@ -1,9 +1,9 @@ firephp = new MockFirePhp(); + $this->chromephp = new MockChromePhp(); } - /** - * Test get FirePhp - */ - public function testGetFirePhp() + + public function testGetChromePhp() { - $writer = new FirePhp($this->firephp); - $this->assertTrue($writer->getFirePhp() instanceof FirePhpInterface); + $writer = new ChromePhp($this->chromephp); + $this->assertTrue($writer->getChromePhp() instanceof ChromePhpInterface); } - /** - * Test set firephp - */ - public function testSetFirePhp() + + public function testSetChromePhp() { - $writer = new FirePhp($this->firephp); - $firephp2 = new MockFirePhp(); + $writer = new ChromePhp($this->chromephp); + $chromephp2 = new MockChromePhp(); - $writer->setFirePhp($firephp2); - $this->assertTrue($writer->getFirePhp() instanceof FirePhpInterface); - $this->assertEquals($firephp2, $writer->getFirePhp()); + $writer->setChromePhp($chromephp2); + $this->assertTrue($writer->getChromePhp() instanceof ChromePhpInterface); + $this->assertEquals($chromephp2, $writer->getChromePhp()); } - /** - * Test write - */ + public function testWrite() { - $writer = new FirePhp($this->firephp); + $writer = new ChromePhp($this->chromephp); $writer->write(array( 'message' => 'my msg', 'priority' => Logger::DEBUG )); - $this->assertEquals('my msg', $this->firephp->calls['trace'][0]); + $this->assertEquals('my msg', $this->chromephp->calls['trace'][0]); } - /** - * Test write with FirePhp disabled - */ + public function testWriteDisabled() { - $firephp = new MockFirePhp(false); - $writer = new FirePhp($firephp); + $chromephp = new MockChromePhp(false); + $writer = new ChromePhp($chromephp); $writer->write(array( 'message' => 'my msg', 'priority' => Logger::DEBUG )); - $this->assertTrue(empty($this->firephp->calls)); + $this->assertTrue(empty($this->chromephp->calls)); } } From 2221468d79a785cf4d867a2fdc6273010a03dce4 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Tue, 21 Aug 2012 21:32:22 +0200 Subject: [PATCH 030/126] Moved the chrome tests from Zend to ZendTest --- tests/{Zend => ZendTest}/Log/TestAsset/MockChromePhp.php | 0 tests/{Zend => ZendTest}/Log/Writer/ChromePhpTest.php | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/{Zend => ZendTest}/Log/TestAsset/MockChromePhp.php (100%) rename tests/{Zend => ZendTest}/Log/Writer/ChromePhpTest.php (100%) diff --git a/tests/Zend/Log/TestAsset/MockChromePhp.php b/tests/ZendTest/Log/TestAsset/MockChromePhp.php similarity index 100% rename from tests/Zend/Log/TestAsset/MockChromePhp.php rename to tests/ZendTest/Log/TestAsset/MockChromePhp.php diff --git a/tests/Zend/Log/Writer/ChromePhpTest.php b/tests/ZendTest/Log/Writer/ChromePhpTest.php similarity index 100% rename from tests/Zend/Log/Writer/ChromePhpTest.php rename to tests/ZendTest/Log/Writer/ChromePhpTest.php From d5c62e0084f0f38207bc475e701f1790a136d437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Thu, 23 Aug 2012 10:55:45 +0200 Subject: [PATCH 031/126] Change inheritance order --- library/Zend/Form/Element/DateSelect.php | 128 +---------- library/Zend/Form/Element/MonthSelect.php | 145 +++++++++++- .../Zend/Form/View/Helper/FormDateSelect.php | 203 +---------------- .../Zend/Form/View/Helper/FormMonthSelect.php | 206 +++++++++++++++++- .../ZendTest/Form/Element/MonthSelectTest.php | 32 +++ 5 files changed, 387 insertions(+), 327 deletions(-) diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index d3fc3c5afc5..944ae080c01 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -11,14 +11,11 @@ namespace Zend\Form\Element; use DateTime; -use Zend\Form\Element; -use Zend\Form\ElementPrepareAwareInterface; use Zend\Form\Form; -use Zend\InputFilter\InputProviderInterface; use Zend\Validator\ValidatorInterface; use Zend\Validator\Date as DateValidator; -class DateSelect extends Element implements InputProviderInterface, ElementPrepareAwareInterface +class DateSelect extends MonthSelect { /** * Select form element that contains values for day @@ -28,40 +25,7 @@ class DateSelect extends Element implements InputProviderInterface, ElementPrepa protected $dayElement; /** - * Select form element that contains values for month - * - * @var Select - */ - protected $monthElement; - - /** - * Select form element that contains values for year - * - * @var Select - */ - protected $yearElement; - - /** - * @var ValidatorInterface - */ - protected $validator; - - /** - * Min year to use for the select (default: current year - 100) - * - * @var int - */ - protected $minYear; - - /** - * Max year to use for the select (default: current year) - * - * @var int - */ - protected $maxYear; - - /** - * Constructor. Add three selects elements + * Constructor. Add the day select element * * @param null|int|string $name Optional name for the element * @param array $options Optional options for the element @@ -71,34 +35,6 @@ public function __construct($name = null, $options = array()) parent::__construct($name, $options); $this->dayElement = new Select('day'); - $this->monthElement = new Select('month'); - $this->yearElement = new Select('year'); - - $this->maxYear = date('Y'); - $this->minYear = $this->maxYear - 100; - } - - /** - * Accepted options for DateSelect: - * - min_year: min year to use in the year select - * - max_year: max year to use in the year select - * - * @param array|\Traversable $options - * @return DateSelect - */ - public function setOptions($options) - { - parent::setOptions($options); - - if (isset($options['min_year'])) { - $this->setMinYear($options['min_year']); - } - - if (isset($options['max_year'])) { - $this->setMaxYear($options['max_year']); - } - - return $this; } /** @@ -109,67 +45,14 @@ public function getDayElement() return $this->dayElement; } - /** - * @return Select - */ - public function getMonthElement() - { - return $this->monthElement; - } - - /** - * @return Select - */ - public function getYearElement() - { - return $this->yearElement; - } - - /** - * @param int $minYear - * @return DateSelect - */ - public function setMinYear($minYear) - { - $this->minYear = $minYear; - return $this; - } - - /** - * @return int - */ - public function getMinYear() - { - return $this->minYear; - } - - /** - * @param int $maxYear - * @return DateSelect - */ - public function setMaxYear($maxYear) - { - $this->maxYear = $maxYear; - return $this; - } - - /** - * @return int - */ - public function getMaxYear() - { - return $this->maxYear; - } - /** * @param mixed $value * @return void|\Zend\Form\Element */ public function setValue($value) { + parent::setValue($value); $this->dayElement->setValue($value['day']); - $this->monthElement->setValue($value['month']); - $this->yearElement->setValue($value['year']); } /** @@ -180,11 +63,10 @@ public function setValue($value) */ public function prepareElement(Form $form) { - $name = $this->getName(); + parent::prepareElement($form); + $name = $this->getName(); $this->dayElement->setName($name . '[day]'); - $this->monthElement->setName($name . '[month]'); - $this->yearElement->setName($name . '[year]'); } /** diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php index 939810fa9ec..4d17e0abd5a 100644 --- a/library/Zend/Form/Element/MonthSelect.php +++ b/library/Zend/Form/Element/MonthSelect.php @@ -10,11 +10,141 @@ namespace Zend\Form\Element; +use Zend\Form\Element; +use Zend\Form\ElementPrepareAwareInterface; +use Zend\Form\Form; +use Zend\InputFilter\InputProviderInterface; use Zend\Validator\ValidatorInterface; use Zend\Validator\Regex as RegexValidator; -class MonthSelect extends DateSelect +class MonthSelect extends Element implements InputProviderInterface, ElementPrepareAwareInterface { + /** + * Select form element that contains values for month + * + * @var Select + */ + protected $monthElement; + + /** + * Select form element that contains values for year + * + * @var Select + */ + protected $yearElement; + + /** + * Min year to use for the select (default: current year - 100) + * + * @var int + */ + protected $minYear; + + /** + * Max year to use for the select (default: current year) + * + * @var int + */ + protected $maxYear; + + /** + * @var ValidatorInterface + */ + protected $validator; + + + /** + * Constructor. Add two selects elements + * + * @param null|int|string $name Optional name for the element + * @param array $options Optional options for the element + */ + public function __construct($name = null, $options = array()) + { + parent::__construct($name, $options); + + $this->monthElement = new Select('month'); + $this->yearElement = new Select('year'); + + $this->maxYear = date('Y'); + $this->minYear = $this->maxYear - 100; + } + + /** + * Accepted options for DateSelect: + * - min_year: min year to use in the year select + * - max_year: max year to use in the year select + * + * @param array|\Traversable $options + * @return DateSelect + */ + public function setOptions($options) + { + parent::setOptions($options); + + if (isset($options['min_year'])) { + $this->setMinYear($options['min_year']); + } + + if (isset($options['max_year'])) { + $this->setMaxYear($options['max_year']); + } + + return $this; + } + + /** + * @return Select + */ + public function getMonthElement() + { + return $this->monthElement; + } + + /** + * @return Select + */ + public function getYearElement() + { + return $this->yearElement; + } + + /** + * @param int $minYear + * @return DateSelect + */ + public function setMinYear($minYear) + { + $this->minYear = $minYear; + return $this; + } + + /** + * @return int + */ + public function getMinYear() + { + return $this->minYear; + } + + /** + * @param int $maxYear + * @return DateSelect + */ + public function setMaxYear($maxYear) + { + $this->maxYear = $maxYear; + return $this; + } + + /** + * @return int + */ + public function getMaxYear() + { + return $this->maxYear; + } + /** * @param mixed $value * @return void|\Zend\Form\Element @@ -25,6 +155,19 @@ public function setValue($value) $this->yearElement->setValue($value['year']); } + /** + * Prepare the form element (mostly used for rendering purposes) + * + * @param Form $form + * @return mixed + */ + public function prepareElement(Form $form) + { + $name = $this->getName(); + $this->monthElement->setName($name . '[month]'); + $this->yearElement->setName($name . '[year]'); + } + /** * Get validator * diff --git a/library/Zend/Form/View/Helper/FormDateSelect.php b/library/Zend/Form/View/Helper/FormDateSelect.php index ca0627ff045..2749f503d04 100644 --- a/library/Zend/Form/View/Helper/FormDateSelect.php +++ b/library/Zend/Form/View/Helper/FormDateSelect.php @@ -12,45 +12,17 @@ use DateTime; use IntlDateFormatter; -use Locale; use Zend\Form\ElementInterface; use Zend\Form\Exception; +use Zend\Form\View\Helper\FormMonthSelect as FormMonthSelectHelper; /** * @category Zend * @package Zend_Form * @subpackage View */ -class FormDateSelect extends AbstractHelper +class FormDateSelect extends FormMonthSelectHelper { - /** - * FormSelect helper - * - * @var FormSelect - */ - protected $selectHelper; - - /** - * Date formatter to use - * - * @var int - */ - protected $dateType = IntlDateFormatter::LONG; - - /** - * Pattern to use for Date rendering - * - * @var string - */ - protected $pattern; - - /** - * Locale to use - * - * @var string - */ - protected $locale; - /** * Render a date element that is composed of three selects * @@ -96,116 +68,6 @@ public function render(ElementInterface $element) return $markup; } - /** - * Invoke helper as function - * - * Proxies to {@link render()}. - * - * @param \Zend\Form\ElementInterface $element - * @param int $dateType - * @param null|string $locale - * @return FormDateSelect - */ - public function __invoke(ElementInterface $element = null, $dateType = IntlDateFormatter::LONG, $locale = null) - { - if (!$element) { - return $this; - } - - $this->setDateType($dateType); - - if ($locale !== null) { - $this->setLocale($locale); - } - - return $this->render($element); - } - - /** - * Parse the pattern - * - * @return array - */ - public function parsePattern() - { - $pattern = $this->getPattern(); - $pregResult = preg_split('/([ -,.\/]+)/', $pattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); - - $result = array(); - foreach ($pregResult as $value) { - if (stripos($value, 'd') !== false) { - $result['day'] = $value; - } elseif (stripos($value, 'm') !== false) { - $result['month'] = $value; - } elseif (stripos($value, 'y') !== false) { - $result['year'] = $value; - } else { - $result[] = $value; - } - } - - return $result; - } - - /** - * @return string - */ - public function getPattern() - { - if ($this->pattern === null) { - $intl = new IntlDateFormatter($this->getLocale(), $this->dateType, IntlDateFormatter::NONE); - $this->pattern = $intl->getPattern(); - } - - return $this->pattern; - } - - /** - * @param int $dateType - * @return FormDateSelect - */ - public function setDateType($dateType) - { - // The FULL format uses values that are not used - if ($dateType === IntlDateFormatter::FULL) { - $dateType = IntlDateFormatter::LONG; - } - - $this->dateType = $dateType; - - return $this; - } - - /** - * @return int - */ - public function getDateType() - { - return $this->dateType; - } - - /** - * @param string $locale - * @return FormDateSelect - */ - public function setLocale($locale) - { - $this->locale = $locale; - return $this; - } - - /** - * @return string - */ - public function getLocale() - { - if ($this->locale === null) { - $this->locale = Locale::getDefault(); - } - - return $this->locale; - } - /** * Create a key => value options for days * @@ -229,66 +91,5 @@ public function getDaysOptions($pattern) return $result; } - - /** - * Create a key => value options for months - * - * @param string $pattern Pattern to use for months - * @return array - */ - public function getMonthsOptions($pattern) - { - $keyFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'MM'); - $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); - $date = new DateTime('1970-01-01'); - - $result = array(); - for ($month = 1; $month <= 12; $month++) { - $key = $keyFormatter->format($date); - $value = $valueFormatter->format($date); - $result[$key] = $value; - - $date->modify('+1 month'); - } - - return $result; - } - - /** - * Create a key => value options for years - * NOTE: we don't use a pattern for years, as years written as two digits can lead to hard to - * read date for users, so we only use four digits years - * - * @param int $minYear - * @param int $maxYear - * @return array - */ - public function getYearsOptions($minYear, $maxYear) - { - $result = array(); - for ($i = $maxYear; $i >= $minYear; --$i) { - $result[$i] = $i; - } - - return $result; - } - - /** - * Retrieve the FormSelect helper - * - * @return FormRow - */ - protected function getSelectElementHelper() - { - if ($this->selectHelper) { - return $this->selectHelper; - } - - if (method_exists($this->view, 'plugin')) { - $this->selectHelper = $this->view->plugin('formselect'); - } - - return $this->selectHelper; - } } diff --git a/library/Zend/Form/View/Helper/FormMonthSelect.php b/library/Zend/Form/View/Helper/FormMonthSelect.php index afb8c274f5f..34643b200c9 100644 --- a/library/Zend/Form/View/Helper/FormMonthSelect.php +++ b/library/Zend/Form/View/Helper/FormMonthSelect.php @@ -10,8 +10,10 @@ namespace Zend\Form\View\Helper; +use DateTime; +use IntlDateFormatter; +use Locale; use Zend\Form\ElementInterface; -use Zend\Form\View\Helper\FormDateSelect as FormDateSelectHelper; use Zend\Form\Exception; /** @@ -19,12 +21,41 @@ * @package Zend_Form * @subpackage View */ -class FormMonthSelect extends FormDateSelectHelper +class FormMonthSelect extends AbstractHelper { + /** + * FormSelect helper + * + * @var FormSelect + */ + protected $selectHelper; + + /** + * Date formatter to use + * + * @var int + */ + protected $dateType = IntlDateFormatter::LONG; + + /** + * Pattern to use for Date rendering + * + * @var string + */ + protected $pattern; + + /** + * Locale to use + * + * @var string + */ + protected $locale; + /** * Render a month element that is composed of two selects * * @param \Zend\Form\ElementInterface $element + * @throws \Zend\Form\Exception\DomainException * @return string */ public function render(ElementInterface $element) @@ -63,5 +94,176 @@ public function render(ElementInterface $element) return $markup; } + + /** + * Invoke helper as function + * + * Proxies to {@link render()}. + * + * @param \Zend\Form\ElementInterface $element + * @param int $dateType + * @param null|string $locale + * @return FormDateSelect + */ + public function __invoke(ElementInterface $element = null, $dateType = IntlDateFormatter::LONG, $locale = null) + { + if (!$element) { + return $this; + } + + $this->setDateType($dateType); + + if ($locale !== null) { + $this->setLocale($locale); + } + + return $this->render($element); + } + + /** + * @return string + */ + public function getPattern() + { + if ($this->pattern === null) { + $intl = new IntlDateFormatter($this->getLocale(), $this->dateType, IntlDateFormatter::NONE); + $this->pattern = $intl->getPattern(); + } + + return $this->pattern; + } + + /** + * Parse the pattern + * + * @return array + */ + protected function parsePattern() + { + $pattern = $this->getPattern(); + $pregResult = preg_split('/([ -,.\/]+)/', $pattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + $result = array(); + foreach ($pregResult as $value) { + if (stripos($value, 'd') !== false) { + $result['day'] = $value; + } elseif (stripos($value, 'm') !== false) { + $result['month'] = $value; + } elseif (stripos($value, 'y') !== false) { + $result['year'] = $value; + } else { + $result[] = $value; + } + } + + return $result; + } + + /** + * @param int $dateType + * @return FormDateSelect + */ + public function setDateType($dateType) + { + // The FULL format uses values that are not used + if ($dateType === IntlDateFormatter::FULL) { + $dateType = IntlDateFormatter::LONG; + } + + $this->dateType = $dateType; + + return $this; + } + + /** + * @return int + */ + public function getDateType() + { + return $this->dateType; + } + + /** + * @param string $locale + * @return FormDateSelect + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Create a key => value options for months + * + * @param string $pattern Pattern to use for months + * @return array + */ + public function getMonthsOptions($pattern) + { + $keyFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'MM'); + $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); + $date = new DateTime('1970-01-01'); + + $result = array(); + for ($month = 1; $month <= 12; $month++) { + $key = $keyFormatter->format($date); + $value = $valueFormatter->format($date); + $result[$key] = $value; + + $date->modify('+1 month'); + } + + return $result; + } + + /** + * Create a key => value options for years + * NOTE: we don't use a pattern for years, as years written as two digits can lead to hard to + * read date for users, so we only use four digits years + * + * @param int $minYear + * @param int $maxYear + * @return array + */ + public function getYearsOptions($minYear, $maxYear) + { + $result = array(); + for ($i = $maxYear; $i >= $minYear; --$i) { + $result[$i] = $i; + } + + return $result; + } + + /** + * Retrieve the FormSelect helper + * + * @return FormRow + */ + protected function getSelectElementHelper() + { + if ($this->selectHelper) { + return $this->selectHelper; + } + + if (method_exists($this->view, 'plugin')) { + $this->selectHelper = $this->view->plugin('formselect'); + } + + return $this->selectHelper; + } } diff --git a/tests/ZendTest/Form/Element/MonthSelectTest.php b/tests/ZendTest/Form/Element/MonthSelectTest.php index f1c3d99c102..105f5b9ab90 100644 --- a/tests/ZendTest/Form/Element/MonthSelectTest.php +++ b/tests/ZendTest/Form/Element/MonthSelectTest.php @@ -39,4 +39,36 @@ public function testProvidesInputSpecificationThatIncludesValidatorsBasedOnAttri } } } + + /** + * Note about those tests: 2012-1 is not valid in HTML5 validation, but here we use selects, and in some + * locales, the month may be expressed using only 1 digit, so this is valid here + * + * @return array + */ + public function monthValuesDataProvider() + { + return array( + // value expected + array('2012-01', true), + array('2012-12', true), + array('2012-13', false), + array('2012-12-01', false), + array('12-2012', false), + array('2012-1', true), + array('12-01', false), + ); + } + + /** + * @dataProvider monthValuesDataProvider + */ + public function testMonthValidation($value, $expected) + { + $element = new MonthSelectElement('foo'); + $inputSpec = $element->getInputSpecification(); + $this->assertArrayHasKey('validators', $inputSpec); + $monthValidator = $inputSpec['validators'][0]; + $this->assertEquals($expected, $monthValidator->isValid($value)); + } } From 25b521a6cb78bcd422712cf99353c58c124364ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 27 Aug 2012 19:26:04 +0200 Subject: [PATCH 032/126] Reorder element helper --- library/Zend/Form/View/Helper/FormElement.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Zend/Form/View/Helper/FormElement.php b/library/Zend/Form/View/Helper/FormElement.php index b69c76d81a2..d1caac2dba2 100644 --- a/library/Zend/Form/View/Helper/FormElement.php +++ b/library/Zend/Form/View/Helper/FormElement.php @@ -58,13 +58,13 @@ public function render(ElementInterface $element) return $helper($element); } - if ($element instanceof Element\MonthSelect) { - $helper = $renderer->plugin('form_month_select'); + if ($element instanceof Element\DateSelect) { + $helper = $renderer->plugin('form_date_select'); return $helper($element); } - if ($element instanceof Element\DateSelect) { - $helper = $renderer->plugin('form_date_select'); + if ($element instanceof Element\MonthSelect) { + $helper = $renderer->plugin('form_month_select'); return $helper($element); } From 904e035b91c9c7b2aba784d5dbf7744c4d05a941 Mon Sep 17 00:00:00 2001 From: Stefan Kleff Date: Thu, 30 Aug 2012 13:44:55 +0200 Subject: [PATCH 033/126] Ported FingersCrossed handler from monolog to ZF2 Original work at https://github.com/Seldaek/monolog/blob/master/src/Monolog/Handler/FingersCrossedHandler.php --- library/Zend/Log/Writer/FingersCrossed.php | 144 ++++++++++++++++++ .../ActivationStrategyInterface.php | 28 ++++ .../ErrorLevelActivationStrategy.php | 45 ++++++ .../Log/Writer/FingersCrossedTest.php | 57 +++++++ 4 files changed, 274 insertions(+) create mode 100644 library/Zend/Log/Writer/FingersCrossed.php create mode 100644 library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php create mode 100644 library/Zend/Log/Writer/FingersCrossed/ErrorLevelActivationStrategy.php create mode 100644 tests/ZendTest/Log/Writer/FingersCrossedTest.php diff --git a/library/Zend/Log/Writer/FingersCrossed.php b/library/Zend/Log/Writer/FingersCrossed.php new file mode 100644 index 00000000000..921d62b9612 --- /dev/null +++ b/library/Zend/Log/Writer/FingersCrossed.php @@ -0,0 +1,144 @@ +writer = $writer; + + if ($activationStrategyOrPriority === null) { + $this->activationStrategy = new ErrorLevelActivationStrategy(Logger::WARN); + } elseif (! $activationStrategyOrPriority instanceof ActivationStrategyInterface) { + $this->activationStrategy = new ErrorLevelActivationStrategy($activationStrategyOrPriority); + } else { + $this->activationStrategy = $activationStrategyOrPriority; + } + + $this->bufferSize = $bufferSize; + } + + /** + * Write message to buffer or delegate event data to the wrapped writer + * + * @param array $event event data + * @return void + */ + protected function doWrite(array $event) + { + if ($this->buffering) { + $this->buffer[] = $event; + + if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { + array_shift($this->buffer); + } + + if ($this->activationStrategy->isWriterActivated($event)) { + $this->buffering = false; + + foreach ($this->buffer as $bufferedEvent) { + $this->writer->write($bufferedEvent); + } + } + } else { + $this->writer->write($event); + } + } + + /** + * Resets the state of the handler. + * Stops forwarding records to the wrapped writer + */ + public function reset() + { + $this->buffering = true; + } + + /** + * Prevent setting a formatter for this writer + * + * @param Formatter $formatter + */ + public function setFormatter(FormatterInterface $formatter) + { + throw new Exception\InvalidArgumentException('Formatter must be set on the wrapped writer'); + } + + /** + * Record shutdown + * + * @return void + */ + public function shutdown() + { + $this->writer->shutdown(); + $this->buffer = null; + } +} \ No newline at end of file diff --git a/library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php b/library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php new file mode 100644 index 00000000000..f0d35024b61 --- /dev/null +++ b/library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php @@ -0,0 +1,28 @@ +priority = $priority; + } + + /** + * Returns whether the given record activates the writer + * + * @param array event data + * @return bool + */ + public function isWriterActivated(array $event) + { + return $event['priority'] <= $this->priority; + } +} \ No newline at end of file diff --git a/tests/ZendTest/Log/Writer/FingersCrossedTest.php b/tests/ZendTest/Log/Writer/FingersCrossedTest.php new file mode 100644 index 00000000000..d0813caccf2 --- /dev/null +++ b/tests/ZendTest/Log/Writer/FingersCrossedTest.php @@ -0,0 +1,57 @@ +write(array('priority' => 3, 'message' => 'foo')); + + $this->assertSame(count($wrappedWriter->events), 0); + } + + public function testFlushing() + { + $wrappedWriter = new MockWriter(); + $writer = new FingersCrossedWriter($wrappedWriter, 2); + + $writer->write(array('priority' => 3, 'message' => 'foo')); + $writer->write(array('priority' => 1, 'message' => 'bar')); + + $this->assertSame(count($wrappedWriter->events), 2); + } + + public function testAfterFlushing() + { + $wrappedWriter = new MockWriter(); + $writer = new FingersCrossedWriter($wrappedWriter, 2); + + $writer->write(array('priority' => 3, 'message' => 'foo')); + $writer->write(array('priority' => 1, 'message' => 'bar')); + $writer->write(array('priority' => 3, 'message' => 'bar')); + + $this->assertSame(count($wrappedWriter->events), 3); + } +} From 1c54d2da7467c5436a50483a85972d92fe2616f8 Mon Sep 17 00:00:00 2001 From: Stefan Kleff Date: Thu, 30 Aug 2012 14:38:23 +0200 Subject: [PATCH 034/126] Fixed CS --- library/Zend/Log/Writer/FingersCrossed.php | 10 +++++----- tests/ZendTest/Log/Writer/FingersCrossedTest.php | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/library/Zend/Log/Writer/FingersCrossed.php b/library/Zend/Log/Writer/FingersCrossed.php index 921d62b9612..b77c3d9d945 100644 --- a/library/Zend/Log/Writer/FingersCrossed.php +++ b/library/Zend/Log/Writer/FingersCrossed.php @@ -73,7 +73,7 @@ class FingersCrossed extends AbstractWriter public function __construct(WriterInterface $writer, $activationStrategyOrPriority = null, $bufferSize = 0) { $this->writer = $writer; - + if ($activationStrategyOrPriority === null) { $this->activationStrategy = new ErrorLevelActivationStrategy(Logger::WARN); } elseif (! $activationStrategyOrPriority instanceof ActivationStrategyInterface) { @@ -81,7 +81,7 @@ public function __construct(WriterInterface $writer, $activationStrategyOrPriori } else { $this->activationStrategy = $activationStrategyOrPriority; } - + $this->bufferSize = $bufferSize; } @@ -95,14 +95,14 @@ protected function doWrite(array $event) { if ($this->buffering) { $this->buffer[] = $event; - + if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { array_shift($this->buffer); } - + if ($this->activationStrategy->isWriterActivated($event)) { $this->buffering = false; - + foreach ($this->buffer as $bufferedEvent) { $this->writer->write($bufferedEvent); } diff --git a/tests/ZendTest/Log/Writer/FingersCrossedTest.php b/tests/ZendTest/Log/Writer/FingersCrossedTest.php index d0813caccf2..a87ce853d04 100644 --- a/tests/ZendTest/Log/Writer/FingersCrossedTest.php +++ b/tests/ZendTest/Log/Writer/FingersCrossedTest.php @@ -26,32 +26,32 @@ public function testBuffering() { $wrappedWriter = new MockWriter(); $writer = new FingersCrossedWriter($wrappedWriter, 2); - + $writer->write(array('priority' => 3, 'message' => 'foo')); - + $this->assertSame(count($wrappedWriter->events), 0); } - + public function testFlushing() { $wrappedWriter = new MockWriter(); $writer = new FingersCrossedWriter($wrappedWriter, 2); - + $writer->write(array('priority' => 3, 'message' => 'foo')); $writer->write(array('priority' => 1, 'message' => 'bar')); - + $this->assertSame(count($wrappedWriter->events), 2); } - + public function testAfterFlushing() { $wrappedWriter = new MockWriter(); $writer = new FingersCrossedWriter($wrappedWriter, 2); - + $writer->write(array('priority' => 3, 'message' => 'foo')); $writer->write(array('priority' => 1, 'message' => 'bar')); $writer->write(array('priority' => 3, 'message' => 'bar')); - + $this->assertSame(count($wrappedWriter->events), 3); } } From d651f559262bcb303b156d4e49d548402c3081bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Sun, 2 Sep 2012 20:30:59 +0200 Subject: [PATCH 035/126] Add an option to create an empty option --- library/Zend/Form/Element/MonthSelect.php | 40 ++++++++++++++++--- .../Zend/Form/View/Helper/FormDateSelect.php | 25 +++++++++--- .../Zend/Form/View/Helper/FormMonthSelect.php | 23 +++++++++-- .../Form/View/Helper/FormDateSelectTest.php | 11 +++++ .../Form/View/Helper/FormMonthSelectTest.php | 11 +++++ 5 files changed, 96 insertions(+), 14 deletions(-) diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php index 4d17e0abd5a..5e2d9721cda 100644 --- a/library/Zend/Form/Element/MonthSelect.php +++ b/library/Zend/Form/Element/MonthSelect.php @@ -47,6 +47,14 @@ class MonthSelect extends Element implements InputProviderInterface, ElementPrep */ protected $maxYear; + /** + * If set to true, it will generate an empty option for every select (this is mainly needed by most JavaScript + * libraries to allow to have a placeholder) + * + * @var bool + */ + protected $createEmptyOption = false; + /** * @var ValidatorInterface */ @@ -61,13 +69,13 @@ class MonthSelect extends Element implements InputProviderInterface, ElementPrep */ public function __construct($name = null, $options = array()) { - parent::__construct($name, $options); + $this->minYear = date('Y') - 100; + $this->maxYear = date('Y'); $this->monthElement = new Select('month'); $this->yearElement = new Select('year'); - $this->maxYear = date('Y'); - $this->minYear = $this->maxYear - 100; + parent::__construct($name, $options); } /** @@ -90,6 +98,10 @@ public function setOptions($options) $this->setMaxYear($options['max_year']); } + if (isset($options['create_empty_option'])) { + $this->setShouldCreateEmptyOption($options['create_empty_option']); + } + return $this; } @@ -111,7 +123,7 @@ public function getYearElement() /** * @param int $minYear - * @return DateSelect + * @return MonthSelect */ public function setMinYear($minYear) { @@ -129,7 +141,7 @@ public function getMinYear() /** * @param int $maxYear - * @return DateSelect + * @return MonthSelect */ public function setMaxYear($maxYear) { @@ -145,6 +157,24 @@ public function getMaxYear() return $this->maxYear; } + /** + * @param bool $createEmptyOption + * @return MonthSelect + */ + public function setShouldCreateEmptyOption($createEmptyOption) + { + $this->createEmptyOption = (bool) $createEmptyOption; + return $this; + } + + /** + * @return bool + */ + public function shouldCreateEmptyOption() + { + return $this->createEmptyOption; + } + /** * @param mixed $value * @return void|\Zend\Form\Element diff --git a/library/Zend/Form/View/Helper/FormDateSelect.php b/library/Zend/Form/View/Helper/FormDateSelect.php index 2749f503d04..543c2dae7bd 100644 --- a/library/Zend/Form/View/Helper/FormDateSelect.php +++ b/library/Zend/Form/View/Helper/FormDateSelect.php @@ -13,6 +13,7 @@ use DateTime; use IntlDateFormatter; use Zend\Form\ElementInterface; +use Zend\Form\Element\DateSelect as DateSelectElement; use Zend\Form\Exception; use Zend\Form\View\Helper\FormMonthSelect as FormMonthSelectHelper; @@ -27,11 +28,19 @@ class FormDateSelect extends FormMonthSelectHelper * Render a date element that is composed of three selects * * @param ElementInterface $element - * @throws Exception\DomainException + * @throws \Zend\Form\Exception\InvalidArgumentException + * @throws \Zend\Form\Exception\DomainException * @return string */ public function render(ElementInterface $element) { + if (!$element instanceof DateSelectElement) { + throw new Exception\InvalidArgumentException(sprintf( + '%s requires that the element is of type Zend\Form\Element\Select', + __METHOD__ + )); + } + $name = $element->getName(); if ($name === null || $name === '') { throw new Exception\DomainException(sprintf( @@ -47,9 +56,15 @@ public function render(ElementInterface $element) $monthsOptions = $this->getMonthsOptions($pattern['month']); $yearOptions = $this->getYearsOptions($element->getMinYear(), $element->getMaxYear()); - $dayElement = $element->getDayElement()->setAttribute('options', $daysOptions); - $monthElement = $element->getMonthElement()->setAttribute('options', $monthsOptions); - $yearElement = $element->getYearElement()->setAttribute('options', $yearOptions); + if ($element->shouldCreateEmptyOption()) { + $daysOptions = array('' => '') + $daysOptions; + $monthsOptions = array('' => '') + $monthsOptions; + $yearOptions = array('' => '') + $yearOptions; + } + + $dayElement = $element->getDayElement()->setValueOptions($daysOptions); + $monthElement = $element->getMonthElement()->setValueOptions($monthsOptions); + $yearElement = $element->getYearElement()->setValueOptions($yearOptions); $markup = array(); $markup[$pattern['day']] = $selectHelper->render($dayElement); @@ -74,7 +89,7 @@ public function render(ElementInterface $element) * @param string $pattern Pattern to use for days * @return array */ - public function getDaysOptions($pattern) + protected function getDaysOptions($pattern) { $keyFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'dd'); $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); diff --git a/library/Zend/Form/View/Helper/FormMonthSelect.php b/library/Zend/Form/View/Helper/FormMonthSelect.php index 34643b200c9..b5e5fba80c9 100644 --- a/library/Zend/Form/View/Helper/FormMonthSelect.php +++ b/library/Zend/Form/View/Helper/FormMonthSelect.php @@ -14,6 +14,7 @@ use IntlDateFormatter; use Locale; use Zend\Form\ElementInterface; +use Zend\Form\Element\MonthSelect as MonthSelectElement; use Zend\Form\Exception; /** @@ -51,15 +52,24 @@ class FormMonthSelect extends AbstractHelper */ protected $locale; + /** * Render a month element that is composed of two selects * * @param \Zend\Form\ElementInterface $element + * @throws \Zend\Form\Exception\InvalidArgumentException * @throws \Zend\Form\Exception\DomainException * @return string */ public function render(ElementInterface $element) { + if (!$element instanceof MonthSelectElement) { + throw new Exception\InvalidArgumentException(sprintf( + '%s requires that the element is of type Zend\Form\Element\Select', + __METHOD__ + )); + } + $name = $element->getName(); if ($name === null || $name === '') { throw new Exception\DomainException(sprintf( @@ -78,8 +88,13 @@ public function render(ElementInterface $element) $monthsOptions = $this->getMonthsOptions($pattern['month']); $yearOptions = $this->getYearsOptions($element->getMinYear(), $element->getMaxYear()); - $monthElement = $element->getMonthElement()->setAttribute('options', $monthsOptions); - $yearElement = $element->getYearElement()->setAttribute('options', $yearOptions); + if ($element->shouldCreateEmptyOption()) { + $monthsOptions = array('' => '') + $monthsOptions; + $yearOptions = array('' => '') + $yearOptions; + } + + $monthElement = $element->getMonthElement()->setValueOptions($monthsOptions); + $yearElement = $element->getYearElement()->setValueOptions($yearOptions); $markup = array(); $markup[$pattern['month']] = $selectHelper->render($monthElement); @@ -211,7 +226,7 @@ public function getLocale() * @param string $pattern Pattern to use for months * @return array */ - public function getMonthsOptions($pattern) + protected function getMonthsOptions($pattern) { $keyFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'MM'); $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern); @@ -238,7 +253,7 @@ public function getMonthsOptions($pattern) * @param int $maxYear * @return array */ - public function getYearsOptions($minYear, $maxYear) + protected function getYearsOptions($minYear, $maxYear) { $result = array(); for ($i = $maxYear; $i >= $minYear; --$i) { diff --git a/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php b/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php index cd590ad1b65..de26a7ac288 100644 --- a/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php +++ b/tests/ZendTest/Form/View/Helper/FormDateSelectTest.php @@ -42,6 +42,17 @@ public function testGeneratesThreeSelectsWithElement() $this->assertContains('assertContains('assertContains('', $markup); + } + public function testInvokeProxiesToRender() { $element = new DateSelect('foo'); diff --git a/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php b/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php index 9babc9e4d85..fabf362bc42 100644 --- a/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php +++ b/tests/ZendTest/Form/View/Helper/FormMonthSelectTest.php @@ -42,6 +42,17 @@ public function testGeneratesTwoSelectsWithElement() $this->assertContains('assertContains('assertContains('', $markup); + } + public function testInvokeProxiesToRender() { $element = new MonthSelect('foo'); From f5a3c19f2e254de921520a63fd5300425ce15899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Thu, 6 Sep 2012 19:23:15 +0200 Subject: [PATCH 036/126] Add support for prev and next link relationships --- library/Zend/View/Helper/HeadLink.php | 33 ++++++++++++++++++++- tests/ZendTest/View/Helper/HeadLinkTest.php | 16 ++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/library/Zend/View/Helper/HeadLink.php b/library/Zend/View/Helper/HeadLink.php index 0fcc1371d7f..836ce26583f 100644 --- a/library/Zend/View/Helper/HeadLink.php +++ b/library/Zend/View/Helper/HeadLink.php @@ -112,7 +112,7 @@ public function __invoke(array $attributes = null, $placement = Placeholder\Cont */ public function __call($method, $args) { - if (preg_match('/^(?Pset|(ap|pre)pend|offsetSet)(?PStylesheet|Alternate)$/', $method, $matches)) { + if (preg_match('/^(?Pset|(ap|pre)pend|offsetSet)(?PStylesheet|Alternate|Prev|Next)$/', $method, $matches)) { $argc = count($args); $action = $matches['action']; $type = $matches['type']; @@ -422,4 +422,35 @@ public function createDataAlternate(array $args) $attributes = compact('rel', 'href', 'type', 'title', 'extras'); return $this->createData($attributes); } + + /** + * Create item for a prev relationship (mainly used for pagination) + * + * @param array $args + * @return stdClass + */ + public function createDataPrev(array $args) + { + $rel = 'prev'; + $href = (string) array_shift($args); + + $attributes = compact('rel', 'href'); + return $this->createData($attributes); + } + + /** + * Create item for a prev relationship (mainly used for pagination) + * + * @param array $args + * @return stdClass + */ + public function createDataNext(array $args) + { + $rel = 'next'; + $href = (string) array_shift($args); + + $attributes = compact('rel', 'href'); + return $this->createData($attributes); + } } + diff --git a/tests/ZendTest/View/Helper/HeadLinkTest.php b/tests/ZendTest/View/Helper/HeadLinkTest.php index 7882393b120..02a89863229 100644 --- a/tests/ZendTest/View/Helper/HeadLinkTest.php +++ b/tests/ZendTest/View/Helper/HeadLinkTest.php @@ -381,6 +381,22 @@ public function testSetStylesheetWithMediaAsArray() $this->assertContains(' media="screen,print"', $test); } + public function testSetPrevRelationship() + { + $this->helper->appendPrev('/foo/bar'); + $test = $this->helper->toString(); + $this->assertContains('href="/foo/bar"', $test); + $this->assertContains('rel="prev"', $test); + } + + public function testSetNextRelationship() + { + $this->helper->appendNext('/foo/bar'); + $test = $this->helper->toString(); + $this->assertContains('href="/foo/bar"', $test); + $this->assertContains('rel="next"', $test); + } + /** * @issue ZF-5435 */ From bb80dd324e454c0cbf6b5ef8dd3d85ab9d2dede9 Mon Sep 17 00:00:00 2001 From: Chris Martin Date: Fri, 7 Sep 2012 19:21:47 -0400 Subject: [PATCH 037/126] Add MVC service factories for Filters and Validators --- .../Feature/FilterProviderInterface.php | 27 +++++++++++++ .../Feature/ValidatorProviderInterface.php | 27 +++++++++++++ .../Zend/Mvc/Service/FilterManagerFactory.php | 40 +++++++++++++++++++ .../Zend/Mvc/Service/ModuleManagerFactory.php | 12 ++++++ .../Mvc/Service/ServiceListenerFactory.php | 2 + .../Mvc/Service/ValidatorManagerFactory.php | 40 +++++++++++++++++++ 6 files changed, 148 insertions(+) create mode 100644 library/Zend/ModuleManager/Feature/FilterProviderInterface.php create mode 100644 library/Zend/ModuleManager/Feature/ValidatorProviderInterface.php create mode 100644 library/Zend/Mvc/Service/FilterManagerFactory.php create mode 100644 library/Zend/Mvc/Service/ValidatorManagerFactory.php diff --git a/library/Zend/ModuleManager/Feature/FilterProviderInterface.php b/library/Zend/ModuleManager/Feature/FilterProviderInterface.php new file mode 100644 index 00000000000..0599f92d6b8 --- /dev/null +++ b/library/Zend/ModuleManager/Feature/FilterProviderInterface.php @@ -0,0 +1,27 @@ +addServiceManager( + 'ValidatorManager', + 'validators', + 'Zend\ModuleManager\Feature\ValidatorProviderInterface', + 'getValidatorConfig' + ); + $serviceListener->addServiceManager( + 'FilterManager', + 'filters', + 'Zend\ModuleManager\Feature\FilterProviderInterface', + 'getFilterConfig' + ); $events = $serviceLocator->get('EventManager'); $events->attach($defaultListeners); diff --git a/library/Zend/Mvc/Service/ServiceListenerFactory.php b/library/Zend/Mvc/Service/ServiceListenerFactory.php index 6889d612320..5ec6250a913 100644 --- a/library/Zend/Mvc/Service/ServiceListenerFactory.php +++ b/library/Zend/Mvc/Service/ServiceListenerFactory.php @@ -52,10 +52,12 @@ class ServiceListenerFactory implements FactoryInterface 'ConsoleAdapter' => 'Zend\Mvc\Service\ConsoleAdapterFactory', 'ConsoleRouter' => 'Zend\Mvc\Service\RouterFactory', 'DependencyInjector' => 'Zend\Mvc\Service\DiFactory', + 'FilterManager' => 'Zend\Mvc\Service\FilterManagerFactory', 'HttpRouter' => 'Zend\Mvc\Service\RouterFactory', 'Request' => 'Zend\Mvc\Service\RequestFactory', 'Response' => 'Zend\Mvc\Service\ResponseFactory', 'Router' => 'Zend\Mvc\Service\RouterFactory', + 'ValidatorManager' => 'Zend\Mvc\Service\ValidatorManagerFactory', 'ViewHelperManager' => 'Zend\Mvc\Service\ViewHelperManagerFactory', 'ViewFeedRenderer' => 'Zend\Mvc\Service\ViewFeedRendererFactory', 'ViewFeedStrategy' => 'Zend\Mvc\Service\ViewFeedStrategyFactory', diff --git a/library/Zend/Mvc/Service/ValidatorManagerFactory.php b/library/Zend/Mvc/Service/ValidatorManagerFactory.php new file mode 100644 index 00000000000..e9ad869f4cb --- /dev/null +++ b/library/Zend/Mvc/Service/ValidatorManagerFactory.php @@ -0,0 +1,40 @@ + Date: Sat, 8 Sep 2012 12:38:57 -0400 Subject: [PATCH 038/126] MVC service factories for Filters and Validators fixes and unit tests --- .../Zend/Mvc/Service/FilterManagerFactory.php | 26 +++---- .../Mvc/Service/ValidatorManagerFactory.php | 24 +++--- .../Filter/FilterPluginManagerTest.php | 46 +++++++++++ .../ZendTest/Validator/ValidatorChainTest.php | 1 + .../Validator/ValidatorPluginManagerTest.php | 76 +++++++++++++++++++ 5 files changed, 144 insertions(+), 29 deletions(-) create mode 100644 tests/ZendTest/Filter/FilterPluginManagerTest.php create mode 100644 tests/ZendTest/Validator/ValidatorPluginManagerTest.php diff --git a/library/Zend/Mvc/Service/FilterManagerFactory.php b/library/Zend/Mvc/Service/FilterManagerFactory.php index e3a5c76c8a7..17a80d0f6c4 100644 --- a/library/Zend/Mvc/Service/FilterManagerFactory.php +++ b/library/Zend/Mvc/Service/FilterManagerFactory.php @@ -10,12 +10,8 @@ namespace Zend\Mvc\Service; -use Zend\Mvc\Exception; -use Zend\Mvc\Router\RouteMatch; use Zend\ServiceManager\ConfigInterface; use Zend\ServiceManager\ServiceLocatorInterface; -use Zend\View\Helper as ViewHelper; -use Zend\View\Helper\HelperInterface as ViewHelperInterface; /** * @category Zend @@ -24,17 +20,17 @@ */ class FilterManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Validator\FilterPluginManager'; + const PLUGIN_MANAGER_CLASS = 'Zend\Filter\FilterPluginManager'; - /** - * Create and return the filter plugin manager - * - * @param ServiceLocatorInterface $serviceLocator - * @return FilterPluginManager - */ - public function createService(ServiceLocatorInterface $serviceLocator) - { - $plugins = parent::createService($serviceLocator); - return $plugins; + /** + * Create and return the filter plugin manager + * + * @param ServiceLocatorInterface $serviceLocator + * @return FilterPluginManager + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $plugins = parent::createService($serviceLocator); + return $plugins; } } diff --git a/library/Zend/Mvc/Service/ValidatorManagerFactory.php b/library/Zend/Mvc/Service/ValidatorManagerFactory.php index e9ad869f4cb..d1c9ce733f7 100644 --- a/library/Zend/Mvc/Service/ValidatorManagerFactory.php +++ b/library/Zend/Mvc/Service/ValidatorManagerFactory.php @@ -10,12 +10,8 @@ namespace Zend\Mvc\Service; -use Zend\Mvc\Exception; -use Zend\Mvc\Router\RouteMatch; use Zend\ServiceManager\ConfigInterface; use Zend\ServiceManager\ServiceLocatorInterface; -use Zend\View\Helper as ViewHelper; -use Zend\View\Helper\HelperInterface as ViewHelperInterface; /** * @category Zend @@ -26,15 +22,15 @@ class ValidatorManagerFactory extends AbstractPluginManagerFactory { const PLUGIN_MANAGER_CLASS = 'Zend\Validator\ValidatorPluginManager'; - /** - * Create and return the validator plugin manager - * - * @param ServiceLocatorInterface $serviceLocator - * @return ValidatorPluginManager - */ - public function createService(ServiceLocatorInterface $serviceLocator) - { - $plugins = parent::createService($serviceLocator); - return $plugins; + /** + * Create and return the validator plugin manager + * + * @param ServiceLocatorInterface $serviceLocator + * @return ValidatorPluginManager + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $plugins = parent::createService($serviceLocator); + return $plugins; } } diff --git a/tests/ZendTest/Filter/FilterPluginManagerTest.php b/tests/ZendTest/Filter/FilterPluginManagerTest.php new file mode 100644 index 00000000000..0a3b512b764 --- /dev/null +++ b/tests/ZendTest/Filter/FilterPluginManagerTest.php @@ -0,0 +1,46 @@ +filters = new FilterPluginManager(); + } + + public function testFilterSuccessfullyRetrieved() + { + $filter = $this->filters->get('int'); + $this->assertInstanceOf('Zend\Filter\Int', $filter); + } + + public function testRegisteringInvalidFilterRaisesException() + { + $this->setExpectedException('Zend\Filter\Exception\RuntimeException'); + $this->filters->setService('test', $this); + } + + public function testLoadingInvalidFilterRaisesException() + { + $this->filters->setInvokableClass('test', get_class($this)); + $this->setExpectedException('Zend\Filter\Exception\RuntimeException'); + $this->filters->get('test'); + } +} diff --git a/tests/ZendTest/Validator/ValidatorChainTest.php b/tests/ZendTest/Validator/ValidatorChainTest.php index ba1084e5409..ccec6b66686 100644 --- a/tests/ZendTest/Validator/ValidatorChainTest.php +++ b/tests/ZendTest/Validator/ValidatorChainTest.php @@ -45,6 +45,7 @@ public function setUp() public function tearDown() { + AbstractValidator::setDefaultTranslator(null); AbstractValidator::setMessageLength(-1); } diff --git a/tests/ZendTest/Validator/ValidatorPluginManagerTest.php b/tests/ZendTest/Validator/ValidatorPluginManagerTest.php new file mode 100644 index 00000000000..fa821242339 --- /dev/null +++ b/tests/ZendTest/Validator/ValidatorPluginManagerTest.php @@ -0,0 +1,76 @@ +validators = new ValidatorPluginManager(); + } + + public function testAllowsInjectingTranslator() + { + $translator = $this->getMock("Zend\I18n\Translator\Translator"); + + $slContents = array(array('translator', $translator)); + $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $serviceLocator->expects($this->once()) + ->method('get') + ->will($this->returnValueMap($slContents)); + $serviceLocator->expects($this->once()) + ->method('has') + ->with($this->equalTo('translator')) + ->will($this->returnValue(true)); + + $this->validators->setServiceLocator($serviceLocator); + $this->assertSame($serviceLocator, $this->validators->getServiceLocator()); + + $validator = $this->validators->get('notempty'); + $this->assertSame($translator, $validator->getTranslator()); + } + + public function testNoTranslatorInjectedWhenTranslatorIsNotPresent() + { + $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $serviceLocator->expects($this->once()) + ->method('has') + ->with($this->equalTo('translator')) + ->will($this->returnValue(false)); + + $this->validators->setServiceLocator($serviceLocator); + $this->assertSame($serviceLocator, $this->validators->getServiceLocator()); + + $validator = $this->validators->get('notempty'); + $this->assertNull($validator->getTranslator()); + } + + public function testRegisteringInvalidValidatorRaisesException() + { + $this->setExpectedException('Zend\Validator\Exception\RuntimeException'); + $this->validators->setService('test', $this); + } + + public function testLoadingInvalidValidatorRaisesException() + { + $this->validators->setInvokableClass('test', get_class($this)); + $this->setExpectedException('Zend\Validator\Exception\RuntimeException'); + $this->validators->get('test'); + } +} From b57d117ee3d9db97456d4835b693813eb2dfb375 Mon Sep 17 00:00:00 2001 From: Christopher Martin Date: Sat, 8 Sep 2012 12:44:00 -0400 Subject: [PATCH 039/126] Cs fixes --- .../Zend/Mvc/Service/FilterManagerFactory.php | 2 +- .../Zend/Mvc/Service/ModuleManagerFactory.php | 20 +++++++++---------- .../Mvc/Service/ValidatorManagerFactory.php | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/Zend/Mvc/Service/FilterManagerFactory.php b/library/Zend/Mvc/Service/FilterManagerFactory.php index 17a80d0f6c4..5685c91799a 100644 --- a/library/Zend/Mvc/Service/FilterManagerFactory.php +++ b/library/Zend/Mvc/Service/FilterManagerFactory.php @@ -21,7 +21,7 @@ class FilterManagerFactory extends AbstractPluginManagerFactory { const PLUGIN_MANAGER_CLASS = 'Zend\Filter\FilterPluginManager'; - + /** * Create and return the filter plugin manager * diff --git a/library/Zend/Mvc/Service/ModuleManagerFactory.php b/library/Zend/Mvc/Service/ModuleManagerFactory.php index 54279eea063..2c8a9942bed 100644 --- a/library/Zend/Mvc/Service/ModuleManagerFactory.php +++ b/library/Zend/Mvc/Service/ModuleManagerFactory.php @@ -74,17 +74,17 @@ public function createService(ServiceLocatorInterface $serviceLocator) 'Zend\ModuleManager\Feature\ViewHelperProviderInterface', 'getViewHelperConfig' ); - $serviceListener->addServiceManager( - 'ValidatorManager', - 'validators', - 'Zend\ModuleManager\Feature\ValidatorProviderInterface', - 'getValidatorConfig' + $serviceListener->addServiceManager( + 'ValidatorManager', + 'validators', + 'Zend\ModuleManager\Feature\ValidatorProviderInterface', + 'getValidatorConfig' ); - $serviceListener->addServiceManager( - 'FilterManager', - 'filters', - 'Zend\ModuleManager\Feature\FilterProviderInterface', - 'getFilterConfig' + $serviceListener->addServiceManager( + 'FilterManager', + 'filters', + 'Zend\ModuleManager\Feature\FilterProviderInterface', + 'getFilterConfig' ); $events = $serviceLocator->get('EventManager'); diff --git a/library/Zend/Mvc/Service/ValidatorManagerFactory.php b/library/Zend/Mvc/Service/ValidatorManagerFactory.php index d1c9ce733f7..da41f71712a 100644 --- a/library/Zend/Mvc/Service/ValidatorManagerFactory.php +++ b/library/Zend/Mvc/Service/ValidatorManagerFactory.php @@ -21,7 +21,7 @@ class ValidatorManagerFactory extends AbstractPluginManagerFactory { const PLUGIN_MANAGER_CLASS = 'Zend\Validator\ValidatorPluginManager'; - + /** * Create and return the validator plugin manager * From 0cf04b3a3f1c7624db31d280c2c30061268677cb Mon Sep 17 00:00:00 2001 From: Eric Boh Date: Sun, 9 Sep 2012 00:00:18 +0200 Subject: [PATCH 040/126] Added missing test files and test case --- .../Loader/_files/BarModule/Module.php | 15 +++ .../ZendTest/Loader/_files/PharModuleMap.phar | Bin 0 -> 6824 bytes .../Listener/ModuleLoaderListenerTest.php | 96 ++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 tests/ZendTest/Loader/_files/BarModule/Module.php create mode 100644 tests/ZendTest/Loader/_files/PharModuleMap.phar create mode 100644 tests/ZendTest/ModuleManager/Listener/ModuleLoaderListenerTest.php diff --git a/tests/ZendTest/Loader/_files/BarModule/Module.php b/tests/ZendTest/Loader/_files/BarModule/Module.php new file mode 100644 index 00000000000..dfd18098c5f --- /dev/null +++ b/tests/ZendTest/Loader/_files/BarModule/Module.php @@ -0,0 +1,15 @@ +}qZ?|N)n z9 zgCw)qvwhZS7?vx(SvkMXTS?&fkwwI6YLZkkZ*5hPz1*uJ&#Q<*JgXw7Q6)LQ&a1eu zvr2*nSWCK8d50XU+$%Dc#2jBrW_rV^cy~t6F z;#u-=MG=-HktmPlri3a$@hKu%r6-=+f^sNCgsMarj|`rcpk`MU64^X!HGv${~;CoKaYY@^h{nVL-&XSp)8Ro>vc;ti}XJ3D{byo!g z_4xbf=}DYbbR*Hv&_K1M=rQix^HY1Z)0jCA6H+G|xoElNzG)^o9LN?EnA&XTr~ARS zXb=TFvP-_HXvh{dO)`ll+OlW@Ne5^W6bZ9l4~P9$d%MjZ?zGuSe91l5=V|CfJj#O` zYnfW>IF?7G%V;RAw_}kfJdra5wjhf^nA6BG9Yl_q8HnLlkv7PE`)1HP!c_ai%7Bx4 z#126TLQ)|k{j{UD>0m$hG_^vr*e+EbI@%rfXy*}o8|Un0yofxClDqSm)%K|I?Ef)h zdn7?$*k11E0pF)_y_8TyVr*&7y-DodNRfGapA0makgB10lDxrcCHWRugtQWZ8nRp~ zrHsG`rOS_|F@>piRt?q3$ik%JQHG|4NlM$RgQOFK-D?hS65eH{fmYf~&2!A7Sw5Fr zIz@8s5-{PD&%cwsm*b#yH zvw493`FP#G>Lj3IH@Nfv$O#~kzIZbF8Cuk|UJvNw?PUwJ4GtMt;umJw@VA}1%0LbPsL>5uvxEHo{ z4s0xrx;^nDC%vgpsfeV|BSNNT2yXq*B7E(|s08@pczE)({Y^)fxp_QlzsCX64KAcZ zPLD+&Q|#+ZqSs(_QKQvnNM;MktVT;eVRO zX_wsw{)81BhWQ!hZ_Y49Cjmx8lY+2VA#c~2R?Z^MJ+MsUR48e>ahRkWEyH8DR5@uT zgHrd1lBX#9&8|*vJ+3vadpo)Hlg?+|E$i6e@#MDiBMys`TP287HF{1AK z8SaICPPwurDiCFxAqzNt)YOF%u^MN06?3poCWB2C9R#nl0(;2ILZYU(5NVTdBOAsxzE&+y(eB zOkUE|l~vLxJp6GN55$%wi+qe$PorMR7vO8%G}<`j$-t@P0MV!uYAGWtwB9o`B~#Yq zJ~K(RC{{vjE72lh5^<@hHO@mdQ)^c#{V}dPnRWw?Zh)yMV103pgfAoAA<3~i1_7qQ z63CXfuLxSmNfU7A6XTd_XlkF!l@gQNqRNf-#8wYPMljZl7MPHySV))Z0alBmh8pw*d44pdB!}{nAYVTt zB}%90Tv{m^SalE=fJzsXbXhaGL5kLrRho?iXw=*+;}d=V3bA1gCQu2G06f{i)Ye=A zyOgBck8lAq1Ks-SRID)G0e<9x z1uwpBZBfQyoJZi;U{;z@Au5|&FuDstnmKw5srxAMp(RMK4okQSF-3zgW71i)j!~fq zr&GRG8{<~KKtn5>a$4t;*16j{_gd$?b&j_O#TB?@vV)DFG>SB=Y92i# zzFH8-tmZQw07*~P-zIfWNSztOSj;G}DpeiY61h!a>4=T0;`@4K>ppJK_UL_q#t6oj zP6QdRtmCRighrp<$WBDHjaMJkqX|WuE`=nXkH~dHAzITFt%fdRZW%udQOwwbGB$Q8 zVWbEpT69kkni`i&i+98XCZ`ZIo|9gbLY4qjySs#pf&!b;mgre)vI-Jv;S~T^$ge_j zijDfA&c_bkMN4R2dlQLQMoheekDNf_QAQI2s0%k=#tHo5qP|^RJfym9(4Z0zL|Nn` z6cK23dcCw7IEodFx>{>rEpYpHQ})6vPCG})W%Ulcrnj} zTH(#z%ig#eYnTcc(arD9uqsf(EQlwz^&9kj0tr)HO=701A2~o3WQ7yK^PC-|p@3Id zblJfo3jBz!jz|`5^BrmW*+ipEscQp7ny%m@HDMbCcsM>fJ?Z23mH|lY`Tj4Ar}ysN`x*ZKN`2x3e+K?9e<^BX^_PGBx=)`+e;ywF zodoc=M?Wnw!yw?4;f~B1{iY)2P8?uV_2NKMj1Qmw^Ur_$GXLV6FaLY~*MI-*_h0^e P^uXa?K+&rgCold7N1__B literal 0 HcmV?d00001 diff --git a/tests/ZendTest/ModuleManager/Listener/ModuleLoaderListenerTest.php b/tests/ZendTest/ModuleManager/Listener/ModuleLoaderListenerTest.php new file mode 100644 index 00000000000..cc654093d0e --- /dev/null +++ b/tests/ZendTest/ModuleManager/Listener/ModuleLoaderListenerTest.php @@ -0,0 +1,96 @@ +tmpdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zend_module_cache_dir'; + @mkdir($this->tmpdir); + + $this->moduleManager = new ModuleManager(array()); + $this->moduleManager->getEventManager()->attach('loadModule.resolve', new ModuleResolverListener, 1000); + } + + public function tearDown() + { + $file = glob($this->tmpdir . DIRECTORY_SEPARATOR . '*'); + @unlink($file[0]); // change this if there's ever > 1 file + @rmdir($this->tmpdir); + } + + public function testModuleLoaderListenerFunctionsAsAggregateListenerEnabledCache() + { + $options = new ListenerOptions(array( + 'cache_dir' => $this->tmpdir, + 'module_map_cache_enabled' => true, + 'module_map_cache_key' => 'foo', + )); + + $moduleLoaderListener = new ModuleLoaderListener($options); + + $moduleManager = $this->moduleManager; + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + + $moduleLoaderListener->attach($moduleManager->getEventManager()); + $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + } + + public function testModuleLoaderListenerFunctionsAsAggregateListenerDisabledCache() + { + $options = new ListenerOptions(array( + 'cache_dir' => $this->tmpdir, + )); + + $moduleLoaderListener = new ModuleLoaderListener($options); + + $moduleManager = $this->moduleManager; + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + + $moduleLoaderListener->attach($moduleManager->getEventManager()); + $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + } + + public function testModuleLoaderListenerFunctionsAsAggregateListenerHasCache() + { + $options = new ListenerOptions(array( + 'cache_dir' => $this->tmpdir, + 'module_map_cache_key' => 'foo', + 'module_map_cache_enabled' => true, + )); + + file_put_contents($options->getModuleMapCacheFile(), 'moduleManager; + $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + + $moduleLoaderListener->attach($moduleManager->getEventManager()); + $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); + $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); + } +} From 13d47e5b93db0bd6aa148279111f5b95b3cea9ac Mon Sep 17 00:00:00 2001 From: Aleksey Khudyakov Date: Sun, 9 Sep 2012 20:50:11 +1100 Subject: [PATCH 041/126] Add fromString() to restore mail message from string --- library/Zend/Mail/Message.php | 16 ++++++++++++++++ tests/ZendTest/Mail/MessageTest.php | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/library/Zend/Mail/Message.php b/library/Zend/Mail/Message.php index 54fe95f5898..f8421e1a5a0 100644 --- a/library/Zend/Mail/Message.php +++ b/library/Zend/Mail/Message.php @@ -535,4 +535,20 @@ public function toString() . Headers::EOL . $this->getBodyText(); } + + /** + * Set from serialized string + * + * @param string $rawMessage + * @return Message + */ + public function fromString($rawMessage) + { + $headers = null; + $content = null; + Mime\Decode::splitMessage($rawMessage, $headers, $content); + $this->setHeaders($headers); + $this->setBody($content); + return $this; + } } diff --git a/tests/ZendTest/Mail/MessageTest.php b/tests/ZendTest/Mail/MessageTest.php index c40eebde260..bb295a85415 100644 --- a/tests/ZendTest/Mail/MessageTest.php +++ b/tests/ZendTest/Mail/MessageTest.php @@ -647,4 +647,18 @@ public function testDefaultDateHeaderEncodingIsAlwaysAscii() $test = substr($test, 0, 16); $this->assertEquals($date, $test); } + + public function testRestoreFromSerializedString() + { + $this->message->addTo('zf-devteam@zend.com', 'ZF DevTeam'); + $this->message->addFrom('matthew@zend.com', "Matthew Weier O'Phinney"); + $this->message->addCc('zf-contributors@lists.zend.com', 'ZF Contributors List'); + $this->message->setSubject('This is a subject'); + $this->message->setBody('foo'); + + $serialized = $this->message->toString(); + $restoredMessage = new Message(); + $restoredMessage->fromString($serialized); + $this->assertEquals($serialized, $restoredMessage->toString()); + } } From fd9f043fa710d849adb19e0e4f2883858ead8ac5 Mon Sep 17 00:00:00 2001 From: Aleksey Khudyakov Date: Mon, 10 Sep 2012 03:12:18 +1100 Subject: [PATCH 042/126] make Mail\Message::fromString() method static --- library/Zend/Mail/Message.php | 12 ++++++++---- tests/ZendTest/Mail/MessageTest.php | 4 +--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/library/Zend/Mail/Message.php b/library/Zend/Mail/Message.php index f8421e1a5a0..2d53f10f7d6 100644 --- a/library/Zend/Mail/Message.php +++ b/library/Zend/Mail/Message.php @@ -542,13 +542,17 @@ public function toString() * @param string $rawMessage * @return Message */ - public function fromString($rawMessage) + public static function fromString($rawMessage) { + $message = new static(); $headers = null; $content = null; Mime\Decode::splitMessage($rawMessage, $headers, $content); - $this->setHeaders($headers); - $this->setBody($content); - return $this; + if ($headers->has('mime-version')) { + // @todo restore body to mime\message + } + $message->setHeaders($headers); + $message->setBody($content); + return $message; } } diff --git a/tests/ZendTest/Mail/MessageTest.php b/tests/ZendTest/Mail/MessageTest.php index bb295a85415..6d33d76b81f 100644 --- a/tests/ZendTest/Mail/MessageTest.php +++ b/tests/ZendTest/Mail/MessageTest.php @@ -655,10 +655,8 @@ public function testRestoreFromSerializedString() $this->message->addCc('zf-contributors@lists.zend.com', 'ZF Contributors List'); $this->message->setSubject('This is a subject'); $this->message->setBody('foo'); - $serialized = $this->message->toString(); - $restoredMessage = new Message(); - $restoredMessage->fromString($serialized); + $restoredMessage = Message::fromString($serialized); $this->assertEquals($serialized, $restoredMessage->toString()); } } From d960eb6eacacd84405ee31382cd3fe666ff14b14 Mon Sep 17 00:00:00 2001 From: Stefan Kleff Date: Mon, 10 Sep 2012 10:21:41 +0200 Subject: [PATCH 043/126] Replaced ActivationStrategy with filters. Removed exception when setting formatter. --- library/Zend/Log/Writer/FingersCrossed.php | 59 +++++++++++++------ .../ActivationStrategyInterface.php | 28 --------- .../ErrorLevelActivationStrategy.php | 45 -------------- 3 files changed, 40 insertions(+), 92 deletions(-) delete mode 100644 library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php delete mode 100644 library/Zend/Log/Writer/FingersCrossed/ErrorLevelActivationStrategy.php diff --git a/library/Zend/Log/Writer/FingersCrossed.php b/library/Zend/Log/Writer/FingersCrossed.php index b77c3d9d945..bd47a3195c5 100644 --- a/library/Zend/Log/Writer/FingersCrossed.php +++ b/library/Zend/Log/Writer/FingersCrossed.php @@ -9,11 +9,11 @@ */ namespace Zend\Log\Writer; +use Zend\Log\Filter\Priority as PriorityFilter; +use Zend\Log\Filter\FilterInterface; use Zend\Log\Formatter\FormatterInterface; use Zend\Log\Exception; use Zend\Log\Logger; -use Zend\Log\Writer\FingersCrossed\ErrorLevelActivationStrategy; -use Zend\Log\Writer\FingersCrossed\ActivationStrategyInterface; use Zend\Log\Writer\WriterInterface; use Zend\Log\Writer\AbstractWriter; @@ -56,35 +56,55 @@ class FingersCrossed extends AbstractWriter */ protected $buffer = array(); - /** - * Strategy which determines if events are buffered - * - * @var ActivationStrategyInterface - */ - protected $activationStrategy; - /** * Constructor * * @param WriterInterface $writer Wrapped writer - * @param ActivationStrategyInterface|int $activationStrategyOrPriority Strategy or log priority which determines buffering of events + * @param FilterInterface|int $filterOrPriority Filter or log priority which determines buffering of events * @param int $bufferSize Maximum buffer size */ - public function __construct(WriterInterface $writer, $activationStrategyOrPriority = null, $bufferSize = 0) + public function __construct(WriterInterface $writer, $filterOrPriority = null, $bufferSize = 0) { $this->writer = $writer; - if ($activationStrategyOrPriority === null) { - $this->activationStrategy = new ErrorLevelActivationStrategy(Logger::WARN); - } elseif (! $activationStrategyOrPriority instanceof ActivationStrategyInterface) { - $this->activationStrategy = new ErrorLevelActivationStrategy($activationStrategyOrPriority); + if (null === $filterOrPriority) { + $this->addFilter(new PriorityFilter(Logger::WARN)); + } elseif (!$filterOrPriority instanceof FilterInterface) { + $this->addFilter(new PriorityFilter($filterOrPriority)); } else { - $this->activationStrategy = $activationStrategyOrPriority; + $this->addFilter($filterOrPriority); } $this->bufferSize = $bufferSize; } + /** + * Log a message to this writer. + * + * @param array $event log data event + * @return void + */ + public function write(array $event) + { + $this->doWrite($event); + } + + /** + * Check if buffered data should be flushed + * + * @param array $event event data + * @return boolean true if buffered data should be flushed + */ + protected function isActivated(array $event) + { + foreach ($this->filters as $filter) { + if (!$filter->filter($event)) { + return false; + } + } + return true; + } + /** * Write message to buffer or delegate event data to the wrapped writer * @@ -100,7 +120,7 @@ protected function doWrite(array $event) array_shift($this->buffer); } - if ($this->activationStrategy->isWriterActivated($event)) { + if ($this->isActivated($event)) { $this->buffering = false; foreach ($this->buffer as $bufferedEvent) { @@ -122,13 +142,14 @@ public function reset() } /** - * Prevent setting a formatter for this writer + * Stub in accordance to parent method signature. + * Fomatters must be set on the wrapped writer. * * @param Formatter $formatter */ public function setFormatter(FormatterInterface $formatter) { - throw new Exception\InvalidArgumentException('Formatter must be set on the wrapped writer'); + return $this->writer; } /** diff --git a/library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php b/library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php deleted file mode 100644 index f0d35024b61..00000000000 --- a/library/Zend/Log/Writer/FingersCrossed/ActivationStrategyInterface.php +++ /dev/null @@ -1,28 +0,0 @@ -priority = $priority; - } - - /** - * Returns whether the given record activates the writer - * - * @param array event data - * @return bool - */ - public function isWriterActivated(array $event) - { - return $event['priority'] <= $this->priority; - } -} \ No newline at end of file From bedd30b0ca99f8e88178613c71fe78e6bb3be47c Mon Sep 17 00:00:00 2001 From: Aleksey Khudyakov Date: Tue, 11 Sep 2012 08:32:46 +1100 Subject: [PATCH 044/126] update emails used in tests to @example.com --- library/Zend/Mail/Message.php | 2 +- tests/ZendTest/Mail/MessageTest.php | 188 ++++++++++++++-------------- 2 files changed, 95 insertions(+), 95 deletions(-) diff --git a/library/Zend/Mail/Message.php b/library/Zend/Mail/Message.php index 2d53f10f7d6..37f3866f26e 100644 --- a/library/Zend/Mail/Message.php +++ b/library/Zend/Mail/Message.php @@ -537,7 +537,7 @@ public function toString() } /** - * Set from serialized string + * Instantiate from raw message string * * @param string $rawMessage * @return Message diff --git a/tests/ZendTest/Mail/MessageTest.php b/tests/ZendTest/Mail/MessageTest.php index 6d33d76b81f..4ee224a2493 100644 --- a/tests/ZendTest/Mail/MessageTest.php +++ b/tests/ZendTest/Mail/MessageTest.php @@ -56,7 +56,7 @@ public function testSetsOrigDateHeaderByDefault() public function testAddingFromAddressMarksAsValid() { - $this->message->addFrom('zf-devteam@zend.com'); + $this->message->addFrom('zf-devteam@example.com'); $this->assertTrue($this->message->isValid()); } @@ -68,14 +68,14 @@ public function testHeadersMethodReturnsHeadersObject() public function testToMethodReturnsAddressListObject() { - $this->message->addTo('zf-devteam@zend.com'); + $this->message->addTo('zf-devteam@example.com'); $to = $this->message->getTo(); $this->assertInstanceOf('Zend\Mail\AddressList', $to); } public function testToAddressListLivesInHeaders() { - $this->message->addTo('zf-devteam@zend.com'); + $this->message->addTo('zf-devteam@example.com'); $to = $this->message->getTo(); $headers = $this->message->getHeaders(); $this->assertInstanceOf('Zend\Mail\Headers', $headers); @@ -86,14 +86,14 @@ public function testToAddressListLivesInHeaders() public function testFromMethodReturnsAddressListObject() { - $this->message->addFrom('zf-devteam@zend.com'); + $this->message->addFrom('zf-devteam@example.com'); $from = $this->message->getFrom(); $this->assertInstanceOf('Zend\Mail\AddressList', $from); } public function testFromAddressListLivesInHeaders() { - $this->message->addFrom('zf-devteam@zend.com'); + $this->message->addFrom('zf-devteam@example.com'); $from = $this->message->getFrom(); $headers = $this->message->getHeaders(); $this->assertInstanceOf('Zend\Mail\Headers', $headers); @@ -104,14 +104,14 @@ public function testFromAddressListLivesInHeaders() public function testCcMethodReturnsAddressListObject() { - $this->message->addCc('zf-devteam@zend.com'); + $this->message->addCc('zf-devteam@example.com'); $cc = $this->message->getCc(); $this->assertInstanceOf('Zend\Mail\AddressList', $cc); } public function testCcAddressListLivesInHeaders() { - $this->message->addCc('zf-devteam@zend.com'); + $this->message->addCc('zf-devteam@example.com'); $cc = $this->message->getCc(); $headers = $this->message->getHeaders(); $this->assertInstanceOf('Zend\Mail\Headers', $headers); @@ -122,14 +122,14 @@ public function testCcAddressListLivesInHeaders() public function testBccMethodReturnsAddressListObject() { - $this->message->addBcc('zf-devteam@zend.com'); + $this->message->addBcc('zf-devteam@example.com'); $bcc = $this->message->getBcc(); $this->assertInstanceOf('Zend\Mail\AddressList', $bcc); } public function testBccAddressListLivesInHeaders() { - $this->message->addBcc('zf-devteam@zend.com'); + $this->message->addBcc('zf-devteam@example.com'); $bcc = $this->message->getBcc(); $headers = $this->message->getHeaders(); $this->assertInstanceOf('Zend\Mail\Headers', $headers); @@ -140,14 +140,14 @@ public function testBccAddressListLivesInHeaders() public function testReplyToMethodReturnsAddressListObject() { - $this->message->addReplyTo('zf-devteam@zend.com'); + $this->message->addReplyTo('zf-devteam@example.com'); $replyTo = $this->message->getReplyTo(); $this->assertInstanceOf('Zend\Mail\AddressList', $replyTo); } public function testReplyToAddressListLivesInHeaders() { - $this->message->addReplyTo('zf-devteam@zend.com'); + $this->message->addReplyTo('zf-devteam@example.com'); $replyTo = $this->message->getReplyTo(); $headers = $this->message->getHeaders(); $this->assertInstanceOf('Zend\Mail\Headers', $headers); @@ -163,14 +163,14 @@ public function testSenderIsNullByDefault() public function testSettingSenderCreatesAddressObject() { - $this->message->setSender('zf-devteam@zend.com'); + $this->message->setSender('zf-devteam@example.com'); $sender = $this->message->getSender(); $this->assertInstanceOf('Zend\Mail\Address', $sender); } public function testCanSpecifyNameWhenSettingSender() { - $this->message->setSender('zf-devteam@zend.com', 'ZF DevTeam'); + $this->message->setSender('zf-devteam@example.com', 'ZF DevTeam'); $sender = $this->message->getSender(); $this->assertInstanceOf('Zend\Mail\Address', $sender); $this->assertEquals('ZF DevTeam', $sender->getName()); @@ -178,7 +178,7 @@ public function testCanSpecifyNameWhenSettingSender() public function testCanProvideAddressObjectWhenSettingSender() { - $sender = new Address('zf-devteam@zend.com'); + $sender = new Address('zf-devteam@example.com'); $this->message->setSender($sender); $test = $this->message->getSender(); $this->assertSame($sender, $test); @@ -188,24 +188,24 @@ public function testSenderAccessorsProxyToSenderHeader() { $header = new Header\Sender(); $this->message->getHeaders()->addHeader($header); - $address = new Address('zf-devteam@zend.com', 'ZF DevTeam'); + $address = new Address('zf-devteam@example.com', 'ZF DevTeam'); $this->message->setSender($address); $this->assertSame($address, $header->getAddress()); } public function testCanAddFromAddressUsingName() { - $this->message->addFrom('zf-devteam@zend.com', 'ZF DevTeam'); + $this->message->addFrom('zf-devteam@example.com', 'ZF DevTeam'); $addresses = $this->message->getFrom(); $this->assertEquals(1, count($addresses)); $address = $addresses->current(); - $this->assertEquals('zf-devteam@zend.com', $address->getEmail()); + $this->assertEquals('zf-devteam@example.com', $address->getEmail()); $this->assertEquals('ZF DevTeam', $address->getName()); } public function testCanAddFromAddressUsingAddressObject() { - $address = new Address('zf-devteam@zend.com', 'ZF DevTeam'); + $address = new Address('zf-devteam@example.com', 'ZF DevTeam'); $this->message->addFrom($address); $addresses = $this->message->getFrom(); @@ -217,59 +217,59 @@ public function testCanAddFromAddressUsingAddressObject() public function testCanAddManyFromAddressesUsingArray() { $addresses = array( - 'zf-devteam@zend.com', - 'zf-contributors@lists.zend.com' => 'ZF Contributors List', - new Address('fw-announce@lists.zend.com', 'ZF Announce List'), + 'zf-devteam@example.com', + 'zf-contributors@example.com' => 'ZF Contributors List', + new Address('fw-announce@example.com', 'ZF Announce List'), ); $this->message->addFrom($addresses); $from = $this->message->getFrom(); $this->assertEquals(3, count($from)); - $this->assertTrue($from->has('zf-devteam@zend.com')); - $this->assertTrue($from->has('zf-contributors@lists.zend.com')); - $this->assertTrue($from->has('fw-announce@lists.zend.com')); + $this->assertTrue($from->has('zf-devteam@example.com')); + $this->assertTrue($from->has('zf-contributors@example.com')); + $this->assertTrue($from->has('fw-announce@example.com')); } public function testCanAddManyFromAddressesUsingAddressListObject() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addFrom('fw-announce@lists.zend.com'); + $this->message->addFrom('fw-announce@example.com'); $this->message->addFrom($list); $from = $this->message->getFrom(); $this->assertEquals(2, count($from)); - $this->assertTrue($from->has('fw-announce@lists.zend.com')); - $this->assertTrue($from->has('zf-devteam@zend.com')); + $this->assertTrue($from->has('fw-announce@example.com')); + $this->assertTrue($from->has('zf-devteam@example.com')); } public function testCanSetFromListFromAddressList() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addFrom('fw-announce@lists.zend.com'); + $this->message->addFrom('fw-announce@example.com'); $this->message->setFrom($list); $from = $this->message->getFrom(); $this->assertEquals(1, count($from)); - $this->assertFalse($from->has('fw-announce@lists.zend.com')); - $this->assertTrue($from->has('zf-devteam@zend.com')); + $this->assertFalse($from->has('fw-announce@example.com')); + $this->assertTrue($from->has('zf-devteam@example.com')); } public function testCanAddCcAddressUsingName() { - $this->message->addCc('zf-devteam@zend.com', 'ZF DevTeam'); + $this->message->addCc('zf-devteam@example.com', 'ZF DevTeam'); $addresses = $this->message->getCc(); $this->assertEquals(1, count($addresses)); $address = $addresses->current(); - $this->assertEquals('zf-devteam@zend.com', $address->getEmail()); + $this->assertEquals('zf-devteam@example.com', $address->getEmail()); $this->assertEquals('ZF DevTeam', $address->getName()); } public function testCanAddCcAddressUsingAddressObject() { - $address = new Address('zf-devteam@zend.com', 'ZF DevTeam'); + $address = new Address('zf-devteam@example.com', 'ZF DevTeam'); $this->message->addCc($address); $addresses = $this->message->getCc(); @@ -281,59 +281,59 @@ public function testCanAddCcAddressUsingAddressObject() public function testCanAddManyCcAddressesUsingArray() { $addresses = array( - 'zf-devteam@zend.com', - 'zf-contributors@lists.zend.com' => 'ZF Contributors List', - new Address('fw-announce@lists.zend.com', 'ZF Announce List'), + 'zf-devteam@example.com', + 'zf-contributors@example.com' => 'ZF Contributors List', + new Address('fw-announce@example.com', 'ZF Announce List'), ); $this->message->addCc($addresses); $cc = $this->message->getCc(); $this->assertEquals(3, count($cc)); - $this->assertTrue($cc->has('zf-devteam@zend.com')); - $this->assertTrue($cc->has('zf-contributors@lists.zend.com')); - $this->assertTrue($cc->has('fw-announce@lists.zend.com')); + $this->assertTrue($cc->has('zf-devteam@example.com')); + $this->assertTrue($cc->has('zf-contributors@example.com')); + $this->assertTrue($cc->has('fw-announce@example.com')); } public function testCanAddManyCcAddressesUsingAddressListObject() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addCc('fw-announce@lists.zend.com'); + $this->message->addCc('fw-announce@example.com'); $this->message->addCc($list); $cc = $this->message->getCc(); $this->assertEquals(2, count($cc)); - $this->assertTrue($cc->has('fw-announce@lists.zend.com')); - $this->assertTrue($cc->has('zf-devteam@zend.com')); + $this->assertTrue($cc->has('fw-announce@example.com')); + $this->assertTrue($cc->has('zf-devteam@example.com')); } public function testCanSetCcListFromAddressList() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addCc('fw-announce@lists.zend.com'); + $this->message->addCc('fw-announce@example.com'); $this->message->setCc($list); $cc = $this->message->getCc(); $this->assertEquals(1, count($cc)); - $this->assertFalse($cc->has('fw-announce@lists.zend.com')); - $this->assertTrue($cc->has('zf-devteam@zend.com')); + $this->assertFalse($cc->has('fw-announce@example.com')); + $this->assertTrue($cc->has('zf-devteam@example.com')); } public function testCanAddBccAddressUsingName() { - $this->message->addBcc('zf-devteam@zend.com', 'ZF DevTeam'); + $this->message->addBcc('zf-devteam@example.com', 'ZF DevTeam'); $addresses = $this->message->getBcc(); $this->assertEquals(1, count($addresses)); $address = $addresses->current(); - $this->assertEquals('zf-devteam@zend.com', $address->getEmail()); + $this->assertEquals('zf-devteam@example.com', $address->getEmail()); $this->assertEquals('ZF DevTeam', $address->getName()); } public function testCanAddBccAddressUsingAddressObject() { - $address = new Address('zf-devteam@zend.com', 'ZF DevTeam'); + $address = new Address('zf-devteam@example.com', 'ZF DevTeam'); $this->message->addBcc($address); $addresses = $this->message->getBcc(); @@ -345,59 +345,59 @@ public function testCanAddBccAddressUsingAddressObject() public function testCanAddManyBccAddressesUsingArray() { $addresses = array( - 'zf-devteam@zend.com', - 'zf-contributors@lists.zend.com' => 'ZF Contributors List', - new Address('fw-announce@lists.zend.com', 'ZF Announce List'), + 'zf-devteam@example.com', + 'zf-contributors@example.com' => 'ZF Contributors List', + new Address('fw-announce@example.com', 'ZF Announce List'), ); $this->message->addBcc($addresses); $bcc = $this->message->getBcc(); $this->assertEquals(3, count($bcc)); - $this->assertTrue($bcc->has('zf-devteam@zend.com')); - $this->assertTrue($bcc->has('zf-contributors@lists.zend.com')); - $this->assertTrue($bcc->has('fw-announce@lists.zend.com')); + $this->assertTrue($bcc->has('zf-devteam@example.com')); + $this->assertTrue($bcc->has('zf-contributors@example.com')); + $this->assertTrue($bcc->has('fw-announce@example.com')); } public function testCanAddManyBccAddressesUsingAddressListObject() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addBcc('fw-announce@lists.zend.com'); + $this->message->addBcc('fw-announce@example.com'); $this->message->addBcc($list); $bcc = $this->message->getBcc(); $this->assertEquals(2, count($bcc)); - $this->assertTrue($bcc->has('fw-announce@lists.zend.com')); - $this->assertTrue($bcc->has('zf-devteam@zend.com')); + $this->assertTrue($bcc->has('fw-announce@example.com')); + $this->assertTrue($bcc->has('zf-devteam@example.com')); } public function testCanSetBccListFromAddressList() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addBcc('fw-announce@lists.zend.com'); + $this->message->addBcc('fw-announce@example.com'); $this->message->setBcc($list); $bcc = $this->message->getBcc(); $this->assertEquals(1, count($bcc)); - $this->assertFalse($bcc->has('fw-announce@lists.zend.com')); - $this->assertTrue($bcc->has('zf-devteam@zend.com')); + $this->assertFalse($bcc->has('fw-announce@example.com')); + $this->assertTrue($bcc->has('zf-devteam@example.com')); } public function testCanAddReplyToAddressUsingName() { - $this->message->addReplyTo('zf-devteam@zend.com', 'ZF DevTeam'); + $this->message->addReplyTo('zf-devteam@example.com', 'ZF DevTeam'); $addresses = $this->message->getReplyTo(); $this->assertEquals(1, count($addresses)); $address = $addresses->current(); - $this->assertEquals('zf-devteam@zend.com', $address->getEmail()); + $this->assertEquals('zf-devteam@example.com', $address->getEmail()); $this->assertEquals('ZF DevTeam', $address->getName()); } public function testCanAddReplyToAddressUsingAddressObject() { - $address = new Address('zf-devteam@zend.com', 'ZF DevTeam'); + $address = new Address('zf-devteam@example.com', 'ZF DevTeam'); $this->message->addReplyTo($address); $addresses = $this->message->getReplyTo(); @@ -409,44 +409,44 @@ public function testCanAddReplyToAddressUsingAddressObject() public function testCanAddManyReplyToAddressesUsingArray() { $addresses = array( - 'zf-devteam@zend.com', - 'zf-contributors@lists.zend.com' => 'ZF Contributors List', - new Address('fw-announce@lists.zend.com', 'ZF Announce List'), + 'zf-devteam@example.com', + 'zf-contributors@example.com' => 'ZF Contributors List', + new Address('fw-announce@example.com', 'ZF Announce List'), ); $this->message->addReplyTo($addresses); $replyTo = $this->message->getReplyTo(); $this->assertEquals(3, count($replyTo)); - $this->assertTrue($replyTo->has('zf-devteam@zend.com')); - $this->assertTrue($replyTo->has('zf-contributors@lists.zend.com')); - $this->assertTrue($replyTo->has('fw-announce@lists.zend.com')); + $this->assertTrue($replyTo->has('zf-devteam@example.com')); + $this->assertTrue($replyTo->has('zf-contributors@example.com')); + $this->assertTrue($replyTo->has('fw-announce@example.com')); } public function testCanAddManyReplyToAddressesUsingAddressListObject() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addReplyTo('fw-announce@lists.zend.com'); + $this->message->addReplyTo('fw-announce@example.com'); $this->message->addReplyTo($list); $replyTo = $this->message->getReplyTo(); $this->assertEquals(2, count($replyTo)); - $this->assertTrue($replyTo->has('fw-announce@lists.zend.com')); - $this->assertTrue($replyTo->has('zf-devteam@zend.com')); + $this->assertTrue($replyTo->has('fw-announce@example.com')); + $this->assertTrue($replyTo->has('zf-devteam@example.com')); } public function testCanSetReplyToListFromAddressList() { $list = new AddressList(); - $list->add('zf-devteam@zend.com'); + $list->add('zf-devteam@example.com'); - $this->message->addReplyTo('fw-announce@lists.zend.com'); + $this->message->addReplyTo('fw-announce@example.com'); $this->message->setReplyTo($list); $replyTo = $this->message->getReplyTo(); $this->assertEquals(1, count($replyTo)); - $this->assertFalse($replyTo->has('fw-announce@lists.zend.com')); - $this->assertTrue($replyTo->has('zf-devteam@zend.com')); + $this->assertFalse($replyTo->has('fw-announce@example.com')); + $this->assertTrue($replyTo->has('zf-devteam@example.com')); } public function testSubjectIsEmptyByDefault() @@ -604,10 +604,10 @@ public function testEncodingIsMutable() public function testSettingNonAsciiEncodingForcesMimeEncodingOfSomeHeaders() { - $this->message->addTo('zf-devteam@zend.com', 'ZF DevTeam'); - $this->message->addFrom('matthew@zend.com', "Matthew Weier O'Phinney"); - $this->message->addCc('zf-contributors@lists.zend.com', 'ZF Contributors List'); - $this->message->addBcc('zf-crteam@lists.zend.com', 'ZF CR Team'); + $this->message->addTo('zf-devteam@example.com', 'ZF DevTeam'); + $this->message->addFrom('matthew@example.com', "Matthew Weier O'Phinney"); + $this->message->addCc('zf-contributors@example.com', 'ZF Contributors List'); + $this->message->addBcc('zf-crteam@example.com', 'ZF CR Team'); $this->message->setSubject('This is a subject'); $this->message->setEncoding('UTF-8'); @@ -615,19 +615,19 @@ public function testSettingNonAsciiEncodingForcesMimeEncodingOfSomeHeaders() $expected = '=?UTF-8?Q?ZF=20DevTeam?='; $this->assertContains($expected, $test); - $this->assertContains('', $test); + $this->assertContains('', $test); $expected = "=?UTF-8?Q?Matthew=20Weier=20O'Phinney?="; $this->assertContains($expected, $test, $test); - $this->assertContains('', $test); + $this->assertContains('', $test); $expected = '=?UTF-8?Q?ZF=20Contributors=20List?='; $this->assertContains($expected, $test); - $this->assertContains('', $test); + $this->assertContains('', $test); $expected = '=?UTF-8?Q?ZF=20CR=20Team?='; $this->assertContains($expected, $test); - $this->assertContains('', $test); + $this->assertContains('', $test); $expected = 'Subject: =?UTF-8?Q?This=20is=20a=20subject?='; $this->assertContains($expected, $test); @@ -650,9 +650,9 @@ public function testDefaultDateHeaderEncodingIsAlwaysAscii() public function testRestoreFromSerializedString() { - $this->message->addTo('zf-devteam@zend.com', 'ZF DevTeam'); - $this->message->addFrom('matthew@zend.com', "Matthew Weier O'Phinney"); - $this->message->addCc('zf-contributors@lists.zend.com', 'ZF Contributors List'); + $this->message->addTo('zf-devteam@example.com', 'ZF DevTeam'); + $this->message->addFrom('matthew@example.com', "Matthew Weier O'Phinney"); + $this->message->addCc('zf-contributors@example.com', 'ZF Contributors List'); $this->message->setSubject('This is a subject'); $this->message->setBody('foo'); $serialized = $this->message->toString(); From 0faa04e6681ad8c597fa26deaf9cfd1202a84fb6 Mon Sep 17 00:00:00 2001 From: John Kelly Date: Tue, 11 Sep 2012 08:21:52 -0700 Subject: [PATCH 045/126] Deprecate getPropertyNames and change to getProperties. --- library/Zend/Code/Scanner/ClassScanner.php | 26 +++++++++---------- .../Code/Scanner/ClassScannerTest.php | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/library/Zend/Code/Scanner/ClassScanner.php b/library/Zend/Code/Scanner/ClassScanner.php index 000b6346bd0..e0183d77c24 100644 --- a/library/Zend/Code/Scanner/ClassScanner.php +++ b/library/Zend/Code/Scanner/ClassScanner.php @@ -207,22 +207,22 @@ public function getConstants() return $return; } + /** + * Returns a list of property names + * + * @deprecated use getProperties() + * @return array + */ public function getPropertyNames() { - $this->scan(); - - $return = array(); - - foreach ($this->infos as $info) { - if ($info['type'] != 'property') { - continue; - } - - $return[] = $info['name']; - } - return $return; + return $this->getProperties(); } + /** + * Returns a list of property names + * + * @return array + */ public function getProperties() { $this->scan(); @@ -234,7 +234,7 @@ public function getProperties() continue; } - $return[] = $this->getProperty($info['name']); + $return[] = $info['name']; } return $return; } diff --git a/tests/ZendTest/Code/Scanner/ClassScannerTest.php b/tests/ZendTest/Code/Scanner/ClassScannerTest.php index c0fdda8d791..3a6c3b38ad0 100644 --- a/tests/ZendTest/Code/Scanner/ClassScannerTest.php +++ b/tests/ZendTest/Code/Scanner/ClassScannerTest.php @@ -44,8 +44,8 @@ public function testClassScannerHasProperties() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); $class = $file->getClass('ZendTest\Code\TestAsset\FooClass'); - $this->assertInternalType('array', $class->getPropertyNames()); - $this->assertContains('bar', $class->getPropertyNames()); + $this->assertInternalType('array', $class->getProperties()); + $this->assertContains('bar', $class->getProperties()); } public function testClassScannerHasMethods() From 4dab8baecbd856d572dd8e759ae1d276e0575f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 11 Sep 2012 17:30:42 +0200 Subject: [PATCH 046/126] Updated for latest master --- library/Zend/Form/View/Helper/FormDateSelect.php | 12 ++++++------ library/Zend/Form/View/Helper/FormMonthSelect.php | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/library/Zend/Form/View/Helper/FormDateSelect.php b/library/Zend/Form/View/Helper/FormDateSelect.php index 543c2dae7bd..70d87c4151a 100644 --- a/library/Zend/Form/View/Helper/FormDateSelect.php +++ b/library/Zend/Form/View/Helper/FormDateSelect.php @@ -56,16 +56,16 @@ public function render(ElementInterface $element) $monthsOptions = $this->getMonthsOptions($pattern['month']); $yearOptions = $this->getYearsOptions($element->getMinYear(), $element->getMaxYear()); - if ($element->shouldCreateEmptyOption()) { - $daysOptions = array('' => '') + $daysOptions; - $monthsOptions = array('' => '') + $monthsOptions; - $yearOptions = array('' => '') + $yearOptions; - } - $dayElement = $element->getDayElement()->setValueOptions($daysOptions); $monthElement = $element->getMonthElement()->setValueOptions($monthsOptions); $yearElement = $element->getYearElement()->setValueOptions($yearOptions); + if ($element->shouldCreateEmptyOption()) { + $dayElement->setEmptyOption(''); + $yearElement->setEmptyOption(''); + $monthElement->setEmptyOption(''); + } + $markup = array(); $markup[$pattern['day']] = $selectHelper->render($dayElement); $markup[$pattern['month']] = $selectHelper->render($monthElement); diff --git a/library/Zend/Form/View/Helper/FormMonthSelect.php b/library/Zend/Form/View/Helper/FormMonthSelect.php index b5e5fba80c9..d022dd27630 100644 --- a/library/Zend/Form/View/Helper/FormMonthSelect.php +++ b/library/Zend/Form/View/Helper/FormMonthSelect.php @@ -88,14 +88,14 @@ public function render(ElementInterface $element) $monthsOptions = $this->getMonthsOptions($pattern['month']); $yearOptions = $this->getYearsOptions($element->getMinYear(), $element->getMaxYear()); - if ($element->shouldCreateEmptyOption()) { - $monthsOptions = array('' => '') + $monthsOptions; - $yearOptions = array('' => '') + $yearOptions; - } - $monthElement = $element->getMonthElement()->setValueOptions($monthsOptions); $yearElement = $element->getYearElement()->setValueOptions($yearOptions); + if ($element->shouldCreateEmptyOption()) { + $monthElement->setEmptyOption(''); + $yearElement->setEmptyOption(''); + } + $markup = array(); $markup[$pattern['month']] = $selectHelper->render($monthElement); $markup[$pattern['year']] = $selectHelper->render($yearElement); From ac1464e04e551ff764130b03ff7dc3a25d28ede7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 12 Sep 2012 11:01:06 +0200 Subject: [PATCH 047/126] Allow to specify attributes per element --- library/Zend/Form/Element/DateSelect.php | 40 ++++++++++++++++ library/Zend/Form/Element/MonthSelect.php | 56 ++++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index 944ae080c01..71a133b4b74 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -37,6 +37,24 @@ public function __construct($name = null, $options = array()) $this->dayElement = new Select('day'); } + /** + * Accepted options for DateSelect (plus the ones from MonthSelect) : + * - day_attributes: HTML attributes to be rendered with the day element + * + * @param array|\Traversable $options + * @return DateSelect + */ + public function setOptions($options) + { + parent::setOptions($options); + + if (isset($options['day_attributes'])) { + $this->setDayAttributes($options['day_attributes']); + } + + return $this; + } + /** * @return Select */ @@ -45,6 +63,28 @@ public function getDayElement() return $this->dayElement; } + /** + * Set the day attributes + * + * @param array $dayAttributes + * @return DateSelect + */ + public function seDayAttributes(array $dayAttributes) + { + $this->dayElement->setAttributes($dayAttributes); + return $this; + } + + /** + * Get the day attributes + * + * @return array + */ + public function getDayAttributes() + { + return $this->dayElement->getAttributes(); + } + /** * @param mixed $value * @return void|\Zend\Form\Element diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php index 5e2d9721cda..de3a6ba5fb9 100644 --- a/library/Zend/Form/Element/MonthSelect.php +++ b/library/Zend/Form/Element/MonthSelect.php @@ -80,16 +80,26 @@ public function __construct($name = null, $options = array()) /** * Accepted options for DateSelect: + * - month_attributes: HTML attributes to be rendered with the month element + * - year_attributes: HTML attributes to be rendered with the month element * - min_year: min year to use in the year select * - max_year: max year to use in the year select * * @param array|\Traversable $options - * @return DateSelect + * @return MonthSelect */ public function setOptions($options) { parent::setOptions($options); + if (isset($options['month_attributes'])) { + $this->setMonthAttributes($options['month_attributes']); + } + + if (isset($options['year_attributes'])) { + $this->setYearAttributes($options['year_attributes']); + } + if (isset($options['min_year'])) { $this->setMinYear($options['min_year']); } @@ -121,6 +131,50 @@ public function getYearElement() return $this->yearElement; } + /** + * Set the month attributes + * + * @param array $monthAttributes + * @return MonthSelect + */ + public function setMonthAttributes(array $monthAttributes) + { + $this->monthElement->setAttributes($monthAttributes); + return $this; + } + + /** + * Get the month attributes + * + * @return array + */ + public function getMonthAttributes() + { + return $this->monthElement->getAttributes(); + } + + /** + * Set the year attributes + * + * @param array $yearAttributes + * @return MonthSelect + */ + public function setYearAttributes(array $yearAttributes) + { + $this->yearElement->setAttributes($yearAttributes); + return $this; + } + + /** + * Get the year attributes + * + * @return array + */ + public function getYearAttributes() + { + return $this->yearElement->getAttributes(); + } + /** * @param int $minYear * @return MonthSelect From cee8b1ded76ee1ca5b7a16d04fa1e2082618f162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 12 Sep 2012 11:03:08 +0200 Subject: [PATCH 048/126] Fix typo --- library/Zend/Form/Element/DateSelect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index 71a133b4b74..5b0fbb2527e 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -69,7 +69,7 @@ public function getDayElement() * @param array $dayAttributes * @return DateSelect */ - public function seDayAttributes(array $dayAttributes) + public function setDayAttributes(array $dayAttributes) { $this->dayElement->setAttributes($dayAttributes); return $this; From d556b6fd22e30f09cf957fd9973370e45c266b31 Mon Sep 17 00:00:00 2001 From: John Kelly Date: Wed, 12 Sep 2012 09:14:17 -0700 Subject: [PATCH 049/126] Undo deprecation and implement PropertyScanner --- library/Zend/Code/Scanner/ClassScanner.php | 53 +++- library/Zend/Code/Scanner/MethodScanner.php | 2 +- library/Zend/Code/Scanner/PropertyScanner.php | 284 ++++++++++++++++++ .../Code/Scanner/ClassScannerTest.php | 17 +- .../Code/Scanner/PropertyScannerTest.php | 47 +++ tests/ZendTest/Code/TestAsset/FooClass.php | 8 + 6 files changed, 402 insertions(+), 9 deletions(-) create mode 100644 tests/ZendTest/Code/Scanner/PropertyScannerTest.php diff --git a/library/Zend/Code/Scanner/ClassScanner.php b/library/Zend/Code/Scanner/ClassScanner.php index e0183d77c24..bdc413bca29 100644 --- a/library/Zend/Code/Scanner/ClassScanner.php +++ b/library/Zend/Code/Scanner/ClassScanner.php @@ -210,16 +210,26 @@ public function getConstants() /** * Returns a list of property names * - * @deprecated use getProperties() * @return array */ public function getPropertyNames() { - return $this->getProperties(); + $this->scan(); + + $return = array(); + + foreach ($this->infos as $info) { + if ($info['type'] != 'property') { + continue; + } + + $return[] = $info['name']; + } + return $return; } /** - * Returns a list of property names + * Returns a list of properties * * @return array */ @@ -234,11 +244,46 @@ public function getProperties() continue; } - $return[] = $info['name']; + $return[] = $this->getProperty($info['name']); } return $return; } + public function getProperty($propertyNameOrInfoIndex) + { + $this->scan(); + + if (is_int($propertyNameOrInfoIndex)) { + $info = $this->infos[$propertyNameOrInfoIndex]; + if ($info['type'] != 'property') { + throw new Exception\InvalidArgumentException('Index of info offset is not about a property'); + } + } elseif (is_string($propertyNameOrInfoIndex)) { + $propertyFound = false; + foreach ($this->infos as $info) { + if ($info['type'] === 'property' && $info['name'] === $propertyNameOrInfoIndex) { + $propertyFound = true; + break; + } + } + if (!$propertyFound) { + return false; + } + } else { + throw new Exception\InvalidArgumentException('Invalid property name of info index type. Must be of type int or string'); + } + if (!isset($info)) { + return false; + } + $p = new PropertyScanner( + array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1), + $this->nameInformation + ); + $p->setClass($this->name); + $p->setScannerClass($this); + return $p; + } + public function getMethodNames() { $this->scan(); diff --git a/library/Zend/Code/Scanner/MethodScanner.php b/library/Zend/Code/Scanner/MethodScanner.php index d7c3ca90f26..e093bfa2ae0 100644 --- a/library/Zend/Code/Scanner/MethodScanner.php +++ b/library/Zend/Code/Scanner/MethodScanner.php @@ -84,7 +84,7 @@ public function getDocComment() /** * @param Annotation\AnnotationManager $annotationManager - * @return Annotation\AnnotationCollection + * @return AnnotationScanner */ public function getAnnotations(Annotation\AnnotationManager $annotationManager) { diff --git a/library/Zend/Code/Scanner/PropertyScanner.php b/library/Zend/Code/Scanner/PropertyScanner.php index b3d9bbc7f37..ffc1a0c02fb 100644 --- a/library/Zend/Code/Scanner/PropertyScanner.php +++ b/library/Zend/Code/Scanner/PropertyScanner.php @@ -1 +1,285 @@ tokens = $propertyTokens; + $this->nameInformation = $nameInformation; + } + + /** + * @param string $class + */ + public function setClass($class) + { + $this->class = $class; + } + + /** + * @param ClassScanner $scannerClass + */ + public function setScannerClass(ClassScanner $scannerClass) + { + $this->scannerClass = $scannerClass; + } + + /** + * @return ClassScanner + */ + public function getClassScanner() + { + return $this->scannerClass; + } + + /** + * @return string + */ + public function getName() + { + $this->scan(); + return $this->name; + } + + /** + * @return bool + */ + public function isPublic() + { + $this->scan(); + return $this->isPublic; + } + + /** + * @return bool + */ + public function isPrivate() + { + $this->scan(); + return $this->isPrivate; + } + + /** + * @return bool + */ + public function isProtected() + { + $this->scan(); + return $this->isProtected; + } + + /** + * @return bool + */ + public function isStatic() + { + $this->scan(); + return $this->isStatic; + } + + /** + * @return string + */ + public function getValue() + { + $this->scan(); + return $this->value; + } + + /** + * @return string + */ + public function getDocComment() + { + $this->scan(); + return $this->docComment; + } + + /** + * @param Annotation\AnnotationManager $annotationManager + * @return AnnotationScanner + */ + public function getAnnotations(Annotation\AnnotationManager $annotationManager) + { + if (($docComment = $this->getDocComment()) == '') { + return false; + } + + return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); + } + + /** + * @return string + */ + public function __toString() + { + $this->scan(); + return var_export($this, true); + } + + /** + * Scan tokens + * + * @throws \Zend\Code\Exception\RuntimeException + */ + protected function scan() + { + if ($this->isScanned) { + return; + } + + if (!$this->tokens) { + throw new Exception\RuntimeException('No tokens were provided'); + } + + /** + * Variables & Setup + */ + $tokens = &$this->tokens; + + reset($tokens); + + SCANNER_TOP: + + $token = current($tokens); + + if (!is_string($token)) { + list($tokenType, $tokenContent, $tokenLine) = $token; + + switch ($tokenType) { + case T_DOC_COMMENT: + if ($this->docComment === null && $this->name === null) { + $this->docComment = $tokenContent; + } + goto SCANNER_CONTINUE; + + case T_VARIABLE: + $this->name = ltrim($tokenContent, '$'); + goto SCANNER_CONTINUE; + + case T_PUBLIC: + // use defaults + goto SCANNER_CONTINUE; + + case T_PROTECTED: + $this->isProtected = true; + $this->isPublic = false; + goto SCANNER_CONTINUE; + + case T_PRIVATE: + $this->isPrivate = true; + $this->isPublic = false; + goto SCANNER_CONTINUE; + + case T_STATIC: + $this->isStatic = true; + goto SCANNER_CONTINUE; + + default: + if ($this->name !== null && trim($tokenContent) !== '') { + $this->value .= (is_string($token)) ? $token : $tokenContent; + if (substr($this->value, 0, 1) === '"' || substr($this->value, 0, 1) === "'") { + $this->value = substr($this->value, 1, -1); // Remove quotes + } + } + goto SCANNER_CONTINUE; + } + } + + SCANNER_CONTINUE: + + if (next($this->tokens) === false) { + goto SCANNER_END; + } + goto SCANNER_TOP; + + SCANNER_END: + + $this->isScanned = true; + } +} \ No newline at end of file diff --git a/tests/ZendTest/Code/Scanner/ClassScannerTest.php b/tests/ZendTest/Code/Scanner/ClassScannerTest.php index 3a6c3b38ad0..0268202e2f1 100644 --- a/tests/ZendTest/Code/Scanner/ClassScannerTest.php +++ b/tests/ZendTest/Code/Scanner/ClassScannerTest.php @@ -44,8 +44,7 @@ public function testClassScannerHasProperties() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); $class = $file->getClass('ZendTest\Code\TestAsset\FooClass'); - $this->assertInternalType('array', $class->getProperties()); - $this->assertContains('bar', $class->getProperties()); + $this->assertContains('bar', $class->getPropertyNames()); } public function testClassScannerHasMethods() @@ -59,12 +58,22 @@ public function testClassScannerReturnsMethodsWithMethodScanners() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); $class = $file->getClass('ZendTest\Code\TestAsset\FooClass'); - $methods = $class->getMethods(true); + $methods = $class->getMethods(); foreach ($methods as $method) { $this->assertInstanceOf('Zend\Code\Scanner\MethodScanner', $method); } } + public function testClassScannerReturnsPropertiesWithPropertyScanners() + { + $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); + $class = $file->getClass('ZendTest\Code\TestAsset\FooClass'); + $properties = $class->getProperties(); + foreach ($properties as $property) { + $this->assertInstanceOf('Zend\Code\Scanner\PropertyScanner', $property); + } + } + public function testClassScannerCanScanInterface() { $file = new FileScanner(__DIR__ . '/../TestAsset/FooInterface.php'); @@ -77,7 +86,7 @@ public function testClassScannerCanReturnLineNumbers() $file = new FileScanner(__DIR__ . '/../TestAsset/FooClass.php'); $class = $file->getClass('ZendTest\Code\TestAsset\FooClass'); $this->assertEquals(11, $class->getLineStart()); - $this->assertEquals(23, $class->getLineEnd()); + $this->assertEquals(31, $class->getLineEnd()); $file = new FileScanner(__DIR__ . '/../TestAsset/BarClass.php'); $class = $file->getClass('ZendTest\Code\TestAsset\BarClass'); diff --git a/tests/ZendTest/Code/Scanner/PropertyScannerTest.php b/tests/ZendTest/Code/Scanner/PropertyScannerTest.php new file mode 100644 index 00000000000..fc9754ad384 --- /dev/null +++ b/tests/ZendTest/Code/Scanner/PropertyScannerTest.php @@ -0,0 +1,47 @@ +getClass('ZendTest\Code\TestAsset\FooClass'); + + $property = $class->getProperty('bar'); + $this->assertEquals('bar', $property->getName()); + $this->assertEquals('value', $property->getValue()); + $this->assertFalse($property->isPublic()); + $this->assertTrue($property->isProtected()); + $this->assertFalse($property->isPrivate()); + $this->assertTrue($property->isStatic()); + + $property = $class->getProperty('foo'); + $this->assertEquals('foo', $property->getName()); + $this->assertEquals('value2', $property->getValue()); + $this->assertTrue($property->isPublic()); + $this->assertFalse($property->isProtected()); + $this->assertFalse($property->isPrivate()); + $this->assertFalse($property->isStatic()); + + $property = $class->getProperty('baz'); + $this->assertEquals('baz', $property->getName()); + $this->assertEquals(3, $property->getValue()); + $this->assertFalse($property->isPublic()); + $this->assertFalse($property->isProtected()); + $this->assertTrue($property->isPrivate()); + $this->assertFalse($property->isStatic()); + } +} diff --git a/tests/ZendTest/Code/TestAsset/FooClass.php b/tests/ZendTest/Code/TestAsset/FooClass.php index a0c47725d19..ee883d975bf 100644 --- a/tests/ZendTest/Code/TestAsset/FooClass.php +++ b/tests/ZendTest/Code/TestAsset/FooClass.php @@ -14,6 +14,14 @@ abstract class FooClass implements \ArrayAccess, E\Blarg, Local\SubClass const FOO = self::BAR; protected static $bar = 'value'; + public $foo = 'value2'; + + /** + * Test comment + * + * @var int + */ + private $baz = 3; final public function fooBarBaz() { From 35d19306b21772a15bcb464cf9473890f946226d Mon Sep 17 00:00:00 2001 From: mikestowe Date: Wed, 12 Sep 2012 15:34:15 -0500 Subject: [PATCH 050/126] Updated international float to return true if values are equal as previously string(5.00) did not equal int(5) after it was parsed --- library/Zend/I18n/Validator/Float.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/I18n/Validator/Float.php b/library/Zend/I18n/Validator/Float.php index db16805fb54..3fc9d0166f5 100644 --- a/library/Zend/I18n/Validator/Float.php +++ b/library/Zend/I18n/Validator/Float.php @@ -123,7 +123,7 @@ public function isValid($value) $valueFiltered = str_replace($groupingSep, '', $value); $valueFiltered = str_replace($decimalSep, '.', $valueFiltered); - if (strval($parsedFloat) !== $valueFiltered) { + if (strval($parsedFloat) != $valueFiltered) { $this->error(self::NOT_FLOAT); return false; } From 4936bc265a46922bc3d12fbe97c6af37bee0f244 Mon Sep 17 00:00:00 2001 From: mikestowe Date: Wed, 12 Sep 2012 16:06:19 -0500 Subject: [PATCH 051/126] Added test case for string('5.00') --- tests/ZendTest/I18n/Validator/FloatTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ZendTest/I18n/Validator/FloatTest.php b/tests/ZendTest/I18n/Validator/FloatTest.php index 83478945466..0ebec2923cb 100644 --- a/tests/ZendTest/I18n/Validator/FloatTest.php +++ b/tests/ZendTest/I18n/Validator/FloatTest.php @@ -59,6 +59,7 @@ public function basicProvider() array(0.01, true), array(-0.1, true), array('10.1', true), + array('5.00', true), array(1, true), array('10.1not a float', false), ); From eb9850e3c9d9cb67f35f8bc8fb73f9c8892274e0 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 13 Sep 2012 13:46:03 -0500 Subject: [PATCH 052/126] [#2333] Add todo annotation - Added @todo annotation so it's discoverable via API docs --- library/Zend/Mail/Message.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/Zend/Mail/Message.php b/library/Zend/Mail/Message.php index 37f3866f26e..48137841809 100644 --- a/library/Zend/Mail/Message.php +++ b/library/Zend/Mail/Message.php @@ -539,6 +539,7 @@ public function toString() /** * Instantiate from raw message string * + * @todo Restore body to Mime\Message * @param string $rawMessage * @return Message */ @@ -549,7 +550,7 @@ public static function fromString($rawMessage) $content = null; Mime\Decode::splitMessage($rawMessage, $headers, $content); if ($headers->has('mime-version')) { - // @todo restore body to mime\message + // todo - restore body to mime\message } $message->setHeaders($headers); $message->setBody($content); From 03145847f1646d956e99034418aab914dffba54c Mon Sep 17 00:00:00 2001 From: Eric Boh Date: Thu, 13 Sep 2012 21:40:42 +0200 Subject: [PATCH 053/126] Removed remains of old Zend test folder. --- tests/Zend/Loader/_files/BarModule/Module.php | 15 --- tests/Zend/Loader/_files/PharModuleMap.phar | Bin 6824 -> 0 bytes .../Listener/ModuleLoaderListenerTest.php | 96 ------------------ 3 files changed, 111 deletions(-) delete mode 100644 tests/Zend/Loader/_files/BarModule/Module.php delete mode 100644 tests/Zend/Loader/_files/PharModuleMap.phar delete mode 100644 tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php diff --git a/tests/Zend/Loader/_files/BarModule/Module.php b/tests/Zend/Loader/_files/BarModule/Module.php deleted file mode 100644 index dfd18098c5f..00000000000 --- a/tests/Zend/Loader/_files/BarModule/Module.php +++ /dev/null @@ -1,15 +0,0 @@ -}qZ?|N)n z9 zgCw)qvwhZS7?vx(SvkMXTS?&fkwwI6YLZkkZ*5hPz1*uJ&#Q<*JgXw7Q6)LQ&a1eu zvr2*nSWCK8d50XU+$%Dc#2jBrW_rV^cy~t6F z;#u-=MG=-HktmPlri3a$@hKu%r6-=+f^sNCgsMarj|`rcpk`MU64^X!HGv${~;CoKaYY@^h{nVL-&XSp)8Ro>vc;ti}XJ3D{byo!g z_4xbf=}DYbbR*Hv&_K1M=rQix^HY1Z)0jCA6H+G|xoElNzG)^o9LN?EnA&XTr~ARS zXb=TFvP-_HXvh{dO)`ll+OlW@Ne5^W6bZ9l4~P9$d%MjZ?zGuSe91l5=V|CfJj#O` zYnfW>IF?7G%V;RAw_}kfJdra5wjhf^nA6BG9Yl_q8HnLlkv7PE`)1HP!c_ai%7Bx4 z#126TLQ)|k{j{UD>0m$hG_^vr*e+EbI@%rfXy*}o8|Un0yofxClDqSm)%K|I?Ef)h zdn7?$*k11E0pF)_y_8TyVr*&7y-DodNRfGapA0makgB10lDxrcCHWRugtQWZ8nRp~ zrHsG`rOS_|F@>piRt?q3$ik%JQHG|4NlM$RgQOFK-D?hS65eH{fmYf~&2!A7Sw5Fr zIz@8s5-{PD&%cwsm*b#yH zvw493`FP#G>Lj3IH@Nfv$O#~kzIZbF8Cuk|UJvNw?PUwJ4GtMt;umJw@VA}1%0LbPsL>5uvxEHo{ z4s0xrx;^nDC%vgpsfeV|BSNNT2yXq*B7E(|s08@pczE)({Y^)fxp_QlzsCX64KAcZ zPLD+&Q|#+ZqSs(_QKQvnNM;MktVT;eVRO zX_wsw{)81BhWQ!hZ_Y49Cjmx8lY+2VA#c~2R?Z^MJ+MsUR48e>ahRkWEyH8DR5@uT zgHrd1lBX#9&8|*vJ+3vadpo)Hlg?+|E$i6e@#MDiBMys`TP287HF{1AK z8SaICPPwurDiCFxAqzNt)YOF%u^MN06?3poCWB2C9R#nl0(;2ILZYU(5NVTdBOAsxzE&+y(eB zOkUE|l~vLxJp6GN55$%wi+qe$PorMR7vO8%G}<`j$-t@P0MV!uYAGWtwB9o`B~#Yq zJ~K(RC{{vjE72lh5^<@hHO@mdQ)^c#{V}dPnRWw?Zh)yMV103pgfAoAA<3~i1_7qQ z63CXfuLxSmNfU7A6XTd_XlkF!l@gQNqRNf-#8wYPMljZl7MPHySV))Z0alBmh8pw*d44pdB!}{nAYVTt zB}%90Tv{m^SalE=fJzsXbXhaGL5kLrRho?iXw=*+;}d=V3bA1gCQu2G06f{i)Ye=A zyOgBck8lAq1Ks-SRID)G0e<9x z1uwpBZBfQyoJZi;U{;z@Au5|&FuDstnmKw5srxAMp(RMK4okQSF-3zgW71i)j!~fq zr&GRG8{<~KKtn5>a$4t;*16j{_gd$?b&j_O#TB?@vV)DFG>SB=Y92i# zzFH8-tmZQw07*~P-zIfWNSztOSj;G}DpeiY61h!a>4=T0;`@4K>ppJK_UL_q#t6oj zP6QdRtmCRighrp<$WBDHjaMJkqX|WuE`=nXkH~dHAzITFt%fdRZW%udQOwwbGB$Q8 zVWbEpT69kkni`i&i+98XCZ`ZIo|9gbLY4qjySs#pf&!b;mgre)vI-Jv;S~T^$ge_j zijDfA&c_bkMN4R2dlQLQMoheekDNf_QAQI2s0%k=#tHo5qP|^RJfym9(4Z0zL|Nn` z6cK23dcCw7IEodFx>{>rEpYpHQ})6vPCG})W%Ulcrnj} zTH(#z%ig#eYnTcc(arD9uqsf(EQlwz^&9kj0tr)HO=701A2~o3WQ7yK^PC-|p@3Id zblJfo3jBz!jz|`5^BrmW*+ipEscQp7ny%m@HDMbCcsM>fJ?Z23mH|lY`Tj4Ar}ysN`x*ZKN`2x3e+K?9e<^BX^_PGBx=)`+e;ywF zodoc=M?Wnw!yw?4;f~B1{iY)2P8?uV_2NKMj1Qmw^Ur_$GXLV6FaLY~*MI-*_h0^e P^uXa?K+&rgCold7N1__B diff --git a/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php b/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php deleted file mode 100644 index cc654093d0e..00000000000 --- a/tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php +++ /dev/null @@ -1,96 +0,0 @@ -tmpdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zend_module_cache_dir'; - @mkdir($this->tmpdir); - - $this->moduleManager = new ModuleManager(array()); - $this->moduleManager->getEventManager()->attach('loadModule.resolve', new ModuleResolverListener, 1000); - } - - public function tearDown() - { - $file = glob($this->tmpdir . DIRECTORY_SEPARATOR . '*'); - @unlink($file[0]); // change this if there's ever > 1 file - @rmdir($this->tmpdir); - } - - public function testModuleLoaderListenerFunctionsAsAggregateListenerEnabledCache() - { - $options = new ListenerOptions(array( - 'cache_dir' => $this->tmpdir, - 'module_map_cache_enabled' => true, - 'module_map_cache_key' => 'foo', - )); - - $moduleLoaderListener = new ModuleLoaderListener($options); - - $moduleManager = $this->moduleManager; - $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - - $moduleLoaderListener->attach($moduleManager->getEventManager()); - $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - } - - public function testModuleLoaderListenerFunctionsAsAggregateListenerDisabledCache() - { - $options = new ListenerOptions(array( - 'cache_dir' => $this->tmpdir, - )); - - $moduleLoaderListener = new ModuleLoaderListener($options); - - $moduleManager = $this->moduleManager; - $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - - $moduleLoaderListener->attach($moduleManager->getEventManager()); - $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - } - - public function testModuleLoaderListenerFunctionsAsAggregateListenerHasCache() - { - $options = new ListenerOptions(array( - 'cache_dir' => $this->tmpdir, - 'module_map_cache_key' => 'foo', - 'module_map_cache_enabled' => true, - )); - - file_put_contents($options->getModuleMapCacheFile(), 'moduleManager; - $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - - $moduleLoaderListener->attach($moduleManager->getEventManager()); - $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES))); - $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST))); - } -} From 954e09c3820ee845dd4fabd252824b9286f16824 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 14 Sep 2012 13:28:45 -0500 Subject: [PATCH 054/126] [#2080] CS fixes - Trailing whitespace --- tests/ZendTest/Log/Writer/ChromePhpTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ZendTest/Log/Writer/ChromePhpTest.php b/tests/ZendTest/Log/Writer/ChromePhpTest.php index 2540637549a..52784fb10c6 100644 --- a/tests/ZendTest/Log/Writer/ChromePhpTest.php +++ b/tests/ZendTest/Log/Writer/ChromePhpTest.php @@ -43,13 +43,13 @@ public function setUp() $this->chromephp = new MockChromePhp(); } - + public function testGetChromePhp() { $writer = new ChromePhp($this->chromephp); $this->assertTrue($writer->getChromePhp() instanceof ChromePhpInterface); } - + public function testSetChromePhp() { $writer = new ChromePhp($this->chromephp); @@ -59,7 +59,7 @@ public function testSetChromePhp() $this->assertTrue($writer->getChromePhp() instanceof ChromePhpInterface); $this->assertEquals($chromephp2, $writer->getChromePhp()); } - + public function testWrite() { $writer = new ChromePhp($this->chromephp); @@ -69,7 +69,7 @@ public function testWrite() )); $this->assertEquals('my msg', $this->chromephp->calls['trace'][0]); } - + public function testWriteDisabled() { $chromephp = new MockChromePhp(false); From 9f8c7049fc4ae413819fe916cf59912dea8b3c87 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 14 Sep 2012 16:26:34 -0500 Subject: [PATCH 055/126] [#2125] CS fixes - Trailing whitespace --- library/Zend/Stdlib/Hydrator/AbstractHydrator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php index 44e77ba0da9..8c8e94a9a76 100644 --- a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php +++ b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php @@ -58,7 +58,7 @@ public function getStrategy($name) */ public function hasStrategy($name) { - return array_key_exists($name, $this->strategies) + return array_key_exists($name, $this->strategies) || array_key_exists('*', $this->strategies); } From 48955452f3cc00598e62ffdf54dda940cb4bd7d4 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 14 Sep 2012 16:29:40 -0500 Subject: [PATCH 056/126] [#2125] Ensure we have a wildcard strategy before attempting to return it --- library/Zend/Stdlib/Hydrator/AbstractHydrator.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php index 8c8e94a9a76..35e81171377 100644 --- a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php +++ b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php @@ -11,6 +11,7 @@ namespace Zend\Stdlib\Hydrator; use ArrayObject; +use Zend\Stdlib\Exception; use Zend\Stdlib\Hydrator\StrategyEnabledInterface; use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; @@ -44,9 +45,18 @@ public function __construct() */ public function getStrategy($name) { - if(isset($this->strategies[$name])) { + if (isset($this->strategies[$name])) { return $this->strategies[$name]; } + + if (!isset($this->strategies['*'])) { + throw new Exception\InvalidArgumentException(sprintf( + '%s: no strategy by name of "%s", and no wildcard strategy present', + __METHOD__, + $name + )); + } + return $this->strategies['*']; } @@ -59,7 +69,7 @@ public function getStrategy($name) public function hasStrategy($name) { return array_key_exists($name, $this->strategies) - || array_key_exists('*', $this->strategies); + || array_key_exists('*', $this->strategies); } /** From cb00ba81959bb2242064db20294ab32672d92c3d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 14 Sep 2012 16:39:58 -0500 Subject: [PATCH 057/126] [#2212] Added suggest to composer.json - added zend-uri as a suggested requirement --- library/Zend/Filter/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/Zend/Filter/composer.json b/library/Zend/Filter/composer.json index b9928d99b19..5853125eb68 100644 --- a/library/Zend/Filter/composer.json +++ b/library/Zend/Filter/composer.json @@ -20,7 +20,8 @@ }, "suggest": { "zendframework/zend-i18n": "Zend\\I18n component", + "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter", "zendframework/zend-validator": "Zend\\Validator component", "zendframework/zend-crypt": "Zend\\Crypt component" } -} \ No newline at end of file +} From ec6b927908b3248d9393cbf297bfcfce72efc2b0 Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Sat, 15 Sep 2012 14:13:18 +0200 Subject: [PATCH 058/126] Convert abstract classes that are only offering static methods To respect recommanation : "For classes that are only offering static methods, we typically recommend making them abstract." --- library/Zend/Barcode/Barcode.php | 2 +- library/Zend/Cache/PatternFactory.php | 2 +- library/Zend/Cache/StorageFactory.php | 2 +- library/Zend/Math/BigInteger/BigInteger.php | 2 +- library/Zend/Serializer/Serializer.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/Zend/Barcode/Barcode.php b/library/Zend/Barcode/Barcode.php index 35911e80830..31f464640c4 100644 --- a/library/Zend/Barcode/Barcode.php +++ b/library/Zend/Barcode/Barcode.php @@ -20,7 +20,7 @@ * @category Zend * @package Zend_Barcode */ -class Barcode +abstract class Barcode { const OBJECT = 'OBJECT'; const RENDERER = 'RENDERER'; diff --git a/library/Zend/Cache/PatternFactory.php b/library/Zend/Cache/PatternFactory.php index 5a9de1bc924..66b8357f2cd 100644 --- a/library/Zend/Cache/PatternFactory.php +++ b/library/Zend/Cache/PatternFactory.php @@ -17,7 +17,7 @@ * @category Zend * @package Zend_Cache */ -class PatternFactory +abstract class PatternFactory { /** * The pattern manager diff --git a/library/Zend/Cache/StorageFactory.php b/library/Zend/Cache/StorageFactory.php index a55227c2990..74dea32e72c 100644 --- a/library/Zend/Cache/StorageFactory.php +++ b/library/Zend/Cache/StorageFactory.php @@ -18,7 +18,7 @@ * @package Zend_Cache * @subpackage Storage */ -class StorageFactory +abstract class StorageFactory { /** * Plugin manager for loading adapters diff --git a/library/Zend/Math/BigInteger/BigInteger.php b/library/Zend/Math/BigInteger/BigInteger.php index ff7ab4cdd2b..052ed1252ab 100644 --- a/library/Zend/Math/BigInteger/BigInteger.php +++ b/library/Zend/Math/BigInteger/BigInteger.php @@ -15,7 +15,7 @@ * @package Zend_Math * @subpackage BigInteger */ -class BigInteger +abstract class BigInteger { /** * Plugin manager for loading adapters diff --git a/library/Zend/Serializer/Serializer.php b/library/Zend/Serializer/Serializer.php index af49627296c..7d7013894e3 100644 --- a/library/Zend/Serializer/Serializer.php +++ b/library/Zend/Serializer/Serializer.php @@ -16,7 +16,7 @@ * @category Zend * @package Zend_Serializer */ -class Serializer +abstract class Serializer { /** * Plugin manager for loading adapters From 9eaa305825f82730f98ebd76a188a33c10bf3ac0 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 17 Sep 2012 10:34:19 -0500 Subject: [PATCH 059/126] Updated version for develop branch - Reflects upcoming 2.1.0 minor release --- library/Zend/Version/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/Version/Version.php b/library/Zend/Version/Version.php index 558c6c26076..778dc34dfd4 100644 --- a/library/Zend/Version/Version.php +++ b/library/Zend/Version/Version.php @@ -23,7 +23,7 @@ final class Version /** * Zend Framework version identification - see compareVersion() */ - const VERSION = '2.0.1'; + const VERSION = '2.1.0dev'; /** * Github Service Identifier for version information is retreived from From 3deacae059b71d12287bc6a050c859189d2f8245 Mon Sep 17 00:00:00 2001 From: Christian Gahlert Date: Mon, 17 Sep 2012 18:46:50 +0200 Subject: [PATCH 060/126] Modified Zend Acl/Navigation to be extendable. --- library/Zend/Permissions/Acl/Acl.php | 2 +- library/Zend/Permissions/Acl/AclInterface.php | 58 +++++++++++++++++++ .../View/Helper/Navigation/AbstractHelper.php | 16 ++--- .../Helper/Navigation/HelperInterface.php | 8 +-- 4 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 library/Zend/Permissions/Acl/AclInterface.php diff --git a/library/Zend/Permissions/Acl/Acl.php b/library/Zend/Permissions/Acl/Acl.php index 30eab0cdbb4..eb287e58ab1 100644 --- a/library/Zend/Permissions/Acl/Acl.php +++ b/library/Zend/Permissions/Acl/Acl.php @@ -15,7 +15,7 @@ * @package Zend_Permissions * @subpackage Acl */ -class Acl +class Acl implements AclInterface { /** * Rule type: allow diff --git a/library/Zend/Permissions/Acl/AclInterface.php b/library/Zend/Permissions/Acl/AclInterface.php new file mode 100644 index 00000000000..9d61e68c898 --- /dev/null +++ b/library/Zend/Permissions/Acl/AclInterface.php @@ -0,0 +1,58 @@ +allow()). + * + * If a $privilege is not provided, then this method returns false if and only if the + * Role is denied access to at least one privilege upon the Resource. In other words, this + * method returns true if and only if the Role is allowed all privileges on the Resource. + * + * This method checks Role inheritance using a depth-first traversal of the Role registry. + * The highest priority parent (i.e., the parent most recently added) is checked first, + * and its respective parents are checked similarly before the lower-priority parents of + * the Role are checked. + * + * @param Role\RoleInterface|string $role + * @param Resource\ResourceInterface|string $resource + * @param string $privilege + * @return boolean + */ + public function isAllowed($role = null, $resource = null, $privilege = null); + +} \ No newline at end of file diff --git a/library/Zend/View/Helper/Navigation/AbstractHelper.php b/library/Zend/View/Helper/Navigation/AbstractHelper.php index 65203d96124..824bfc0611f 100644 --- a/library/Zend/View/Helper/Navigation/AbstractHelper.php +++ b/library/Zend/View/Helper/Navigation/AbstractHelper.php @@ -15,7 +15,7 @@ use Zend\I18n\Translator\TranslatorAwareInterface; use Zend\Navigation; use Zend\Navigation\Page\AbstractPage; -use Zend\Permissions\Acl; +use Zend\Permissions\AclInterface; use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View; @@ -69,7 +69,7 @@ abstract class AbstractHelper extends View\Helper\AbstractHtmlElement implements /** * ACL to use when iterating pages * - * @var Acl\Acl + * @var Acl\AclInterface */ protected $acl; @@ -119,7 +119,7 @@ abstract class AbstractHelper extends View\Helper\AbstractHtmlElement implements * Default ACL to use when iterating pages if not explicitly set in the * instance by calling {@link setAcl()} * - * @var Acl\Acl + * @var Acl\AclInterface */ protected static $defaultAcl; @@ -316,10 +316,10 @@ public function getIndent() * * Implements {@link HelperInterface::setAcl()}. * - * @param Acl\Acl $acl [optional] ACL object. Default is null. + * @param Acl\AclInterface $acl [optional] ACL object. Default is null. * @return AbstractHelper fluent interface, returns self */ - public function setAcl(Acl\Acl $acl = null) + public function setAcl(Acl\AclInterface $acl = null) { $this->acl = $acl; return $this; @@ -331,7 +331,7 @@ public function setAcl(Acl\Acl $acl = null) * * Implements {@link HelperInterface::getAcl()}. * - * @return Acl\Acl|null ACL object or null + * @return Acl\AclInterface|null ACL object or null */ public function getAcl() { @@ -844,11 +844,11 @@ protected function normalizeId($value) /** * Sets default ACL to use if another ACL is not explicitly set * - * @param Acl\Acl $acl [optional] ACL object. Default is null, which + * @param Acl\AclInterface $acl [optional] ACL object. Default is null, which * sets no ACL object. * @return void */ - public static function setDefaultAcl(Acl\Acl $acl = null) + public static function setDefaultAcl(Acl\AclInterface $acl = null) { self::$defaultAcl = $acl; } diff --git a/library/Zend/View/Helper/Navigation/HelperInterface.php b/library/Zend/View/Helper/Navigation/HelperInterface.php index eb64181b13f..2c65978d614 100644 --- a/library/Zend/View/Helper/Navigation/HelperInterface.php +++ b/library/Zend/View/Helper/Navigation/HelperInterface.php @@ -12,7 +12,7 @@ use Zend\I18n\Translator\Translator; use Zend\Navigation; -use Zend\Permissions\Acl; +use Zend\Permissions\AclInterface; use Zend\View\Helper\HelperInterface as BaseHelperInterface; /** @@ -45,16 +45,16 @@ public function getContainer(); /** * Sets ACL to use when iterating pages * - * @param Acl\Acl $acl [optional] ACL instance + * @param Acl\AclInterface $acl [optional] ACL instance * @return HelperInterface fluent interface, returns self */ - public function setAcl(Acl\Acl $acl = null); + public function setAcl(Acl\AclInterface $acl = null); /** * Returns ACL or null if it isn't set using {@link setAcl()} or * {@link setDefaultAcl()} * - * @return Acl\Acl|null ACL object or null + * @return Acl\AclInterface|null ACL object or null */ public function getAcl(); From 4510500f822c842d25c906a903e17fbfa6fbdc7a Mon Sep 17 00:00:00 2001 From: Christian Gahlert Date: Mon, 17 Sep 2012 19:26:09 +0200 Subject: [PATCH 061/126] Fixed wrong imports. All unit tests seem to pass. --- library/Zend/View/Helper/Navigation/AbstractHelper.php | 2 +- library/Zend/View/Helper/Navigation/HelperInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Zend/View/Helper/Navigation/AbstractHelper.php b/library/Zend/View/Helper/Navigation/AbstractHelper.php index 824bfc0611f..8c97074d3e1 100644 --- a/library/Zend/View/Helper/Navigation/AbstractHelper.php +++ b/library/Zend/View/Helper/Navigation/AbstractHelper.php @@ -15,7 +15,7 @@ use Zend\I18n\Translator\TranslatorAwareInterface; use Zend\Navigation; use Zend\Navigation\Page\AbstractPage; -use Zend\Permissions\AclInterface; +use Zend\Permissions\Acl; use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View; diff --git a/library/Zend/View/Helper/Navigation/HelperInterface.php b/library/Zend/View/Helper/Navigation/HelperInterface.php index 2c65978d614..080bd675b81 100644 --- a/library/Zend/View/Helper/Navigation/HelperInterface.php +++ b/library/Zend/View/Helper/Navigation/HelperInterface.php @@ -12,7 +12,7 @@ use Zend\I18n\Translator\Translator; use Zend\Navigation; -use Zend\Permissions\AclInterface; +use Zend\Permissions\Acl; use Zend\View\Helper\HelperInterface as BaseHelperInterface; /** From 60fca598128a6ef9d09f9178cf095a54ce51923b Mon Sep 17 00:00:00 2001 From: Christian Gahlert Date: Mon, 17 Sep 2012 19:38:08 +0200 Subject: [PATCH 062/126] Fixed spaces/braces. --- library/Zend/Permissions/Acl/AclInterface.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Zend/Permissions/Acl/AclInterface.php b/library/Zend/Permissions/Acl/AclInterface.php index 9d61e68c898..d738ffe83bd 100644 --- a/library/Zend/Permissions/Acl/AclInterface.php +++ b/library/Zend/Permissions/Acl/AclInterface.php @@ -1,4 +1,5 @@ Date: Mon, 17 Sep 2012 19:42:26 +0200 Subject: [PATCH 063/126] And removed another additional line feed... :( --- library/Zend/Permissions/Acl/AclInterface.php | 1 - 1 file changed, 1 deletion(-) diff --git a/library/Zend/Permissions/Acl/AclInterface.php b/library/Zend/Permissions/Acl/AclInterface.php index d738ffe83bd..b390aac0885 100644 --- a/library/Zend/Permissions/Acl/AclInterface.php +++ b/library/Zend/Permissions/Acl/AclInterface.php @@ -1,5 +1,4 @@ Date: Mon, 17 Sep 2012 20:01:33 +0200 Subject: [PATCH 064/126] Changed CRLF linefeeds to LF. Stupid netbeans! --- library/Zend/Permissions/Acl/AclInterface.php | 112 +++++++++--------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/library/Zend/Permissions/Acl/AclInterface.php b/library/Zend/Permissions/Acl/AclInterface.php index b390aac0885..93beb4b341a 100644 --- a/library/Zend/Permissions/Acl/AclInterface.php +++ b/library/Zend/Permissions/Acl/AclInterface.php @@ -1,57 +1,57 @@ -allow()). - * - * If a $privilege is not provided, then this method returns false if and only if the - * Role is denied access to at least one privilege upon the Resource. In other words, this - * method returns true if and only if the Role is allowed all privileges on the Resource. - * - * This method checks Role inheritance using a depth-first traversal of the Role registry. - * The highest priority parent (i.e., the parent most recently added) is checked first, - * and its respective parents are checked similarly before the lower-priority parents of - * the Role are checked. - * - * @param Role\RoleInterface|string $role - * @param Resource\ResourceInterface|string $resource - * @param string $privilege - * @return boolean - */ - public function isAllowed($role = null, $resource = null, $privilege = null); +allow()). + * + * If a $privilege is not provided, then this method returns false if and only if the + * Role is denied access to at least one privilege upon the Resource. In other words, this + * method returns true if and only if the Role is allowed all privileges on the Resource. + * + * This method checks Role inheritance using a depth-first traversal of the Role registry. + * The highest priority parent (i.e., the parent most recently added) is checked first, + * and its respective parents are checked similarly before the lower-priority parents of + * the Role are checked. + * + * @param Role\RoleInterface|string $role + * @param Resource\ResourceInterface|string $resource + * @param string $privilege + * @return boolean + */ + public function isAllowed($role = null, $resource = null, $privilege = null); } \ No newline at end of file From 461438372868dbf383a82253431fb25911367d02 Mon Sep 17 00:00:00 2001 From: Christopher Martin Date: Tue, 18 Sep 2012 00:19:11 -0400 Subject: [PATCH 065/126] ZF2-417 Annotation Hydrator options support --- .../AbstractArrayOrStringAnnotation.php | 43 ++++++++++++++++++ library/Zend/Form/Annotation/Hydrator.php | 4 +- library/Zend/Form/Factory.php | 26 ++++++++--- .../Zend/Stdlib/Hydrator/AbstractHydrator.php | 2 +- library/Zend/Stdlib/Hydrator/ClassMethods.php | 45 +++++++++++++++++-- .../Hydrator/HydratorOptionsInterface.php | 25 +++++++++++ .../Form/Annotation/AnnotationBuilderTest.php | 11 +++++ tests/ZendTest/Form/FactoryTest.php | 16 +++++++ .../Annotation/EntityWithHydratorArray.php | 26 +++++++++++ tests/ZendTest/Stdlib/HydratorTest.php | 10 +++++ 10 files changed, 197 insertions(+), 11 deletions(-) create mode 100644 library/Zend/Form/Annotation/AbstractArrayOrStringAnnotation.php create mode 100644 library/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php create mode 100644 tests/ZendTest/Form/TestAsset/Annotation/EntityWithHydratorArray.php diff --git a/library/Zend/Form/Annotation/AbstractArrayOrStringAnnotation.php b/library/Zend/Form/Annotation/AbstractArrayOrStringAnnotation.php new file mode 100644 index 00000000000..a9bf814c32e --- /dev/null +++ b/library/Zend/Form/Annotation/AbstractArrayOrStringAnnotation.php @@ -0,0 +1,43 @@ +value = $data['value']; + } +} diff --git a/library/Zend/Form/Annotation/Hydrator.php b/library/Zend/Form/Annotation/Hydrator.php index d4fb9554957..ec88828b45a 100644 --- a/library/Zend/Form/Annotation/Hydrator.php +++ b/library/Zend/Form/Annotation/Hydrator.php @@ -21,12 +21,12 @@ * @package Zend_Form * @subpackage Annotation */ -class Hydrator extends AbstractStringAnnotation +class Hydrator extends AbstractArrayOrStringAnnotation { /** * Retrieve the hydrator class * - * @return null|string + * @return null|string|array */ public function getHydrator() { diff --git a/library/Zend/Form/Factory.php b/library/Zend/Form/Factory.php index 24d4eb37dbb..68e45b75a92 100644 --- a/library/Zend/Form/Factory.php +++ b/library/Zend/Form/Factory.php @@ -351,9 +351,9 @@ protected function prepareAndInjectObject($objectName, FieldsetInterface $fields * Takes a string indicating a hydrator class name (or a concrete instance), instantiates the class * by that name, and injects the hydrator instance into the form. * - * @param string $hydratorOrName - * @param FieldsetInterface $fieldset - * @param string $method + * @param string|array|Hydrator\HydratorInterface $hydratorOrName + * @param FieldsetInterface $fieldset + * @param string $method * @return void * @throws Exception\DomainException If $hydratorOrName is not a string, does not resolve to a known class, or * the class does not implement Hydrator\HydratorInterface @@ -365,14 +365,27 @@ protected function prepareAndInjectHydrator($hydratorOrName, FieldsetInterface $ return; } - if (!is_string($hydratorOrName)) { + if (!is_string($hydratorOrName) && !is_array($hydratorOrName)) { throw new Exception\DomainException(sprintf( - '%s expects string hydrator class name; received "%s"', + '%s expects string hydrator class name or an array specification; received "%s"', $method, (is_object($hydratorOrName) ? get_class($hydratorOrName) : gettype($hydratorOrName)) )); } + if (is_array($hydratorOrName)) { + if (!isset($hydratorOrName['type'])) { + throw new Exception\DomainException(sprintf( + '%s expects array specification to have a type value', + $method + )); + } + $hydratorOptions = (isset($hydratorOrName['options'])) ? $hydratorOrName['options'] : array(); + $hydratorOrName = $hydratorOrName['type']; + } else { + $hydratorOptions = array(); + } + if (!class_exists($hydratorOrName)) { throw new Exception\DomainException(sprintf( '%s expects string hydrator name to be a valid class name; received "%s"', @@ -389,6 +402,9 @@ protected function prepareAndInjectHydrator($hydratorOrName, FieldsetInterface $ $hydratorOrName )); } + if (!empty($hydratorOptions) && $hydrator instanceof Hydrator\HydratorOptionsInterface) { + $hydrator->setOptions($hydratorOptions); + } $fieldset->setHydrator($hydrator); } diff --git a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php index 35e81171377..964dc95618e 100644 --- a/library/Zend/Stdlib/Hydrator/AbstractHydrator.php +++ b/library/Zend/Stdlib/Hydrator/AbstractHydrator.php @@ -56,7 +56,7 @@ public function getStrategy($name) $name )); } - + return $this->strategies['*']; } diff --git a/library/Zend/Stdlib/Hydrator/ClassMethods.php b/library/Zend/Stdlib/Hydrator/ClassMethods.php index d480829879c..f53eb885a8d 100644 --- a/library/Zend/Stdlib/Hydrator/ClassMethods.php +++ b/library/Zend/Stdlib/Hydrator/ClassMethods.php @@ -17,22 +17,61 @@ * @package Zend_Stdlib * @subpackage Hydrator */ -class ClassMethods extends AbstractHydrator +class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface { /** * Flag defining whether array keys are underscore-separated (true) or camel case (false) * @var boolean */ - protected $underscoreSeparatedKeys; + protected $underscoreSeparatedKeys = true; /** * Define if extract values will use camel case or name with underscore - * @param boolean $underscoreSeparatedKeys + * @param boolean|array $underscoreSeparatedKeys */ public function __construct($underscoreSeparatedKeys = true) { parent::__construct(); + $this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys); + } + + /** + * @param array|\Traversable $options + * @return ClassMethods + * @throws Exception\InvalidArgumentException + */ + public function setOptions($options) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (!is_array($options)) { + throw new Exception\InvalidArgumentException( + 'The options parameter must be an array or a Traversable' + ); + } + if (isset($options['underscoreSeparatedKeys'])) { + $this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']); + } + + return $this; + } + + /** + * @param boolean $underscoreSeparatedKeys + * @return ClassMethods + */ + public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) + { $this->underscoreSeparatedKeys = $underscoreSeparatedKeys; + return $this; + } + + /** + * @return boolean + */ + public function getUnderscoreSeparatedKeys() + { + return $this->underscoreSeparatedKeys; } /** diff --git a/library/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php b/library/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php new file mode 100644 index 00000000000..056aca97e35 --- /dev/null +++ b/library/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php @@ -0,0 +1,25 @@ +assertEquals(array('class' => 'label'), $username->getLabelAttributes()); } + public function testCanHandleHydratorArrayAnnotation() + { + $entity = new TestAsset\Annotation\EntityWithHydratorArray(); + $builder = new Annotation\AnnotationBuilder(); + $form = $builder->createForm($entity); + + $hydrator = $form->getHydrator(); + $this->assertInstanceOf('Zend\Stdlib\Hydrator\ClassMethods', $hydrator); + $this->assertFalse($hydrator->getUnderscoreSeparatedKeys()); + } + public function testAllowTypeAsElementNameInInputFilter() { $entity = new TestAsset\Annotation\EntityWithTypeAsElementName(); diff --git a/tests/ZendTest/Form/FactoryTest.php b/tests/ZendTest/Form/FactoryTest.php index 77c77d2e396..d3baf0720e8 100644 --- a/tests/ZendTest/Form/FactoryTest.php +++ b/tests/ZendTest/Form/FactoryTest.php @@ -317,6 +317,22 @@ public function testCanCreateFormsAndSpecifyHydrator() $this->assertInstanceOf('Zend\Stdlib\Hydrator\ObjectProperty', $hydrator); } + public function testCanCreateHydratorFromArray() + { + $form = $this->factory->createForm(array( + 'name' => 'foo', + 'hydrator' => array( + 'type' => 'Zend\Stdlib\Hydrator\ClassMethods', + 'options' => array('underscoreSeparatedKeys' => false), + ), + )); + + $this->assertInstanceOf('Zend\Form\FormInterface', $form); + $hydrator = $form->getHydrator(); + $this->assertInstanceOf('Zend\Stdlib\Hydrator\ClassMethods', $hydrator); + $this->assertFalse($hydrator->getUnderscoreSeparatedKeys()); + } + public function testCanCreateHydratorFromConcreteClass() { $form = $this->factory->createForm(array( diff --git a/tests/ZendTest/Form/TestAsset/Annotation/EntityWithHydratorArray.php b/tests/ZendTest/Form/TestAsset/Annotation/EntityWithHydratorArray.php new file mode 100644 index 00000000000..dd91b0456d8 --- /dev/null +++ b/tests/ZendTest/Form/TestAsset/Annotation/EntityWithHydratorArray.php @@ -0,0 +1,26 @@ +assertEquals($test->hasBar(), false); } + public function testHydratorClassMethodsOptions() + { + $hydrator = new ClassMethods(); + $this->assertTrue($hydrator->getUnderscoreSeparatedKeys()); + $hydrator->setOptions(array('underscoreSeparatedKeys' => false)); + $this->assertFalse($hydrator->getUnderscoreSeparatedKeys()); + $hydrator->setUnderscoreSeparatedKeys(true); + $this->assertTrue($hydrator->getUnderscoreSeparatedKeys()); + } + public function testHydratorClassMethodsIgnoresInvalidValues() { $hydrator = new ClassMethods(true); From 576b759823906b7c8b63860d43192ffe92df0bfb Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 18 Sep 2012 10:25:42 -0500 Subject: [PATCH 066/126] [#2271] Incorporate feedbac - Incorporated feedback from comments - Added @see annotation pointing to python Logbook documentation - Added writer to WriterPluginManager --- library/Zend/Log/Writer/FingersCrossed.php | 43 ++++++++++++---------- library/Zend/Log/WriterPluginManager.php | 17 +++++---- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/library/Zend/Log/Writer/FingersCrossed.php b/library/Zend/Log/Writer/FingersCrossed.php index bd47a3195c5..83cfeff2a5f 100644 --- a/library/Zend/Log/Writer/FingersCrossed.php +++ b/library/Zend/Log/Writer/FingersCrossed.php @@ -20,8 +20,9 @@ /** * Buffers all events until the strategy determines to flush them. * - * @category Zend - * @package Zend_Log + * @see http://packages.python.org/Logbook/api/handlers.html#logbook.FingersCrossedHandler + * @category Zend + * @package Zend_Log * @subpackage Writer */ class FingersCrossed extends AbstractWriter @@ -68,13 +69,12 @@ public function __construct(WriterInterface $writer, $filterOrPriority = null, $ $this->writer = $writer; if (null === $filterOrPriority) { - $this->addFilter(new PriorityFilter(Logger::WARN)); + $filterOrPriority = new PriorityFilter(Logger::WARN); } elseif (!$filterOrPriority instanceof FilterInterface) { - $this->addFilter(new PriorityFilter($filterOrPriority)); - } else { - $this->addFilter($filterOrPriority); + $filterOrPriority = new PriorityFilter($filterOrPriority); } + $this->addFilter($filterOrPriority); $this->bufferSize = $bufferSize; } @@ -113,22 +113,25 @@ protected function isActivated(array $event) */ protected function doWrite(array $event) { - if ($this->buffering) { - $this->buffer[] = $event; + if (!$this->buffering) { + $this->writer->write($event); + return; + } + + $this->buffer[] = $event; - if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { - array_shift($this->buffer); - } + if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { + array_shift($this->buffer); + } - if ($this->isActivated($event)) { - $this->buffering = false; + if (!$this->isActivated($event)) { + return; + } + + $this->buffering = false; - foreach ($this->buffer as $bufferedEvent) { - $this->writer->write($bufferedEvent); - } - } - } else { - $this->writer->write($event); + foreach ($this->buffer as $bufferedEvent) { + $this->writer->write($bufferedEvent); } } @@ -162,4 +165,4 @@ public function shutdown() $this->writer->shutdown(); $this->buffer = null; } -} \ No newline at end of file +} diff --git a/library/Zend/Log/WriterPluginManager.php b/library/Zend/Log/WriterPluginManager.php index 68ee6281fca..7e306ce507d 100644 --- a/library/Zend/Log/WriterPluginManager.php +++ b/library/Zend/Log/WriterPluginManager.php @@ -24,14 +24,15 @@ class WriterPluginManager extends AbstractPluginManager * @var array */ protected $invokableClasses = array( - 'db' => 'Zend\Log\Writer\Db', - 'firephp' => 'Zend\Log\Writer\FirePhp', - 'mail' => 'Zend\Log\Writer\Mail', - 'mock' => 'Zend\Log\Writer\Mock', - 'null' => 'Zend\Log\Writer\Null', - 'stream' => 'Zend\Log\Writer\Stream', - 'syslog' => 'Zend\Log\Writer\Syslog', - 'zendmonitor' => 'Zend\Log\Writer\ZendMonitor', + 'db' => 'Zend\Log\Writer\Db', + 'fingerscrossed' => 'Zend\Log\Writer\FingersCrossed', + 'firephp' => 'Zend\Log\Writer\FirePhp', + 'mail' => 'Zend\Log\Writer\Mail', + 'mock' => 'Zend\Log\Writer\Mock', + 'null' => 'Zend\Log\Writer\Null', + 'stream' => 'Zend\Log\Writer\Stream', + 'syslog' => 'Zend\Log\Writer\Syslog', + 'zendmonitor' => 'Zend\Log\Writer\ZendMonitor', ); /** From cc87e8a71999b115870e7200d012cc31ec97637a Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 18 Sep 2012 11:13:15 -0500 Subject: [PATCH 067/126] [TESTS] Fix bad assumptions in Feed tests - Was using hard-coded version string, instead of current VERSION constant. Updated. --- tests/ZendTest/Feed/Writer/FeedTest.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/ZendTest/Feed/Writer/FeedTest.php b/tests/ZendTest/Feed/Writer/FeedTest.php index 05f38c0823b..8053db57241 100644 --- a/tests/ZendTest/Feed/Writer/FeedTest.php +++ b/tests/ZendTest/Feed/Writer/FeedTest.php @@ -13,6 +13,7 @@ use DateTime; use Zend\Feed\Writer; use Zend\Feed\Writer\Feed; +use Zend\Version\Version; /** * @category Zend @@ -1017,12 +1018,14 @@ public function testExportRss() foo bar - Zend_Feed_Writer 2.0.1 (http://framework.zend.com) + Zend_Feed_Writer %VERSION% (http://framework.zend.com) http://www.example.org EOT; + $version = Version::VERSION; + $feed = str_replace('%VERSION%', $version, $feed); $this->assertEquals($feed, $export); } @@ -1038,11 +1041,13 @@ public function testExportRssIgnoreExceptions() - Zend_Feed_Writer 2.0.1 (http://framework.zend.com) + Zend_Feed_Writer %VERSION% (http://framework.zend.com) EOT; + $version = Version::VERSION; + $feed = str_replace('%VERSION%', $version, $feed); $this->assertEquals($feed, $export); } From 7bb0a29464d099866ef9808efc468815b89f1b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 19 Sep 2012 18:18:43 +0200 Subject: [PATCH 068/126] Add plural view helper --- library/Zend/View/Helper/Plural.php | 39 ++++++++++++++++++ tests/ZendTest/View/Helper/PluralTest.php | 49 +++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 library/Zend/View/Helper/Plural.php create mode 100644 tests/ZendTest/View/Helper/PluralTest.php diff --git a/library/Zend/View/Helper/Plural.php b/library/Zend/View/Helper/Plural.php new file mode 100644 index 00000000000..2271324c4a1 --- /dev/null +++ b/library/Zend/View/Helper/Plural.php @@ -0,0 +1,39 @@ + 1) { + return $plural; + } + + return $singular; + } +} + diff --git a/tests/ZendTest/View/Helper/PluralTest.php b/tests/ZendTest/View/Helper/PluralTest.php new file mode 100644 index 00000000000..17a2eef1831 --- /dev/null +++ b/tests/ZendTest/View/Helper/PluralTest.php @@ -0,0 +1,49 @@ +helper = new PluralHelper(); + } + + public function testVerifySingularString() + { + $result = $this->helper->__invoke(1, 'one car', 'two cars'); + $this->assertEquals('one car', $result); + } + + public function testVerifyPluralString() + { + $result = $this->helper->__invoke(2, 'one car', 'two cars'); + $this->assertEquals('two cars', $result); + } +} From 9a32df3b148c0ed8e0fac4d8ad6b6c16280b95a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 19 Sep 2012 18:20:36 +0200 Subject: [PATCH 069/126] Reorder parameters according to i18n --- library/Zend/View/Helper/Plural.php | 4 ++-- tests/ZendTest/View/Helper/PluralTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Zend/View/Helper/Plural.php b/library/Zend/View/Helper/Plural.php index 2271324c4a1..c6e35546036 100644 --- a/library/Zend/View/Helper/Plural.php +++ b/library/Zend/View/Helper/Plural.php @@ -22,12 +22,12 @@ class Plural extends AbstractHelper { /** - * @param int $number The number that is used to decide if it's singular or plurial * @param string $singular String to use if singular * @param string $plural String to use if plural + * @param int $number The number that is used to decide if it's singular or plurial * @return string */ - public function __invoke($number, $singular, $plural) + public function __invoke($singular, $plural, $number) { if ($number > 1) { return $plural; diff --git a/tests/ZendTest/View/Helper/PluralTest.php b/tests/ZendTest/View/Helper/PluralTest.php index 17a2eef1831..04bd162178f 100644 --- a/tests/ZendTest/View/Helper/PluralTest.php +++ b/tests/ZendTest/View/Helper/PluralTest.php @@ -37,13 +37,13 @@ public function setUp() public function testVerifySingularString() { - $result = $this->helper->__invoke(1, 'one car', 'two cars'); + $result = $this->helper->__invoke('one car', 'two cars', 1); $this->assertEquals('one car', $result); } public function testVerifyPluralString() { - $result = $this->helper->__invoke(2, 'one car', 'two cars'); + $result = $this->helper->__invoke('one car', 'two cars', 2); $this->assertEquals('two cars', $result); } } From 227f283fa99a2bf3e2a79e4dc270303b1f635633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 19 Sep 2012 18:22:08 +0200 Subject: [PATCH 070/126] add it to the helper plugin manager --- library/Zend/View/HelperPluginManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Zend/View/HelperPluginManager.php b/library/Zend/View/HelperPluginManager.php index 517c07a3dc9..af8fbcd55e2 100644 --- a/library/Zend/View/HelperPluginManager.php +++ b/library/Zend/View/HelperPluginManager.php @@ -64,6 +64,7 @@ class HelperPluginManager extends AbstractPluginManager 'partialloop' => 'Zend\View\Helper\PartialLoop', 'partial' => 'Zend\View\Helper\Partial', 'placeholder' => 'Zend\View\Helper\Placeholder', + 'plural' => 'Zend\View\Helper\Plural', 'renderchildmodel' => 'Zend\View\Helper\RenderChildModel', 'rendertoplaceholder' => 'Zend\View\Helper\RenderToPlaceholder', 'serverurl' => 'Zend\View\Helper\ServerUrl', From 2eb66030d9a12018ba1cc438317321f2538a6ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Thu, 20 Sep 2012 15:19:08 +0200 Subject: [PATCH 071/126] Updated to handle every cases --- library/Zend/I18n/View/Helper/Plural.php | 326 ++++++++++++++++++ library/Zend/I18n/View/HelperConfig.php | 1 + library/Zend/View/Helper/Plural.php | 39 --- library/Zend/View/HelperPluginManager.php | 1 - .../ZendTest/I18n/View/Helper/PluralTest.php | 70 ++++ tests/ZendTest/View/Helper/PluralTest.php | 49 --- 6 files changed, 397 insertions(+), 89 deletions(-) create mode 100644 library/Zend/I18n/View/Helper/Plural.php delete mode 100644 library/Zend/View/Helper/Plural.php create mode 100644 tests/ZendTest/I18n/View/Helper/PluralTest.php delete mode 100644 tests/ZendTest/View/Helper/PluralTest.php diff --git a/library/Zend/I18n/View/Helper/Plural.php b/library/Zend/I18n/View/Helper/Plural.php new file mode 100644 index 00000000000..03e0b8813ff --- /dev/null +++ b/library/Zend/I18n/View/Helper/Plural.php @@ -0,0 +1,326 @@ + 0, + 'dz' => 0, + 'id' => 0, + 'ja' => 0, + 'jv' => 0, + 'ka' => 0, + 'km' => 0, + 'kn' => 0, + 'ko' => 0, + 'ms' => 0, + 'th' => 0, + 'tr' => 0, + 'vi' => 0, + 'zh' => 0, + + // Plural form n°1 (families: Germanic, Semitic, Romanic...) + 'af' => 1, + 'az' => 1, + 'bn' => 1, + 'bg' => 1, + 'ca' => 1, + 'da' => 1, + 'de' => 1, + 'el' => 1, + 'en' => 1, + 'eo' => 1, + 'es' => 1, + 'et' => 1, + 'eu' => 1, + 'fa' => 1, + 'fi' => 1, + 'fo' => 1, + 'fur' => 1, + 'fy' => 1, + 'gl' => 1, + 'gu' => 1, + 'ha' => 1, + 'he' => 1, + 'hu' => 1, + 'it' => 1, + 'ku' => 1, + 'lb' => 1, + 'ml' => 1, + 'mn' => 1, + 'mr' => 1, + 'nah' => 1, + 'nb' => 1, + 'ne' => 1, + 'nl' => 1, + 'nn' => 1, + 'no' => 1, + 'om' => 1, + 'or' => 1, + 'pa' => 1, + 'pap' => 1, + 'ps' => 1, + 'pt' => 1, + 'so' => 1, + 'sq' => 1, + 'sv' => 1, + 'sw' => 1, + 'ta' => 1, + 'te' => 1, + 'tk' => 1, + 'ur' => 1, + 'zu' => 1, + + // Plural form n°2 (romanic: French, Brazilian Portuguese...) + 'am' => 2, + 'bh' => 2, + 'fil' => 2, + 'fr' => 2, + 'gun' => 2, + 'hi' => 2, + 'ln' => 2, + 'mg' => 2, + 'nso' => 2, + 'xbr' => 2, + 'ti' => 2, + 'wa' => 2, + 'pt_BR' => 2, + + // Plural form n°3 (baltic: Latvian) + 'lv' => 3, + + // Plural form n°4 (celtic: Scottish Gaelic) + 'gd' => 4, + + // Plural form n°5 (romanic: Romanian) + 'ro' => 5, + + // Plural form n°6 (baltic: Lithunian) + 'lt' => 6, + + // Plural form n°7 (slavic: Bosnian, Croatian, Serbian, Russian, Ukrainian) + 'be' => 7, + 'bs' => 7, + 'hr' => 7, + 'ru' => 7, + 'sr' => 7, + 'uk' => 7, + + // Plural form n°8 (slavic: Slovak, Czech) + 'cs' => 8, + 'sk' => 8, + + // Plural form n°9 (slavic: Polish) + 'pl' => 9, + + // Plural form n°10 (slavic: Slovenian, Sorbian) + 'sl' => 10, + 'sb' => 10, + + // Plural form n°11 (gaelic: Irish Gaelic) + 'gd_IE' => 11, + + // Plural form n°12 (semitic: Arab) + 'ar' => 12, + + // Plural form n°13 (semitic: Maltese) + 'mt' => 13, + + // Plural form n°14 (slavic: Macedonian) + 'mk' => 14, + + // Plural form n°15 (Icelandic) + 'is' => 15, + + // Plural form n°16 (celtic: Breton) + 'br' => 16 + ); + + + /** + * Set locale to use instead of the default. + * + * @param string $locale + * @return DateFormat + */ + public function setLocale($locale) + { + $this->locale = (string) $locale; + return $this; + } + + /** + * Get the locale to use. + * + * @return string|null + */ + public function getLocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Given an array of strings, a number and, if wanted, an optional locale (the default one is used + * otherwise), this picks the right string according to plural rules of the locale + * + * @param array|string $strings + * @param int|float $number + * @param string $locale + * @throws Exception\OutOfBoundsException + * @return string + */ + public function __invoke($strings, $number, $locale = null) + { + if (is_string($strings)) { + $strings = (array) $strings; + } + + if ($locale === null) { + $locale = $this->getLocale(); + } + + $pluralForm = $this->getPluralForm($locale); + $pluralNumber = $this->getPluralNumber($number, $pluralForm); + + if (!isset($strings[$pluralNumber])) { + throw new Exception\OutOfBoundsException(sprintf( + 'The plural number %s for the locale %s has not been specified', + $pluralNumber, + $locale + )); + } + + return $strings[$pluralNumber]; + } + + /** + * Locale to use to determine the plural form + * + * @param string $locale + * @throws Exception\InvalidArgumentException + * @return string + */ + protected function getPluralForm($locale) + { + $locale = strtolower(str_replace('-', '_', $locale)); + + // Note that we first check the complete locale code, as some countries have different way to handle plurals, + // for instance Brazilian Portuguese handles it differently from normal Portuguese + + if (isset($this->pluralForms[$locale])) { + return $this->pluralForms[$locale]; + } + + $languageCode = strtok($locale, '_'); + + if (isset($this->pluralForms[$languageCode])) { + return $this->pluralForms[$languageCode]; + } + + throw new Exception\InvalidArgumentException(sprintf( + 'Plural form could not be found for locale %s. Please check if this locale exists', + $locale + )); + } + + /** + * Get the plural number + * + * @param int $number + * @param string $pluralForm + * @throws Exception\RuntimeException + * @return int + */ + protected function getPluralNumber($number, $pluralForm) + { + switch($pluralForm) { + case 0: + return 0; + case 1: + return ($number == 1) ? 0 : 1; + case 2: + return (($number == 0) || ($number == 1)) ? 0 : 1; + case 3: + return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); + case 4: + return (($number == 1 || $number == 11) ? 0 : (($number == 2 || $number == 12) ? 1 : ((($number > 2 && $number < 11)) || ($number > 12 && $number < 20)) ? 2 : 3)); + case 5: + return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); + case 6: + return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + case 7: + return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + case 8: + return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); + case 9: + return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); + case 10: + return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); + case 11: + return ($number == 1) ? 0 : ($number == 2) ? 1 : ($number > 2 && $number < 7) ? 2 : ($number > 6 && $number < 11) ? 3 : 4; + case 12: + return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5)))); + case 13: + return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); + case 14: + return ($number % 10 == 1) ? 0 : 1; + case 15: + return (($number % 10) == 1 && $number != 11) ? 0 : 1; + case 16: + // Breton is just crazy to write (especially with ternaries). If someone want to do it... ;-) Here are the rules : + /** + * n == 1 => 0 + * n mod 10 is 1 and n mod 100 not in 11,71,91 => 1; + * mod 10 is 2 and n mod 100 not in 12,72,92 => 2; + * mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99 => 3; + * n mod 1000000 is 0 and n is not 0 => 4 + * everything else => 5 + */ + throw new Exception\RuntimeException('Breton is not implemented yet'); + default: + return 0; + } + } +} + diff --git a/library/Zend/I18n/View/HelperConfig.php b/library/Zend/I18n/View/HelperConfig.php index 3dfe2782411..2034f194f3f 100644 --- a/library/Zend/I18n/View/HelperConfig.php +++ b/library/Zend/I18n/View/HelperConfig.php @@ -29,6 +29,7 @@ class HelperConfig implements ConfigInterface 'currencyformat' => 'Zend\I18n\View\Helper\CurrencyFormat', 'dateformat' => 'Zend\I18n\View\Helper\DateFormat', 'numberformat' => 'Zend\I18n\View\Helper\NumberFormat', + 'plural' => 'Zend\I18n\View\Helper\Plural', 'translate' => 'Zend\I18n\View\Helper\Translate', 'translateplural' => 'Zend\I18n\View\Helper\TranslatePlural', ); diff --git a/library/Zend/View/Helper/Plural.php b/library/Zend/View/Helper/Plural.php deleted file mode 100644 index c6e35546036..00000000000 --- a/library/Zend/View/Helper/Plural.php +++ /dev/null @@ -1,39 +0,0 @@ - 1) { - return $plural; - } - - return $singular; - } -} - diff --git a/library/Zend/View/HelperPluginManager.php b/library/Zend/View/HelperPluginManager.php index af8fbcd55e2..517c07a3dc9 100644 --- a/library/Zend/View/HelperPluginManager.php +++ b/library/Zend/View/HelperPluginManager.php @@ -64,7 +64,6 @@ class HelperPluginManager extends AbstractPluginManager 'partialloop' => 'Zend\View\Helper\PartialLoop', 'partial' => 'Zend\View\Helper\Partial', 'placeholder' => 'Zend\View\Helper\Placeholder', - 'plural' => 'Zend\View\Helper\Plural', 'renderchildmodel' => 'Zend\View\Helper\RenderChildModel', 'rendertoplaceholder' => 'Zend\View\Helper\RenderToPlaceholder', 'serverurl' => 'Zend\View\Helper\ServerUrl', diff --git a/tests/ZendTest/I18n/View/Helper/PluralTest.php b/tests/ZendTest/I18n/View/Helper/PluralTest.php new file mode 100644 index 00000000000..97339167637 --- /dev/null +++ b/tests/ZendTest/I18n/View/Helper/PluralTest.php @@ -0,0 +1,70 @@ +helper = new PluralHelper(); + } + + /** + * @return array + */ + public function pluralsTestProvider() + { + return array( + array('かさ', 0, 'ja', 'かさ'), + array('かさ', 10, 'ja', 'かさ'), + + array(array('umbrella', 'umbrellas'), 0, 'en', 'umbrellas'), + array(array('umbrella', 'umbrellas'), 1, 'en', 'umbrella'), + array(array('umbrella', 'umbrellas'), 2, 'en', 'umbrellas'), + + array(array('parapluie', 'parapluies'), 0, 'fr', 'parapluie'), + array(array('parapluie', 'parapluies'), 1, 'fr', 'parapluie'), + array(array('parapluie', 'parapluies'), 2, 'fr', 'parapluies'), + + array(array('зонтик', 'зонтика', 'зонтиков', 'Зонтики'), 1, 'ru', 'зонтик'), + array(array('зонтик', 'зонтика', 'зонтиков', 'Зонтики'), 22, 'ru', 'зонтика'), + array(array('зонтик', 'зонтика', 'зонтиков', 'Зонтики'), 36, 'ru', 'зонтиков') + ); + } + + /** + * @dataProvider pluralsTestProvider + */ + public function testGetCorrectPlurals($strings, $number, $locale, $expected) + { + $result = $this->helper->__invoke($strings, $number, $locale); + $this->assertEquals($expected, $result); + } +} diff --git a/tests/ZendTest/View/Helper/PluralTest.php b/tests/ZendTest/View/Helper/PluralTest.php deleted file mode 100644 index 04bd162178f..00000000000 --- a/tests/ZendTest/View/Helper/PluralTest.php +++ /dev/null @@ -1,49 +0,0 @@ -helper = new PluralHelper(); - } - - public function testVerifySingularString() - { - $result = $this->helper->__invoke('one car', 'two cars', 1); - $this->assertEquals('one car', $result); - } - - public function testVerifyPluralString() - { - $result = $this->helper->__invoke('one car', 'two cars', 2); - $this->assertEquals('two cars', $result); - } -} From 82bebc4eac19ae72b838cbe6a3bf74decfbe4075 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 20 Sep 2012 13:00:52 -0500 Subject: [PATCH 072/126] CS fixes - Trailing whitespace --- library/Zend/Log/Writer/FingersCrossed.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Zend/Log/Writer/FingersCrossed.php b/library/Zend/Log/Writer/FingersCrossed.php index 83cfeff2a5f..9b7ecfc1651 100644 --- a/library/Zend/Log/Writer/FingersCrossed.php +++ b/library/Zend/Log/Writer/FingersCrossed.php @@ -117,7 +117,7 @@ protected function doWrite(array $event) $this->writer->write($event); return; } - + $this->buffer[] = $event; if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { @@ -127,7 +127,7 @@ protected function doWrite(array $event) if (!$this->isActivated($event)) { return; } - + $this->buffering = false; foreach ($this->buffer as $bufferedEvent) { From a5843a7f35d65c35837e18d5f2f702300900e245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 24 Sep 2012 15:16:10 +0200 Subject: [PATCH 073/126] Allow to specify custom pattern --- library/Zend/I18n/View/Helper/DateFormat.php | 15 +++-- .../I18n/View/Helper/DateFormatTest.php | 62 +++++++++++++++++-- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/library/Zend/I18n/View/Helper/DateFormat.php b/library/Zend/I18n/View/Helper/DateFormat.php index 279f0b5c6f0..a43f3940b7b 100644 --- a/library/Zend/I18n/View/Helper/DateFormat.php +++ b/library/Zend/I18n/View/Helper/DateFormat.php @@ -105,17 +105,18 @@ public function getlocale() /** * Format a date. * - * @param DateTime|integer|array $date - * @param integer $dateType - * @param integer $timeType - * @param string $locale + * @param DateTime|integer|array $date + * @param int $dateType + * @param int $timeType + * @param string|null $pattern + * @param string $locale * @return string - * @throws Exception\RuntimeException */ public function __invoke( $date, $dateType = IntlDateFormatter::NONE, $timeType = IntlDateFormatter::NONE, + $pattern = null, $locale = null ) { if ($locale === null) { @@ -130,7 +131,9 @@ public function __invoke( $locale, $dateType, $timeType, - $timezone + $timezone, + IntlDateFormatter::GREGORIAN, + $pattern ); } diff --git a/tests/ZendTest/I18n/View/Helper/DateFormatTest.php b/tests/ZendTest/I18n/View/Helper/DateFormatTest.php index 38873d57f4a..5192e1fe0fe 100644 --- a/tests/ZendTest/I18n/View/Helper/DateFormatTest.php +++ b/tests/ZendTest/I18n/View/Helper/DateFormatTest.php @@ -53,7 +53,7 @@ public function tearDown() unset($this->helper); } - public function currencyTestsDataProvider() + public function dateTestsDataProvider() { $date = new DateTime('2012-07-02T22:44:03Z'); return array( @@ -160,19 +160,62 @@ public function currencyTestsDataProvider() ); } + public function dateTestsDataProviderWithPattern() + { + $date = new DateTime('2012-07-02T22:44:03Z'); + return array( + // FULL format varies based on OS + // array( + // 'de_DE', + // 'Europe/Berlin', + // IntlDateFormatter::FULL, + // IntlDateFormatter::FULL, + // $date, + // 'Dienstag, 3. Juli 2012 00:44:03 Deutschland', + // ), + array( + 'de_DE', + 'Europe/Berlin', + null, + null, + 'MMMM', + $date, + 'Juli', + ), + array( + 'de_DE', + 'Europe/Berlin', + null, + null, + 'MMMM.Y', + $date, + 'Juli.2012', + ), + array( + 'de_DE', + 'Europe/Berlin', + null, + null, + 'dd/Y', + $date, + '03/2012', + ), + ); + } + /** - * @dataProvider currencyTestsDataProvider + * @dataProvider dateTestsDataProvider */ public function testBasic($locale, $timezone, $timeType, $dateType, $date, $expected) { $this->helper->setTimezone($timezone); $this->assertMbStringEquals($expected, $this->helper->__invoke( - $date, $dateType, $timeType, $locale + $date, $dateType, $timeType, null, $locale )); } /** - * @dataProvider currencyTestsDataProvider + * @dataProvider dateTestsDataProvider */ public function testSettersProvideDefaults($locale, $timezone, $timeType, $dateType, $date, $expected) { @@ -185,6 +228,17 @@ public function testSettersProvideDefaults($locale, $timezone, $timeType, $dateT )); } + /** + * @dataProvider dateTestsDataProviderWithPattern + */ + public function testUseCustomPattern($locale, $timezone, $timeType, $dateType, $pattern, $date, $expected) + { + $this->helper->setTimezone($timezone); + $this->assertMbStringEquals($expected, $this->helper->__invoke( + $date, $dateType, $timeType, $pattern, $locale + )); + } + public function testDefaultLocale() { $this->assertEquals(Locale::getDefault(), $this->helper->getLocale()); From c169ec04a61dc5fd79e92408711ee5fdc306ef61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 24 Sep 2012 16:50:40 +0200 Subject: [PATCH 074/126] DateSelect can extract from DateTime --- library/Zend/Form/Element/DateSelect.php | 11 ++++++++++- library/Zend/Form/Element/MonthSelect.php | 10 +++++++++- tests/ZendTest/Form/Element/DateSelectTest.php | 11 +++++++++++ tests/ZendTest/Form/Element/MonthSelectTest.php | 10 ++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index 5b0fbb2527e..3038bbb88ad 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -91,7 +91,16 @@ public function getDayAttributes() */ public function setValue($value) { - parent::setValue($value); + if ($value instanceof DateTime) { + $value = array( + 'year' => $value->format('Y'), + 'month' => $value->format('m'), + 'day' => $value->format('d') + ); + } + + $this->yearElement->setValue($value['year']); + $this->monthElement->setValue($value['month']); $this->dayElement->setValue($value['day']); } diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php index de3a6ba5fb9..34fa7cbbb7c 100644 --- a/library/Zend/Form/Element/MonthSelect.php +++ b/library/Zend/Form/Element/MonthSelect.php @@ -10,6 +10,7 @@ namespace Zend\Form\Element; +use DateTime; use Zend\Form\Element; use Zend\Form\ElementPrepareAwareInterface; use Zend\Form\Form; @@ -235,8 +236,15 @@ public function shouldCreateEmptyOption() */ public function setValue($value) { - $this->monthElement->setValue($value['month']); + if ($value instanceof DateTime) { + $value = array( + 'year' => $value->format('Y'), + 'month' => $value->format('m') + ); + } + $this->yearElement->setValue($value['year']); + $this->monthElement->setValue($value['month']); } /** diff --git a/tests/ZendTest/Form/Element/DateSelectTest.php b/tests/ZendTest/Form/Element/DateSelectTest.php index dd87802c949..420c9d9736a 100644 --- a/tests/ZendTest/Form/Element/DateSelectTest.php +++ b/tests/ZendTest/Form/Element/DateSelectTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Form\Element; +use DateTime; use PHPUnit_Framework_TestCase as TestCase; use Zend\Form\Element\DateSelect as DateSelectElement; use Zend\Form\Factory; @@ -39,4 +40,14 @@ public function testProvidesInputSpecificationThatIncludesValidatorsBasedOnAttri } } } + + public function testCanSetDateFromDateTime() + { + $element = new DateSelectElement(); + $element->setValue(new DateTime('2012-09-24')); + + $this->assertEquals('2012', $element->getYearElement()->getValue()); + $this->assertEquals('09', $element->getMonthElement()->getValue()); + $this->assertEquals('24', $element->getDayElement()->getValue()); + } } diff --git a/tests/ZendTest/Form/Element/MonthSelectTest.php b/tests/ZendTest/Form/Element/MonthSelectTest.php index 105f5b9ab90..7bffab54f19 100644 --- a/tests/ZendTest/Form/Element/MonthSelectTest.php +++ b/tests/ZendTest/Form/Element/MonthSelectTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Form\Element; +use DateTime; use PHPUnit_Framework_TestCase as TestCase; use Zend\Form\Element\MonthSelect as MonthSelectElement; use Zend\Form\Factory; @@ -71,4 +72,13 @@ public function testMonthValidation($value, $expected) $monthValidator = $inputSpec['validators'][0]; $this->assertEquals($expected, $monthValidator->isValid($value)); } + + public function testCanSetMonthFromDateTime() + { + $element = new MonthSelectElement(); + $element->setValue(new DateTime('2012-09')); + + $this->assertEquals('2012', $element->getYearElement()->getValue()); + $this->assertEquals('09', $element->getMonthElement()->getValue()); + } } From 986df503b6ae6b57d37d9873b475e84036ae6a9d Mon Sep 17 00:00:00 2001 From: Jurgen Van de Moere Date: Tue, 25 Sep 2012 11:06:56 +0200 Subject: [PATCH 075/126] Add new validator to check if input is instance of a certain class Change-Id: I6365cf9a6652ca42a1f6897002e5abe455ed4f44 --- library/Zend/Validator/IsInstanceOf.php | 112 ++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 library/Zend/Validator/IsInstanceOf.php diff --git a/library/Zend/Validator/IsInstanceOf.php b/library/Zend/Validator/IsInstanceOf.php new file mode 100644 index 00000000000..77455479089 --- /dev/null +++ b/library/Zend/Validator/IsInstanceOf.php @@ -0,0 +1,112 @@ + "The input is not an instance of '%className%'" + ); + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = array( + 'className' => 'className' + ); + + /** + * Class name + * + * @var string + */ + protected $className; + + /** + * Sets validator options + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (!is_array($options)) { + $options = func_get_args(); + + $tmpOptions = array(); + $tmpOptions['classname'] = array_shift($options); + + $options = $tmpOptions; + } + + if (!array_key_exists('className', $options)) { + throw new Exception\InvalidArgumentException("Missing option 'className'"); + } + + $this->setClassName($options['className']); + + parent::__construct($options); + } + + /** + * Get class name + * + * @return string + */ + public function getClassName() + { + return $this->className; + } + + /** + * Set class name + * + * @param string $className + * @return self + */ + public function setClassName($className) + { + $this->className = $className; + return $this; + } + + /** + * Returns true if $value is instance of $this->className + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + if($value instanceof $this->className) { + return true; + } + $this->error(self::NOT_INSTANCE_OF); + return false; + } +} From fa62b406b56995527f8d645decb35400b798c5ae Mon Sep 17 00:00:00 2001 From: Medewerker Date: Tue, 25 Sep 2012 14:07:05 +0200 Subject: [PATCH 076/126] Fix prepareindex counter --- library/Zend/Db/Sql/AbstractSql.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/Zend/Db/Sql/AbstractSql.php b/library/Zend/Db/Sql/AbstractSql.php index e8ece875777..21d0e88fe9a 100644 --- a/library/Zend/Db/Sql/AbstractSql.php +++ b/library/Zend/Db/Sql/AbstractSql.php @@ -27,6 +27,11 @@ abstract class AbstractSql */ protected $processInfo = array('paramPrefix' => '', 'subselectCount' => 0); + /** + * @var array + */ + protected $instanceParameterIndex = array(); + protected function processExpression(ExpressionInterface $expression, PlatformInterface $platform, Adapter $adapter = null, $namedParameterPrefix = null) { // static counter for the number of times this method was invoked across the PHP runtime @@ -42,7 +47,12 @@ protected function processExpression(ExpressionInterface $expression, PlatformIn // initialize variables $parts = $expression->getExpressionData(); - $expressionParamIndex = 1; + + if(!isset($this->instanceParameterIndex[$namedParameterPrefix])) { + $this->instanceParameterIndex[$namedParameterPrefix] = 1; + } + + $expressionParamIndex = &$this->instanceParameterIndex[$namedParameterPrefix]; foreach ($parts as $part) { From f3ee95e38d04cf0ed5559783c9e1a47afea4990e Mon Sep 17 00:00:00 2001 From: Jurgen Van de Moere Date: Tue, 25 Sep 2012 14:07:54 +0200 Subject: [PATCH 077/126] - Removed empty line - Removed call to setClassName() in constructor so it uses the parent constructor (and setOptions()) to set the options Change-Id: I0720d0543b0a6918b7e8a0817d353aff668f5517 --- library/Zend/Validator/IsInstanceOf.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/Zend/Validator/IsInstanceOf.php b/library/Zend/Validator/IsInstanceOf.php index 77455479089..ab8866ab22e 100644 --- a/library/Zend/Validator/IsInstanceOf.php +++ b/library/Zend/Validator/IsInstanceOf.php @@ -15,8 +15,7 @@ use Zend\Validator\AbstractValidator; class IsInstanceOf extends AbstractValidator -{ - +{ const NOT_INSTANCE_OF = 'notInstanceOf'; /** @@ -67,9 +66,7 @@ public function __construct($options = null) if (!array_key_exists('className', $options)) { throw new Exception\InvalidArgumentException("Missing option 'className'"); } - - $this->setClassName($options['className']); - + parent::__construct($options); } From 468ae7438b07942ea7c57ea44f3117ddc97719a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 25 Sep 2012 14:33:22 +0200 Subject: [PATCH 078/126] Take advantage of PluralRule --- library/Zend/I18n/View/Helper/Plural.php | 295 ++++-------------- .../ZendTest/I18n/View/Helper/PluralTest.php | 10 +- 2 files changed, 72 insertions(+), 233 deletions(-) diff --git a/library/Zend/I18n/View/Helper/Plural.php b/library/Zend/I18n/View/Helper/Plural.php index 03e0b8813ff..f116e995216 100644 --- a/library/Zend/I18n/View/Helper/Plural.php +++ b/library/Zend/I18n/View/Helper/Plural.php @@ -12,14 +12,20 @@ use Locale; use Zend\I18n\Exception; +use Zend\I18n\Translator\Plural\Rule as PluralRule; use Zend\View\Helper\AbstractHelper; /** - * Helper for helping rendering text based on a count number (like the i18n plural translation helper, but - * when translation is not needed). This helper uses different pre-defined plural forms in order to choose - * the right string. Some references: - * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html - * https://developer.mozilla.org/en-US/docs/Localization_and_Plurals + * Helper for rendering text based on a count number (like the I18n plural translation helper, but when translation + * is not needed). + * + * Please note that we did not write any hard-coded rules for languages, as languages can evolve, we prefered to + * let the developer define the rules himself, instead of potentially break applications if we change rules in the + * future. + * + * However, you can find most of the up-to-date plural rules for most languages in those links: + * - http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html + * - https://developer.mozilla.org/en-US/docs/Localization_and_Plurals * * @category Zend * @package Zend_I18n @@ -35,143 +41,11 @@ class Plural extends AbstractHelper protected $locale; /** - * List of languages code (eventually a full locale code) associated to a plural form + * Associative array that associate a locale to a plural rule * * @var array */ - protected $pluralForms = array( - // Plural form n°0 (families: Asian, Persian, Turkic/Altaic, Thai, Lao...) - 'bo' => 0, - 'dz' => 0, - 'id' => 0, - 'ja' => 0, - 'jv' => 0, - 'ka' => 0, - 'km' => 0, - 'kn' => 0, - 'ko' => 0, - 'ms' => 0, - 'th' => 0, - 'tr' => 0, - 'vi' => 0, - 'zh' => 0, - - // Plural form n°1 (families: Germanic, Semitic, Romanic...) - 'af' => 1, - 'az' => 1, - 'bn' => 1, - 'bg' => 1, - 'ca' => 1, - 'da' => 1, - 'de' => 1, - 'el' => 1, - 'en' => 1, - 'eo' => 1, - 'es' => 1, - 'et' => 1, - 'eu' => 1, - 'fa' => 1, - 'fi' => 1, - 'fo' => 1, - 'fur' => 1, - 'fy' => 1, - 'gl' => 1, - 'gu' => 1, - 'ha' => 1, - 'he' => 1, - 'hu' => 1, - 'it' => 1, - 'ku' => 1, - 'lb' => 1, - 'ml' => 1, - 'mn' => 1, - 'mr' => 1, - 'nah' => 1, - 'nb' => 1, - 'ne' => 1, - 'nl' => 1, - 'nn' => 1, - 'no' => 1, - 'om' => 1, - 'or' => 1, - 'pa' => 1, - 'pap' => 1, - 'ps' => 1, - 'pt' => 1, - 'so' => 1, - 'sq' => 1, - 'sv' => 1, - 'sw' => 1, - 'ta' => 1, - 'te' => 1, - 'tk' => 1, - 'ur' => 1, - 'zu' => 1, - - // Plural form n°2 (romanic: French, Brazilian Portuguese...) - 'am' => 2, - 'bh' => 2, - 'fil' => 2, - 'fr' => 2, - 'gun' => 2, - 'hi' => 2, - 'ln' => 2, - 'mg' => 2, - 'nso' => 2, - 'xbr' => 2, - 'ti' => 2, - 'wa' => 2, - 'pt_BR' => 2, - - // Plural form n°3 (baltic: Latvian) - 'lv' => 3, - - // Plural form n°4 (celtic: Scottish Gaelic) - 'gd' => 4, - - // Plural form n°5 (romanic: Romanian) - 'ro' => 5, - - // Plural form n°6 (baltic: Lithunian) - 'lt' => 6, - - // Plural form n°7 (slavic: Bosnian, Croatian, Serbian, Russian, Ukrainian) - 'be' => 7, - 'bs' => 7, - 'hr' => 7, - 'ru' => 7, - 'sr' => 7, - 'uk' => 7, - - // Plural form n°8 (slavic: Slovak, Czech) - 'cs' => 8, - 'sk' => 8, - - // Plural form n°9 (slavic: Polish) - 'pl' => 9, - - // Plural form n°10 (slavic: Slovenian, Sorbian) - 'sl' => 10, - 'sb' => 10, - - // Plural form n°11 (gaelic: Irish Gaelic) - 'gd_IE' => 11, - - // Plural form n°12 (semitic: Arab) - 'ar' => 12, - - // Plural form n°13 (semitic: Maltese) - 'mt' => 13, - - // Plural form n°14 (slavic: Macedonian) - 'mk' => 14, - - // Plural form n°15 (Icelandic) - 'is' => 15, - - // Plural form n°16 (celtic: Breton) - 'br' => 16 - ); + protected $rules; /** @@ -201,126 +75,89 @@ public function getLocale() } /** - * Given an array of strings, a number and, if wanted, an optional locale (the default one is used - * otherwise), this picks the right string according to plural rules of the locale + * Add a plural rule for a specific locale. If a rule already exists for this locale, it is overriden * - * @param array|string $strings - * @param int|float $number - * @param string $locale - * @throws Exception\OutOfBoundsException - * @return string + * @param string $locale + * @param PluralRule|string $pluralRule + * @return self */ - public function __invoke($strings, $number, $locale = null) + public function addPluralRule($locale, $pluralRule) { - if (is_string($strings)) { - $strings = (array) $strings; - } - - if ($locale === null) { - $locale = $this->getLocale(); + if (is_string($pluralRule)) { + $pluralRule = PluralRule::fromString($pluralRule); } - $pluralForm = $this->getPluralForm($locale); - $pluralNumber = $this->getPluralNumber($number, $pluralForm); - - if (!isset($strings[$pluralNumber])) { - throw new Exception\OutOfBoundsException(sprintf( - 'The plural number %s for the locale %s has not been specified', - $pluralNumber, - $locale - )); - } + $this->rules[str_replace('-', '_', $locale)] = $pluralRule; - return $strings[$pluralNumber]; + return $this; } /** - * Locale to use to determine the plural form + * Get the plural rule for the given locale. It first checks the complete locale for an exact match, if + * none found, it tries to find the plural rule only using the language code * * @param string $locale * @throws Exception\InvalidArgumentException - * @return string + * @return PluralRule */ - protected function getPluralForm($locale) + public function getPluralRule($locale) { - $locale = strtolower(str_replace('-', '_', $locale)); + $locale = str_replace('-', '_', $locale); - // Note that we first check the complete locale code, as some countries have different way to handle plurals, - // for instance Brazilian Portuguese handles it differently from normal Portuguese - - if (isset($this->pluralForms[$locale])) { - return $this->pluralForms[$locale]; + if (isset($this->rules[$locale])) { + return $this->rules[$locale]; } - $languageCode = strtok($locale, '_'); + $language = strtok($locale, '_'); - if (isset($this->pluralForms[$languageCode])) { - return $this->pluralForms[$languageCode]; + if (isset($this->rules[$language])) { + return $this->rules[$language]; } throw new Exception\InvalidArgumentException(sprintf( - 'Plural form could not be found for locale %s. Please check if this locale exists', + 'No plural rule was found for the %s locale', $locale )); } /** - * Get the plural number + * This function checks if there is a rule for this locale. It makes a strict comparison, so if the locale + * contains both a lang and region, the registered locale must have both * - * @param int $number - * @param string $pluralForm - * @throws Exception\RuntimeException - * @return int + * @param string $locale + * @return bool */ - protected function getPluralNumber($number, $pluralForm) + public function hasPluralRule($locale) { - switch($pluralForm) { - case 0: - return 0; - case 1: - return ($number == 1) ? 0 : 1; - case 2: - return (($number == 0) || ($number == 1)) ? 0 : 1; - case 3: - return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); - case 4: - return (($number == 1 || $number == 11) ? 0 : (($number == 2 || $number == 12) ? 1 : ((($number > 2 && $number < 11)) || ($number > 12 && $number < 20)) ? 2 : 3)); - case 5: - return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); - case 6: - return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); - case 7: - return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); - case 8: - return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); - case 9: - return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); - case 10: - return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); - case 11: - return ($number == 1) ? 0 : ($number == 2) ? 1 : ($number > 2 && $number < 7) ? 2 : ($number > 6 && $number < 11) ? 3 : 4; - case 12: - return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5)))); - case 13: - return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); - case 14: - return ($number % 10 == 1) ? 0 : 1; - case 15: - return (($number % 10) == 1 && $number != 11) ? 0 : 1; - case 16: - // Breton is just crazy to write (especially with ternaries). If someone want to do it... ;-) Here are the rules : - /** - * n == 1 => 0 - * n mod 10 is 1 and n mod 100 not in 11,71,91 => 1; - * mod 10 is 2 and n mod 100 not in 12,72,92 => 2; - * mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99 => 3; - * n mod 1000000 is 0 and n is not 0 => 4 - * everything else => 5 - */ - throw new Exception\RuntimeException('Breton is not implemented yet'); - default: - return 0; + $locale = str_replace('-', '_', $locale); + + return isset($this->rules[$locale]); + } + + /** + * Given an array of strings, a number and, if wanted, an optional locale (the default one is used + * otherwise), this picks the right string according to plural rules of the locale + * + * @param array|string $strings + * @param int|float $number + * @param string $locale + * @throws Exception\OutOfBoundsException + * @return string + */ + public function __invoke($strings, $number, $locale = null) + { + if ($locale === null) { + $locale = $this->getLocale(); } + + $rule = $this->getPluralRule($locale); + $pluralIndex = $rule->evaluate($number); + + if (!is_array($strings)) { + $strings = (array) $strings; + } + + return $strings[$pluralIndex]; } } diff --git a/tests/ZendTest/I18n/View/Helper/PluralTest.php b/tests/ZendTest/I18n/View/Helper/PluralTest.php index 97339167637..01f7012cb9b 100644 --- a/tests/ZendTest/I18n/View/Helper/PluralTest.php +++ b/tests/ZendTest/I18n/View/Helper/PluralTest.php @@ -10,6 +10,7 @@ namespace ZendTest\I18n\View\Helper; +use Zend\I18n\Translator\Plural\Rule as PluralRule; use Zend\I18n\View\Helper\Plural as PluralHelper; /** @@ -34,6 +35,11 @@ class PluralTest extends \PHPUnit_Framework_TestCase public function setUp() { $this->helper = new PluralHelper(); + + // Add some rules rules for languages + $this->helper->addPluralRule('ja', 'nplurals=1; plural=0'); + $this->helper->addPluralRule('fr', 'nplurals=2; plural=(n==0 || n==1 ? 0 : 1)'); + $this->helper->addPluralRule('en', 'nplurals=2; plural=(n==1 ? 0 : 1)'); } /** @@ -52,10 +58,6 @@ public function pluralsTestProvider() array(array('parapluie', 'parapluies'), 0, 'fr', 'parapluie'), array(array('parapluie', 'parapluies'), 1, 'fr', 'parapluie'), array(array('parapluie', 'parapluies'), 2, 'fr', 'parapluies'), - - array(array('зонтик', 'зонтика', 'зонтиков', 'Зонтики'), 1, 'ru', 'зонтик'), - array(array('зонтик', 'зонтика', 'зонтиков', 'Зонтики'), 22, 'ru', 'зонтика'), - array(array('зонтик', 'зонтика', 'зонтиков', 'Зонтики'), 36, 'ru', 'зонтиков') ); } From 58b3424c9c13fa68405effcf59ed5779749984bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 25 Sep 2012 15:28:41 +0200 Subject: [PATCH 079/126] Allow to render template separately --- .../Zend/Form/View/Helper/FormCollection.php | 41 +++++++++++++------ .../Form/View/Helper/FormCollectionTest.php | 9 ++++ 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/library/Zend/Form/View/Helper/FormCollection.php b/library/Zend/Form/View/Helper/FormCollection.php index c376a24f608..442704982ce 100644 --- a/library/Zend/Form/View/Helper/FormCollection.php +++ b/library/Zend/Form/View/Helper/FormCollection.php @@ -64,13 +64,7 @@ public function render(ElementInterface $element) $elementHelper = $this->getElementHelper(); if ($element instanceof CollectionElement && $element->shouldCreateTemplate()) { - $elementOrFieldset = $element->getTemplateElement(); - - if ($elementOrFieldset instanceof FieldsetInterface) { - $templateMarkup .= $this->render($elementOrFieldset); - } elseif ($elementOrFieldset instanceof ElementInterface) { - $templateMarkup .= $elementHelper($elementOrFieldset); - } + $templateMarkup = $this->renderTemplate($element); } foreach ($element->getIterator() as $elementOrFieldset) { @@ -83,12 +77,7 @@ public function render(ElementInterface $element) // If $templateMarkup is not empty, use it for simplify adding new element in JavaScript if (!empty($templateMarkup)) { - $escapeHtmlAttribHelper = $this->getEscapeHtmlAttrHelper(); - - $markup .= sprintf( - '', - $escapeHtmlAttribHelper($templateMarkup) - ); + $markup .= $templateMarkup; } // Every collection is wrapped by a fieldset if needed @@ -109,6 +98,32 @@ public function render(ElementInterface $element) return $markup; } + /** + * Only render a template + * + * @param CollectionElement $collection + * @return string + */ + public function renderTemplate(CollectionElement $collection) + { + $elementHelper = $this->getElementHelper(); + $escapeHtmlAttribHelper = $this->getEscapeHtmlAttrHelper(); + $templateMarkup = ''; + + $elementOrFieldset = $collection->getTemplateElement(); + + if ($elementOrFieldset instanceof FieldsetInterface) { + $templateMarkup .= $this->render($elementOrFieldset); + } elseif ($elementOrFieldset instanceof ElementInterface) { + $templateMarkup .= $elementHelper($elementOrFieldset); + } + + return sprintf( + '', + $escapeHtmlAttribHelper($templateMarkup) + ); + } + /** * Invoke helper as function * diff --git a/tests/ZendTest/Form/View/Helper/FormCollectionTest.php b/tests/ZendTest/Form/View/Helper/FormCollectionTest.php index 5f8cb1395ab..ce8672addce 100644 --- a/tests/ZendTest/Form/View/Helper/FormCollectionTest.php +++ b/tests/ZendTest/Form/View/Helper/FormCollectionTest.php @@ -139,5 +139,14 @@ public function testSetDefaultElementHelperToFoo() $this->assertSame('foo', $defaultElement); } + public function testCanRenderTemplateAlone() + { + $form = $this->getForm(); + $collection = $form->get('colors'); + $collection->setShouldCreateTemplate(true); + $markup = $this->helper->renderTemplate($collection); + $this->assertContains('assertContains($collection->getTemplatePlaceholder(), $markup); + } } From 1df92007f20cdd10df87fb3869330716b1ca7b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 25 Sep 2012 16:05:44 +0200 Subject: [PATCH 080/126] Does not take into account locale --- library/Zend/I18n/View/Helper/Plural.php | 108 +++--------------- .../ZendTest/I18n/View/Helper/PluralTest.php | 27 ++--- 2 files changed, 27 insertions(+), 108 deletions(-) diff --git a/library/Zend/I18n/View/Helper/Plural.php b/library/Zend/I18n/View/Helper/Plural.php index f116e995216..9fe804699a6 100644 --- a/library/Zend/I18n/View/Helper/Plural.php +++ b/library/Zend/I18n/View/Helper/Plural.php @@ -10,7 +10,6 @@ namespace Zend\I18n\View\Helper; -use Locale; use Zend\I18n\Exception; use Zend\I18n\Translator\Plural\Rule as PluralRule; use Zend\View\Helper\AbstractHelper; @@ -34,129 +33,52 @@ class Plural extends AbstractHelper { /** - * Locale to use instead of the default + * Rule to use * - * @var string + * @var PluralRule */ - protected $locale; + protected $rule; /** - * Associative array that associate a locale to a plural rule + * Set the plural rule to use * - * @var array - */ - protected $rules; - - - /** - * Set locale to use instead of the default. - * - * @param string $locale - * @return DateFormat - */ - public function setLocale($locale) - { - $this->locale = (string) $locale; - return $this; - } - - /** - * Get the locale to use. - * - * @return string|null - */ - public function getLocale() - { - if ($this->locale === null) { - $this->locale = Locale::getDefault(); - } - - return $this->locale; - } - - /** - * Add a plural rule for a specific locale. If a rule already exists for this locale, it is overriden - * - * @param string $locale * @param PluralRule|string $pluralRule * @return self */ - public function addPluralRule($locale, $pluralRule) + public function setPluralRule($pluralRule) { if (is_string($pluralRule)) { $pluralRule = PluralRule::fromString($pluralRule); } - $this->rules[str_replace('-', '_', $locale)] = $pluralRule; + $this->rule = $pluralRule; return $this; } - /** - * Get the plural rule for the given locale. It first checks the complete locale for an exact match, if - * none found, it tries to find the plural rule only using the language code - * - * @param string $locale - * @throws Exception\InvalidArgumentException - * @return PluralRule - */ - public function getPluralRule($locale) - { - $locale = str_replace('-', '_', $locale); - - if (isset($this->rules[$locale])) { - return $this->rules[$locale]; - } - - $language = strtok($locale, '_'); - - if (isset($this->rules[$language])) { - return $this->rules[$language]; - } - - throw new Exception\InvalidArgumentException(sprintf( - 'No plural rule was found for the %s locale', - $locale - )); - } - - /** - * This function checks if there is a rule for this locale. It makes a strict comparison, so if the locale - * contains both a lang and region, the registered locale must have both - * - * @param string $locale - * @return bool - */ - public function hasPluralRule($locale) - { - $locale = str_replace('-', '_', $locale); - - return isset($this->rules[$locale]); - } - /** * Given an array of strings, a number and, if wanted, an optional locale (the default one is used * otherwise), this picks the right string according to plural rules of the locale * * @param array|string $strings - * @param int|float $number - * @param string $locale - * @throws Exception\OutOfBoundsException + * @param int $number + * @throws Exception\InvalidArgumentException * @return string */ - public function __invoke($strings, $number, $locale = null) + public function __invoke($strings, $number) { - if ($locale === null) { - $locale = $this->getLocale(); + if ($this->rule === null) { + throw new Exception\InvalidArgumentException(sprintf( + 'No plural rule was set' + )); } - $rule = $this->getPluralRule($locale); - $pluralIndex = $rule->evaluate($number); - if (!is_array($strings)) { $strings = (array) $strings; } + $pluralIndex = $this->rule->evaluate($number); + return $strings[$pluralIndex]; } } diff --git a/tests/ZendTest/I18n/View/Helper/PluralTest.php b/tests/ZendTest/I18n/View/Helper/PluralTest.php index 01f7012cb9b..ce51f763258 100644 --- a/tests/ZendTest/I18n/View/Helper/PluralTest.php +++ b/tests/ZendTest/I18n/View/Helper/PluralTest.php @@ -35,11 +35,6 @@ class PluralTest extends \PHPUnit_Framework_TestCase public function setUp() { $this->helper = new PluralHelper(); - - // Add some rules rules for languages - $this->helper->addPluralRule('ja', 'nplurals=1; plural=0'); - $this->helper->addPluralRule('fr', 'nplurals=2; plural=(n==0 || n==1 ? 0 : 1)'); - $this->helper->addPluralRule('en', 'nplurals=2; plural=(n==1 ? 0 : 1)'); } /** @@ -48,25 +43,27 @@ public function setUp() public function pluralsTestProvider() { return array( - array('かさ', 0, 'ja', 'かさ'), - array('かさ', 10, 'ja', 'かさ'), + array('nplurals=1; plural=0', 'かさ', 0, 'かさ'), + array('nplurals=1; plural=0', 'かさ', 10, 'かさ'), - array(array('umbrella', 'umbrellas'), 0, 'en', 'umbrellas'), - array(array('umbrella', 'umbrellas'), 1, 'en', 'umbrella'), - array(array('umbrella', 'umbrellas'), 2, 'en', 'umbrellas'), + array('nplurals=2; plural=(n==1 ? 0 : 1)', array('umbrella', 'umbrellas'), 0, 'umbrellas'), + array('nplurals=2; plural=(n==1 ? 0 : 1)', array('umbrella', 'umbrellas'), 1, 'umbrella'), + array('nplurals=2; plural=(n==1 ? 0 : 1)', array('umbrella', 'umbrellas'), 2, 'umbrellas'), - array(array('parapluie', 'parapluies'), 0, 'fr', 'parapluie'), - array(array('parapluie', 'parapluies'), 1, 'fr', 'parapluie'), - array(array('parapluie', 'parapluies'), 2, 'fr', 'parapluies'), + array('nplurals=2; plural=(n==0 || n==1 ? 0 : 1)', array('parapluie', 'parapluies'), 0, 'parapluie'), + array('nplurals=2; plural=(n==0 || n==1 ? 0 : 1)', array('parapluie', 'parapluies'), 1, 'parapluie'), + array('nplurals=2; plural=(n==0 || n==1 ? 0 : 1)', array('parapluie', 'parapluies'), 2, 'parapluies'), ); } /** * @dataProvider pluralsTestProvider */ - public function testGetCorrectPlurals($strings, $number, $locale, $expected) + public function testGetCorrectPlurals($pluralRule, $strings, $number, $expected) { - $result = $this->helper->__invoke($strings, $number, $locale); + $this->helper->setPluralRule($pluralRule); + $result = $this->helper->__invoke($strings, $number); $this->assertEquals($expected, $result); } } + From 76c1d3d1e011870377f9c08e743707d493561f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 25 Sep 2012 16:10:48 +0200 Subject: [PATCH 081/126] Change condition --- library/Zend/I18n/View/Helper/Plural.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/I18n/View/Helper/Plural.php b/library/Zend/I18n/View/Helper/Plural.php index 9fe804699a6..9571890f924 100644 --- a/library/Zend/I18n/View/Helper/Plural.php +++ b/library/Zend/I18n/View/Helper/Plural.php @@ -47,7 +47,7 @@ class Plural extends AbstractHelper */ public function setPluralRule($pluralRule) { - if (is_string($pluralRule)) { + if (!$pluralRule instanceof PluralRule) { $pluralRule = PluralRule::fromString($pluralRule); } From d7e70c137203bcfccaa1005fba3cb607e00b8b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 25 Sep 2012 16:16:27 +0200 Subject: [PATCH 082/126] Updated docblock --- library/Zend/I18n/View/Helper/Plural.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/I18n/View/Helper/Plural.php b/library/Zend/I18n/View/Helper/Plural.php index 9571890f924..3f073187ad8 100644 --- a/library/Zend/I18n/View/Helper/Plural.php +++ b/library/Zend/I18n/View/Helper/Plural.php @@ -43,7 +43,7 @@ class Plural extends AbstractHelper * Set the plural rule to use * * @param PluralRule|string $pluralRule - * @return self + * @return Plural */ public function setPluralRule($pluralRule) { From 7864834a035734821f1be85baecbd3cfa75d666f Mon Sep 17 00:00:00 2001 From: Jurgen Van de Moere Date: Tue, 25 Sep 2012 18:03:29 +0200 Subject: [PATCH 083/126] Fix trailing spaces Change-Id: I5e6aa688d783761c23d179b154a7fff8ef6785d4 --- library/Zend/Validator/IsInstanceOf.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Zend/Validator/IsInstanceOf.php b/library/Zend/Validator/IsInstanceOf.php index ab8866ab22e..fd6b1e03d1b 100644 --- a/library/Zend/Validator/IsInstanceOf.php +++ b/library/Zend/Validator/IsInstanceOf.php @@ -15,7 +15,7 @@ use Zend\Validator\AbstractValidator; class IsInstanceOf extends AbstractValidator -{ +{ const NOT_INSTANCE_OF = 'notInstanceOf'; /** @@ -106,4 +106,4 @@ public function isValid($value) $this->error(self::NOT_INSTANCE_OF); return false; } -} +} \ No newline at end of file From cc80c42f8e19134c72a75b0934a57fab7183f8ae Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 25 Sep 2012 11:38:06 -0500 Subject: [PATCH 084/126] CS fixes - EOF ending --- library/Zend/Code/Scanner/PropertyScanner.php | 2 +- library/Zend/Form/Element/DateSelect.php | 1 - library/Zend/Form/Element/MonthSelect.php | 1 - library/Zend/Form/View/Helper/FormDateSelect.php | 1 - library/Zend/Form/View/Helper/FormMonthSelect.php | 1 - library/Zend/Permissions/Acl/AclInterface.php | 2 +- library/Zend/View/Helper/HeadLink.php | 1 - .../Code/Annotation/TestAsset/EntityWithAnnotations.php | 2 +- tests/ZendTest/Serializer/Adapter/MsgPackTest.php | 2 +- tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php | 2 +- 10 files changed, 5 insertions(+), 10 deletions(-) diff --git a/library/Zend/Code/Scanner/PropertyScanner.php b/library/Zend/Code/Scanner/PropertyScanner.php index ffc1a0c02fb..1de3e988889 100644 --- a/library/Zend/Code/Scanner/PropertyScanner.php +++ b/library/Zend/Code/Scanner/PropertyScanner.php @@ -282,4 +282,4 @@ protected function scan() $this->isScanned = true; } -} \ No newline at end of file +} diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index 5b0fbb2527e..51f6ec27a99 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -155,4 +155,3 @@ public function getInputSpecification() ); } } - diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php index de3a6ba5fb9..14e4d770f4d 100644 --- a/library/Zend/Form/Element/MonthSelect.php +++ b/library/Zend/Form/Element/MonthSelect.php @@ -294,4 +294,3 @@ public function getInputSpecification() ); } } - diff --git a/library/Zend/Form/View/Helper/FormDateSelect.php b/library/Zend/Form/View/Helper/FormDateSelect.php index 70d87c4151a..55a05c52cd6 100644 --- a/library/Zend/Form/View/Helper/FormDateSelect.php +++ b/library/Zend/Form/View/Helper/FormDateSelect.php @@ -107,4 +107,3 @@ protected function getDaysOptions($pattern) return $result; } } - diff --git a/library/Zend/Form/View/Helper/FormMonthSelect.php b/library/Zend/Form/View/Helper/FormMonthSelect.php index d022dd27630..6f47247eac6 100644 --- a/library/Zend/Form/View/Helper/FormMonthSelect.php +++ b/library/Zend/Form/View/Helper/FormMonthSelect.php @@ -281,4 +281,3 @@ protected function getSelectElementHelper() return $this->selectHelper; } } - diff --git a/library/Zend/Permissions/Acl/AclInterface.php b/library/Zend/Permissions/Acl/AclInterface.php index 93beb4b341a..5f2cf94da97 100644 --- a/library/Zend/Permissions/Acl/AclInterface.php +++ b/library/Zend/Permissions/Acl/AclInterface.php @@ -54,4 +54,4 @@ public function hasResource($resource); * @return boolean */ public function isAllowed($role = null, $resource = null, $privilege = null); -} \ No newline at end of file +} diff --git a/library/Zend/View/Helper/HeadLink.php b/library/Zend/View/Helper/HeadLink.php index a5224a0d9e6..fff301c7c91 100644 --- a/library/Zend/View/Helper/HeadLink.php +++ b/library/Zend/View/Helper/HeadLink.php @@ -456,4 +456,3 @@ public function createDataNext(array $args) return $this->createData($attributes); } } - diff --git a/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php b/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php index 0472e5d6610..7e59b7db381 100644 --- a/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php +++ b/tests/ZendTest/Code/Annotation/TestAsset/EntityWithAnnotations.php @@ -25,4 +25,4 @@ class EntityWithAnnotations * @Bogus(does not exist) */ public $test; -} \ No newline at end of file +} diff --git a/tests/ZendTest/Serializer/Adapter/MsgPackTest.php b/tests/ZendTest/Serializer/Adapter/MsgPackTest.php index 90f0ee62220..7774ff7e113 100644 --- a/tests/ZendTest/Serializer/Adapter/MsgPackTest.php +++ b/tests/ZendTest/Serializer/Adapter/MsgPackTest.php @@ -151,4 +151,4 @@ public function testUnserialzeInvalid() ); $this->adapter->unserialize($value); } -} \ No newline at end of file +} diff --git a/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php b/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php index 1bd88c774a6..f36980de2c3 100644 --- a/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php +++ b/tests/ZendTest/Stdlib/Strategy/SerializableStrategyTest.php @@ -50,4 +50,4 @@ public function testCanUnserialize() $serialized = $serializerStrategy->hydrate('s:3:"foo";'); $this->assertEquals($serialized, 'foo'); } -} \ No newline at end of file +} From 9562484b097e00fea3ecaf216135ed7806f34479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Tue, 25 Sep 2012 18:45:27 +0200 Subject: [PATCH 085/126] Reorder parameters to not BC --- library/Zend/I18n/View/Helper/DateFormat.php | 6 +++--- tests/ZendTest/I18n/View/Helper/DateFormatTest.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/Zend/I18n/View/Helper/DateFormat.php b/library/Zend/I18n/View/Helper/DateFormat.php index a43f3940b7b..da40cddd8aa 100644 --- a/library/Zend/I18n/View/Helper/DateFormat.php +++ b/library/Zend/I18n/View/Helper/DateFormat.php @@ -108,16 +108,16 @@ public function getlocale() * @param DateTime|integer|array $date * @param int $dateType * @param int $timeType - * @param string|null $pattern * @param string $locale + * @param string|null $pattern * @return string */ public function __invoke( $date, $dateType = IntlDateFormatter::NONE, $timeType = IntlDateFormatter::NONE, - $pattern = null, - $locale = null + $locale = null, + $pattern = null ) { if ($locale === null) { $locale = $this->getlocale(); diff --git a/tests/ZendTest/I18n/View/Helper/DateFormatTest.php b/tests/ZendTest/I18n/View/Helper/DateFormatTest.php index 5192e1fe0fe..4ed864ec25c 100644 --- a/tests/ZendTest/I18n/View/Helper/DateFormatTest.php +++ b/tests/ZendTest/I18n/View/Helper/DateFormatTest.php @@ -210,7 +210,7 @@ public function testBasic($locale, $timezone, $timeType, $dateType, $date, $expe { $this->helper->setTimezone($timezone); $this->assertMbStringEquals($expected, $this->helper->__invoke( - $date, $dateType, $timeType, null, $locale + $date, $dateType, $timeType, $locale, null )); } @@ -235,7 +235,7 @@ public function testUseCustomPattern($locale, $timezone, $timeType, $dateType, $ { $this->helper->setTimezone($timezone); $this->assertMbStringEquals($expected, $this->helper->__invoke( - $date, $dateType, $timeType, $pattern, $locale + $date, $dateType, $timeType, $locale, $pattern )); } From 5ff1474068fff72b1e1a2e6d89b6ce6cf4dbbfca Mon Sep 17 00:00:00 2001 From: Jurgen Van de Moere Date: Tue, 25 Sep 2012 23:02:59 +0200 Subject: [PATCH 086/126] Validor suggestions implemented and entries added to ValidatorLoader Change-Id: Idd449f4a6ac538050e4ca2d114504668ebe7faaa --- library/Zend/Validator/IsInstanceOf.php | 31 ++++++++++++---------- library/Zend/Validator/ValidatorLoader.php | 5 +++- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/library/Zend/Validator/IsInstanceOf.php b/library/Zend/Validator/IsInstanceOf.php index fd6b1e03d1b..cb6e7767ca7 100644 --- a/library/Zend/Validator/IsInstanceOf.php +++ b/library/Zend/Validator/IsInstanceOf.php @@ -7,15 +7,16 @@ * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Validator */ - namespace Zend\Validator; use Traversable; use Zend\Stdlib\ArrayUtils; use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception\InvalidArgumentException; class IsInstanceOf extends AbstractValidator { + const NOT_INSTANCE_OF = 'notInstanceOf'; /** @@ -47,24 +48,26 @@ class IsInstanceOf extends AbstractValidator * Sets validator options * * @param array|Traversable $options - * @throws Exception\InvalidArgumentException + * @throws Zend\Validator\Exception\InvalidArgumentException */ - public function __construct($options = null) + public function __construct ($options = null) { if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } - if (!is_array($options)) { + + // If argument is not an array, consider first argument as class name + if (! is_array($options)) { $options = func_get_args(); $tmpOptions = array(); - $tmpOptions['classname'] = array_shift($options); - + $tmpOptions['className'] = array_shift($options); + $options = $tmpOptions; } - - if (!array_key_exists('className', $options)) { - throw new Exception\InvalidArgumentException("Missing option 'className'"); + + if (! array_key_exists('className', $options)) { + throw new InvalidArgumentException("Missing option 'className'"); } parent::__construct($options); @@ -75,7 +78,7 @@ public function __construct($options = null) * * @return string */ - public function getClassName() + public function getClassName () { return $this->className; } @@ -86,7 +89,7 @@ public function getClassName() * @param string $className * @return self */ - public function setClassName($className) + public function setClassName ($className) { $this->className = $className; return $this; @@ -98,12 +101,12 @@ public function setClassName($className) * @param mixed $value * @return boolean */ - public function isValid($value) + public function isValid ($value) { - if($value instanceof $this->className) { + if ($value instanceof $this->className) { return true; } $this->error(self::NOT_INSTANCE_OF); return false; } -} \ No newline at end of file +} diff --git a/library/Zend/Validator/ValidatorLoader.php b/library/Zend/Validator/ValidatorLoader.php index f9e4adcedd9..d52de5ecb6f 100644 --- a/library/Zend/Validator/ValidatorLoader.php +++ b/library/Zend/Validator/ValidatorLoader.php @@ -33,7 +33,7 @@ class ValidatorLoader extends PluginClassLoader { /** - * @var array Pre-aliased filter + * @var array Pre-aliased filter */ protected $plugins = array( 'alnum' => 'Zend\Validator\Alnum', @@ -224,6 +224,9 @@ class ValidatorLoader extends PluginClassLoader 'int' => 'Zend\Validator\Int', 'ip' => 'Zend\Validator\Ip', 'isbn' => 'Zend\Validator\Isbn', + 'isinstanceof' => 'Zend\Validator\IsInstanceOf', + 'is_instanceof' => 'Zend\Validator\IsInstanceOf', + 'is_instance_of' => 'Zend\Validator\IsInstanceOf', 'less_than' => 'Zend\Validator\LessThan', 'lessthan' => 'Zend\Validator\LessThan', 'not_empty' => 'Zend\Validator\NotEmpty', From 09bf94e509c5e02587ed713a578a92780ffd8ecb Mon Sep 17 00:00:00 2001 From: Jurgen Van de Moere Date: Wed, 26 Sep 2012 00:40:05 +0200 Subject: [PATCH 087/126] Added PHPUnit test IsInstanceOfTest for Zend\Validator\IsInstanceOf Change-Id: I11ad45466dc91e481e03f74936ca859fba44b70b --- tests/Zend/Validator/IsInstanceOfTest.php | 121 ++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 tests/Zend/Validator/IsInstanceOfTest.php diff --git a/tests/Zend/Validator/IsInstanceOfTest.php b/tests/Zend/Validator/IsInstanceOfTest.php new file mode 100644 index 00000000000..83d45e5a9ef --- /dev/null +++ b/tests/Zend/Validator/IsInstanceOfTest.php @@ -0,0 +1,121 @@ +assertTrue($validator->isValid(new \DateTime())); // True + $this->assertFalse($validator->isValid(null)); // False + $this->assertFalse($validator->isValid($this)); // False + + $validator = new Validator\IsInstanceOf('\Exception'); + + $this->assertTrue($validator->isValid(new \Exception())); // True + $this->assertFalse($validator->isValid(null)); // False + $this->assertFalse($validator->isValid($this)); // False + + $validator = new Validator\IsInstanceOf('\PHPUnit_Framework_TestCase'); + + $this->assertTrue($validator->isValid($this)); // True + } + + /** + * Ensures that getMessages() returns expected default value + * + * @return void + */ + public function testGetMessages () + { + $validator = new Validator\IsInstanceOf('\DateTime'); + $this->assertEquals(array(), $validator->getMessages()); + } + + /** + * Ensures that getClassName() returns expected value + * + * @return void + */ + public function testGetClassName () + { + $validator = new Validator\IsInstanceOf('\DateTime'); + $this->assertEquals('\DateTime', $validator->getClassName()); + } + + public function testEqualsMessageTemplates () + { + $validator = new Validator\IsInstanceOf('\DateTime'); + $reflection = new ReflectionClass($validator); + + if (! $reflection->hasProperty('_messageTemplates')) { + return; + } + + $property = $reflection->getProperty('_messageTemplates'); + $property->setAccessible(true); + + $this->assertEquals($property->getValue($validator), + $validator->getOption('messageTemplates')); + } + + public function testEqualsMessageVariables () + { + $validator = new Validator\IsInstanceOf('\DateTime'); + $reflection = new ReflectionClass($validator); + + if (! $reflection->hasProperty('_messageVariables')) { + return; + } + + $property = $reflection->getProperty('_messageVariables'); + $property->setAccessible(true); + + $this->assertEquals($property->getValue($validator), + $validator->getOption('messageVariables')); + } +} From 62e57ee520895656e2db26656932c352551db18a Mon Sep 17 00:00:00 2001 From: Jurgen Van de Moere Date: Wed, 26 Sep 2012 00:42:20 +0200 Subject: [PATCH 088/126] Corrected reference in comment Change-Id: Ib5e2b582481dd943941a5277630c6b0d39dd7191 --- tests/Zend/Validator/IsInstanceOfTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Zend/Validator/IsInstanceOfTest.php b/tests/Zend/Validator/IsInstanceOfTest.php index 83d45e5a9ef..494b0e21ea7 100644 --- a/tests/Zend/Validator/IsInstanceOfTest.php +++ b/tests/Zend/Validator/IsInstanceOfTest.php @@ -27,7 +27,7 @@ */ /** - * @see Zend_Validator_LessThan + * @see Zend_Validator_IsInstanceOf */ /** From b7668b223b9782e32e39d108ae763ebc3ea46f89 Mon Sep 17 00:00:00 2001 From: Robert Basic Date: Wed, 26 Sep 2012 11:06:23 +0200 Subject: [PATCH 089/126] Decorator plugin manager was pointing to an inexistent class --- library/Zend/Tag/Cloud/DecoratorPluginManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/Tag/Cloud/DecoratorPluginManager.php b/library/Zend/Tag/Cloud/DecoratorPluginManager.php index d885f53659e..316153c21c7 100644 --- a/library/Zend/Tag/Cloud/DecoratorPluginManager.php +++ b/library/Zend/Tag/Cloud/DecoratorPluginManager.php @@ -34,7 +34,7 @@ class DecoratorPluginManager extends AbstractPluginManager protected $invokableClasses = array( 'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud', 'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag', - 'tag' => 'Zend\Tag\Cloud\Decorator\Tag', + 'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag', ); /** From bce7cde8934687e8b089a94d8deed5ef8f0eb592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 26 Sep 2012 19:05:41 +0200 Subject: [PATCH 090/126] Fix bug with Collections --- library/Zend/Form/Element/DateSelect.php | 10 ++++++++++ library/Zend/Form/Element/MonthSelect.php | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/library/Zend/Form/Element/DateSelect.php b/library/Zend/Form/Element/DateSelect.php index 3038bbb88ad..4cc270e175d 100644 --- a/library/Zend/Form/Element/DateSelect.php +++ b/library/Zend/Form/Element/DateSelect.php @@ -163,5 +163,15 @@ public function getInputSpecification() ) ); } + + /** + * Clone the element (this is needed by Collection element, as it needs different copies of the elements) + */ + public function __clone() + { + $this->dayElement = clone $this->dayElement; + $this->monthElement = clone $this->monthElement; + $this->yearElement = clone $this->yearElement; + } } diff --git a/library/Zend/Form/Element/MonthSelect.php b/library/Zend/Form/Element/MonthSelect.php index 34fa7cbbb7c..adbd0f6843a 100644 --- a/library/Zend/Form/Element/MonthSelect.php +++ b/library/Zend/Form/Element/MonthSelect.php @@ -301,5 +301,14 @@ public function getInputSpecification() ) ); } + + /** + * Clone the element (this is needed by Collection element, as it needs different copies of the elements) + */ + public function __clone() + { + $this->monthElement = clone $this->monthElement; + $this->yearElement = clone $this->yearElement; + } } From 19c78a5612e8827488b17d560d8bef7b2a97a50f Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 27 Sep 2012 11:51:43 +0200 Subject: [PATCH 091/126] Added the scrypt key derivation algorithm --- library/Zend/Crypt/Hmac.php | 4 - library/Zend/Crypt/Key/Derivation/Scrypt.php | 343 ++++++++++++++++++ tests/ZendTest/Crypt/HmacTest.php | 7 - .../Crypt/Key/Derivation/ScryptTest.php | 195 ++++++++++ 4 files changed, 538 insertions(+), 11 deletions(-) create mode 100644 library/Zend/Crypt/Key/Derivation/Scrypt.php create mode 100644 tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php diff --git a/library/Zend/Crypt/Hmac.php b/library/Zend/Crypt/Hmac.php index 8c14f273da2..fc7dd2ba7bf 100644 --- a/library/Zend/Crypt/Hmac.php +++ b/library/Zend/Crypt/Hmac.php @@ -42,10 +42,6 @@ class Hmac */ public static function compute($key, $hash, $data, $output = self::OUTPUT_STRING) { - if (!isset($key) || empty($key)) { - throw new Exception\InvalidArgumentException('Provided key is null or empty'); - } - $hash = strtolower($hash); if (!self::isSupported($hash)) { throw new Exception\InvalidArgumentException( diff --git a/library/Zend/Crypt/Key/Derivation/Scrypt.php b/library/Zend/Crypt/Key/Derivation/Scrypt.php new file mode 100644 index 00000000000..f66103558d0 --- /dev/null +++ b/library/Zend/Crypt/Key/Derivation/Scrypt.php @@ -0,0 +1,343 @@ + 0 and a power of 2"); + } + if ($n > PHP_INT_MAX / 128 / $r) { + throw new Exception\InvalidArgumentException("Parameter n is too large"); + } + if ($r > PHP_INT_MAX / 128 / $p) { + throw new Exception\InvalidArgumentException("Parameter r is too large"); + } + + if (extension_loaded('Scrypt')) { + if ($length < 16) { + throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16"); + } + return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); + } + + $b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r); + + $s = ''; + for ($i = 0; $i < $p; $i++) { + $s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r); + } + + return Pbkdf2::calc('sha256', $password, $s, 1, $length); + } + + /** + * scryptROMix + * + * @param string $b + * @param integer $n + * @param integer $r + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 + */ + protected static function scryptROMix($b, $n, $r) + { + $x = $b; + $v = array(); + for ($i = 0; $i < $n; $i++) { + $v[$i] = $x; + $x = self::scryptBlockMix($x, $r); + } + for ($i = 0; $i < $n; $i++) { + $j = self::integerify($x) % $n; + $t = $x ^ $v[$j]; + $x = self::scryptBlockMix($t, $r); + } + return $x; + } + + /** + * scryptBlockMix + * + * @param string $b + * @param integer $r + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3 + */ + protected static function scryptBlockMix($b, $r) + { + $x = substr($b, -64); + $even = ''; + $odd = ''; + $len = 2 * $r; + + for ($i = 0; $i < $len; $i++) { + if (PHP_INT_SIZE === 4) { + $x = self::salsa208Core32($x ^ substr($b, 64 * $i, 64)); + } else { + $x = self::salsa208Core64($x ^ substr($b, 64 * $i, 64)); + } + if ($i % 2 == 0) { + $even .= $x; + } else { + $odd .= $x; + } + } + return $even . $odd; + } + + /** + * Salsa 20/8 core (32 bit version) + * + * @param string $b + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 + * @see http://cr.yp.to/salsa20.html + */ + protected static function salsa208Core32($b) + { + $b32 = array(); + for ($i = 0; $i < 16; $i++) { + list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); + } + + $x = $b32; + for ($i = 0; $i < 8; $i += 2) { + $a = ($x[ 0] + $x[12]); + $x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 4] + $x[ 0]); + $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 8] + $x[ 4]); + $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[12] + $x[ 8]); + $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[ 5] + $x[ 1]); + $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 9] + $x[ 5]); + $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[13] + $x[ 9]); + $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 1] + $x[13]); + $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[10] + $x[ 6]); + $x[14] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[14] + $x[10]); + $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 2] + $x[14]); + $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 6] + $x[ 2]); + $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[15] + $x[11]); + $x[ 3] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 3] + $x[15]); + $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 7] + $x[ 3]); + $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[11] + $x[ 7]); + $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[ 0] + $x[ 3]); + $x[ 1] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 1] + $x[ 0]); + $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 2] + $x[ 1]); + $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 3] + $x[ 2]); + $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[ 5] + $x[ 4]); + $x[ 6] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 6] + $x[ 5]); + $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 7] + $x[ 6]); + $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 4] + $x[ 7]); + $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[10] + $x[ 9]); + $x[11] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[11] + $x[10]); + $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 8] + $x[11]); + $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 9] + $x[ 8]); + $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[15] + $x[14]); + $x[12] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[12] + $x[15]); + $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[13] + $x[12]); + $x[14] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[14] + $x[13]); + $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + } + for ($i = 0; $i < 16; $i++) { + $b32[$i] = $b32[$i] + $x[$i]; + } + $result = ''; + for ($i = 0; $i < 16; $i++) { + $result .= pack("V", $b32[$i]); + } + + return $result; + } + + /** + * Salsa 20/8 core (64 bit version) + * + * @param string $b + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 + * @see http://cr.yp.to/salsa20.html + */ + protected static function salsa208Core64($b) + { + $b32 = array(); + for ($i = 0; $i < 16; $i++) { + list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); + } + + $x = $b32; + for ($i = 0; $i < 8; $i += 2) { + $a = ($x[ 0] + $x[12]) & 0xffffffff; + $x[ 4] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 4] + $x[ 0]) & 0xffffffff; + $x[ 8] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 8] + $x[ 4]) & 0xffffffff; + $x[12] ^= ($a << 13) | ($a >> 19); + $a = ($x[12] + $x[ 8]) & 0xffffffff; + $x[ 0] ^= ($a << 18) | ($a >> 14); + $a = ($x[ 5] + $x[ 1]) & 0xffffffff; + $x[ 9] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 9] + $x[ 5]) & 0xffffffff; + $x[13] ^= ($a << 9) | ($a >> 23); + $a = ($x[13] + $x[ 9]) & 0xffffffff; + $x[ 1] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 1] + $x[13]) & 0xffffffff; + $x[ 5] ^= ($a << 18) | ($a >> 14); + $a = ($x[10] + $x[ 6]) & 0xffffffff; + $x[14] ^= ($a << 7) | ($a >> 25); + $a = ($x[14] + $x[10]) & 0xffffffff; + $x[ 2] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 2] + $x[14]) & 0xffffffff; + $x[ 6] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 6] + $x[ 2]) & 0xffffffff; + $x[10] ^= ($a << 18) | ($a >> 14); + $a = ($x[15] + $x[11]) & 0xffffffff; + $x[ 3] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 3] + $x[15]) & 0xffffffff; + $x[ 7] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 7] + $x[ 3]) & 0xffffffff; + $x[11] ^= ($a << 13) | ($a >> 19); + $a = ($x[11] + $x[ 7]) & 0xffffffff; + $x[15] ^= ($a << 18) | ($a >> 14); + $a = ($x[ 0] + $x[ 3]) & 0xffffffff; + $x[ 1] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 1] + $x[ 0]) & 0xffffffff; + $x[ 2] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 2] + $x[ 1]) & 0xffffffff; + $x[ 3] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 3] + $x[ 2]) & 0xffffffff; + $x[ 0] ^= ($a << 18) | ($a >> 14); + $a = ($x[ 5] + $x[ 4]) & 0xffffffff; + $x[ 6] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 6] + $x[ 5]) & 0xffffffff; + $x[ 7] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 7] + $x[ 6]) & 0xffffffff; + $x[ 4] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 4] + $x[ 7]) & 0xffffffff; + $x[ 5] ^= ($a << 18) | ($a >> 14); + $a = ($x[10] + $x[ 9]) & 0xffffffff; + $x[11] ^= ($a << 7) | ($a >> 25); + $a = ($x[11] + $x[10]) & 0xffffffff; + $x[ 8] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 8] + $x[11]) & 0xffffffff; + $x[ 9] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 9] + $x[ 8]) & 0xffffffff; + $x[10] ^= ($a << 18) | ($a >> 14); + $a = ($x[15] + $x[14]) & 0xffffffff; + $x[12] ^= ($a << 7) | ($a >> 25); + $a = ($x[12] + $x[15]) & 0xffffffff; + $x[13] ^= ($a << 9) | ($a >> 23); + $a = ($x[13] + $x[12]) & 0xffffffff; + $x[14] ^= ($a << 13) | ($a >> 19); + $a = ($x[14] + $x[13]) & 0xffffffff; + $x[15] ^= ($a << 18) | ($a >> 14); + } + for ($i = 0; $i < 16; $i++) { + $b32[$i] = ($b32[$i] + $x[$i]) & 0xffffffff; + } + $result = ''; + for ($i = 0; $i < 16; $i++) { + $result .= pack("V", $b32[$i]); + } + + return $result; + } + + /** + * Integerify + * + * Integerify (B[0] ... B[2 * r - 1]) is defined as the result + * of interpreting B[2 * r - 1] as a little-endian integer. + * Each block B is a string of 64 bytes. + * + * @param string $b + * @return integer + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 + */ + protected static function integerify($b) { + $v = 'v'; + if (PHP_INT_SIZE === 8) { + $v = 'V'; + } + list(,$n) = unpack($v, substr($b, -64)); + return $n; + } + + /** + * Convert hex string in a binary string + * + * @param string $hex + * @return string + */ + protected static function hex2bin($hex) { + if (version_compare(PHP_VERSION, '5.4') >= 0) { + return hex2bin($hex); + } + $len = strlen($hex); + $result = ''; + for ($i = 0; $i < $len; $i+=2) { + $result .= chr(hexdec($hex[$i] . $hex[$i+1])); + } + return $result; + } +} diff --git a/tests/ZendTest/Crypt/HmacTest.php b/tests/ZendTest/Crypt/HmacTest.php index c71b35dbdf7..a6d70ec7ab7 100644 --- a/tests/ZendTest/Crypt/HmacTest.php +++ b/tests/ZendTest/Crypt/HmacTest.php @@ -200,13 +200,6 @@ public function testHmacRIPEMD160_7() $this->assertEquals('69ea60798d71616cce5fd0871e23754cd75d5a0a', $hmac); } - public function testEmptyKey() - { - $this->setExpectedException('Zend\Crypt\Exception\InvalidArgumentException', - 'Provided key is null or empty'); - $hash = HMAC::compute(null, 'md5', 'test'); - } - public function testWrongHashAlgorithm() { $this->setExpectedException('Zend\Crypt\Exception\InvalidArgumentException', diff --git a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php new file mode 100644 index 00000000000..240100b0bac --- /dev/null +++ b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php @@ -0,0 +1,195 @@ +getMethod($name); + $method->setAccessible(true); + return $method; + } + + /** + * Test vector of Salsa 20/8 core + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7 + */ + public function testVectorSalsa208Core() + { + $hexInput = '7e 87 9a 21 4f 3e c9 86 7c a9 40 e6 41 71 8f 26 + ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d + ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32 + 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e'; + + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 + 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 + b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba + e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81'; + + + $salsaAlg = 'salsa208Core32'; + if (PHP_INT_SIZE === 8) { + $salsaAlg = 'salsa208Core64'; + } + $salsa20 = self::getMethod($salsaAlg); + $obj = new Scrypt; + $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput)); + $result = $salsa20->invokeArgs($obj, array($input)); + + $this->assertEquals(64, strlen($input), 'Input must be a string of 64 bytes'); + $this->assertEquals(64, strlen($result), 'Output must be a string of 64 bytes'); + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + /** + * Test vector of Scrypt BlockMix + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8 + */ + public function testVectorScryptBlockMix() + { + $hexInput = 'f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd + 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad + 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 + 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 + + 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb + cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 + 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b + 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89'; + + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 + 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 + b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba + e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81 + + 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c + 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7 + 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6 + 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25'; + + $blockMix = self::getMethod('scryptBlockMix'); + $obj = new Scrypt; + $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); + $result = $blockMix->invokeArgs($obj, array($input, 1)); + + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + + /** + * Test vector of Scrypt ROMix + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-9 + */ + public function testVectorScryptROMix() + { + $hexInput = 'f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd + 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad + 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 + 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 + 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb + cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 + 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b + 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89'; + + $hexOutput = '79 cc c1 93 62 9d eb ca 04 7f 0b 70 60 4b f6 b6 + 2c e3 dd 4a 96 26 e3 55 fa fc 61 98 e6 ea 2b 46 + d5 84 13 67 3b 99 b0 29 d6 65 c3 57 60 1f b4 26 + a0 b2 f4 bb a2 00 ee 9f 0a 43 d1 9b 57 1a 9c 71 + ef 11 42 e6 5d 5a 26 6f dd ca 83 2c e5 9f aa 7c + ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4 + ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f + 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e'; + + + $roMix = self::getMethod('scryptROMix'); + $obj = new Scrypt; + $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); + $result = $roMix->invokeArgs($obj, array($input, 16, 1)); + + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + + + /** + * Test Vector Scrypt + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-11 + */ + public function testVectorScrypt() + { + $hexOutput = '77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 + f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 + fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 + e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06'; + + $result = Scrypt::calc('', '', 16, 1, 1, 64); + $this->assertEquals(64, strlen($result)); + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + + /** + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + */ + public function testScryptWrongN() + { + $result = Scrypt::calc('test', 'salt', 17, 1, 1, 64); + $result = Scrypt::calc('test', 'salt', PHP_INT_MAX, 1, 1, 64); + } + + /** + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + */ + public function testScryptWrongR() + { + $result = Scrypt::calc('test', 'salt', PHP_INT_MAX / 128, 4, 1, 64); + } + + /** + * Test scrypt correct size output + */ + public function testScryptSize() + { + for ($size = 0; $size < 64; $size++) { + if (extension_loaded('Scrypt') && ($size < 16)) { + $this->setExpectedException('Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException'); + } + $result = Scrypt::calc('test', 'salt', 16, 1, 1, $size); + $this->assertEquals($size, strlen($result)); + } + } + + /** + * Convert a string with hex values in binary string + * + * @param string $hex + * @return string + */ + protected static function hex2bin($hex) + { + $len = strlen($hex); + $result = ''; + for ($i = 0; $i < $len; $i += 2) { + $result .= chr(hexdec($hex[$i] . $hex[$i+1])); + } + return $result; + } +} From b37ca184d8be70acb1275b887ee4c443b4f6129f Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 27 Sep 2012 12:15:45 +0200 Subject: [PATCH 092/126] Fixed PSR2 for scrypt --- library/Zend/Crypt/Key/Derivation/Scrypt.php | 128 +++++++++--------- .../Crypt/Key/Derivation/ScryptTest.php | 57 ++++---- 2 files changed, 94 insertions(+), 91 deletions(-) diff --git a/library/Zend/Crypt/Key/Derivation/Scrypt.php b/library/Zend/Crypt/Key/Derivation/Scrypt.php index f66103558d0..3e10946f744 100644 --- a/library/Zend/Crypt/Key/Derivation/Scrypt.php +++ b/library/Zend/Crypt/Key/Derivation/Scrypt.php @@ -13,19 +13,19 @@ use Zend\Crypt\Key\Derivation\Pbkdf2; /** - * Scrypt key derivation function - * + * Scrypt key derivation function + * * @category Zend * @package Zend_Crypt - * @see http://www.tarsnap.com/scrypt.html + * @see http://www.tarsnap.com/scrypt.html * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01 */ class Scrypt -{ +{ /** * Execute the scrypt algorithm - * - * @param string $password + * + * @param string $password * @param string $salt * @param integer $n CPU cost * @param integer $r Memory cost @@ -33,7 +33,7 @@ class Scrypt * @param integer $length size of the output key * @return string */ - public static function calc($password, $salt, $n, $r, $p, $length) + public static function calc($password, $salt, $n, $r, $p, $length) { if ($n == 0 || ($n & ($n - 1)) != 0) { throw new Exception\InvalidArgumentException("N must be > 0 and a power of 2"); @@ -44,31 +44,31 @@ public static function calc($password, $salt, $n, $r, $p, $length) if ($r > PHP_INT_MAX / 128 / $p) { throw new Exception\InvalidArgumentException("Parameter r is too large"); } - + if (extension_loaded('Scrypt')) { if ($length < 16) { throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16"); } - return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); + return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); } - + $b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r); $s = ''; for ($i = 0; $i < $p; $i++) { $s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r); } - + return Pbkdf2::calc('sha256', $password, $s, 1, $length); } - + /** * scryptROMix - * + * * @param string $b * @param integer $n * @param integer $r - * @return string + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 */ protected static function scryptROMix($b, $n, $r) @@ -86,13 +86,13 @@ protected static function scryptROMix($b, $n, $r) } return $x; } - + /** * scryptBlockMix - * + * * @param string $b * @param integer $r - * @return string + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3 */ protected static function scryptBlockMix($b, $r) @@ -101,7 +101,7 @@ protected static function scryptBlockMix($b, $r) $even = ''; $odd = ''; $len = 2 * $r; - + for ($i = 0; $i < $len; $i++) { if (PHP_INT_SIZE === 4) { $x = self::salsa208Core32($x ^ substr($b, 64 * $i, 64)); @@ -116,38 +116,38 @@ protected static function scryptBlockMix($b, $r) } return $even . $odd; } - + /** * Salsa 20/8 core (32 bit version) - * - * @param string $b - * @return string + * + * @param string $b + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 * @see http://cr.yp.to/salsa20.html */ - protected static function salsa208Core32($b) - { + protected static function salsa208Core32($b) + { $b32 = array(); for ($i = 0; $i < 16; $i++) { list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); } - - $x = $b32; + + $x = $b32; for ($i = 0; $i < 8; $i += 2) { $a = ($x[ 0] + $x[12]); $x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f; $a = ($x[ 4] + $x[ 0]); $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 8] + $x[ 4]); - $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[12] + $x[ 8]); $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[ 5] + $x[ 1]); - $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f; + $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f; $a = ($x[ 9] + $x[ 5]); - $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[13] + $x[ 9]); - $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 1] + $x[13]); $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[10] + $x[ 6]); @@ -155,7 +155,7 @@ protected static function salsa208Core32($b) $a = ($x[14] + $x[10]); $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 2] + $x[14]); - $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 6] + $x[ 2]); $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[15] + $x[11]); @@ -163,7 +163,7 @@ protected static function salsa208Core32($b) $a = ($x[ 3] + $x[15]); $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 7] + $x[ 3]); - $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[11] + $x[ 7]); $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[ 0] + $x[ 3]); @@ -171,7 +171,7 @@ protected static function salsa208Core32($b) $a = ($x[ 1] + $x[ 0]); $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 2] + $x[ 1]); - $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 3] + $x[ 2]); $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[ 5] + $x[ 4]); @@ -179,7 +179,7 @@ protected static function salsa208Core32($b) $a = ($x[ 6] + $x[ 5]); $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 7] + $x[ 6]); - $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 4] + $x[ 7]); $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[10] + $x[ 9]); @@ -187,7 +187,7 @@ protected static function salsa208Core32($b) $a = ($x[11] + $x[10]); $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 8] + $x[11]); - $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 9] + $x[ 8]); $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[15] + $x[14]); @@ -206,41 +206,41 @@ protected static function salsa208Core32($b) for ($i = 0; $i < 16; $i++) { $result .= pack("V", $b32[$i]); } - + return $result; } - + /** * Salsa 20/8 core (64 bit version) - * - * @param string $b - * @return string + * + * @param string $b + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 * @see http://cr.yp.to/salsa20.html */ - protected static function salsa208Core64($b) - { + protected static function salsa208Core64($b) + { $b32 = array(); for ($i = 0; $i < 16; $i++) { list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); } - + $x = $b32; for ($i = 0; $i < 8; $i += 2) { $a = ($x[ 0] + $x[12]) & 0xffffffff; - $x[ 4] ^= ($a << 7) | ($a >> 25); + $x[ 4] ^= ($a << 7) | ($a >> 25); $a = ($x[ 4] + $x[ 0]) & 0xffffffff; $x[ 8] ^= ($a << 9) | ($a >> 23); $a = ($x[ 8] + $x[ 4]) & 0xffffffff; - $x[12] ^= ($a << 13) | ($a >> 19); + $x[12] ^= ($a << 13) | ($a >> 19); $a = ($x[12] + $x[ 8]) & 0xffffffff; $x[ 0] ^= ($a << 18) | ($a >> 14); $a = ($x[ 5] + $x[ 1]) & 0xffffffff; - $x[ 9] ^= ($a << 7) | ($a >> 25); + $x[ 9] ^= ($a << 7) | ($a >> 25); $a = ($x[ 9] + $x[ 5]) & 0xffffffff; - $x[13] ^= ($a << 9) | ($a >> 23); + $x[13] ^= ($a << 9) | ($a >> 23); $a = ($x[13] + $x[ 9]) & 0xffffffff; - $x[ 1] ^= ($a << 13) | ($a >> 19); + $x[ 1] ^= ($a << 13) | ($a >> 19); $a = ($x[ 1] + $x[13]) & 0xffffffff; $x[ 5] ^= ($a << 18) | ($a >> 14); $a = ($x[10] + $x[ 6]) & 0xffffffff; @@ -248,7 +248,7 @@ protected static function salsa208Core64($b) $a = ($x[14] + $x[10]) & 0xffffffff; $x[ 2] ^= ($a << 9) | ($a >> 23); $a = ($x[ 2] + $x[14]) & 0xffffffff; - $x[ 6] ^= ($a << 13) | ($a >> 19); + $x[ 6] ^= ($a << 13) | ($a >> 19); $a = ($x[ 6] + $x[ 2]) & 0xffffffff; $x[10] ^= ($a << 18) | ($a >> 14); $a = ($x[15] + $x[11]) & 0xffffffff; @@ -256,7 +256,7 @@ protected static function salsa208Core64($b) $a = ($x[ 3] + $x[15]) & 0xffffffff; $x[ 7] ^= ($a << 9) | ($a >> 23); $a = ($x[ 7] + $x[ 3]) & 0xffffffff; - $x[11] ^= ($a << 13) | ($a >> 19); + $x[11] ^= ($a << 13) | ($a >> 19); $a = ($x[11] + $x[ 7]) & 0xffffffff; $x[15] ^= ($a << 18) | ($a >> 14); $a = ($x[ 0] + $x[ 3]) & 0xffffffff; @@ -264,7 +264,7 @@ protected static function salsa208Core64($b) $a = ($x[ 1] + $x[ 0]) & 0xffffffff; $x[ 2] ^= ($a << 9) | ($a >> 23); $a = ($x[ 2] + $x[ 1]) & 0xffffffff; - $x[ 3] ^= ($a << 13) | ($a >> 19); + $x[ 3] ^= ($a << 13) | ($a >> 19); $a = ($x[ 3] + $x[ 2]) & 0xffffffff; $x[ 0] ^= ($a << 18) | ($a >> 14); $a = ($x[ 5] + $x[ 4]) & 0xffffffff; @@ -272,7 +272,7 @@ protected static function salsa208Core64($b) $a = ($x[ 6] + $x[ 5]) & 0xffffffff; $x[ 7] ^= ($a << 9) | ($a >> 23); $a = ($x[ 7] + $x[ 6]) & 0xffffffff; - $x[ 4] ^= ($a << 13) | ($a >> 19); + $x[ 4] ^= ($a << 13) | ($a >> 19); $a = ($x[ 4] + $x[ 7]) & 0xffffffff; $x[ 5] ^= ($a << 18) | ($a >> 14); $a = ($x[10] + $x[ 9]) & 0xffffffff; @@ -280,7 +280,7 @@ protected static function salsa208Core64($b) $a = ($x[11] + $x[10]) & 0xffffffff; $x[ 8] ^= ($a << 9) | ($a >> 23); $a = ($x[ 8] + $x[11]) & 0xffffffff; - $x[ 9] ^= ($a << 13) | ($a >> 19); + $x[ 9] ^= ($a << 13) | ($a >> 19); $a = ($x[ 9] + $x[ 8]) & 0xffffffff; $x[10] ^= ($a << 18) | ($a >> 14); $a = ($x[15] + $x[14]) & 0xffffffff; @@ -299,22 +299,23 @@ protected static function salsa208Core64($b) for ($i = 0; $i < 16; $i++) { $result .= pack("V", $b32[$i]); } - + return $result; } - + /** * Integerify - * + * * Integerify (B[0] ... B[2 * r - 1]) is defined as the result * of interpreting B[2 * r - 1] as a little-endian integer. * Each block B is a string of 64 bytes. - * + * * @param string $b - * @return integer + * @return integer * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 */ - protected static function integerify($b) { + protected static function integerify($b) + { $v = 'v'; if (PHP_INT_SIZE === 8) { $v = 'V'; @@ -322,14 +323,15 @@ protected static function integerify($b) { list(,$n) = unpack($v, substr($b, -64)); return $n; } - + /** * Convert hex string in a binary string - * + * * @param string $hex - * @return string + * @return string */ - protected static function hex2bin($hex) { + protected static function hex2bin($hex) + { if (version_compare(PHP_VERSION, '5.4') >= 0) { return hex2bin($hex); } diff --git a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php index 240100b0bac..cb6e3316ad9 100644 --- a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php +++ b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php @@ -21,7 +21,8 @@ class ScryptTest extends \PHPUnit_Framework_TestCase { - protected static function getMethod($name) { + protected static function getMethod($name) + { $class = new \ReflectionClass('Zend\Crypt\Key\Derivation\Scrypt'); $method = $class->getMethod($name); $method->setAccessible(true); @@ -30,8 +31,8 @@ protected static function getMethod($name) { /** * Test vector of Salsa 20/8 core - * - * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7 + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7 */ public function testVectorSalsa208Core() { @@ -39,7 +40,7 @@ public function testVectorSalsa208Core() ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e'; - + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba @@ -54,15 +55,15 @@ public function testVectorSalsa208Core() $obj = new Scrypt; $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput)); $result = $salsa20->invokeArgs($obj, array($input)); - + $this->assertEquals(64, strlen($input), 'Input must be a string of 64 bytes'); $this->assertEquals(64, strlen($result), 'Output must be a string of 64 bytes'); $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } /** * Test vector of Scrypt BlockMix - * - * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8 + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8 */ public function testVectorScryptBlockMix() { @@ -70,22 +71,22 @@ public function testVectorScryptBlockMix() 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 - + 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89'; - + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81 - + 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25'; - + $blockMix = self::getMethod('scryptBlockMix'); $obj = new Scrypt; $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); @@ -93,10 +94,10 @@ public function testVectorScryptBlockMix() $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } - + /** - * Test vector of Scrypt ROMix - * + * Test vector of Scrypt ROMix + * * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-9 */ public function testVectorScryptROMix() @@ -118,8 +119,8 @@ public function testVectorScryptROMix() ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4 ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e'; - - + + $roMix = self::getMethod('scryptROMix'); $obj = new Scrypt; $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); @@ -127,11 +128,11 @@ public function testVectorScryptROMix() $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } - - + + /** * Test Vector Scrypt - * + * * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-11 */ public function testVectorScrypt() @@ -140,31 +141,31 @@ public function testVectorScrypt() f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06'; - + $result = Scrypt::calc('', '', 16, 1, 1, 64); $this->assertEquals(64, strlen($result)); $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } /** - * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException */ public function testScryptWrongN() { $result = Scrypt::calc('test', 'salt', 17, 1, 1, 64); $result = Scrypt::calc('test', 'salt', PHP_INT_MAX, 1, 1, 64); } - + /** - * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException */ public function testScryptWrongR() { $result = Scrypt::calc('test', 'salt', PHP_INT_MAX / 128, 4, 1, 64); } - + /** - * Test scrypt correct size output + * Test scrypt correct size output */ public function testScryptSize() { @@ -176,12 +177,12 @@ public function testScryptSize() $this->assertEquals($size, strlen($result)); } } - + /** * Convert a string with hex values in binary string - * + * * @param string $hex - * @return string + * @return string */ protected static function hex2bin($hex) { From f259efd742d8ed8d904db748846e43e417f5a807 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 27 Sep 2012 17:31:01 +0200 Subject: [PATCH 093/126] Changed Scrypt in abstract class --- library/Zend/Crypt/Key/Derivation/Scrypt.php | 2 +- tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Zend/Crypt/Key/Derivation/Scrypt.php b/library/Zend/Crypt/Key/Derivation/Scrypt.php index 3e10946f744..cd6d82ab6e0 100644 --- a/library/Zend/Crypt/Key/Derivation/Scrypt.php +++ b/library/Zend/Crypt/Key/Derivation/Scrypt.php @@ -20,7 +20,7 @@ * @see http://www.tarsnap.com/scrypt.html * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01 */ -class Scrypt +abstract class Scrypt { /** * Execute the scrypt algorithm diff --git a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php index cb6e3316ad9..0a8498c1b07 100644 --- a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php +++ b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php @@ -52,7 +52,7 @@ public function testVectorSalsa208Core() $salsaAlg = 'salsa208Core64'; } $salsa20 = self::getMethod($salsaAlg); - $obj = new Scrypt; + $obj = $this->getMockForAbstractClass('Zend\Crypt\Key\Derivation\Scrypt'); $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput)); $result = $salsa20->invokeArgs($obj, array($input)); @@ -88,7 +88,7 @@ public function testVectorScryptBlockMix() 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25'; $blockMix = self::getMethod('scryptBlockMix'); - $obj = new Scrypt; + $obj = $this->getMockForAbstractClass('Zend\Crypt\Key\Derivation\Scrypt'); $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); $result = $blockMix->invokeArgs($obj, array($input, 1)); @@ -122,7 +122,7 @@ public function testVectorScryptROMix() $roMix = self::getMethod('scryptROMix'); - $obj = new Scrypt; + $obj = $this->getMockForAbstractClass('Zend\Crypt\Key\Derivation\Scrypt'); $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); $result = $roMix->invokeArgs($obj, array($input, 16, 1)); From 06760ba5dd50164a525a9d326b3f59a5aa42b67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Fri, 28 Sep 2012 22:07:46 +0200 Subject: [PATCH 094/126] try to make tests pass --- library/Zend/I18n/View/Helper/Plural.php | 1 - tests/ZendTest/I18n/View/Helper/PluralTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/library/Zend/I18n/View/Helper/Plural.php b/library/Zend/I18n/View/Helper/Plural.php index 3f073187ad8..10faf2a0080 100644 --- a/library/Zend/I18n/View/Helper/Plural.php +++ b/library/Zend/I18n/View/Helper/Plural.php @@ -82,4 +82,3 @@ public function __invoke($strings, $number) return $strings[$pluralIndex]; } } - diff --git a/tests/ZendTest/I18n/View/Helper/PluralTest.php b/tests/ZendTest/I18n/View/Helper/PluralTest.php index ce51f763258..dbb0d37b5c9 100644 --- a/tests/ZendTest/I18n/View/Helper/PluralTest.php +++ b/tests/ZendTest/I18n/View/Helper/PluralTest.php @@ -66,4 +66,3 @@ public function testGetCorrectPlurals($pluralRule, $strings, $number, $expected) $this->assertEquals($expected, $result); } } - From 98667170178374de2c7991ecc863ef4c2dde8ae9 Mon Sep 17 00:00:00 2001 From: Kyle Spraggs Date: Sat, 29 Sep 2012 00:07:51 -0500 Subject: [PATCH 095/126] Initial ZF2 RBAC Component --- .../Permissions/Rbac/AbstractIterator.php | 102 +++++++++++ .../Zend/Permissions/Rbac/AbstractRole.php | 124 ++++++++++++++ .../Permissions/Rbac/AssertionInterface.php | 27 +++ .../Rbac/Exception/ExceptionInterface.php | 19 +++ .../Exception/InvalidArgumentException.php | 20 +++ library/Zend/Permissions/Rbac/Rbac.php | 159 ++++++++++++++++++ library/Zend/Permissions/Rbac/Role.php | 27 +++ tests/ZendTest/Permissions/Rbac/RbacTest.php | 144 ++++++++++++++++ .../Rbac/TestAsset/RoleMustMatchAssertion.php | 45 +++++ .../Rbac/TestAsset/SimpleFalseAssertion.php | 34 ++++ .../Rbac/TestAsset/SimpleTrueAssertion.php | 34 ++++ 11 files changed, 735 insertions(+) create mode 100644 library/Zend/Permissions/Rbac/AbstractIterator.php create mode 100644 library/Zend/Permissions/Rbac/AbstractRole.php create mode 100644 library/Zend/Permissions/Rbac/AssertionInterface.php create mode 100644 library/Zend/Permissions/Rbac/Exception/ExceptionInterface.php create mode 100644 library/Zend/Permissions/Rbac/Exception/InvalidArgumentException.php create mode 100644 library/Zend/Permissions/Rbac/Rbac.php create mode 100644 library/Zend/Permissions/Rbac/Role.php create mode 100644 tests/ZendTest/Permissions/Rbac/RbacTest.php create mode 100644 tests/ZendTest/Permissions/Rbac/TestAsset/RoleMustMatchAssertion.php create mode 100644 tests/ZendTest/Permissions/Rbac/TestAsset/SimpleFalseAssertion.php create mode 100644 tests/ZendTest/Permissions/Rbac/TestAsset/SimpleTrueAssertion.php diff --git a/library/Zend/Permissions/Rbac/AbstractIterator.php b/library/Zend/Permissions/Rbac/AbstractIterator.php new file mode 100644 index 00000000000..be9fd93cf47 --- /dev/null +++ b/library/Zend/Permissions/Rbac/AbstractIterator.php @@ -0,0 +1,102 @@ + + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return mixed Can return any type. + */ + public function current() + { + return $this->children[$this->index]; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + $this->index++; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return scalar scalar on success, or null on failure. + */ + public function key() + { + return $this->index; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->children[$this->index]); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->index = 0; + } + + /** + * (PHP 5 >= 5.1.0)
+ * Returns if an iterator can be created fot the current entry. + * @link http://php.net/manual/en/recursiveiterator.haschildren.php + * @return bool true if the current entry can be iterated over, otherwise returns false. + */ + public function hasChildren() + { + return count($this->children) > 0; + } + + /** + * (PHP 5 >= 5.1.0)
+ * Returns an iterator for the current entry. + * @link http://php.net/manual/en/recursiveiterator.getRoles.php + * @return RecursiveIterator An iterator for the current entry. + */ + public function getChildren() + { + return $this->children[$this->index]; + } +} diff --git a/library/Zend/Permissions/Rbac/AbstractRole.php b/library/Zend/Permissions/Rbac/AbstractRole.php new file mode 100644 index 00000000000..85de86a11a6 --- /dev/null +++ b/library/Zend/Permissions/Rbac/AbstractRole.php @@ -0,0 +1,124 @@ +name; + } + + /** + * Add permission to the role. + * + * @param $name + * @return AbstractRole + */ + public function addPermission($name) + { + $this->permissions[$name] = true; + + return $this; + } + + /** + * Checks if a permission exists for this role or any child roles. + * + * @param string $name + * @return bool + */ + public function hasPermission($name) + { + if (isset($this->permissions[$name])) { + return true; + } + + $it = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($it as $leaf) { + /** @var AbstractRole $leaf */ + if ($leaf->hasPermission($name)) { + return true; + } + } + + return false; + } + + /** + * Add a child. + * + * @param AbstractRole|string $child + * @return Role + */ + public function addChild($child) + { + if (is_string($child)) { + $child = new Role($child); + } + if (!$child instanceof AbstractRole) { + throw new Exception\InvalidArgumentException( + 'Child must be a string or instance of Zend\Permissions\Rbac\AbstractRole' + ); + } + + $child->setParent($this); + $this->children[] = $child; + + return $this; + } + + /** + * @param AbstractRole $parent + * @return AbstractRole + */ + public function setParent($parent) + { + $this->parent = $parent; + + return $this; + } + + /** + * @return null|AbstractRole + */ + public function getParent() + { + return $this->parent; + } +} diff --git a/library/Zend/Permissions/Rbac/AssertionInterface.php b/library/Zend/Permissions/Rbac/AssertionInterface.php new file mode 100644 index 00000000000..868ed7fd616 --- /dev/null +++ b/library/Zend/Permissions/Rbac/AssertionInterface.php @@ -0,0 +1,27 @@ +createMissingRoles = $createMissingRoles; + + return $this; + } + + /** + * @return boolean + */ + public function getCreateMissingRoles() + { + return $this->createMissingRoles; + } + + /** + * Add a child. + * + * @param string|AbstractRole $child + * @return AbstractRole + * @throws Exception\InvalidArgumentException + */ + public function addRole($child, $parents = null) + { + if (is_string($child)) { + $child = new Role($child); + } + if (!$child instanceof AbstractRole) { + throw new Exception\InvalidArgumentException( + 'Child must be a string or instance of Zend\Permissions\Rbac\AbstractRole' + ); + } + + if ($parents) { + if (!is_array($parents)) { + $parents = array($parents); + } + foreach ($parents as $parent) { + if ($this->createMissingRoles && !$this->hasRole($parent)) { + $this->addRole($parent); + } + $this->getRole($parent)->addChild($child); + } + } + + $this->children[] = $child; + + return $this; + } + + /** + * Is a child with $name registered? + * + * @param \Zend\Permissions\Rbac\AbstractRole|string $objectOrName + * @return bool + */ + public function hasRole($objectOrName) + { + try { + $this->getRole($objectOrName); + + return true; + } catch (Exception\InvalidArgumentException $e) { + return false; + } + } + + /** + * Get a child. + * + * @param \Zend\Permissions\Rbac\AbstractRole|string $objectOrName + * @return AbstractRole + * @throws Exception\InvalidArgumentException + */ + public function getRole($objectOrName) + { + if (!is_string($objectOrName) && !$objectOrName instanceof AbstractRole) { + throw new Exception\InvalidArgumentException( + 'Expected string or instance of \Zend\Permissions\Rbac\AbstractRole' + ); + } + + $it = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($it as $leaf) { + if ((is_string($objectOrName) && $leaf->getName() == $objectOrName) || $leaf == $objectOrName) { + return $leaf; + } + } + + throw new Exception\InvalidArgumentException(sprintf( + 'No child with name "%s" could be found', + is_object($objectOrName) ? $objectOrName->getName() : $objectOrName + )); + } + + /** + * Determines if access is granted by checking the role and child roles for permission. + * + * @param string $permission + * @param \Zend\Permissions\Rbac\AssertionInterface|Callable|null $assert + */ + public function isGranted($role, $permission, $assert = null) + { + if ($assert) { + if ($assert instanceof AssertionInterface) { + if (!$assert->assert($this)) { + return false; + } + } elseif (is_callable($assert)) { + if (!$assert($this)) { + return false; + } + } else { + throw new Exception\InvalidArgumentException( + 'Assertions must be a Callable or an instance of Zend\Permissions\Rbac\AssertionInterface' + ); + } + } + + if ($this->getRole($role)->hasPermission($permission)) { + return true; + } + + return false; + } +} diff --git a/library/Zend/Permissions/Rbac/Role.php b/library/Zend/Permissions/Rbac/Role.php new file mode 100644 index 00000000000..b83e2c818d9 --- /dev/null +++ b/library/Zend/Permissions/Rbac/Role.php @@ -0,0 +1,27 @@ +name = $name; + } +} diff --git a/tests/ZendTest/Permissions/Rbac/RbacTest.php b/tests/ZendTest/Permissions/Rbac/RbacTest.php new file mode 100644 index 00000000000..51342bdb01c --- /dev/null +++ b/tests/ZendTest/Permissions/Rbac/RbacTest.php @@ -0,0 +1,144 @@ +rbac = new Rbac\Rbac(); + } + + public function testIsGrantedAssertion() + { + $foo = new Rbac\Role('foo'); + $bar = new Rbac\Role('bar'); + + $true = new TestAsset\SimpleTrueAssertion(); + $false = new TestAsset\SimpleFalseAssertion(); + + $roleNoMatch = new TestAsset\RoleMustMatchAssertion($bar); + $roleMatch = new TestAsset\RoleMustMatchAssertion($foo); + + $foo->addPermission('can.foo'); + $bar->addPermission('can.bar'); + + $this->rbac->addRole($foo); + $this->rbac->addRole($bar); + + $this->assertEquals(true, $this->rbac->isGranted($foo, 'can.foo', $true)); + $this->assertEquals(false, $this->rbac->isGranted($bar, 'can.bar', $false)); + + $this->assertEquals(false, $this->rbac->isGranted($bar, 'can.bar', $roleNoMatch)); + $this->assertEquals(false, $this->rbac->isGranted($bar, 'can.foo', $roleNoMatch)); + + $this->assertEquals(true, $this->rbac->isGranted($foo, 'can.foo', $roleMatch)); + } + + public function testIsGrantedSingleRole() + { + $foo = new Rbac\Role('foo'); + $foo->addPermission('can.bar'); + + $this->rbac->addRole($foo); + + $this->assertEquals(true, $this->rbac->isGranted('foo', 'can.bar')); + $this->assertEquals(false, $this->rbac->isGranted('foo', 'can.baz')); + } + + public function testIsGrantedChildRoles() + { + $foo = new Rbac\Role('foo'); + $bar = new Rbac\Role('bar'); + + $foo->addPermission('can.foo'); + $bar->addPermission('can.bar'); + + $this->rbac->addRole($foo); + $this->rbac->addRole($bar, $foo); + + $this->assertEquals(true, $this->rbac->isGranted('foo', 'can.bar')); + $this->assertEquals(true, $this->rbac->isGranted('foo', 'can.foo')); + $this->assertEquals(true, $this->rbac->isGranted('bar', 'can.bar')); + + $this->assertEquals(false, $this->rbac->isGranted('foo', 'can.baz')); + $this->assertEquals(false, $this->rbac->isGranted('bar', 'can.baz')); + } + + public function testHasRole() + { + $foo = new Rbac\Role('foo'); + + $this->rbac->addRole('bar'); + $this->rbac->addRole($foo); + + $this->assertEquals(true, $this->rbac->hasRole($foo)); + $this->assertEquals(true, $this->rbac->hasRole('bar')); + $this->assertEquals(false, $this->rbac->hasRole('baz')); + } + + public function testAddRoleFromString() + { + $this->rbac->addRole('foo'); + + $foo = $this->rbac->getRole('foo'); + $this->assertInstanceOf('Zend\Permissions\Rbac\Role', $foo); + } + + public function testAddRoleFromClass() + { + $foo = new Rbac\Role('foo'); + + $this->rbac->addRole('foo'); + $foo2 = $this->rbac->getRole('foo'); + + $this->assertEquals($foo, $foo2); + $this->assertInstanceOf('Zend\Permissions\Rbac\Role', $foo2); + } + + public function testAddRoleWithParentsUsingRbac() + { + $foo = new Rbac\Role('foo'); + $bar = new Rbac\Role('bar'); + + $this->rbac->addRole($foo); + $this->rbac->addRole($bar, $foo); + + $this->assertEquals($bar->getParent(), $foo); + $this->assertEquals(1, count($foo->getChildren())); + } + + public function testAddRoleWithAutomaticParentsUsingRbac() + { + $foo = new Rbac\Role('foo'); + $bar = new Rbac\Role('bar'); + + $this->rbac->setCreateMissingRoles(true); + $this->rbac->addRole($bar, $foo); + + $this->assertEquals($bar->getParent(), $foo); + $this->assertEquals(1, count($foo->getChildren())); + } +} diff --git a/tests/ZendTest/Permissions/Rbac/TestAsset/RoleMustMatchAssertion.php b/tests/ZendTest/Permissions/Rbac/TestAsset/RoleMustMatchAssertion.php new file mode 100644 index 00000000000..4032e8647b3 --- /dev/null +++ b/tests/ZendTest/Permissions/Rbac/TestAsset/RoleMustMatchAssertion.php @@ -0,0 +1,45 @@ +role = $role; + } + + /** + * Assertion method - must return a boolean. + * + * @param Rbac $bac + * @return boolean + */ + public function assert(Rbac $rbac) + { + return $this->role->getName() == 'foo'; + } +} diff --git a/tests/ZendTest/Permissions/Rbac/TestAsset/SimpleFalseAssertion.php b/tests/ZendTest/Permissions/Rbac/TestAsset/SimpleFalseAssertion.php new file mode 100644 index 00000000000..4b8e2e59d5d --- /dev/null +++ b/tests/ZendTest/Permissions/Rbac/TestAsset/SimpleFalseAssertion.php @@ -0,0 +1,34 @@ + Date: Sat, 29 Sep 2012 21:48:13 +0100 Subject: [PATCH 096/126] Fix wrong exception caught when calling unset() on undefined option --- library/Zend/Stdlib/AbstractOptions.php | 4 ++-- tests/ZendTest/Stdlib/OptionsTest.php | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/library/Zend/Stdlib/AbstractOptions.php b/library/Zend/Stdlib/AbstractOptions.php index 86e69c3d51c..b5d7be77f32 100644 --- a/library/Zend/Stdlib/AbstractOptions.php +++ b/library/Zend/Stdlib/AbstractOptions.php @@ -131,14 +131,14 @@ public function __isset($key) /** * @see ParameterObject::__unset() * @param string $key - * @return void * @throws Exception\InvalidArgumentException + * @return void */ public function __unset($key) { try { $this->__set($key, null); - } catch (\InvalidArgumentException $e) { + } catch (Exception\BadMethodCallException $e) { throw new Exception\InvalidArgumentException( 'The class property $' . $key . ' cannot be unset as' . ' NULL is an invalid value for it', diff --git a/tests/ZendTest/Stdlib/OptionsTest.php b/tests/ZendTest/Stdlib/OptionsTest.php index 718e9d991f8..b41bf86bb83 100644 --- a/tests/ZendTest/Stdlib/OptionsTest.php +++ b/tests/ZendTest/Stdlib/OptionsTest.php @@ -66,4 +66,11 @@ public function testUnsetting() unset($options->testField); $this->assertEquals(false, isset($options->test_field)); } + + public function testUnsetThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new TestOptions; + unset($options->foobarField); + } } From dffc335c7b293c380614174e9133a0f6fd36ddc3 Mon Sep 17 00:00:00 2001 From: bullfrogblues Date: Sat, 29 Sep 2012 22:00:26 +0100 Subject: [PATCH 097/126] Refactor; short-circuit if array given, no need to check if traversable too --- .../Listener/ListenerOptions.php | 84 ++++++++++--------- library/Zend/Stdlib/AbstractOptions.php | 17 ++-- .../Listener/ListenerOptionsTest.php | 29 ++++++- tests/ZendTest/Stdlib/OptionsTest.php | 9 +- 4 files changed, 86 insertions(+), 53 deletions(-) diff --git a/library/Zend/ModuleManager/Listener/ListenerOptions.php b/library/Zend/ModuleManager/Listener/ListenerOptions.php index 3d6d215a9de..2e39e99dc23 100644 --- a/library/Zend/ModuleManager/Listener/ListenerOptions.php +++ b/library/Zend/ModuleManager/Listener/ListenerOptions.php @@ -82,20 +82,21 @@ public function getModulePaths() * * @param array|Traversable $modulePaths * @throws Exception\InvalidArgumentException - * @return ListenerOptions + * @return ListenerOptions Provides fluent interface */ public function setModulePaths($modulePaths) { - if (!is_array($modulePaths) && !$modulePaths instanceof Traversable) { - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($modulePaths)) - ); + if (is_array($modulePaths) || $modulePaths instanceof Traversable) { + $this->modulePaths = $modulePaths; + return $this; } - $this->modulePaths = $modulePaths; - return $this; + + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($modulePaths)) + ); } /** @@ -123,20 +124,21 @@ public function getConfigStaticPaths() * * @param array|Traversable $configGlobPaths * @throws Exception\InvalidArgumentException - * @return ListenerOptions + * @return ListenerOptions Provides fluent interface */ public function setConfigGlobPaths($configGlobPaths) { - if (!is_array($configGlobPaths) && !$configGlobPaths instanceof Traversable) { - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($configGlobPaths)) - ); + if (is_array($configGlobPaths) || $configGlobPaths instanceof Traversable) { + $this->configGlobPaths = $configGlobPaths; + return $this; } - $this->configGlobPaths = $configGlobPaths; - return $this; + + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($configGlobPaths)) + ); } /** @@ -144,20 +146,21 @@ public function setConfigGlobPaths($configGlobPaths) * * @param array|Traversable $configStaticPaths * @throws Exception\InvalidArgumentException - * @return ListenerOptions + * @return ListenerOptions Provides fluent interface */ public function setConfigStaticPaths($configStaticPaths) { - if (!is_array($configStaticPaths) && !$configStaticPaths instanceof Traversable) { - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($configStaticPaths)) - ); + if (is_array($configStaticPaths) || $configStaticPaths instanceof Traversable) { + $this->configStaticPaths = $configStaticPaths; + return $this; } - $this->configStaticPaths = $configStaticPaths; - return $this; + + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($configStaticPaths)) + ); } /** @@ -176,20 +179,21 @@ public function getExtraConfig() * * @param array|Traversable $extraConfig * @throws Exception\InvalidArgumentException - * @return ListenerOptions + * @return ListenerOptions Provides fluent interface */ public function setExtraConfig($extraConfig) { - if (!is_array($extraConfig) && !$extraConfig instanceof Traversable) { - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($extraConfig)) - ); + if (is_array($extraConfig) || $extraConfig instanceof Traversable) { + $this->extraConfig = $extraConfig; + return $this; } - $this->extraConfig = $extraConfig; - return $this; + + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($extraConfig)) + ); } /** diff --git a/library/Zend/Stdlib/AbstractOptions.php b/library/Zend/Stdlib/AbstractOptions.php index b5d7be77f32..628570a59b1 100644 --- a/library/Zend/Stdlib/AbstractOptions.php +++ b/library/Zend/Stdlib/AbstractOptions.php @@ -28,8 +28,6 @@ abstract class AbstractOptions implements ParameterObjectInterface /** * @param array|Traversable|null $options - * @return AbstractOptions - * @throws Exception\InvalidArgumentException */ public function __construct($options = null) { @@ -108,14 +106,15 @@ public function __set($key, $value) 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' - ); + if (method_exists($this, $getter)) { + return $this->{$getter}(); } - return $this->{$getter}(); + + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $getter . ' getter method ' + . 'which must be defined' + ); } /** diff --git a/tests/ZendTest/ModuleManager/Listener/ListenerOptionsTest.php b/tests/ZendTest/ModuleManager/Listener/ListenerOptionsTest.php index 37277862485..956e39bae6c 100644 --- a/tests/ZendTest/ModuleManager/Listener/ListenerOptionsTest.php +++ b/tests/ZendTest/ModuleManager/Listener/ListenerOptionsTest.php @@ -10,8 +10,6 @@ namespace ZendTest\ModuleManager\Listener; -use BadMethodCallException; -use InvalidArgumentException; use PHPUnit_Framework_TestCase as TestCase; use Zend\Config\Config; use Zend\ModuleManager\Listener\ListenerOptions; @@ -93,4 +91,31 @@ public function testSetConfigGlobPathsThrowsInvalidArgumentException() $options = new ListenerOptions; $options->setConfigGlobPaths('asd'); } + + public function testSetConfigStaticPathsThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new ListenerOptions; + $options->setConfigStaticPaths('asd'); + } + + public function testSetExtraConfigAcceptsArrayOrTraverable() + { + $array = array(__DIR__); + $traversable = new Config($array); + $options = new ListenerOptions; + + $this->assertSame($options, $options->setExtraConfig($array)); + $this->assertSame($array, $options->getExtraConfig()); + + $this->assertSame($options, $options->setExtraConfig($traversable)); + $this->assertSame($traversable, $options->getExtraConfig()); + } + + public function testSetExtraConfigThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new ListenerOptions; + $options->setExtraConfig('asd'); + } } diff --git a/tests/ZendTest/Stdlib/OptionsTest.php b/tests/ZendTest/Stdlib/OptionsTest.php index b41bf86bb83..8b64e7715f5 100644 --- a/tests/ZendTest/Stdlib/OptionsTest.php +++ b/tests/ZendTest/Stdlib/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 @@ -48,7 +47,6 @@ public function testNonStrictOptionsDoesNotThrowException() } } - public function testConstructionWithNull() { try { @@ -73,4 +71,11 @@ public function testUnsetThrowsInvalidArgumentException() $options = new TestOptions; unset($options->foobarField); } + + public function testGetThrowsBadMethodCallException() + { + $this->setExpectedException('BadMethodCallException'); + $options = new TestOptions(); + $options->fieldFoobar; + } } From df3498a2fac849cf84bc66e2f21e9db6db1bb6d9 Mon Sep 17 00:00:00 2001 From: bullfrogblues Date: Sat, 29 Sep 2012 22:11:21 +0100 Subject: [PATCH 098/126] Make setFromArray() a fluent interface & refactor: short-circuit if array --- library/Zend/Stdlib/AbstractOptions.php | 19 ++++++++++--------- tests/ZendTest/Stdlib/OptionsTest.php | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/library/Zend/Stdlib/AbstractOptions.php b/library/Zend/Stdlib/AbstractOptions.php index 628570a59b1..8dadafa52fa 100644 --- a/library/Zend/Stdlib/AbstractOptions.php +++ b/library/Zend/Stdlib/AbstractOptions.php @@ -39,20 +39,21 @@ public function __construct($options = null) /** * @param array|Traversable $options * @throws Exception\InvalidArgumentException - * @return void + * @return AbstractOptions Provides fluent interface */ 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__ - )); + if (is_array($options) || $options instanceof Traversable) { + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + return $this; } - foreach ($options as $key => $value) { - $this->__set($key, $value); - } + throw new Exception\InvalidArgumentException(sprintf( + 'Parameter provided to %s must be an array or Traversable', + __METHOD__ + )); } /** diff --git a/tests/ZendTest/Stdlib/OptionsTest.php b/tests/ZendTest/Stdlib/OptionsTest.php index 8b64e7715f5..93f5b76588a 100644 --- a/tests/ZendTest/Stdlib/OptionsTest.php +++ b/tests/ZendTest/Stdlib/OptionsTest.php @@ -78,4 +78,20 @@ public function testGetThrowsBadMethodCallException() $options = new TestOptions(); $options->fieldFoobar; } + + public function testSetFromArrayAcceptsArray() + { + $array = array('test_field' => 3); + $options = new TestOptions(); + + $this->assertSame($options, $options->setFromArray($array)); + $this->assertEquals(3, $options->test_field); + } + + public function testSetFromArrayThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new TestOptions; + $options->setFromArray('asd'); + } } From e4a7e98327616f7228bff9774da95301466333b6 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 1 Oct 2012 16:03:07 -0500 Subject: [PATCH 099/126] [#2414] Added IsInstanceOf to ValidatorPluginManager --- library/Zend/Validator/ValidatorPluginManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Zend/Validator/ValidatorPluginManager.php b/library/Zend/Validator/ValidatorPluginManager.php index 056486d9de3..44ad2e5fa53 100644 --- a/library/Zend/Validator/ValidatorPluginManager.php +++ b/library/Zend/Validator/ValidatorPluginManager.php @@ -95,6 +95,7 @@ class ValidatorPluginManager extends AbstractPluginManager 'int' => 'Zend\I18n\Validator\Int', 'ip' => 'Zend\Validator\Ip', 'isbn' => 'Zend\Validator\Isbn', + 'isinstanceof' => 'Zend\Validator\IsInstanceOf', 'lessthan' => 'Zend\Validator\LessThan', 'notempty' => 'Zend\Validator\NotEmpty', 'postcode' => 'Zend\I18n\Validator\PostCode', From 0107f111a8aeab021f8c11cae6de3473cfe20f56 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 1 Oct 2012 16:09:26 -0500 Subject: [PATCH 100/126] [#2414] CS review - Removed unnecessary imports - Added required imports (in testing) - Removed extraneous whitespace - Removed unnecessary dependency (ArrayUtils) --- library/Zend/Validator/IsInstanceOf.php | 28 ++++----- tests/Zend/Validator/IsInstanceOfTest.php | 69 +++++++++-------------- 2 files changed, 42 insertions(+), 55 deletions(-) diff --git a/library/Zend/Validator/IsInstanceOf.php b/library/Zend/Validator/IsInstanceOf.php index 9b8e94af421..52ce9d42384 100644 --- a/library/Zend/Validator/IsInstanceOf.php +++ b/library/Zend/Validator/IsInstanceOf.php @@ -10,13 +10,13 @@ namespace Zend\Validator; use Traversable; -use Zend\Stdlib\ArrayUtils; -use Zend\Validator\AbstractValidator; -use Zend\Validator\Exception\InvalidArgumentException; +/** + * @category Zend + * @package Zend_Validate + */ class IsInstanceOf extends AbstractValidator { - const NOT_INSTANCE_OF = 'notInstanceOf'; /** @@ -25,7 +25,7 @@ class IsInstanceOf extends AbstractValidator * @var array */ protected $messageTemplates = array( - self::NOT_INSTANCE_OF => "The input is not an instance of '%className%'" + self::NOT_INSTANCE_OF => "The input is not an instance of '%className%'", ); /** @@ -48,16 +48,16 @@ class IsInstanceOf extends AbstractValidator * Sets validator options * * @param array|Traversable $options - * @throws Zend\Validator\Exception\InvalidArgumentException + * @throws Exception\InvalidArgumentException */ - public function __construct ($options = null) + public function __construct($options = null) { if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); + $options = iterator_to_array($options); } // If argument is not an array, consider first argument as class name - if (! is_array($options)) { + if (!is_array($options)) { $options = func_get_args(); $tmpOptions = array(); @@ -66,8 +66,8 @@ public function __construct ($options = null) $options = $tmpOptions; } - if (! array_key_exists('className', $options)) { - throw new InvalidArgumentException("Missing option 'className'"); + if (!array_key_exists('className', $options)) { + throw new Exception\InvalidArgumentException('Missing option "className"'); } parent::__construct($options); @@ -78,7 +78,7 @@ public function __construct ($options = null) * * @return string */ - public function getClassName () + public function getClassName() { return $this->className; } @@ -89,7 +89,7 @@ public function getClassName () * @param string $className * @return self */ - public function setClassName ($className) + public function setClassName($className) { $this->className = $className; return $this; @@ -101,7 +101,7 @@ public function setClassName ($className) * @param mixed $value * @return boolean */ - public function isValid ($value) + public function isValid($value) { if ($value instanceof $this->className) { return true; diff --git a/tests/Zend/Validator/IsInstanceOfTest.php b/tests/Zend/Validator/IsInstanceOfTest.php index 65013cae440..6594147df0b 100644 --- a/tests/Zend/Validator/IsInstanceOfTest.php +++ b/tests/Zend/Validator/IsInstanceOfTest.php @@ -20,17 +20,12 @@ */ namespace ZendTest\Validator; -use Zend\Validator, ReflectionClass; - -/** - * Test helper - */ - -/** - * @see Zend_Validator_IsInstanceOf - */ +use DateTime; +use ReflectionClass; +use Zend\Validator; /** + * @covers Zend\Validator\IsInstanceOf * @category Zend * @package Zend_Validator * @subpackage UnitTests @@ -40,28 +35,24 @@ */ class IsInstanceOfTest extends \PHPUnit_Framework_TestCase { - /** * Ensures that the validator follows expected behavior * * @return void */ - public function testBasic () + public function testBasic() { - $validator = new Validator\IsInstanceOf('\DateTime'); - - $this->assertTrue($validator->isValid(new \DateTime())); // True + $validator = new Validator\IsInstanceOf('DateTime'); + $this->assertTrue($validator->isValid(new DateTime())); // True $this->assertFalse($validator->isValid(null)); // False $this->assertFalse($validator->isValid($this)); // False - $validator = new Validator\IsInstanceOf('\Exception'); - + $validator = new Validator\IsInstanceOf('Exception'); $this->assertTrue($validator->isValid(new \Exception())); // True $this->assertFalse($validator->isValid(null)); // False $this->assertFalse($validator->isValid($this)); // False - $validator = new Validator\IsInstanceOf('\PHPUnit_Framework_TestCase'); - + $validator = new Validator\IsInstanceOf('PHPUnit_Framework_TestCase'); $this->assertTrue($validator->isValid($this)); // True } @@ -70,9 +61,9 @@ public function testBasic () * * @return void */ - public function testGetMessages () + public function testGetMessages() { - $validator = new Validator\IsInstanceOf('\DateTime'); + $validator = new Validator\IsInstanceOf('DateTime'); $this->assertEquals(array(), $validator->getMessages()); } @@ -81,41 +72,37 @@ public function testGetMessages () * * @return void */ - public function testGetClassName () + public function testGetClassName() { - $validator = new Validator\IsInstanceOf('\DateTime'); - $this->assertEquals('\DateTime', $validator->getClassName()); + $validator = new Validator\IsInstanceOf('DateTime'); + $this->assertEquals('DateTime', $validator->getClassName()); } - public function testEqualsMessageTemplates () + public function testEqualsMessageTemplates() { - $validator = new Validator\IsInstanceOf('\DateTime'); + $validator = new Validator\IsInstanceOf('DateTime'); $reflection = new ReflectionClass($validator); - if (! $reflection->hasProperty('_messageTemplates')) { - return; - } - - $property = $reflection->getProperty('_messageTemplates'); + $property = $reflection->getProperty('messageTemplates'); $property->setAccessible(true); - $this->assertEquals($property->getValue($validator), - $validator->getOption('messageTemplates')); + $this->assertEquals( + $property->getValue($validator), + $validator->getOption('messageTemplates') + ); } - public function testEqualsMessageVariables () + public function testEqualsMessageVariables() { - $validator = new Validator\IsInstanceOf('\DateTime'); + $validator = new Validator\IsInstanceOf('\DateTime'); $reflection = new ReflectionClass($validator); - if (! $reflection->hasProperty('_messageVariables')) { - return; - } - - $property = $reflection->getProperty('_messageVariables'); + $property = $reflection->getProperty('messageVariables'); $property->setAccessible(true); - $this->assertEquals($property->getValue($validator), - $validator->getOption('messageVariables')); + $this->assertEquals( + $property->getValue($validator), + $validator->getOption('messageVariables') + ); } } From 95918544a0935be6c5651a5284113c390878767d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 1 Oct 2012 16:36:25 -0500 Subject: [PATCH 101/126] CS fixes - Trailing whitespace --- library/Zend/Form/Element/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Zend/Form/Element/Collection.php b/library/Zend/Form/Element/Collection.php index eccfea2cdf8..b8544d81718 100644 --- a/library/Zend/Form/Element/Collection.php +++ b/library/Zend/Form/Element/Collection.php @@ -158,7 +158,7 @@ public function setObject($object) $this->object = $object; $this->count = count($object); - + return $this; } From ecbc968ec41a6bf151278b2935c313ec580c8305 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 27 Sep 2012 11:51:43 +0200 Subject: [PATCH 102/126] Added the scrypt key derivation algorithm --- library/Zend/Crypt/Hmac.php | 4 - library/Zend/Crypt/Key/Derivation/Scrypt.php | 343 ++++++++++++++++++ tests/ZendTest/Crypt/HmacTest.php | 7 - .../Crypt/Key/Derivation/ScryptTest.php | 195 ++++++++++ 4 files changed, 538 insertions(+), 11 deletions(-) create mode 100644 library/Zend/Crypt/Key/Derivation/Scrypt.php create mode 100644 tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php diff --git a/library/Zend/Crypt/Hmac.php b/library/Zend/Crypt/Hmac.php index 8c14f273da2..fc7dd2ba7bf 100644 --- a/library/Zend/Crypt/Hmac.php +++ b/library/Zend/Crypt/Hmac.php @@ -42,10 +42,6 @@ class Hmac */ public static function compute($key, $hash, $data, $output = self::OUTPUT_STRING) { - if (!isset($key) || empty($key)) { - throw new Exception\InvalidArgumentException('Provided key is null or empty'); - } - $hash = strtolower($hash); if (!self::isSupported($hash)) { throw new Exception\InvalidArgumentException( diff --git a/library/Zend/Crypt/Key/Derivation/Scrypt.php b/library/Zend/Crypt/Key/Derivation/Scrypt.php new file mode 100644 index 00000000000..f66103558d0 --- /dev/null +++ b/library/Zend/Crypt/Key/Derivation/Scrypt.php @@ -0,0 +1,343 @@ + 0 and a power of 2"); + } + if ($n > PHP_INT_MAX / 128 / $r) { + throw new Exception\InvalidArgumentException("Parameter n is too large"); + } + if ($r > PHP_INT_MAX / 128 / $p) { + throw new Exception\InvalidArgumentException("Parameter r is too large"); + } + + if (extension_loaded('Scrypt')) { + if ($length < 16) { + throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16"); + } + return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); + } + + $b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r); + + $s = ''; + for ($i = 0; $i < $p; $i++) { + $s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r); + } + + return Pbkdf2::calc('sha256', $password, $s, 1, $length); + } + + /** + * scryptROMix + * + * @param string $b + * @param integer $n + * @param integer $r + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 + */ + protected static function scryptROMix($b, $n, $r) + { + $x = $b; + $v = array(); + for ($i = 0; $i < $n; $i++) { + $v[$i] = $x; + $x = self::scryptBlockMix($x, $r); + } + for ($i = 0; $i < $n; $i++) { + $j = self::integerify($x) % $n; + $t = $x ^ $v[$j]; + $x = self::scryptBlockMix($t, $r); + } + return $x; + } + + /** + * scryptBlockMix + * + * @param string $b + * @param integer $r + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3 + */ + protected static function scryptBlockMix($b, $r) + { + $x = substr($b, -64); + $even = ''; + $odd = ''; + $len = 2 * $r; + + for ($i = 0; $i < $len; $i++) { + if (PHP_INT_SIZE === 4) { + $x = self::salsa208Core32($x ^ substr($b, 64 * $i, 64)); + } else { + $x = self::salsa208Core64($x ^ substr($b, 64 * $i, 64)); + } + if ($i % 2 == 0) { + $even .= $x; + } else { + $odd .= $x; + } + } + return $even . $odd; + } + + /** + * Salsa 20/8 core (32 bit version) + * + * @param string $b + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 + * @see http://cr.yp.to/salsa20.html + */ + protected static function salsa208Core32($b) + { + $b32 = array(); + for ($i = 0; $i < 16; $i++) { + list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); + } + + $x = $b32; + for ($i = 0; $i < 8; $i += 2) { + $a = ($x[ 0] + $x[12]); + $x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 4] + $x[ 0]); + $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 8] + $x[ 4]); + $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[12] + $x[ 8]); + $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[ 5] + $x[ 1]); + $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 9] + $x[ 5]); + $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[13] + $x[ 9]); + $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 1] + $x[13]); + $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[10] + $x[ 6]); + $x[14] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[14] + $x[10]); + $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 2] + $x[14]); + $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 6] + $x[ 2]); + $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[15] + $x[11]); + $x[ 3] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 3] + $x[15]); + $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 7] + $x[ 3]); + $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[11] + $x[ 7]); + $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[ 0] + $x[ 3]); + $x[ 1] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 1] + $x[ 0]); + $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 2] + $x[ 1]); + $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 3] + $x[ 2]); + $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[ 5] + $x[ 4]); + $x[ 6] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[ 6] + $x[ 5]); + $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 7] + $x[ 6]); + $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 4] + $x[ 7]); + $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[10] + $x[ 9]); + $x[11] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[11] + $x[10]); + $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[ 8] + $x[11]); + $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[ 9] + $x[ 8]); + $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + $a = ($x[15] + $x[14]); + $x[12] ^= ($a << 7) | ($a >> 25) & 0x7f; + $a = ($x[12] + $x[15]); + $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $a = ($x[13] + $x[12]); + $x[14] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $a = ($x[14] + $x[13]); + $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff; + } + for ($i = 0; $i < 16; $i++) { + $b32[$i] = $b32[$i] + $x[$i]; + } + $result = ''; + for ($i = 0; $i < 16; $i++) { + $result .= pack("V", $b32[$i]); + } + + return $result; + } + + /** + * Salsa 20/8 core (64 bit version) + * + * @param string $b + * @return string + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 + * @see http://cr.yp.to/salsa20.html + */ + protected static function salsa208Core64($b) + { + $b32 = array(); + for ($i = 0; $i < 16; $i++) { + list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); + } + + $x = $b32; + for ($i = 0; $i < 8; $i += 2) { + $a = ($x[ 0] + $x[12]) & 0xffffffff; + $x[ 4] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 4] + $x[ 0]) & 0xffffffff; + $x[ 8] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 8] + $x[ 4]) & 0xffffffff; + $x[12] ^= ($a << 13) | ($a >> 19); + $a = ($x[12] + $x[ 8]) & 0xffffffff; + $x[ 0] ^= ($a << 18) | ($a >> 14); + $a = ($x[ 5] + $x[ 1]) & 0xffffffff; + $x[ 9] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 9] + $x[ 5]) & 0xffffffff; + $x[13] ^= ($a << 9) | ($a >> 23); + $a = ($x[13] + $x[ 9]) & 0xffffffff; + $x[ 1] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 1] + $x[13]) & 0xffffffff; + $x[ 5] ^= ($a << 18) | ($a >> 14); + $a = ($x[10] + $x[ 6]) & 0xffffffff; + $x[14] ^= ($a << 7) | ($a >> 25); + $a = ($x[14] + $x[10]) & 0xffffffff; + $x[ 2] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 2] + $x[14]) & 0xffffffff; + $x[ 6] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 6] + $x[ 2]) & 0xffffffff; + $x[10] ^= ($a << 18) | ($a >> 14); + $a = ($x[15] + $x[11]) & 0xffffffff; + $x[ 3] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 3] + $x[15]) & 0xffffffff; + $x[ 7] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 7] + $x[ 3]) & 0xffffffff; + $x[11] ^= ($a << 13) | ($a >> 19); + $a = ($x[11] + $x[ 7]) & 0xffffffff; + $x[15] ^= ($a << 18) | ($a >> 14); + $a = ($x[ 0] + $x[ 3]) & 0xffffffff; + $x[ 1] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 1] + $x[ 0]) & 0xffffffff; + $x[ 2] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 2] + $x[ 1]) & 0xffffffff; + $x[ 3] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 3] + $x[ 2]) & 0xffffffff; + $x[ 0] ^= ($a << 18) | ($a >> 14); + $a = ($x[ 5] + $x[ 4]) & 0xffffffff; + $x[ 6] ^= ($a << 7) | ($a >> 25); + $a = ($x[ 6] + $x[ 5]) & 0xffffffff; + $x[ 7] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 7] + $x[ 6]) & 0xffffffff; + $x[ 4] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 4] + $x[ 7]) & 0xffffffff; + $x[ 5] ^= ($a << 18) | ($a >> 14); + $a = ($x[10] + $x[ 9]) & 0xffffffff; + $x[11] ^= ($a << 7) | ($a >> 25); + $a = ($x[11] + $x[10]) & 0xffffffff; + $x[ 8] ^= ($a << 9) | ($a >> 23); + $a = ($x[ 8] + $x[11]) & 0xffffffff; + $x[ 9] ^= ($a << 13) | ($a >> 19); + $a = ($x[ 9] + $x[ 8]) & 0xffffffff; + $x[10] ^= ($a << 18) | ($a >> 14); + $a = ($x[15] + $x[14]) & 0xffffffff; + $x[12] ^= ($a << 7) | ($a >> 25); + $a = ($x[12] + $x[15]) & 0xffffffff; + $x[13] ^= ($a << 9) | ($a >> 23); + $a = ($x[13] + $x[12]) & 0xffffffff; + $x[14] ^= ($a << 13) | ($a >> 19); + $a = ($x[14] + $x[13]) & 0xffffffff; + $x[15] ^= ($a << 18) | ($a >> 14); + } + for ($i = 0; $i < 16; $i++) { + $b32[$i] = ($b32[$i] + $x[$i]) & 0xffffffff; + } + $result = ''; + for ($i = 0; $i < 16; $i++) { + $result .= pack("V", $b32[$i]); + } + + return $result; + } + + /** + * Integerify + * + * Integerify (B[0] ... B[2 * r - 1]) is defined as the result + * of interpreting B[2 * r - 1] as a little-endian integer. + * Each block B is a string of 64 bytes. + * + * @param string $b + * @return integer + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 + */ + protected static function integerify($b) { + $v = 'v'; + if (PHP_INT_SIZE === 8) { + $v = 'V'; + } + list(,$n) = unpack($v, substr($b, -64)); + return $n; + } + + /** + * Convert hex string in a binary string + * + * @param string $hex + * @return string + */ + protected static function hex2bin($hex) { + if (version_compare(PHP_VERSION, '5.4') >= 0) { + return hex2bin($hex); + } + $len = strlen($hex); + $result = ''; + for ($i = 0; $i < $len; $i+=2) { + $result .= chr(hexdec($hex[$i] . $hex[$i+1])); + } + return $result; + } +} diff --git a/tests/ZendTest/Crypt/HmacTest.php b/tests/ZendTest/Crypt/HmacTest.php index c71b35dbdf7..a6d70ec7ab7 100644 --- a/tests/ZendTest/Crypt/HmacTest.php +++ b/tests/ZendTest/Crypt/HmacTest.php @@ -200,13 +200,6 @@ public function testHmacRIPEMD160_7() $this->assertEquals('69ea60798d71616cce5fd0871e23754cd75d5a0a', $hmac); } - public function testEmptyKey() - { - $this->setExpectedException('Zend\Crypt\Exception\InvalidArgumentException', - 'Provided key is null or empty'); - $hash = HMAC::compute(null, 'md5', 'test'); - } - public function testWrongHashAlgorithm() { $this->setExpectedException('Zend\Crypt\Exception\InvalidArgumentException', diff --git a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php new file mode 100644 index 00000000000..240100b0bac --- /dev/null +++ b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php @@ -0,0 +1,195 @@ +getMethod($name); + $method->setAccessible(true); + return $method; + } + + /** + * Test vector of Salsa 20/8 core + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7 + */ + public function testVectorSalsa208Core() + { + $hexInput = '7e 87 9a 21 4f 3e c9 86 7c a9 40 e6 41 71 8f 26 + ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d + ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32 + 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e'; + + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 + 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 + b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba + e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81'; + + + $salsaAlg = 'salsa208Core32'; + if (PHP_INT_SIZE === 8) { + $salsaAlg = 'salsa208Core64'; + } + $salsa20 = self::getMethod($salsaAlg); + $obj = new Scrypt; + $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput)); + $result = $salsa20->invokeArgs($obj, array($input)); + + $this->assertEquals(64, strlen($input), 'Input must be a string of 64 bytes'); + $this->assertEquals(64, strlen($result), 'Output must be a string of 64 bytes'); + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + /** + * Test vector of Scrypt BlockMix + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8 + */ + public function testVectorScryptBlockMix() + { + $hexInput = 'f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd + 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad + 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 + 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 + + 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb + cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 + 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b + 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89'; + + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 + 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 + b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba + e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81 + + 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c + 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7 + 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6 + 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25'; + + $blockMix = self::getMethod('scryptBlockMix'); + $obj = new Scrypt; + $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); + $result = $blockMix->invokeArgs($obj, array($input, 1)); + + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + + /** + * Test vector of Scrypt ROMix + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-9 + */ + public function testVectorScryptROMix() + { + $hexInput = 'f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd + 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad + 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 + 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 + 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb + cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 + 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b + 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89'; + + $hexOutput = '79 cc c1 93 62 9d eb ca 04 7f 0b 70 60 4b f6 b6 + 2c e3 dd 4a 96 26 e3 55 fa fc 61 98 e6 ea 2b 46 + d5 84 13 67 3b 99 b0 29 d6 65 c3 57 60 1f b4 26 + a0 b2 f4 bb a2 00 ee 9f 0a 43 d1 9b 57 1a 9c 71 + ef 11 42 e6 5d 5a 26 6f dd ca 83 2c e5 9f aa 7c + ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4 + ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f + 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e'; + + + $roMix = self::getMethod('scryptROMix'); + $obj = new Scrypt; + $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); + $result = $roMix->invokeArgs($obj, array($input, 16, 1)); + + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + + + /** + * Test Vector Scrypt + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-11 + */ + public function testVectorScrypt() + { + $hexOutput = '77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 + f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 + fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 + e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06'; + + $result = Scrypt::calc('', '', 16, 1, 1, 64); + $this->assertEquals(64, strlen($result)); + $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); + } + + /** + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + */ + public function testScryptWrongN() + { + $result = Scrypt::calc('test', 'salt', 17, 1, 1, 64); + $result = Scrypt::calc('test', 'salt', PHP_INT_MAX, 1, 1, 64); + } + + /** + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + */ + public function testScryptWrongR() + { + $result = Scrypt::calc('test', 'salt', PHP_INT_MAX / 128, 4, 1, 64); + } + + /** + * Test scrypt correct size output + */ + public function testScryptSize() + { + for ($size = 0; $size < 64; $size++) { + if (extension_loaded('Scrypt') && ($size < 16)) { + $this->setExpectedException('Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException'); + } + $result = Scrypt::calc('test', 'salt', 16, 1, 1, $size); + $this->assertEquals($size, strlen($result)); + } + } + + /** + * Convert a string with hex values in binary string + * + * @param string $hex + * @return string + */ + protected static function hex2bin($hex) + { + $len = strlen($hex); + $result = ''; + for ($i = 0; $i < $len; $i += 2) { + $result .= chr(hexdec($hex[$i] . $hex[$i+1])); + } + return $result; + } +} From eab7d49f78541d01c5accbb18c1ea867c16388e5 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 27 Sep 2012 12:15:45 +0200 Subject: [PATCH 103/126] Fixed PSR2 for scrypt --- library/Zend/Crypt/Key/Derivation/Scrypt.php | 128 +++++++++--------- .../Crypt/Key/Derivation/ScryptTest.php | 57 ++++---- 2 files changed, 94 insertions(+), 91 deletions(-) diff --git a/library/Zend/Crypt/Key/Derivation/Scrypt.php b/library/Zend/Crypt/Key/Derivation/Scrypt.php index f66103558d0..3e10946f744 100644 --- a/library/Zend/Crypt/Key/Derivation/Scrypt.php +++ b/library/Zend/Crypt/Key/Derivation/Scrypt.php @@ -13,19 +13,19 @@ use Zend\Crypt\Key\Derivation\Pbkdf2; /** - * Scrypt key derivation function - * + * Scrypt key derivation function + * * @category Zend * @package Zend_Crypt - * @see http://www.tarsnap.com/scrypt.html + * @see http://www.tarsnap.com/scrypt.html * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01 */ class Scrypt -{ +{ /** * Execute the scrypt algorithm - * - * @param string $password + * + * @param string $password * @param string $salt * @param integer $n CPU cost * @param integer $r Memory cost @@ -33,7 +33,7 @@ class Scrypt * @param integer $length size of the output key * @return string */ - public static function calc($password, $salt, $n, $r, $p, $length) + public static function calc($password, $salt, $n, $r, $p, $length) { if ($n == 0 || ($n & ($n - 1)) != 0) { throw new Exception\InvalidArgumentException("N must be > 0 and a power of 2"); @@ -44,31 +44,31 @@ public static function calc($password, $salt, $n, $r, $p, $length) if ($r > PHP_INT_MAX / 128 / $p) { throw new Exception\InvalidArgumentException("Parameter r is too large"); } - + if (extension_loaded('Scrypt')) { if ($length < 16) { throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16"); } - return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); + return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); } - + $b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r); $s = ''; for ($i = 0; $i < $p; $i++) { $s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r); } - + return Pbkdf2::calc('sha256', $password, $s, 1, $length); } - + /** * scryptROMix - * + * * @param string $b * @param integer $n * @param integer $r - * @return string + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 */ protected static function scryptROMix($b, $n, $r) @@ -86,13 +86,13 @@ protected static function scryptROMix($b, $n, $r) } return $x; } - + /** * scryptBlockMix - * + * * @param string $b * @param integer $r - * @return string + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3 */ protected static function scryptBlockMix($b, $r) @@ -101,7 +101,7 @@ protected static function scryptBlockMix($b, $r) $even = ''; $odd = ''; $len = 2 * $r; - + for ($i = 0; $i < $len; $i++) { if (PHP_INT_SIZE === 4) { $x = self::salsa208Core32($x ^ substr($b, 64 * $i, 64)); @@ -116,38 +116,38 @@ protected static function scryptBlockMix($b, $r) } return $even . $odd; } - + /** * Salsa 20/8 core (32 bit version) - * - * @param string $b - * @return string + * + * @param string $b + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 * @see http://cr.yp.to/salsa20.html */ - protected static function salsa208Core32($b) - { + protected static function salsa208Core32($b) + { $b32 = array(); for ($i = 0; $i < 16; $i++) { list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); } - - $x = $b32; + + $x = $b32; for ($i = 0; $i < 8; $i += 2) { $a = ($x[ 0] + $x[12]); $x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f; $a = ($x[ 4] + $x[ 0]); $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 8] + $x[ 4]); - $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[12] + $x[ 8]); $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[ 5] + $x[ 1]); - $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f; + $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f; $a = ($x[ 9] + $x[ 5]); - $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; + $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[13] + $x[ 9]); - $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 1] + $x[13]); $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[10] + $x[ 6]); @@ -155,7 +155,7 @@ protected static function salsa208Core32($b) $a = ($x[14] + $x[10]); $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 2] + $x[14]); - $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 6] + $x[ 2]); $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[15] + $x[11]); @@ -163,7 +163,7 @@ protected static function salsa208Core32($b) $a = ($x[ 3] + $x[15]); $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 7] + $x[ 3]); - $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[11] + $x[ 7]); $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[ 0] + $x[ 3]); @@ -171,7 +171,7 @@ protected static function salsa208Core32($b) $a = ($x[ 1] + $x[ 0]); $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 2] + $x[ 1]); - $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 3] + $x[ 2]); $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[ 5] + $x[ 4]); @@ -179,7 +179,7 @@ protected static function salsa208Core32($b) $a = ($x[ 6] + $x[ 5]); $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 7] + $x[ 6]); - $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 4] + $x[ 7]); $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[10] + $x[ 9]); @@ -187,7 +187,7 @@ protected static function salsa208Core32($b) $a = ($x[11] + $x[10]); $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff; $a = ($x[ 8] + $x[11]); - $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff; + $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff; $a = ($x[ 9] + $x[ 8]); $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff; $a = ($x[15] + $x[14]); @@ -206,41 +206,41 @@ protected static function salsa208Core32($b) for ($i = 0; $i < 16; $i++) { $result .= pack("V", $b32[$i]); } - + return $result; } - + /** * Salsa 20/8 core (64 bit version) - * - * @param string $b - * @return string + * + * @param string $b + * @return string * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2 * @see http://cr.yp.to/salsa20.html */ - protected static function salsa208Core64($b) - { + protected static function salsa208Core64($b) + { $b32 = array(); for ($i = 0; $i < 16; $i++) { list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4)); } - + $x = $b32; for ($i = 0; $i < 8; $i += 2) { $a = ($x[ 0] + $x[12]) & 0xffffffff; - $x[ 4] ^= ($a << 7) | ($a >> 25); + $x[ 4] ^= ($a << 7) | ($a >> 25); $a = ($x[ 4] + $x[ 0]) & 0xffffffff; $x[ 8] ^= ($a << 9) | ($a >> 23); $a = ($x[ 8] + $x[ 4]) & 0xffffffff; - $x[12] ^= ($a << 13) | ($a >> 19); + $x[12] ^= ($a << 13) | ($a >> 19); $a = ($x[12] + $x[ 8]) & 0xffffffff; $x[ 0] ^= ($a << 18) | ($a >> 14); $a = ($x[ 5] + $x[ 1]) & 0xffffffff; - $x[ 9] ^= ($a << 7) | ($a >> 25); + $x[ 9] ^= ($a << 7) | ($a >> 25); $a = ($x[ 9] + $x[ 5]) & 0xffffffff; - $x[13] ^= ($a << 9) | ($a >> 23); + $x[13] ^= ($a << 9) | ($a >> 23); $a = ($x[13] + $x[ 9]) & 0xffffffff; - $x[ 1] ^= ($a << 13) | ($a >> 19); + $x[ 1] ^= ($a << 13) | ($a >> 19); $a = ($x[ 1] + $x[13]) & 0xffffffff; $x[ 5] ^= ($a << 18) | ($a >> 14); $a = ($x[10] + $x[ 6]) & 0xffffffff; @@ -248,7 +248,7 @@ protected static function salsa208Core64($b) $a = ($x[14] + $x[10]) & 0xffffffff; $x[ 2] ^= ($a << 9) | ($a >> 23); $a = ($x[ 2] + $x[14]) & 0xffffffff; - $x[ 6] ^= ($a << 13) | ($a >> 19); + $x[ 6] ^= ($a << 13) | ($a >> 19); $a = ($x[ 6] + $x[ 2]) & 0xffffffff; $x[10] ^= ($a << 18) | ($a >> 14); $a = ($x[15] + $x[11]) & 0xffffffff; @@ -256,7 +256,7 @@ protected static function salsa208Core64($b) $a = ($x[ 3] + $x[15]) & 0xffffffff; $x[ 7] ^= ($a << 9) | ($a >> 23); $a = ($x[ 7] + $x[ 3]) & 0xffffffff; - $x[11] ^= ($a << 13) | ($a >> 19); + $x[11] ^= ($a << 13) | ($a >> 19); $a = ($x[11] + $x[ 7]) & 0xffffffff; $x[15] ^= ($a << 18) | ($a >> 14); $a = ($x[ 0] + $x[ 3]) & 0xffffffff; @@ -264,7 +264,7 @@ protected static function salsa208Core64($b) $a = ($x[ 1] + $x[ 0]) & 0xffffffff; $x[ 2] ^= ($a << 9) | ($a >> 23); $a = ($x[ 2] + $x[ 1]) & 0xffffffff; - $x[ 3] ^= ($a << 13) | ($a >> 19); + $x[ 3] ^= ($a << 13) | ($a >> 19); $a = ($x[ 3] + $x[ 2]) & 0xffffffff; $x[ 0] ^= ($a << 18) | ($a >> 14); $a = ($x[ 5] + $x[ 4]) & 0xffffffff; @@ -272,7 +272,7 @@ protected static function salsa208Core64($b) $a = ($x[ 6] + $x[ 5]) & 0xffffffff; $x[ 7] ^= ($a << 9) | ($a >> 23); $a = ($x[ 7] + $x[ 6]) & 0xffffffff; - $x[ 4] ^= ($a << 13) | ($a >> 19); + $x[ 4] ^= ($a << 13) | ($a >> 19); $a = ($x[ 4] + $x[ 7]) & 0xffffffff; $x[ 5] ^= ($a << 18) | ($a >> 14); $a = ($x[10] + $x[ 9]) & 0xffffffff; @@ -280,7 +280,7 @@ protected static function salsa208Core64($b) $a = ($x[11] + $x[10]) & 0xffffffff; $x[ 8] ^= ($a << 9) | ($a >> 23); $a = ($x[ 8] + $x[11]) & 0xffffffff; - $x[ 9] ^= ($a << 13) | ($a >> 19); + $x[ 9] ^= ($a << 13) | ($a >> 19); $a = ($x[ 9] + $x[ 8]) & 0xffffffff; $x[10] ^= ($a << 18) | ($a >> 14); $a = ($x[15] + $x[14]) & 0xffffffff; @@ -299,22 +299,23 @@ protected static function salsa208Core64($b) for ($i = 0; $i < 16; $i++) { $result .= pack("V", $b32[$i]); } - + return $result; } - + /** * Integerify - * + * * Integerify (B[0] ... B[2 * r - 1]) is defined as the result * of interpreting B[2 * r - 1] as a little-endian integer. * Each block B is a string of 64 bytes. - * + * * @param string $b - * @return integer + * @return integer * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4 */ - protected static function integerify($b) { + protected static function integerify($b) + { $v = 'v'; if (PHP_INT_SIZE === 8) { $v = 'V'; @@ -322,14 +323,15 @@ protected static function integerify($b) { list(,$n) = unpack($v, substr($b, -64)); return $n; } - + /** * Convert hex string in a binary string - * + * * @param string $hex - * @return string + * @return string */ - protected static function hex2bin($hex) { + protected static function hex2bin($hex) + { if (version_compare(PHP_VERSION, '5.4') >= 0) { return hex2bin($hex); } diff --git a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php index 240100b0bac..cb6e3316ad9 100644 --- a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php +++ b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php @@ -21,7 +21,8 @@ class ScryptTest extends \PHPUnit_Framework_TestCase { - protected static function getMethod($name) { + protected static function getMethod($name) + { $class = new \ReflectionClass('Zend\Crypt\Key\Derivation\Scrypt'); $method = $class->getMethod($name); $method->setAccessible(true); @@ -30,8 +31,8 @@ protected static function getMethod($name) { /** * Test vector of Salsa 20/8 core - * - * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7 + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7 */ public function testVectorSalsa208Core() { @@ -39,7 +40,7 @@ public function testVectorSalsa208Core() ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e'; - + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba @@ -54,15 +55,15 @@ public function testVectorSalsa208Core() $obj = new Scrypt; $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput)); $result = $salsa20->invokeArgs($obj, array($input)); - + $this->assertEquals(64, strlen($input), 'Input must be a string of 64 bytes'); $this->assertEquals(64, strlen($result), 'Output must be a string of 64 bytes'); $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } /** * Test vector of Scrypt BlockMix - * - * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8 + * + * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8 */ public function testVectorScryptBlockMix() { @@ -70,22 +71,22 @@ public function testVectorScryptBlockMix() 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 - + 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89'; - + $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81 - + 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25'; - + $blockMix = self::getMethod('scryptBlockMix'); $obj = new Scrypt; $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); @@ -93,10 +94,10 @@ public function testVectorScryptBlockMix() $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } - + /** - * Test vector of Scrypt ROMix - * + * Test vector of Scrypt ROMix + * * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-9 */ public function testVectorScryptROMix() @@ -118,8 +119,8 @@ public function testVectorScryptROMix() ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4 ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e'; - - + + $roMix = self::getMethod('scryptROMix'); $obj = new Scrypt; $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); @@ -127,11 +128,11 @@ public function testVectorScryptROMix() $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } - - + + /** * Test Vector Scrypt - * + * * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-11 */ public function testVectorScrypt() @@ -140,31 +141,31 @@ public function testVectorScrypt() f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06'; - + $result = Scrypt::calc('', '', 16, 1, 1, 64); $this->assertEquals(64, strlen($result)); $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result)); } /** - * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException */ public function testScryptWrongN() { $result = Scrypt::calc('test', 'salt', 17, 1, 1, 64); $result = Scrypt::calc('test', 'salt', PHP_INT_MAX, 1, 1, 64); } - + /** - * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException + * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException */ public function testScryptWrongR() { $result = Scrypt::calc('test', 'salt', PHP_INT_MAX / 128, 4, 1, 64); } - + /** - * Test scrypt correct size output + * Test scrypt correct size output */ public function testScryptSize() { @@ -176,12 +177,12 @@ public function testScryptSize() $this->assertEquals($size, strlen($result)); } } - + /** * Convert a string with hex values in binary string - * + * * @param string $hex - * @return string + * @return string */ protected static function hex2bin($hex) { From 9e9022ff051e3217648e9ac71bb3013027537406 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 27 Sep 2012 17:31:01 +0200 Subject: [PATCH 104/126] Changed Scrypt in abstract class --- library/Zend/Crypt/Key/Derivation/Scrypt.php | 2 +- tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Zend/Crypt/Key/Derivation/Scrypt.php b/library/Zend/Crypt/Key/Derivation/Scrypt.php index 3e10946f744..cd6d82ab6e0 100644 --- a/library/Zend/Crypt/Key/Derivation/Scrypt.php +++ b/library/Zend/Crypt/Key/Derivation/Scrypt.php @@ -20,7 +20,7 @@ * @see http://www.tarsnap.com/scrypt.html * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01 */ -class Scrypt +abstract class Scrypt { /** * Execute the scrypt algorithm diff --git a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php index cb6e3316ad9..0a8498c1b07 100644 --- a/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php +++ b/tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php @@ -52,7 +52,7 @@ public function testVectorSalsa208Core() $salsaAlg = 'salsa208Core64'; } $salsa20 = self::getMethod($salsaAlg); - $obj = new Scrypt; + $obj = $this->getMockForAbstractClass('Zend\Crypt\Key\Derivation\Scrypt'); $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput)); $result = $salsa20->invokeArgs($obj, array($input)); @@ -88,7 +88,7 @@ public function testVectorScryptBlockMix() 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25'; $blockMix = self::getMethod('scryptBlockMix'); - $obj = new Scrypt; + $obj = $this->getMockForAbstractClass('Zend\Crypt\Key\Derivation\Scrypt'); $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); $result = $blockMix->invokeArgs($obj, array($input, 1)); @@ -122,7 +122,7 @@ public function testVectorScryptROMix() $roMix = self::getMethod('scryptROMix'); - $obj = new Scrypt; + $obj = $this->getMockForAbstractClass('Zend\Crypt\Key\Derivation\Scrypt'); $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput)); $result = $roMix->invokeArgs($obj, array($input, 16, 1)); From 7bd71ae97a045e4eee07d78a1b9e09a481901d5c Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Tue, 2 Oct 2012 18:12:01 +0200 Subject: [PATCH 105/126] Fix for the issue #2524 --- library/Zend/Crypt/Password/Bcrypt.php | 28 +++++++++++++++++++- tests/ZendTest/Crypt/Password/BcryptTest.php | 16 +++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/library/Zend/Crypt/Password/Bcrypt.php b/library/Zend/Crypt/Password/Bcrypt.php index b80ab500cfe..fb58b68523d 100644 --- a/library/Zend/Crypt/Password/Bcrypt.php +++ b/library/Zend/Crypt/Password/Bcrypt.php @@ -34,6 +34,11 @@ class Bcrypt implements PasswordInterface * @var string */ protected $salt; + + /** + * @var boolean + */ + protected $backwardCompatibility = false; /** * Constructor @@ -83,7 +88,7 @@ public function create($password) * Check for security flaw in the bcrypt implementation used by crypt() * @see http://php.net/security/crypt_blowfish.php */ - if (version_compare(PHP_VERSION, '5.3.7') >= 0) { + if ((version_compare(PHP_VERSION, '5.3.7') >= 0) && !$this->backwardCompatibility) { $prefix = '$2y$'; } else { $prefix = '$2a$'; @@ -173,4 +178,25 @@ public function getSalt() { return $this->salt; } + + /** + * Set the backward compatibility $2a$ instead of $2y$ for PHP 5.3.7+ + * + * @param boolean $value + */ + public function setBackwardCompatibility($value) + { + $this->backwardCompatibility = (boolean) $value; + return $this; + } + + /** + * Get the backward compatibility + * + * @return boolean + */ + public function getBackwardCompatibility() + { + return $this->backwardCompatibility; + } } diff --git a/tests/ZendTest/Crypt/Password/BcryptTest.php b/tests/ZendTest/Crypt/Password/BcryptTest.php index 7b37dd70fa1..feffa2d22b1 100644 --- a/tests/ZendTest/Crypt/Password/BcryptTest.php +++ b/tests/ZendTest/Crypt/Password/BcryptTest.php @@ -139,4 +139,20 @@ public function testPasswordWith8bitCharacter() $output = $this->bcrypt->create($password); } } + + public function testSetBackwardCompatibility() + { + $result = $this->bcrypt->setBackwardCompatibility(true); + $this->assertTrue($result instanceof Bcrypt); + $this->assertTrue($this->bcrypt->getBackwardCompatibility()); + } + + public function testBackwardCompatibility() + { + $this->bcrypt->setSalt($this->salt); + $this->bcrypt->setBackwardCompatibility(true); + $password = $this->bcrypt->create($this->password); + $this->assertEquals('$2a$', substr($password, 0, 4)); + $this->assertEquals(substr($password, 4), substr($this->bcryptPassword, 4)); + } } From ef9a512dc038b5a7983c922cc39796cfc0d56965 Mon Sep 17 00:00:00 2001 From: Demian Katz Date: Tue, 2 Oct 2012 14:26:22 -0400 Subject: [PATCH 106/126] AbstractPluginManager should not respond to ServiceManagerAwareInterface; that is a more specific marker not intended for generic plugins. --- library/Zend/ServiceManager/AbstractPluginManager.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/Zend/ServiceManager/AbstractPluginManager.php b/library/Zend/ServiceManager/AbstractPluginManager.php index 54da31343fb..4d2f63d8829 100644 --- a/library/Zend/ServiceManager/AbstractPluginManager.php +++ b/library/Zend/ServiceManager/AbstractPluginManager.php @@ -69,9 +69,6 @@ public function __construct(ConfigInterface $configuration = null) if ($instance instanceof ServiceLocatorAwareInterface) { $instance->setServiceLocator($self); } - if ($instance instanceof ServiceManagerAwareInterface) { - $instance->setServiceManager($self); - } }); } From 2679e593e9efd4cb23692025204b747d1e5753cf Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 2 Oct 2012 15:14:44 -0500 Subject: [PATCH 107/126] [#2648] Added note to README.md - Noted the change in README.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11047798197..eac7054c3b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## 2.1.0: + +- The initializer for ServiceManagerAwareInterface was removed to prevent + confusion between ServiceManagerAwareInterface and + ServiceLocatorAwareInterface, and to promote using the latter interface. + ## 2.0.2: - 2383: Changed unreserved char definition in Zend\Uri (ZF2-533) and added shell From cd32c3f9d01d79c05b1a5703ac7a01bcfcf494aa Mon Sep 17 00:00:00 2001 From: Tim Roediger Date: Wed, 3 Oct 2012 11:29:40 +1000 Subject: [PATCH 108/126] Add view helper and controller plugin to pull the current identity from an AuthenticationService --- .../Zend/Mvc/Controller/Plugin/Identity.php | 65 +++++++++++++++++++ library/Zend/View/Helper/Identity.php | 65 +++++++++++++++++++ .../Mvc/Controller/Plugin/IdentityTest.php | 51 +++++++++++++++ .../TestAsset/AuthenticationAdapter.php | 30 +++++++++ .../Plugin/TestAsset/IdentityObject.php | 56 ++++++++++++++++ tests/ZendTest/View/Helper/IdentityTest.php | 57 ++++++++++++++++ .../TestAsset/AuthenticationAdapter.php | 30 +++++++++ .../View/Helper/TestAsset/IdentityObject.php | 56 ++++++++++++++++ 8 files changed, 410 insertions(+) create mode 100644 library/Zend/Mvc/Controller/Plugin/Identity.php create mode 100644 library/Zend/View/Helper/Identity.php create mode 100644 tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php create mode 100644 tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php create mode 100644 tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php create mode 100644 tests/ZendTest/View/Helper/IdentityTest.php create mode 100644 tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php create mode 100644 tests/ZendTest/View/Helper/TestAsset/IdentityObject.php diff --git a/library/Zend/Mvc/Controller/Plugin/Identity.php b/library/Zend/Mvc/Controller/Plugin/Identity.php new file mode 100644 index 00000000000..3464adb5bd0 --- /dev/null +++ b/library/Zend/Mvc/Controller/Plugin/Identity.php @@ -0,0 +1,65 @@ +authenticationService; + } + + /** + * + * @param \Zend\Authentication\AuthenticationService $authetnicationService + */ + public function setAuthenticationService(AuthenticationService $authenticationService) + { + $this->authenticationService = $authenticationService; + } + + /** + * + * @return mixed | null + * @throws Exception\RuntimeException + */ + public function __invoke() + { + if ( ! $this->authenticationService instanceof AuthenticationService){ + throw new Exception\RuntimeException('No AuthenticationService instance provided'); + } + if ($this->authenticationService->hasIdentity()) { + return $this->authenticationService->getIdentity(); + } + return null; + } +} \ No newline at end of file diff --git a/library/Zend/View/Helper/Identity.php b/library/Zend/View/Helper/Identity.php new file mode 100644 index 00000000000..9fe5951094c --- /dev/null +++ b/library/Zend/View/Helper/Identity.php @@ -0,0 +1,65 @@ +authenticationService; + } + + /** + * + * @param \Zend\Authentication\AuthenticationService $authetnicationService + */ + public function setAuthenticationService(AuthenticationService $authenticationService) + { + $this->authenticationService = $authenticationService; + } + + /** + * + * @return mixed | null + * @throws Exception\RuntimeException + */ + public function __invoke() + { + if ( ! $this->authenticationService instanceof AuthenticationService){ + throw new Exception\RuntimeException('No AuthenticationService instance provided'); + } + if ($this->authenticationService->hasIdentity()) { + return $this->authenticationService->getIdentity(); + } + return null; + } +} \ No newline at end of file diff --git a/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php b/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php new file mode 100644 index 00000000000..da5de3075c9 --- /dev/null +++ b/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php @@ -0,0 +1,51 @@ +setUsername('a username'); + $identity->setPassword('a password'); + + $authenticationService = new AuthenticationService(new NonPersistentStorage, new AuthenticationAdapter); + + $identityPlugin = new IdentityPlugin; + $identityPlugin->setAuthenticationService($authenticationService); + + $this->assertNull($identityPlugin()); + + $this->assertFalse($authenticationService->hasIdentity()); + + $authenticationService->getAdapter()->setIdentity($identity); + $result = $authenticationService->authenticate(); + $this->assertTrue($result->isValid()); + + $this->assertEquals($identity, $identityPlugin()); + } +} diff --git a/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php new file mode 100644 index 00000000000..b1cc7953f1c --- /dev/null +++ b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php @@ -0,0 +1,30 @@ +identity = $identity; + } + + public function authenticate() + { + return new Result(Result::SUCCESS, $this->identity); + } +} diff --git a/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php new file mode 100644 index 00000000000..4007907923d --- /dev/null +++ b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php @@ -0,0 +1,56 @@ +password = (string) $password; + } + + /** + * @return string|null + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param string $username + */ + public function setUsername($username) + { + $this->username = (string) $username; + } + + /** + * @return string|null + */ + public function getUsername() + { + return $this->username; + } +} diff --git a/tests/ZendTest/View/Helper/IdentityTest.php b/tests/ZendTest/View/Helper/IdentityTest.php new file mode 100644 index 00000000000..33ff74ae69a --- /dev/null +++ b/tests/ZendTest/View/Helper/IdentityTest.php @@ -0,0 +1,57 @@ +setUsername('a username'); + $identity->setPassword('a password'); + + + $authenticationService = new AuthenticationService(new NonPersistentStorage, new AuthenticationAdapter); + + $identityHelper = new IdentityHelper; + $identityHelper->setAuthenticationService($authenticationService); + + $this->assertNull($identityHelper()); + + $this->assertFalse($authenticationService->hasIdentity()); + + $authenticationService->getAdapter()->setIdentity($identity); + $result = $authenticationService->authenticate(); + $this->assertTrue($result->isValid()); + + $this->assertEquals($identity, $identityHelper()); + } +} diff --git a/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php b/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php new file mode 100644 index 00000000000..5bb58c2577e --- /dev/null +++ b/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php @@ -0,0 +1,30 @@ +identity = $identity; + } + + public function authenticate() + { + return new Result(Result::SUCCESS, $this->identity); + } +} diff --git a/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php b/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php new file mode 100644 index 00000000000..0517fce0027 --- /dev/null +++ b/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php @@ -0,0 +1,56 @@ +password = (string) $password; + } + + /** + * @return string|null + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param string $username + */ + public function setUsername($username) + { + $this->username = (string) $username; + } + + /** + * @return string|null + */ + public function getUsername() + { + return $this->username; + } +} From a24a888d40fd99f4e03febeb0831bb01672d3ba7 Mon Sep 17 00:00:00 2001 From: Tim Roediger Date: Wed, 3 Oct 2012 11:56:07 +1000 Subject: [PATCH 109/126] Fix EOF --- library/Zend/Mvc/Controller/Plugin/Identity.php | 2 +- library/Zend/View/Helper/Identity.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Identity.php b/library/Zend/Mvc/Controller/Plugin/Identity.php index 3464adb5bd0..6bc36ff84ea 100644 --- a/library/Zend/Mvc/Controller/Plugin/Identity.php +++ b/library/Zend/Mvc/Controller/Plugin/Identity.php @@ -62,4 +62,4 @@ public function __invoke() } return null; } -} \ No newline at end of file +} diff --git a/library/Zend/View/Helper/Identity.php b/library/Zend/View/Helper/Identity.php index 9fe5951094c..1fb1fc304c7 100644 --- a/library/Zend/View/Helper/Identity.php +++ b/library/Zend/View/Helper/Identity.php @@ -62,4 +62,4 @@ public function __invoke() } return null; } -} \ No newline at end of file +} From 01985e796248d1d75b892582d5a5873f007e8e0a Mon Sep 17 00:00:00 2001 From: Gerard Roche Date: Tue, 2 Oct 2012 16:18:41 +0100 Subject: [PATCH 110/126] Add missing module event type hint --- .../ModuleManager/Listener/ModuleResolverListener.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/Zend/ModuleManager/Listener/ModuleResolverListener.php b/library/Zend/ModuleManager/Listener/ModuleResolverListener.php index 3a18625c3f6..8868790a745 100644 --- a/library/Zend/ModuleManager/Listener/ModuleResolverListener.php +++ b/library/Zend/ModuleManager/Listener/ModuleResolverListener.php @@ -10,6 +10,8 @@ namespace Zend\ModuleManager\Listener; +use Zend\ModuleManager\ModuleEvent; + /** * Module resolver listener * @@ -20,10 +22,10 @@ class ModuleResolverListener extends AbstractListener { /** - * @param \Zend\EventManager\EventInterface $e - * @return object + * @param ModuleEvent $e + * @return object|false False if module class does not exist */ - public function __invoke($e) + public function __invoke(ModuleEvent $e) { $moduleName = $e->getModuleName(); $class = $moduleName . '\Module'; From dee2cc42230dbe0ee8823551935b27327aa21615 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 3 Oct 2012 10:47:41 -0500 Subject: [PATCH 111/126] [#2621] revert changes to conditional flow - Reverts changes to conditional flows. Original code was more semantically correct, as it was validating arguments immediately, and then doing the work of the method in the method body, not in the conditional body. --- .../Listener/ListenerOptions.php | 72 +++++++++---------- library/Zend/Stdlib/AbstractOptions.php | 32 ++++----- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/library/Zend/ModuleManager/Listener/ListenerOptions.php b/library/Zend/ModuleManager/Listener/ListenerOptions.php index 2e39e99dc23..7bbf73edc66 100644 --- a/library/Zend/ModuleManager/Listener/ListenerOptions.php +++ b/library/Zend/ModuleManager/Listener/ListenerOptions.php @@ -86,17 +86,17 @@ public function getModulePaths() */ public function setModulePaths($modulePaths) { - if (is_array($modulePaths) || $modulePaths instanceof Traversable) { - $this->modulePaths = $modulePaths; - return $this; + if (!is_array($modulePaths) && !$modulePaths instanceof Traversable) { + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($modulePaths)) + ); } - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($modulePaths)) - ); + $this->modulePaths = $modulePaths; + return $this; } /** @@ -128,17 +128,17 @@ public function getConfigStaticPaths() */ public function setConfigGlobPaths($configGlobPaths) { - if (is_array($configGlobPaths) || $configGlobPaths instanceof Traversable) { - $this->configGlobPaths = $configGlobPaths; - return $this; + if (!is_array($configGlobPaths) && !$configGlobPaths instanceof Traversable) { + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($configGlobPaths)) + ); } - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($configGlobPaths)) - ); + $this->configGlobPaths = $configGlobPaths; + return $this; } /** @@ -150,17 +150,17 @@ public function setConfigGlobPaths($configGlobPaths) */ public function setConfigStaticPaths($configStaticPaths) { - if (is_array($configStaticPaths) || $configStaticPaths instanceof Traversable) { - $this->configStaticPaths = $configStaticPaths; - return $this; + if (!is_array($configStaticPaths) && !$configStaticPaths instanceof Traversable) { + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($configStaticPaths)) + ); } - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($configStaticPaths)) - ); + $this->configStaticPaths = $configStaticPaths; + return $this; } /** @@ -183,17 +183,17 @@ public function getExtraConfig() */ public function setExtraConfig($extraConfig) { - if (is_array($extraConfig) || $extraConfig instanceof Traversable) { - $this->extraConfig = $extraConfig; - return $this; + if (!is_array($extraConfig) && !$extraConfig instanceof Traversable) { + throw new Exception\InvalidArgumentException( + sprintf('Argument passed to %s::%s() must be an array, ' + . 'implement the \Traversable interface, or be an ' + . 'instance of Zend\Config\Config. %s given.', + __CLASS__, __METHOD__, gettype($extraConfig)) + ); } - throw new Exception\InvalidArgumentException( - sprintf('Argument passed to %s::%s() must be an array, ' - . 'implement the \Traversable interface, or be an ' - . 'instance of Zend\Config\Config. %s given.', - __CLASS__, __METHOD__, gettype($extraConfig)) - ); + $this->extraConfig = $extraConfig; + return $this; } /** diff --git a/library/Zend/Stdlib/AbstractOptions.php b/library/Zend/Stdlib/AbstractOptions.php index 8dadafa52fa..f9365e8112b 100644 --- a/library/Zend/Stdlib/AbstractOptions.php +++ b/library/Zend/Stdlib/AbstractOptions.php @@ -43,17 +43,17 @@ public function __construct($options = null) */ public function setFromArray($options) { - if (is_array($options) || $options instanceof Traversable) { - foreach ($options as $key => $value) { - $this->__set($key, $value); - } - return $this; + if (!is_array($options) && !$options instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Parameter provided to %s must be an array or Traversable', + __METHOD__ + )); } - 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); + } + return $this; } /** @@ -107,15 +107,15 @@ public function __set($key, $value) public function __get($key) { $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); - if (method_exists($this, $getter)) { - return $this->{$getter}(); + if (!method_exists($this, $getter)) { + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $getter . ' getter method ' + . 'which must be defined' + ); } - throw new Exception\BadMethodCallException( - 'The option "' . $key . '" does not ' - . 'have a matching ' . $getter . ' getter method ' - . 'which must be defined' - ); + return $this->{$getter}(); } /** From 7f86eacbd14d5ff5a42ad480b8c1602fba74075e Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 3 Oct 2012 12:42:58 -0500 Subject: [PATCH 112/126] [#2650] CS fixes - Removed unnecessary empty lines and empty docblock lines - Removed unnecessary imports (and resolved class names relative to existing imports or current namespace) - Ensured all docblocks were present - Minor flow fixes --- .../Zend/Mvc/Controller/Plugin/Identity.php | 23 +++++++++--------- library/Zend/View/Helper/Identity.php | 24 +++++++++---------- .../Mvc/Controller/Plugin/IdentityTest.php | 8 ++----- .../TestAsset/AuthenticationAdapter.php | 6 ++++- .../Plugin/TestAsset/IdentityObject.php | 5 ++++ tests/ZendTest/View/Helper/IdentityTest.php | 10 ++------ .../TestAsset/AuthenticationAdapter.php | 6 ++++- .../View/Helper/TestAsset/IdentityObject.php | 5 ++++ 8 files changed, 47 insertions(+), 40 deletions(-) diff --git a/library/Zend/Mvc/Controller/Plugin/Identity.php b/library/Zend/Mvc/Controller/Plugin/Identity.php index 6bc36ff84ea..9e30d89436e 100644 --- a/library/Zend/Mvc/Controller/Plugin/Identity.php +++ b/library/Zend/Mvc/Controller/Plugin/Identity.php @@ -22,16 +22,13 @@ */ class Identity extends AbstractPlugin { - /** - * - * @var \Zend\Authentication\AuthenticationService + * @var AuthenticationService */ protected $authenticationService; /** - * - * @return \Zend\Authentication\AuthenticationService + * @return AuthenticationService */ public function getAuthenticationService() { @@ -39,8 +36,7 @@ public function getAuthenticationService() } /** - * - * @param \Zend\Authentication\AuthenticationService $authetnicationService + * @param AuthenticationService $authenticationService */ public function setAuthenticationService(AuthenticationService $authenticationService) { @@ -48,18 +44,21 @@ public function setAuthenticationService(AuthenticationService $authenticationSe } /** + * Retrieve the current identity, if any. + * + * If none is present, returns null. * - * @return mixed | null + * @return mixed|null * @throws Exception\RuntimeException */ public function __invoke() { - if ( ! $this->authenticationService instanceof AuthenticationService){ + if (!$this->authenticationService instanceof AuthenticationService){ throw new Exception\RuntimeException('No AuthenticationService instance provided'); } - if ($this->authenticationService->hasIdentity()) { - return $this->authenticationService->getIdentity(); + if (!$this->authenticationService->hasIdentity()) { + return null; } - return null; + return $this->authenticationService->getIdentity(); } } diff --git a/library/Zend/View/Helper/Identity.php b/library/Zend/View/Helper/Identity.php index 1fb1fc304c7..34dc8a234a3 100644 --- a/library/Zend/View/Helper/Identity.php +++ b/library/Zend/View/Helper/Identity.php @@ -22,16 +22,13 @@ */ class Identity extends AbstractHelper { - /** - * - * @var \Zend\Authentication\AuthenticationService + * @var AuthenticationService */ protected $authenticationService; /** - * - * @return \Zend\Authentication\AuthenticationService + * @return AuthenticationService */ public function getAuthenticationService() { @@ -39,8 +36,7 @@ public function getAuthenticationService() } /** - * - * @param \Zend\Authentication\AuthenticationService $authetnicationService + * @param AuthenticationService $authenticationService */ public function setAuthenticationService(AuthenticationService $authenticationService) { @@ -48,18 +44,22 @@ public function setAuthenticationService(AuthenticationService $authenticationSe } /** + * Retrieve the current identity, if any. + * + * If none available, returns null. * - * @return mixed | null + * @return mixed|null * @throws Exception\RuntimeException */ public function __invoke() { - if ( ! $this->authenticationService instanceof AuthenticationService){ + if (!$this->authenticationService instanceof AuthenticationService){ throw new Exception\RuntimeException('No AuthenticationService instance provided'); } - if ($this->authenticationService->hasIdentity()) { - return $this->authenticationService->getIdentity(); + + if (!$this->authenticationService->hasIdentity()) { + return null; } - return null; + return $this->authenticationService->getIdentity(); } } diff --git a/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php b/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php index da5de3075c9..730c86b4b6d 100644 --- a/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php +++ b/tests/ZendTest/Mvc/Controller/Plugin/IdentityTest.php @@ -13,8 +13,6 @@ use Zend\Authentication\AuthenticationService; use Zend\Authentication\Storage\NonPersistent as NonPersistentStorage; use Zend\Mvc\Controller\Plugin\Identity as IdentityPlugin; -use ZendTest\Mvc\Controller\Plugin\TestAsset\IdentityObject; -use ZendTest\Mvc\Controller\Plugin\TestAsset\AuthenticationAdapter; /** * Tests Identity plugin @@ -25,15 +23,13 @@ */ class IdentityTest extends \PHPUnit_Framework_TestCase { - public function testGetIdentity() { - - $identity = new IdentityObject(); + $identity = new TestAsset\IdentityObject(); $identity->setUsername('a username'); $identity->setPassword('a password'); - $authenticationService = new AuthenticationService(new NonPersistentStorage, new AuthenticationAdapter); + $authenticationService = new AuthenticationService(new NonPersistentStorage, new TestAsset\AuthenticationAdapter); $identityPlugin = new IdentityPlugin; $identityPlugin->setAuthenticationService($authenticationService); diff --git a/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php index b1cc7953f1c..4eedbe677b9 100644 --- a/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php +++ b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/AuthenticationAdapter.php @@ -13,9 +13,13 @@ use Zend\Authentication\Adapter\AdapterInterface; use Zend\Authentication\Result; +/** + * @category Zend + * @package Zend_Mvc + * @subpackage UnitTests + */ class AuthenticationAdapter implements AdapterInterface { - protected $identity; public function setIdentity($identity) diff --git a/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php index 4007907923d..c978326aaf7 100644 --- a/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php +++ b/tests/ZendTest/Mvc/Controller/Plugin/TestAsset/IdentityObject.php @@ -10,6 +10,11 @@ namespace ZendTest\Mvc\Controller\Plugin\TestAsset; +/** + * @category Zend + * @package Zend_Mvc + * @subpackage UnitTests + */ class IdentityObject { /** diff --git a/tests/ZendTest/View/Helper/IdentityTest.php b/tests/ZendTest/View/Helper/IdentityTest.php index 33ff74ae69a..20dd70a544b 100644 --- a/tests/ZendTest/View/Helper/IdentityTest.php +++ b/tests/ZendTest/View/Helper/IdentityTest.php @@ -13,8 +13,6 @@ use Zend\Authentication\AuthenticationService; use Zend\Authentication\Storage\NonPersistent as NonPersistentStorage; use Zend\View\Helper\Identity as IdentityHelper; -use ZendTest\View\Helper\TestAsset\IdentityObject; -use ZendTest\View\Helper\TestAsset\AuthenticationAdapter; /** * Zend_View_Helper_IdentityTest @@ -27,19 +25,15 @@ * @group Zend_View * @group Zend_View_Helper */ - class IdentityTest extends \PHPUnit_Framework_TestCase { - public function testGetIdentity() { - - $identity = new IdentityObject(); + $identity = new TestAsset\IdentityObject(); $identity->setUsername('a username'); $identity->setPassword('a password'); - - $authenticationService = new AuthenticationService(new NonPersistentStorage, new AuthenticationAdapter); + $authenticationService = new AuthenticationService(new NonPersistentStorage, new TestAsset\AuthenticationAdapter); $identityHelper = new IdentityHelper; $identityHelper->setAuthenticationService($authenticationService); diff --git a/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php b/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php index 5bb58c2577e..1ed89161614 100644 --- a/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php +++ b/tests/ZendTest/View/Helper/TestAsset/AuthenticationAdapter.php @@ -13,9 +13,13 @@ use Zend\Authentication\Adapter\AdapterInterface; use Zend\Authentication\Result; +/** + * @category Zend + * @package Zend_View + * @subpackage UnitTests + */ class AuthenticationAdapter implements AdapterInterface { - protected $identity; public function setIdentity($identity) diff --git a/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php b/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php index 0517fce0027..d1606901a58 100644 --- a/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php +++ b/tests/ZendTest/View/Helper/TestAsset/IdentityObject.php @@ -10,6 +10,11 @@ namespace ZendTest\View\Helper\TestAsset; +/** + * @category Zend + * @package Zend_View + * @subpackage UnitTests + */ class IdentityObject { /** From 9150bcc4fe24b8b7439eb0c0ccacec9051b4c66b Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 3 Oct 2012 12:56:23 -0500 Subject: [PATCH 113/126] [#2650] Added factories for identity plugins - In View HelperPluginManager and Mvc Controller\PluginManager - Includes tests for expected behavior --- library/Zend/Mvc/Controller/PluginManager.php | 11 +++++++++++ library/Zend/View/HelperPluginManager.php | 11 +++++++++++ .../Mvc/Controller/PluginManagerTest.php | 18 ++++++++++++++++++ .../ZendTest/View/HelperPluginManagerTest.php | 16 ++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/library/Zend/Mvc/Controller/PluginManager.php b/library/Zend/Mvc/Controller/PluginManager.php index 5ef7cb0131a..4466dbb32fc 100644 --- a/library/Zend/Mvc/Controller/PluginManager.php +++ b/library/Zend/Mvc/Controller/PluginManager.php @@ -67,6 +67,17 @@ class PluginManager extends AbstractPluginManager public function __construct(ConfigInterface $configuration = null) { parent::__construct($configuration); + + $this->setFactory('identity', function ($plugins) { + $services = $plugins->getServiceLocator(); + $plugin = new Plugin\Identity(); + if (!$services->has('Zend\Authentication\AuthenticationService')) { + return $plugin; + } + $plugin->setAuthenticationService($services->get('Zend\Authentication\AuthenticationService')); + return $plugin; + }); + $this->addInitializer(array($this, 'injectController')); } diff --git a/library/Zend/View/HelperPluginManager.php b/library/Zend/View/HelperPluginManager.php index 517c07a3dc9..aee4f6ef670 100644 --- a/library/Zend/View/HelperPluginManager.php +++ b/library/Zend/View/HelperPluginManager.php @@ -86,6 +86,17 @@ class HelperPluginManager extends AbstractPluginManager public function __construct(ConfigInterface $configuration = null) { parent::__construct($configuration); + + $this->setFactory('identity', function ($helpers) { + $services = $helpers->getServiceLocator(); + $helper = new Helper\Identity(); + if (!$services->has('Zend\Authentication\AuthenticationService')) { + return $helper; + } + $helper->setAuthenticationService($services->get('Zend\Authentication\AuthenticationService')); + return $helper; + }); + $this->addInitializer(array($this, 'injectRenderer')) ->addInitializer(array($this, 'injectTranslator')); } diff --git a/tests/ZendTest/Mvc/Controller/PluginManagerTest.php b/tests/ZendTest/Mvc/Controller/PluginManagerTest.php index 005a9bed2ae..2d9da55b117 100644 --- a/tests/ZendTest/Mvc/Controller/PluginManagerTest.php +++ b/tests/ZendTest/Mvc/Controller/PluginManagerTest.php @@ -15,6 +15,7 @@ use ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin; use ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePluginWithConstructor; use Zend\Mvc\Controller\PluginManager; +use Zend\ServiceManager\ServiceManager; class PluginManagerTest extends TestCase { @@ -71,4 +72,21 @@ public function testGetWithConstrutorAndOptions() $plugin = $pluginManager->get('samplePlugin', 'foo'); $this->assertEquals($plugin->getBar(), 'foo'); } + + public function testDefinesFactoryForIdentityPlugin() + { + $pluginManager = new PluginManager; + $this->assertTrue($pluginManager->has('identity')); + } + + public function testIdentityFactoryCanInjectAuthenticationServiceIfInParentServiceManager() + { + $services = new ServiceManager(); + $services->setInvokableClass('Zend\Authentication\AuthenticationService', 'Zend\Authentication\AuthenticationService'); + $pluginManager = new PluginManager; + $pluginManager->setServiceLocator($services); + $identity = $pluginManager->get('identity'); + $expected = $services->get('Zend\Authentication\AuthenticationService'); + $this->assertSame($expected, $identity->getAuthenticationService()); + } } diff --git a/tests/ZendTest/View/HelperPluginManagerTest.php b/tests/ZendTest/View/HelperPluginManagerTest.php index fd5c8142a0c..b47613c8886 100644 --- a/tests/ZendTest/View/HelperPluginManagerTest.php +++ b/tests/ZendTest/View/HelperPluginManagerTest.php @@ -10,6 +10,7 @@ namespace ZendTest\View; +use Zend\ServiceManager\ServiceManager; use Zend\View\HelperPluginManager; use Zend\View\Renderer\PhpRenderer; @@ -64,4 +65,19 @@ public function testLoadingInvalidHelperRaisesException() $this->setExpectedException('Zend\View\Exception\InvalidHelperException'); $this->helpers->get('test'); } + + public function testDefinesFactoryForIdentityPlugin() + { + $this->assertTrue($this->helpers->has('identity')); + } + + public function testIdentityFactoryCanInjectAuthenticationServiceIfInParentServiceManager() + { + $services = new ServiceManager(); + $services->setInvokableClass('Zend\Authentication\AuthenticationService', 'Zend\Authentication\AuthenticationService'); + $this->helpers->setServiceLocator($services); + $identity = $this->helpers->get('identity'); + $expected = $services->get('Zend\Authentication\AuthenticationService'); + $this->assertSame($expected, $identity->getAuthenticationService()); + } } From ceb20c5503f03cdb84fb8c19a3d8d3c1306e7188 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 3 Oct 2012 13:11:55 -0500 Subject: [PATCH 114/126] [#2414] move test to correct directory - was in tests/Zend/ instead of tests/ZendTest/ --- tests/{Zend => ZendTest}/Validator/IsInstanceOfTest.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{Zend => ZendTest}/Validator/IsInstanceOfTest.php (100%) diff --git a/tests/Zend/Validator/IsInstanceOfTest.php b/tests/ZendTest/Validator/IsInstanceOfTest.php similarity index 100% rename from tests/Zend/Validator/IsInstanceOfTest.php rename to tests/ZendTest/Validator/IsInstanceOfTest.php From dedd8ce8321170fdbeb1acaa0919e82ec9d32a35 Mon Sep 17 00:00:00 2001 From: Jerry Saravia Date: Wed, 3 Oct 2012 22:20:49 -0400 Subject: [PATCH 115/126] Added fluent inteface to prepend and set method. --- .../View/Helper/Placeholder/Container/AbstractContainer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/Zend/View/Helper/Placeholder/Container/AbstractContainer.php b/library/Zend/View/Helper/Placeholder/Container/AbstractContainer.php index 37d52e701dd..d116fbea70e 100644 --- a/library/Zend/View/Helper/Placeholder/Container/AbstractContainer.php +++ b/library/Zend/View/Helper/Placeholder/Container/AbstractContainer.php @@ -98,6 +98,7 @@ public function __construct() public function set($value) { $this->exchangeArray(array($value)); + return $this; } /** @@ -111,6 +112,7 @@ public function prepend($value) $values = $this->getArrayCopy(); array_unshift($values, $value); $this->exchangeArray($values); + return $this; } /** From eaa3c4fcfbd02f4e5a66b983bd7b6b84a9d1c07d Mon Sep 17 00:00:00 2001 From: Jerry Saravia Date: Wed, 3 Oct 2012 22:44:31 -0400 Subject: [PATCH 116/126] Added tests for set and prepend fluency. --- .../View/Helper/Placeholder/ContainerTest.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/ZendTest/View/Helper/Placeholder/ContainerTest.php b/tests/ZendTest/View/Helper/Placeholder/ContainerTest.php index e62fb9d5687..7422039e4e7 100644 --- a/tests/ZendTest/View/Helper/Placeholder/ContainerTest.php +++ b/tests/ZendTest/View/Helper/Placeholder/ContainerTest.php @@ -123,6 +123,26 @@ public function testSetPostfixImplementsFluentInterface() $this->assertSame($this->container, $result); } + /** + * @return void + */ + + public function testPrependImplementsFluentInterface() + { + $result = $this->container->prepend( 'test' ); + $this->assertSame($this->container, $result); + } + + /** + * @return void + */ + public function testSetImplementsFluentInterface() + { + $result = $this->container->set( 'test' ); + $this->assertSame($this->container, $result); + } + + /** * @return void */ From 1fd9b98133be8659950e8d203d35bc5ad2049162 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 4 Oct 2012 14:32:09 -0500 Subject: [PATCH 117/126] [#2647] CS fixes - Trailing whitespace --- library/Zend/Crypt/Password/Bcrypt.php | 12 ++++++------ tests/ZendTest/Crypt/Password/BcryptTest.php | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/Zend/Crypt/Password/Bcrypt.php b/library/Zend/Crypt/Password/Bcrypt.php index fb58b68523d..b68896c4eb0 100644 --- a/library/Zend/Crypt/Password/Bcrypt.php +++ b/library/Zend/Crypt/Password/Bcrypt.php @@ -34,7 +34,7 @@ class Bcrypt implements PasswordInterface * @var string */ protected $salt; - + /** * @var boolean */ @@ -178,21 +178,21 @@ public function getSalt() { return $this->salt; } - + /** * Set the backward compatibility $2a$ instead of $2y$ for PHP 5.3.7+ - * - * @param boolean $value + * + * @param boolean $value */ public function setBackwardCompatibility($value) { $this->backwardCompatibility = (boolean) $value; return $this; } - + /** * Get the backward compatibility - * + * * @return boolean */ public function getBackwardCompatibility() diff --git a/tests/ZendTest/Crypt/Password/BcryptTest.php b/tests/ZendTest/Crypt/Password/BcryptTest.php index feffa2d22b1..6207428ca28 100644 --- a/tests/ZendTest/Crypt/Password/BcryptTest.php +++ b/tests/ZendTest/Crypt/Password/BcryptTest.php @@ -139,14 +139,14 @@ public function testPasswordWith8bitCharacter() $output = $this->bcrypt->create($password); } } - + public function testSetBackwardCompatibility() { $result = $this->bcrypt->setBackwardCompatibility(true); $this->assertTrue($result instanceof Bcrypt); $this->assertTrue($this->bcrypt->getBackwardCompatibility()); } - + public function testBackwardCompatibility() { $this->bcrypt->setSalt($this->salt); From 4298307fe96100703b17c12554c6310158a215f4 Mon Sep 17 00:00:00 2001 From: Jesper Dolieslager Date: Sun, 7 Oct 2012 23:09:29 +0200 Subject: [PATCH 118/126] Inital commit WriterPluginManager --- library/Zend/Config/Factory.php | 113 ++++++++++++++++++++ library/Zend/Config/WriterPluginManager.php | 30 ++++++ 2 files changed, 143 insertions(+) create mode 100755 library/Zend/Config/WriterPluginManager.php diff --git a/library/Zend/Config/Factory.php b/library/Zend/Config/Factory.php index 53e5b41c59a..6c900ddef30 100644 --- a/library/Zend/Config/Factory.php +++ b/library/Zend/Config/Factory.php @@ -25,6 +25,13 @@ class Factory */ public static $readers = null; + /** + * Plugin manager for loading writers + * + * @var null|WriterPluginManager + */ + public static $writers = null; + /** * Registered config file extensions. * key is extension, value is reader instance or plugin name @@ -38,6 +45,19 @@ class Factory 'yaml' => 'yaml', ); + /** + * Register config file extensions for writing + * key is extension, value is writer instance or plugin name + * + * @var array + */ + protected static $writerExtensions = array( + 'php' => 'PhpArray', + 'ini' => 'ini', + 'json' => 'json', + 'xml' => 'xml', + 'yaml' => 'yaml', + ); /** * Read a config from a file. @@ -107,6 +127,59 @@ public static function fromFiles(array $files, $returnConfigObject = false) return ($returnConfigObject) ? new Config($config) : $config; } + /** + * Writes a config to a file + * + * @param string $filename + * @param array|Config $config + * + * @return boolean TRUE on success | FALSE on failure + */ + public static function toFile($filename, $config) + { + if ( + (is_object($config) && !($config instanceOf Config)) || + (!is_object($config) && !is_array($config)) + ) { + throw new Exception\InvalidArgumentException( + __METHOD__." \$config should be an array or instance of Zend\Config\Config" + ); + } + + $extension = substr(strrchr($filename, '.'), 1); + $directory = dirname($filename); + + if (!is_dir($directory)) { + throw new Exception\RuntimeException( + "Directory '{$directory}' does not exists!" + ); + } + + if (!is_writable($directory)) { + throw new Exception\RuntimeException( + "Cannot write in directory '{$directory}'" + ); + } + + if(!isset(self::$extensionWriters[$extension])) { + throw new Exception\RuntimeException( + "Unsupported config file extension: .{$extension}" + ); + } + + $writer = self::$extensionWriters[$extension]; + if (($writer instanceOf Writer\AbstractWriter) === false) { + $writer = self::getWriterPluginManager()->get($writer); + self::$extensionWriters[$extension] = $writer; + } + + if (is_object($config)) { + $config = $config->toArray(); + } + + return file_put_contents($filename, $writer->processConfig($config)); + } + /** * Set reader plugin manager * @@ -130,6 +203,30 @@ public static function getReaderPluginManager() return static::$readers; } + /** + * Set writer plugin manager + * + * @param WriterPluginManager $writers + */ + public static function setWriterPluginManager(WriterPluginManager $writers) + { + self::$writers = $writers; + } + + /** + * Get the writer plugin manager + * + * @return WriterPluginManager + */ + public static function getWriterPluginManager() + { + if (static::$writers === null) { + static::$writers = new WriterPluginManager(); + } + + return static::$writers; + } + /** * Set config reader for file extension * @@ -152,4 +249,20 @@ public static function registerReader($extension, $reader) self::$extensions[$extension] = $reader; } + + public static function registerWriter($extension, $writer) + { + $extension = strtolower($extension); + + if (!is_string($writer) && !$writer instanceof Writer\AbstractWriter) { + throw new Exception\InvalidArgumentException(sprintf( + 'Writer should be plugin name, class name or ' . + 'instance of %s\Writer\AbstractWriter; received "%s"', + __NAMESPACE__, + (is_object($writer) ? get_class($writer) : gettype($writer)) + )); + } + + self::$extensions[$extension] = $writer; + } } diff --git a/library/Zend/Config/WriterPluginManager.php b/library/Zend/Config/WriterPluginManager.php new file mode 100755 index 00000000000..58598c56738 --- /dev/null +++ b/library/Zend/Config/WriterPluginManager.php @@ -0,0 +1,30 @@ + 'Zend\Config\Writer\PhpArray', + 'ini' => 'Zend\Config\Writer\Ini', + 'json' => 'Zend\Config\Writer\Json', + 'yaml' => 'Zend\Config\Writer\Yaml', + 'xml' => 'Zend\Config\Writer\Xml', + ); + + public function validatePlugin($plugin) + { + if ($plugin instanceOf Writer\AbstractWriter) { + return; + } + + $type = is_object($plugin) ? get_class($plugin) : gettype($plugin); + + throw new Exception\InvalidArgumentException( + "Plugin of type {$type} is invalid. Plugin must extend ". + __NAMESPACE__.'\Writer\AbstractWriter' + ); + } +} + From 868074569a15cccbbc7bf09b176bd211fdee28f9 Mon Sep 17 00:00:00 2001 From: Robert Boloc Date: Mon, 8 Oct 2012 15:34:36 +0200 Subject: [PATCH 119/126] added addUseClass method in ClassGenerator --- .../Zend/Code/Generator/ClassGenerator.php | 33 +++++++++++++++++++ .../Code/Generator/ClassGeneratorTest.php | 15 +++++++++ 2 files changed, 48 insertions(+) diff --git a/library/Zend/Code/Generator/ClassGenerator.php b/library/Zend/Code/Generator/ClassGenerator.php index c17b66a97bf..6aa44a84087 100644 --- a/library/Zend/Code/Generator/ClassGenerator.php +++ b/library/Zend/Code/Generator/ClassGenerator.php @@ -67,6 +67,11 @@ class ClassGenerator extends AbstractGenerator */ protected $methods = array(); + /** + * @var array Array of string names + */ + protected $useClasses = array(); + /** * fromReflection() - build a Code Generation Php Object from a Class Reflection * @@ -479,6 +484,16 @@ public function addPropertyFromGenerator(PropertyGenerator $property) return $this; } + /** + * Add a class to "use" classes + * + * @param string $useClass + */ + public function addUseClass($useClass) + { + $this->useClasses[] = $useClass; + } + /** * getProperties() * @@ -505,6 +520,16 @@ public function getProperty($propertyName) return false; } + /** + * Returns the "use" classes + * + * @return array + */ + public function getUseClasses() + { + return $this->useClasses; + } + /** * hasProperty() * @@ -664,6 +689,14 @@ public function generate() $output .= 'namespace ' . $namespace . ';' . self::LINE_FEED . self::LINE_FEED; } + $useClasses = $this->getUseClasses(); + if (!empty($useClasses)) { + foreach ($useClasses as $useClass) { + $output .= 'use ' . $useClass . ';' . self::LINE_FEED; + } + $output .= self::LINE_FEED; + } + if (null !== ($docBlock = $this->getDocBlock())) { $docBlock->setIndentation(''); $output .= $docBlock->generate(); diff --git a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php index d813f23d693..bca844c731e 100644 --- a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php +++ b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php @@ -362,4 +362,19 @@ public function testPassingANamespacedClassnameShouldGenerateAClassnameWithoutIt $received = $classGeneratorClass->generate(); $this->assertContains('class FunClass', $received, $received); } + + /** + * @group ZF2-151 + */ + public function testAddUseClass() + { + $classGenerator = new ClassGenerator(); + $classGenerator->setName('My\Class'); + $classGenerator->addUseClass('My\First\Use\Class'); + $classGenerator->addUseClass('My\Second\Use\Class'); + $generated = $classGenerator->generate(); + + $this->assertContains('use My\First\Use\Class;', $generated); + $this->assertContains('use My\Second\Use\Class;', $generated); + } } From 17e81de864c94436ba9a61e1cc502565010af198 Mon Sep 17 00:00:00 2001 From: Jesper Dolieslager Date: Mon, 8 Oct 2012 20:27:45 +0200 Subject: [PATCH 120/126] Add unit tests and fix minor errors --- library/Zend/Config/Factory.php | 32 +++++-- tests/ZendTest/Config/FactoryTest.php | 92 ++++++++++++++++++- .../Config/Writer/TestAssets/DummyWriter.php | 23 +++++ 3 files changed, 137 insertions(+), 10 deletions(-) create mode 100755 tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php diff --git a/library/Zend/Config/Factory.php b/library/Zend/Config/Factory.php index 6c900ddef30..0407e8fb383 100644 --- a/library/Zend/Config/Factory.php +++ b/library/Zend/Config/Factory.php @@ -52,7 +52,7 @@ class Factory * @var array */ protected static $writerExtensions = array( - 'php' => 'PhpArray', + 'php' => 'php', 'ini' => 'ini', 'json' => 'json', 'xml' => 'xml', @@ -132,8 +132,9 @@ public static function fromFiles(array $files, $returnConfigObject = false) * * @param string $filename * @param array|Config $config - * * @return boolean TRUE on success | FALSE on failure + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException */ public static function toFile($filename, $config) { @@ -142,7 +143,7 @@ public static function toFile($filename, $config) (!is_object($config) && !is_array($config)) ) { throw new Exception\InvalidArgumentException( - __METHOD__." \$config should be an array or instance of Zend\Config\Config" + __METHOD__." \$config should be an array or instance of Zend\\Config\\Config" ); } @@ -161,29 +162,32 @@ public static function toFile($filename, $config) ); } - if(!isset(self::$extensionWriters[$extension])) { + if(!isset(self::$writerExtensions[$extension])) { throw new Exception\RuntimeException( - "Unsupported config file extension: .{$extension}" + "Unsupported config file extension: '.{$extension}' for writing." ); } - $writer = self::$extensionWriters[$extension]; + $writer = self::$writerExtensions[$extension]; if (($writer instanceOf Writer\AbstractWriter) === false) { $writer = self::getWriterPluginManager()->get($writer); - self::$extensionWriters[$extension] = $writer; + self::$writerExtensions[$extension] = $writer; } if (is_object($config)) { $config = $config->toArray(); } - return file_put_contents($filename, $writer->processConfig($config)); + $content = $writer->processConfig($config); + + return (bool) (file_put_contents($filename, $content) !== false); } /** * Set reader plugin manager * * @param ReaderPluginManager $readers + * @return void */ public static function setReaderPluginManager(ReaderPluginManager $readers) { @@ -207,6 +211,7 @@ public static function getReaderPluginManager() * Set writer plugin manager * * @param WriterPluginManager $writers + * @return void */ public static function setWriterPluginManager(WriterPluginManager $writers) { @@ -233,6 +238,7 @@ public static function getWriterPluginManager() * @param string $extension * @param string|Reader\ReaderInterface $reader * @throws Exception\InvalidArgumentException + * @return void */ public static function registerReader($extension, $reader) { @@ -250,6 +256,14 @@ public static function registerReader($extension, $reader) self::$extensions[$extension] = $reader; } + /** + * Set config writer for file extension + * + * @param string $extension + * @param string|Writer\AbstractWriter $writer + * @throw Exception\InvalidArgumentException + * @return void + */ public static function registerWriter($extension, $writer) { $extension = strtolower($extension); @@ -263,6 +277,6 @@ public static function registerWriter($extension, $writer) )); } - self::$extensions[$extension] = $writer; + self::$writerExtensions[$extension] = $writer; } } diff --git a/tests/ZendTest/Config/FactoryTest.php b/tests/ZendTest/Config/FactoryTest.php index 3f5d724f520..3f72b74f3cd 100644 --- a/tests/ZendTest/Config/FactoryTest.php +++ b/tests/ZendTest/Config/FactoryTest.php @@ -20,6 +20,28 @@ */ class FactoryTest extends \PHPUnit_Framework_TestCase { + protected $tmpFiles = array(); + + protected function getTestAssetFileName($ext) + { + if (empty($this->tmpfiles[$ext])) { + $this->tmpfiles[$ext] = tempnam(sys_get_temp_dir(), 'zend-config-writer').'.'.$ext; + } + return $this->tmpfiles[$ext]; + } + + public function tearDown() + { + foreach($this->tmpFiles as $file) { + if (file_exists($file)) { + if (!is_writable($file)) { + chmod($file, 0777); + } + @unlink($file); + } + } + } + public function testFromIni() { $config = Factory::fromFile(__DIR__ . '/TestAssets/Ini/include-base.ini'); @@ -125,7 +147,7 @@ public function testFactoryCanRegisterCustomReaderInstance() $this->assertEquals($configObject['one'], 1); } - public function testFactoryCanRegisterCustomReaderPlugn() + public function testFactoryCanRegisterCustomReaderPlugin() { $dummyReader = new Reader\TestAssets\DummyReader(); Factory::getReaderPluginManager()->setService('DummyReader', $dummyReader); @@ -138,5 +160,73 @@ public function testFactoryCanRegisterCustomReaderPlugn() $this->assertEquals($configObject['one'], 1); } + public function testFactoryToFileInvalidFileExtension() + { + $this->setExpectedException('RuntimeException'); + $result = Factory::toFile(__DIR__.'/TestAssets/bad.ext', array()); + } + + public function testFactoryToFileNoDirInHere() + { + $this->setExpectedException('RuntimeException'); + $result = Factory::toFile(__DIR__.'/TestAssets/NoDirInHere/nonExisiting/dummy.php', array()); + } + + public function testFactoryWriteToFile() + { + $config = array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo')); + + $file = $this->getTestAssetFileName('php'); + $result = Factory::toFile($file, $config); + + // build string line by line as we are trailing-whitespace sensitive. + $expected = " 'foo',\n"; + $expected .= " 'bar' => \n"; + $expected .= " array (\n"; + $expected .= " 0 => 'baz',\n"; + $expected .= " 1 => 'foo',\n"; + $expected .= " ),\n"; + $expected .= ");\n"; + + $this->assertEquals(true, $result); + $this->assertEquals($expected, file_get_contents($file)); + } + + public function testFactoryToFileWrongConfig() + { + $this->setExpectedException('InvalidArgumentException'); + $result = Factory::toFile('test.ini', 'Im wrong'); + } + + public function testFactoryRegisterInvalidWriter() + { + $this->setExpectedException('InvalidArgumentException'); + Factory::registerWriter('dum', new Reader\TestAssets\DummyReader()); + } + + public function testFactoryCanRegisterCustomWriterInstance() + { + Factory::registerWriter('dum', new Writer\TestAssets\DummyWriter()); + + $file = $this->getTestAssetFileName('dum'); + $res = Factory::toFile($file, array('one' => 1)); + + $this->assertEquals($res, true); + } + + public function testFactoryCanRegisterCustomWriterPlugin() + { + $dummyWriter = new Writer\TestAssets\DummyWriter(); + Factory::getWriterPluginManager()->setService('DummyWriter', $dummyWriter); + + Factory::registerWriter('dum', 'DummyWriter'); + + $file = $this->getTestAssetFileName('dum'); + + $res = Factory::toFile($file, array('one' => 1)); + $this->assertEquals($res, true); + } } diff --git a/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php b/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php new file mode 100755 index 00000000000..8bf8ba9260f --- /dev/null +++ b/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php @@ -0,0 +1,23 @@ + Date: Mon, 8 Oct 2012 20:30:47 +0200 Subject: [PATCH 121/126] fix comment --- library/Zend/Config/Factory.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/Zend/Config/Factory.php b/library/Zend/Config/Factory.php index 0407e8fb383..25986d23aa1 100644 --- a/library/Zend/Config/Factory.php +++ b/library/Zend/Config/Factory.php @@ -128,14 +128,14 @@ public static function fromFiles(array $files, $returnConfigObject = false) } /** - * Writes a config to a file - * - * @param string $filename - * @param array|Config $config - * @return boolean TRUE on success | FALSE on failure - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - */ + * Writes a config to a file + * + * @param string $filename + * @param array|Config $config + * @return boolean TRUE on success | FALSE on failure + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException + */ public static function toFile($filename, $config) { if ( From 635cea686cd55fc01323adb6690128eaf559c862 Mon Sep 17 00:00:00 2001 From: Jesper Dolieslager Date: Mon, 8 Oct 2012 22:04:39 +0200 Subject: [PATCH 122/126] fix eof --- library/Zend/Config/WriterPluginManager.php | 1 - 1 file changed, 1 deletion(-) diff --git a/library/Zend/Config/WriterPluginManager.php b/library/Zend/Config/WriterPluginManager.php index 58598c56738..35717f51788 100755 --- a/library/Zend/Config/WriterPluginManager.php +++ b/library/Zend/Config/WriterPluginManager.php @@ -27,4 +27,3 @@ public function validatePlugin($plugin) ); } } - From 4cf730f22127bc8793ffa8ee31197f2e7a178831 Mon Sep 17 00:00:00 2001 From: Robert Boloc Date: Mon, 8 Oct 2012 15:34:36 +0200 Subject: [PATCH 123/126] added addUseClass method in ClassGenerator --- .../Zend/Code/Generator/ClassGenerator.php | 33 +++++++++++++++++++ .../Code/Generator/ClassGeneratorTest.php | 15 +++++++++ 2 files changed, 48 insertions(+) diff --git a/library/Zend/Code/Generator/ClassGenerator.php b/library/Zend/Code/Generator/ClassGenerator.php index c17b66a97bf..6aa44a84087 100644 --- a/library/Zend/Code/Generator/ClassGenerator.php +++ b/library/Zend/Code/Generator/ClassGenerator.php @@ -67,6 +67,11 @@ class ClassGenerator extends AbstractGenerator */ protected $methods = array(); + /** + * @var array Array of string names + */ + protected $useClasses = array(); + /** * fromReflection() - build a Code Generation Php Object from a Class Reflection * @@ -479,6 +484,16 @@ public function addPropertyFromGenerator(PropertyGenerator $property) return $this; } + /** + * Add a class to "use" classes + * + * @param string $useClass + */ + public function addUseClass($useClass) + { + $this->useClasses[] = $useClass; + } + /** * getProperties() * @@ -505,6 +520,16 @@ public function getProperty($propertyName) return false; } + /** + * Returns the "use" classes + * + * @return array + */ + public function getUseClasses() + { + return $this->useClasses; + } + /** * hasProperty() * @@ -664,6 +689,14 @@ public function generate() $output .= 'namespace ' . $namespace . ';' . self::LINE_FEED . self::LINE_FEED; } + $useClasses = $this->getUseClasses(); + if (!empty($useClasses)) { + foreach ($useClasses as $useClass) { + $output .= 'use ' . $useClass . ';' . self::LINE_FEED; + } + $output .= self::LINE_FEED; + } + if (null !== ($docBlock = $this->getDocBlock())) { $docBlock->setIndentation(''); $output .= $docBlock->generate(); diff --git a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php index d813f23d693..bca844c731e 100644 --- a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php +++ b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php @@ -362,4 +362,19 @@ public function testPassingANamespacedClassnameShouldGenerateAClassnameWithoutIt $received = $classGeneratorClass->generate(); $this->assertContains('class FunClass', $received, $received); } + + /** + * @group ZF2-151 + */ + public function testAddUseClass() + { + $classGenerator = new ClassGenerator(); + $classGenerator->setName('My\Class'); + $classGenerator->addUseClass('My\First\Use\Class'); + $classGenerator->addUseClass('My\Second\Use\Class'); + $generated = $classGenerator->generate(); + + $this->assertContains('use My\First\Use\Class;', $generated); + $this->assertContains('use My\Second\Use\Class;', $generated); + } } From d532e3619db2b949ac31cee6bf63e1f979e8f03a Mon Sep 17 00:00:00 2001 From: Jesper Dolieslager Date: Tue, 9 Oct 2012 07:55:12 +0200 Subject: [PATCH 124/126] eol in tests ;) --- tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php b/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php index 8bf8ba9260f..d5a989ccc15 100755 --- a/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php +++ b/tests/ZendTest/Config/Writer/TestAssets/DummyWriter.php @@ -20,4 +20,3 @@ public function processConfig(array $config) return serialize($config); } } - From 1c909df6218d3131012e7512f76f2faa6d3984bb Mon Sep 17 00:00:00 2001 From: Robert Boloc Date: Tue, 9 Oct 2012 08:31:08 +0200 Subject: [PATCH 125/126] added aliasing support --- library/Zend/Code/Generator/ClassGenerator.php | 5 ++++- tests/ZendTest/Code/Generator/ClassGeneratorTest.php | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/library/Zend/Code/Generator/ClassGenerator.php b/library/Zend/Code/Generator/ClassGenerator.php index 6aa44a84087..5ec7a777984 100644 --- a/library/Zend/Code/Generator/ClassGenerator.php +++ b/library/Zend/Code/Generator/ClassGenerator.php @@ -489,8 +489,11 @@ public function addPropertyFromGenerator(PropertyGenerator $property) * * @param string $useClass */ - public function addUseClass($useClass) + public function addUseClass($useClass, $useClassAlias = null) { + if (!empty($useClassAlias)) { + $useClass .= ' as ' . $useClassAlias; + } $this->useClasses[] = $useClass; } diff --git a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php index bca844c731e..e8bf7bc22a9 100644 --- a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php +++ b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php @@ -371,10 +371,10 @@ public function testAddUseClass() $classGenerator = new ClassGenerator(); $classGenerator->setName('My\Class'); $classGenerator->addUseClass('My\First\Use\Class'); - $classGenerator->addUseClass('My\Second\Use\Class'); + $classGenerator->addUseClass('My\Second\Use\Class', 'MyAlias'); $generated = $classGenerator->generate(); $this->assertContains('use My\First\Use\Class;', $generated); - $this->assertContains('use My\Second\Use\Class;', $generated); + $this->assertContains('use My\Second\Use\Class as MyAlias;', $generated); } } From 3d80da03822a63f17b49353ef92894d26aae4c7c Mon Sep 17 00:00:00 2001 From: Robert Boloc Date: Wed, 10 Oct 2012 08:25:55 +0200 Subject: [PATCH 126/126] refactored variable and method names --- .../Zend/Code/Generator/ClassGenerator.php | 22 +++++++++---------- .../Code/Generator/ClassGeneratorTest.php | 6 ++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/library/Zend/Code/Generator/ClassGenerator.php b/library/Zend/Code/Generator/ClassGenerator.php index 5ec7a777984..123aca150f6 100644 --- a/library/Zend/Code/Generator/ClassGenerator.php +++ b/library/Zend/Code/Generator/ClassGenerator.php @@ -70,7 +70,7 @@ class ClassGenerator extends AbstractGenerator /** * @var array Array of string names */ - protected $useClasses = array(); + protected $uses = array(); /** * fromReflection() - build a Code Generation Php Object from a Class Reflection @@ -489,12 +489,12 @@ public function addPropertyFromGenerator(PropertyGenerator $property) * * @param string $useClass */ - public function addUseClass($useClass, $useClassAlias = null) + public function addUse($use, $useAlias = null) { - if (!empty($useClassAlias)) { - $useClass .= ' as ' . $useClassAlias; + if (!empty($useAlias)) { + $use .= ' as ' . $useAlias; } - $this->useClasses[] = $useClass; + $this->uses[] = $use; } /** @@ -528,9 +528,9 @@ public function getProperty($propertyName) * * @return array */ - public function getUseClasses() + public function getUses() { - return $this->useClasses; + return $this->uses; } /** @@ -692,10 +692,10 @@ public function generate() $output .= 'namespace ' . $namespace . ';' . self::LINE_FEED . self::LINE_FEED; } - $useClasses = $this->getUseClasses(); - if (!empty($useClasses)) { - foreach ($useClasses as $useClass) { - $output .= 'use ' . $useClass . ';' . self::LINE_FEED; + $uses = $this->getUses(); + if (!empty($uses)) { + foreach ($uses as $use) { + $output .= 'use ' . $use . ';' . self::LINE_FEED; } $output .= self::LINE_FEED; } diff --git a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php index e8bf7bc22a9..e88330ad9e4 100644 --- a/tests/ZendTest/Code/Generator/ClassGeneratorTest.php +++ b/tests/ZendTest/Code/Generator/ClassGeneratorTest.php @@ -366,12 +366,12 @@ public function testPassingANamespacedClassnameShouldGenerateAClassnameWithoutIt /** * @group ZF2-151 */ - public function testAddUseClass() + public function testAddUses() { $classGenerator = new ClassGenerator(); $classGenerator->setName('My\Class'); - $classGenerator->addUseClass('My\First\Use\Class'); - $classGenerator->addUseClass('My\Second\Use\Class', 'MyAlias'); + $classGenerator->addUse('My\First\Use\Class'); + $classGenerator->addUse('My\Second\Use\Class', 'MyAlias'); $generated = $classGenerator->generate(); $this->assertContains('use My\First\Use\Class;', $generated);