From 7a7b448680a0a8321f3f4ab0840b4004aea9a57d Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Mon, 25 Apr 2011 21:12:35 -0700 Subject: [PATCH] [HttpKernel] added BundleInterface::getContainerExtension() which is implicitly loaded --- .../Component/HttpKernel/Bundle/Bundle.php | 29 +++++++++--------- .../HttpKernel/Bundle/BundleInterface.php | 7 +++++ .../MergeExtensionConfigurationPass.php | 26 ++++++++-------- src/Symfony/Component/HttpKernel/Kernel.php | 14 ++++++--- .../MergeExtensionConfigurationPassTest.php | 30 ++++++------------- 5 files changed, 52 insertions(+), 54 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index 7910a0bfe6..fd80e1ca87 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -27,6 +27,7 @@ abstract class Bundle extends ContainerAware implements BundleInterface { protected $name; protected $reflected; + protected $extension; /** * Boots the Bundle. @@ -47,13 +48,6 @@ abstract class Bundle extends ContainerAware implements BundleInterface * * It is only ever called once when the cache is empty. * - * The default implementation automatically registers a DIC extension - * if its name is the same as the bundle name after replacing the - * Bundle suffix by Extension (DependencyInjection\SensioBlogExtension - * for a SensioBlogBundle for instance). In such a case, the alias - * is forced to be the underscore version of the bundle name - * (sensio_blog for a SensioBlogBundle for instance). - * * This method can be overridden to register compilation passes, * other extensions, ... * @@ -61,16 +55,21 @@ abstract class Bundle extends ContainerAware implements BundleInterface */ public function build(ContainerBuilder $container) { - $class = $this->getNamespace().'\\DependencyInjection\\'.str_replace('Bundle', 'Extension', $this->getName()); - if (class_exists($class)) { - $extension = new $class(); - $alias = Container::underscore(str_replace('Bundle', '', $this->getName())); - if ($alias !== $extension->getAlias()) { - throw new \LogicException(sprintf('The extension alias for the default extension of a bundle must be the underscored version of the bundle name ("%s" vs "%s")', $alias, $extension->getAlias())); - } + } - $container->registerExtension($extension); + /** + * Returns the bundle's container extension. + * + * @return ExtensionInterface|null The container extension + */ + public function getContainerExtension() + { + if (null === $this->extension) { + $class = $this->getNamespace().'\\DependencyInjection\\'.str_replace('Bundle', 'Extension', $this->getName()); + $this->extension = class_exists($class) ? new $class() : false; } + + return $this->extension ?: null; } /** diff --git a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php index 483635c492..c76619cafa 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php +++ b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php @@ -39,6 +39,13 @@ interface BundleInterface */ function build(ContainerBuilder $container); + /** + * Returns the container extension that should be implicitly loaded. + * + * @return ExtensionInterface|null The default extension + */ + function getContainerExtension(); + /** * Returns the bundle parent name. * diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php index 05f6fa32d9..d7d9c18073 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php @@ -15,26 +15,24 @@ use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPa use Symfony\Component\DependencyInjection\ContainerBuilder; /** - * Handles automatically loading each bundle's default extension. + * Ensures certain extensions are always loaded. * - * @author Kris Wallsmith + * @author Kris Wallsmith */ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass { + private $extensions; + + public function __construct(array $extensions) + { + $this->extensions = $extensions; + } + 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()); - } + foreach ($this->extensions as $extension) { + if (!count($container->getExtensionConfig($extension))) { + $container->loadFromExtension($extension, array()); } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d996da2f3f..88e462c1b9 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -529,19 +529,25 @@ abstract class Kernel implements KernelInterface */ protected function buildContainer() { - $parameterBag = new ParameterBag($this->getKernelParameters()); - - $container = new ContainerBuilder($parameterBag); - $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass()); + $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + $extensions = array(); foreach ($this->bundles as $bundle) { $bundle->build($container); + if ($extension = $bundle->getContainerExtension()) { + $container->registerExtension($extension); + $extensions[] = $extension->getAlias(); + } + if ($this->debug) { $container->addObjectResource($bundle); } } $container->addObjectResource($this); + // ensure these extensions are implicitly loaded + $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); + if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { $container->merge($cont); } diff --git a/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php b/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php index 78720eedd8..d2b4a40d3e 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPassTest.php @@ -17,32 +17,20 @@ 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)) + $container->expects($this->at(0)) ->method('getExtensionConfig') - ->will($this->returnCallback(function($name) { - switch ($name) { - case 'extension_present': - return array(); - case 'extension_loaded': - return array(array()); - } - })); + ->with('loaded') + ->will($this->returnValue(array(array()))); + $container->expects($this->at(1)) + ->method('getExtensionConfig') + ->with('notloaded') + ->will($this->returnValue(array())); $container->expects($this->once()) ->method('loadFromExtension') - ->with('extension_present', array()); + ->with('notloaded', array()); $container->expects($this->any()) ->method('getParameterBag') @@ -60,7 +48,7 @@ class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase ->method('getExtensions') ->will($this->returnValue(array())); - $configPass = new MergeExtensionConfigurationPass(); + $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded')); $configPass->process($container); } }