diff --git a/autoload.php.dist b/autoload.php.dist index fea397bb8ad1..a5d826ba6010 100644 --- a/autoload.php.dist +++ b/autoload.php.dist @@ -6,6 +6,7 @@ use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( + 'Symfony\\Tests' => __DIR__.'/tests', 'Symfony' => __DIR__.'/src', 'Doctrine\\MongoDB' => __DIR__.'/vendor/doctrine-mongodb/lib', 'Doctrine\\ODM\\MongoDB' => __DIR__.'/vendor/doctrine-mongodb-odm/lib', diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index bcaf9aa125e6..da40583d9b12 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -30,10 +30,15 @@ public function process(ContainerBuilder $container) $aliases = $container->getAliases(); foreach ($container->getExtensions() as $name => $extension) { + if (!$config = $container->getExtensionConfig($name)) { + // this extension was not called + continue; + } + $tmpContainer = new ContainerBuilder($container->getParameterBag()); $tmpContainer->addObjectResource($extension); - $extension->load($container->getExtensionConfig($name), $tmpContainer); + $extension->load($config, $tmpContainer); $container->merge($tmpContainer); } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 19f7c23d94da..44e66de269a5 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -46,6 +46,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface public function __construct(ParameterBagInterface $parameterBag = null) { parent::__construct($parameterBag); + + $this->compiler = new Compiler(); } /** @@ -166,47 +168,35 @@ public function loadFromExtension($extension, array $values = array()) } /** - * Adds a compiler pass at the end of the current passes + * Adds a compiler pass. * - * @param CompilerPassInterface $pass - * @param string $type + * @param CompilerPassInterface $pass A compiler pass + * @param string $type The type of compiler pass */ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { - if (null === $this->compiler) { - $this->initializeCompiler(); - } - $this->compiler->addPass($pass, $type); $this->addObjectResource($pass); } /** - * Returns the compiler pass config which can then be modified + * Returns the compiler pass config which can then be modified. * - * @return PassConfig + * @return PassConfig The compiler pass config */ public function getCompilerPassConfig() { - if (null === $this->compiler) { - $this->initializeCompiler(); - } - return $this->compiler->getPassConfig(); } /** - * Returns the compiler instance + * Returns the compiler. * - * @return Compiler + * @return Compiler The compiler */ public function getCompiler() { - if (null === $this->compiler) { - $this->initializeCompiler(); - } - return $this->compiler; } @@ -379,7 +369,7 @@ public function merge(ContainerBuilder $container) public function getExtensionConfig($name) { if (!isset($this->extensionConfigs[$name])) { - return array(array()); + $this->extensionConfigs[$name] = array(); } return $this->extensionConfigs[$name]; @@ -401,8 +391,8 @@ public function getExtensionConfig($name) */ public function compile() { - if (null === $this->compiler) { - $this->initializeCompiler(); + foreach ($this->compiler->getPassConfig()->getPasses() as $pass) { + $this->addObjectResource($pass); } $this->compiler->compile($this); @@ -836,19 +826,6 @@ public function findTaggedServiceIds($name) return $tags; } - /** - * Initializes the compiler - * - * @return void - */ - protected function initializeCompiler() - { - $this->compiler = new Compiler(); - foreach ($this->compiler->getPassConfig()->getPasses() as $pass) { - $this->addObjectResource($pass); - } - } - /** * Returns the Service Conditionals. * diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php new file mode 100644 index 000000000000..47dbb60e25b5 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php @@ -0,0 +1,43 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Handles automatically loading each bundle's default extension. + * + * @author Kris Wallsmith + */ +class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass +{ + public function process(ContainerBuilder $container) + { + foreach ($container->getParameter('kernel.bundles') as $bundleName => $bundleClass) { + $bundleRefl = new \ReflectionClass($bundleClass); + $extClass = $bundleRefl->getNamespaceName().'\\DependencyInjection\\'.substr($bundleName, 0, -6).'Extension'; + + if (class_exists($extClass)) { + $ext = new $extClass(); + $alias = $ext->getAlias(); + + // ensure all "main" extensions are loaded + if (!count($container->getExtensionConfig($alias))) { + $container->loadFromExtension($alias, array()); + } + } + } + + parent::process($container); + } +} diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0e1502a1e3f4..ba3bc1225e43 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -24,6 +24,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Config\FileLocator; +use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; use Symfony\Component\Config\ConfigCache; @@ -457,6 +458,7 @@ protected function buildContainer() $parameterBag = new ParameterBag($this->getKernelParameters()); $container = new ContainerBuilder($parameterBag); + $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass()); foreach ($this->bundles as $bundle) { $bundle->build($container); diff --git a/tests/Symfony/Tests/Component/DependencyInjection/ContainerBuilderTest.php b/tests/Symfony/Tests/Component/DependencyInjection/ContainerBuilderTest.php index 795c9d8c0e2f..47a1bd266f56 100644 --- a/tests/Symfony/Tests/Component/DependencyInjection/ContainerBuilderTest.php +++ b/tests/Symfony/Tests/Component/DependencyInjection/ContainerBuilderTest.php @@ -447,6 +447,29 @@ public function testExtension() $container->getExtension('no_registered'); } + public function testRegisteredButNotLoadedExtension() + { + $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface'); + $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project')); + $extension->expects($this->never())->method('load'); + + $container = new ContainerBuilder(); + $container->registerExtension($extension); + $container->compile(); + } + + public function testRegisteredAndLoadedExtension() + { + $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface'); + $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project')); + $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar'))); + + $container = new ContainerBuilder(); + $container->registerExtension($extension); + $container->loadFromExtension('project', array('foo' => 'bar')); + $container->compile(); + } + /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addInterfaceInjector * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addInterfaceInjectors diff --git a/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php b/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php new file mode 100644 index 000000000000..b930c57f35cf --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpKernel; + +use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; + +class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase +{ + public function testAutoloadMainExtension() + { + $bundles = array( + 'ExtensionAbsentBundle' => 'Symfony\\Tests\\Component\\HttpKernel\\Fixtures\\ExtensionAbsentBundle\\ExtensionAbsentBundle', + 'ExtensionLoadedBundle' => 'Symfony\\Tests\\Component\\HttpKernel\\Fixtures\\ExtensionLoadedBundle\\ExtensionLoadedBundle', + 'ExtensionPresentBundle' => 'Symfony\\Tests\\Component\\HttpKernel\\Fixtures\\ExtensionPresentBundle\\ExtensionPresentBundle', + ); + + $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); + $params = $this->getMock('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag'); + + $container->expects($this->once()) + ->method('getParameter') + ->with('kernel.bundles') + ->will($this->returnValue($bundles)); + $container->expects($this->exactly(2)) + ->method('getExtensionConfig') + ->will($this->returnCallback(function($name) { + switch ($name) { + case 'extension_present': + return array(); + case 'extension_loaded': + return array(array()); + } + })); + $container->expects($this->once()) + ->method('loadFromExtension') + ->with('extension_present', array()); + + $container->expects($this->any()) + ->method('getParameterBag') + ->will($this->returnValue($params)); + $params->expects($this->any()) + ->method('all') + ->will($this->returnValue(array())); + $container->expects($this->any()) + ->method('getDefinitions') + ->will($this->returnValue(array())); + $container->expects($this->any()) + ->method('getAliases') + ->will($this->returnValue(array())); + $container->expects($this->any()) + ->method('getExtensions') + ->will($this->returnValue(array())); + + $configPass = new MergeExtensionConfigurationPass(); + $configPass->process($container); + } +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php new file mode 100644 index 000000000000..1fdd63f054f9 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpKernel\Fixtures\ExtensionAbsentBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionAbsentBundle extends Bundle +{ +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php new file mode 100644 index 000000000000..95af21748258 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpKernel\Fixtures\ExtensionLoadedBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +class ExtensionLoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + } +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php new file mode 100644 index 000000000000..00a96b2aed00 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpKernel\Fixtures\ExtensionLoadedBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionLoadedBundle extends Bundle +{ +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php new file mode 100644 index 000000000000..1f6162eccdcc --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpKernel\Fixtures\ExtensionPresentBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +class ExtensionPresentExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + } +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php new file mode 100644 index 000000000000..987bb4c2fcfa --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpKernel/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpKernel\Fixtures\ExtensionPresentBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionPresentBundle extends Bundle +{ +}