Browse Source

[HttpKernel] added BundleInterface::getContainerExtension() which is implicitly loaded

Kris Wallsmith 14 years ago
parent
commit
7a7b448680

+ 14 - 15
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;
     }
 
     /**

+ 7 - 0
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.
      *

+ 12 - 14
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 <kris.wallsmith@symfony.com>
+ * @author Kris Wallsmith <kris@symfony.com>
  */
 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';
+    private $extensions;
 
-            if (class_exists($extClass)) {
-                $ext = new $extClass();
-                $alias = $ext->getAlias();
+    public function __construct(array $extensions)
+    {
+        $this->extensions = $extensions;
+    }
 
-                // ensure all "main" extensions are loaded
-                if (!count($container->getExtensionConfig($alias))) {
-                    $container->loadFromExtension($alias, array());
-                }
+    public function process(ContainerBuilder $container)
+    {
+        foreach ($this->extensions as $extension) {
+            if (!count($container->getExtensionConfig($extension))) {
+                $container->loadFromExtension($extension, array());
             }
         }
 

+ 10 - 4
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);
         }

+ 9 - 21
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);
     }
 }