Quellcode durchsuchen

ZF-6679, ZF-7550: Do not store options with flattened keys; ensure that autoloadable plugin resources will be loaded

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@17801 44c647ce-9c0f-0410-b52a-842ac1e357ba
matthew vor 16 Jahren
Ursprung
Commit
8f97a8973b

+ 15 - 4
library/Zend/Application.php

@@ -49,6 +49,13 @@ class Zend_Application
     protected $_environment;
 
     /**
+     * Flattened (lowercase) option keys
+     * 
+     * @var array
+     */
+    protected $_optionKeys = array();
+
+    /**
      * Options for Zend_Application
      *
      * @var array
@@ -116,14 +123,16 @@ class Zend_Application
      */
     public function setOptions(array $options)
     {
-        $options = array_change_key_case($options, CASE_LOWER);
-
         if (!empty($options['config'])) {
             $options = $this->mergeOptions($options, $this->_loadConfig($options['config']));
         }
 
         $this->_options = $options;
 
+        $options = array_change_key_case($options, CASE_LOWER);
+
+        $this->_optionKeys = array_keys($options);
+
         if (!empty($options['phpsettings'])) {
             $this->setPhpSettings($options['phpsettings']);
         }
@@ -180,7 +189,7 @@ class Zend_Application
      */
     public function hasOption($key)
     {
-        return array_key_exists($key, $this->_options);
+        return in_array($key, $this->_optionKeys);
     }
 
     /**
@@ -192,7 +201,9 @@ class Zend_Application
     public function getOption($key)
     {
         if ($this->hasOption($key)) {
-            return $this->_options[$key];
+            $options = $this->getOptions();
+            $options = array_change_key_case($options, CASE_LOWER);
+            return $options[strtolower($key)];
         }
         return null;
     }

+ 28 - 26
library/Zend/Application/Bootstrap/BootstrapAbstract.php

@@ -56,6 +56,13 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
     protected $_environment;
 
     /**
+     * Flattened (lowercase) option keys used for lookups
+     * 
+     * @var array
+     */
+    protected $_optionKeys = array();
+
+    /**
      * @var array
      */
     protected $_options = array();
@@ -105,7 +112,11 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
      */
     public function setOptions(array $options)
     {
+        $this->_options = $this->mergeOptions($this->_options, $options);
+
         $options = array_change_key_case($options, CASE_LOWER);
+        $this->_optionKeys = array_keys($options);
+
         $methods = get_class_methods($this);
         foreach ($methods as $key => $method) {
             $methods[$key] = strtolower($method);
@@ -117,7 +128,6 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
             foreach ($options['pluginpaths'] as $prefix => $path) {
                 $pluginLoader->addPrefixPath($prefix, $path);
             }
-
             unset($options['pluginpaths']);
         }
 
@@ -132,7 +142,6 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
                 }
             }
         }
-        $this->_options = $this->mergeOptions($this->_options, $options);
         return $this;
     }
 
@@ -154,7 +163,7 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
      */
     public function hasOption($key)
     {
-        return array_key_exists($key, $this->_options);
+        return in_array($key, $this->_optionKeys);
     }
 
     /**
@@ -166,7 +175,9 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
     public function getOption($key)
     {
         if ($this->hasOption($key)) {
-            return $this->_options[$key];
+            $options = $this->getOptions();
+            $options = array_change_key_case($options, CASE_LOWER);
+            return $options[strtolower($key)];
         }
         return null;
     }
@@ -249,13 +260,6 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
      */
     public function registerPluginResource($resource, $options = null)
     {
-        /*
-        if (is_string($resource) && class_exists($resource)) {
-            $options = (array) $options;
-            $options['bootstrap'] = $this;
-            $resource = new $resource($options);
-        }
-         */
         if ($resource instanceof Zend_Application_Resource_Resource) {
             $resource->setBootstrap($this);
             $pluginName = $this->_resolvePluginResourceName($resource);
@@ -267,7 +271,6 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
             throw new Zend_Application_Bootstrap_Exception('Invalid resource provided to ' . __METHOD__);
         }
 
-        // $resource = strtolower($resource);
         $this->_pluginResources[$resource] = $options;
         return $this;
     }
@@ -342,14 +345,13 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
                 continue;
             }
 
-
             if (false !== $pluginName = $this->_loadPluginResource($plugin, $spec)) {
                 if (0 === strcasecmp($resource, $pluginName)) {
                     return $this->_pluginResources[$pluginName];
                 }
             }
 
-            if (class_exists($plugin, false)) {
+            if (class_exists($plugin)) {
                 $spec = (array) $spec;
                 $spec['bootstrap'] = $this;
                 $instance = new $plugin($spec);
@@ -643,40 +645,40 @@ abstract class Zend_Application_Bootstrap_BootstrapAbstract
      */
     protected function _executeResource($resource)
     {
-        $resource = strtolower($resource);
+        $resourceName = strtolower($resource);
 
-        if (in_array($resource, $this->_run)) {
+        if (in_array($resourceName, $this->_run)) {
             return;
         }
 
-        if (isset($this->_started[$resource]) && $this->_started[$resource]) {
+        if (isset($this->_started[$resourceName]) && $this->_started[$resourceName]) {
             throw new Zend_Application_Bootstrap_Exception('Circular resource dependency detected');
         }
 
         $classResources = $this->getClassResources();
-        if (array_key_exists($resource, $classResources)) {
-            $this->_started[$resource] = true;
-            $method = $classResources[$resource];
+        if (array_key_exists($resourceName, $classResources)) {
+            $this->_started[$resourceName] = true;
+            $method = $classResources[$resourceName];
             $return = $this->$method();
-            unset($this->_started[$resource]);
+            unset($this->_started[$resourceName]);
             $this->_markRun($resource);
 
             if (null !== $return) {
-                $this->getContainer()->{$resource} = $return;
+                $this->getContainer()->{$resourceName} = $return;
             }
 
             return;
         }
 
         if ($this->hasPluginResource($resource)) {
-            $this->_started[$resource] = true;
+            $this->_started[$resourceName] = true;
             $plugin = $this->getPluginResource($resource);
             $return = $plugin->init();
-            unset($this->_started[$resource]);
-            $this->_markRun($resource);
+            unset($this->_started[$resourceName]);
+            $this->_markRun($resourceName);
 
             if (null !== $return) {
-                $this->getContainer()->{$resource} = $return;
+                $this->getContainer()->{$resourceName} = $return;
             }
 
             return;

+ 2 - 2
library/Zend/Application/Module/Bootstrap.php

@@ -78,8 +78,8 @@ abstract class Zend_Application_Module_Bootstrap
         }
 
         // ZF-6545: prevent recursive registration of modules
-        if ($this->hasPluginResource('Modules')) {
-            $this->unregisterPluginResource('Modules');
+        if ($this->hasPluginResource('modules')) {
+            $this->unregisterPluginResource('modules');
         }
     }
 

+ 37 - 0
tests/Zend/Application/ApplicationTest.php

@@ -357,6 +357,43 @@ class Zend_Application_ApplicationTest extends PHPUnit_Framework_TestCase
         ));
         $bootstrap = $this->application->getBootstrap();
     }
+
+    public function testOptionsShouldRetainOriginalCase()
+    {
+        require_once dirname(__FILE__) . '/_files/ZfModuleBootstrap.php';
+        $options = array(
+            'pluginPaths' => array(
+                'Zend_Application_Test_Path' => dirname(__FILE__),
+            ),
+            'Resources' => array(
+                'modules' => array(),
+                'FrontController' => array(
+                    'baseUrl'             => '/foo',
+                    'moduleDirectory'     => dirname(__FILE__) . '/_files/modules',
+                ),
+            ),
+            'Bootstrap' => array(
+                'path'  => dirname(__FILE__) . '/_files/ZfAppBootstrap.php',
+                'class' => 'ZfAppBootstrap',
+            ),
+        );
+        $this->application->setOptions($options);
+        $setOptions = $this->application->getOptions();
+        $this->assertSame(array_keys($options), array_keys($setOptions));
+    }
+
+    /**
+     * @group ZF-6679
+     */
+    public function testSetOptionsShouldProperlyMergeTwoConfigFileOptions()
+    {
+        $application = new Zend_Application(
+            'production', dirname(__FILE__) . 
+            '/_files/zf-6679-1.inc'
+        );
+        $options = $application->getOptions();
+        $this->assertEquals(array('config', 'includePaths'), array_keys($options));
+    }
 }
 
 if (PHPUnit_MAIN_METHOD == 'Zend_Application_ApplicationTest::main') {

+ 21 - 0
tests/Zend/Application/Bootstrap/BootstrapAbstractTest.php

@@ -643,6 +643,27 @@ class Zend_Application_Bootstrap_BootstrapAbstractTest extends PHPUnit_Framework
         restore_error_handler();
         $this->assertTrue(false === $this->error, $this->error);
     }
+
+    /**
+     * @group ZF-7550
+     */
+    public function testRequestingPluginsByAutoloadableClassNameShouldNotRaiseFatalErrors()
+    {
+        // Using namesapce 'zabt' to prevent conflict with Zend namespace
+        $rl = new Zend_Loader_Autoloader_Resource(array(
+            'namespace' => 'Zabt',
+            'basePath'  => dirname(__FILE__) . '/../_files',
+        ));
+        $rl->addResourceType('resources', 'resources', 'Resource');
+        $options = array(
+            'resources' => array(
+                'Zabt_Resource_Autoloaded' => array('bar' => 'baz')
+            ),
+        );
+        $this->application->setOptions($options);
+        $bootstrap = new Zend_Application_Bootstrap_Bootstrap($this->application);
+        $bootstrap->bootstrap();
+    }
 }
 
 class Zend_Application_Bootstrap_BootstrapAbstractTest_View

+ 6 - 2
tests/Zend/Application/Module/BootstrapTest.php

@@ -193,9 +193,13 @@ class Zend_Application_Module_BootstrapTest extends PHPUnit_Framework_TestCase
         $appBootstrap = $this->application->getBootstrap();
         $appBootstrap->bootstrap('Modules');
         $modules = $appBootstrap->getResource('Modules');
-        foreach ($modules as $bootstrap) {
+        foreach ($modules as $module => $bootstrap) {
+            if ($module == 'default') {
+                // "default" module gets lumped in, and is not a Module_Bootstrap
+                continue;
+            }
             $resources = $bootstrap->getPluginResourceNames();
-            $this->assertFalse($bootstrap->hasPluginResource('Modules'), var_export($resources, 1));
+            $this->assertFalse($bootstrap->hasPluginResource('Modules'));
         }
     }
 

+ 36 - 0
tests/Zend/Application/_files/resources/Autoloaded.php

@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Application
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Application
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zabt_Resource_Autoloaded extends Zend_Application_Resource_ResourceAbstract
+{
+    public function init()
+    {
+        $this->getBootstrap()->executedAutoloadedResource = true;
+    }
+}

+ 8 - 0
tests/Zend/Application/_files/zf-6679-1.inc

@@ -0,0 +1,8 @@
+<?php
+$config = array(
+    'config' => dirname(__FILE__) . '/zf-6679-2.inc',
+    'includePaths' => array(
+        'path1' => 'some/path',
+    ),
+);
+return $config;

+ 7 - 0
tests/Zend/Application/_files/zf-6679-2.inc

@@ -0,0 +1,7 @@
+<?php
+$config = array(
+    'includePaths' => array(
+        'path2' => 'another/path',
+    ),
+);
+return $config;