From 14aa95ba218c9fd6d02e770e279ed854314fea75 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 15 Feb 2011 04:47:19 +0100 Subject: [PATCH] added the concept of a main DIC extension for bundles This allows for better conventions and better error messages if you use the wrong configuration alias in a config file. This is also the first step for a bigger refactoring of how the configuration works (see next commits). * Bundle::registerExtensions() method has been renamed to Bundle::build() * The "main" DIC extension must be renamed to the new convention to be automatically registered: SensioBlogBundle -> DependencyInjection\SensioBlogExtension * The main DIC extension alias must follow the convention: sensio_blog for SensioBlogBundle * If you have more than one extension for a bundle (which should really never be the case), they must be registered manually by overriding the build() method * If you use YAML or PHP for your configuration, renamed the following configuration entry points in your configs: app -> framework webprofiler -> web_profiler doctrine_odm -> doctrine_mongo_db --- .../Bundle/AsseticBundle/AsseticBundle.php | 4 +- .../Bundle/DoctrineBundle/DoctrineBundle.php | 4 +- .../DoctrineMongoDBExtension.php | 2 +- .../DoctrineMongoDBBundle.php | 4 +- .../FrameworkExtension.php | 2 +- .../FrameworkBundle/FrameworkBundle.php | 4 +- .../Bundle/SecurityBundle/SecurityBundle.php | 4 +- src/Symfony/Bundle/TwigBundle/TwigBundle.php | 4 +- .../WebProfilerExtension.php | 2 +- src/Symfony/Bundle/ZendBundle/ZendBundle.php | 4 +- .../Component/HttpKernel/Bundle/Bundle.php | 59 ++++++++++--------- .../HttpKernel/Bundle/BundleInterface.php | 11 ++++ src/Symfony/Component/HttpKernel/Kernel.php | 2 +- .../Component/HttpKernel/bootstrap.php | 30 +++++----- .../Component/HttpKernel/bootstrap_cache.php | 2 +- 15 files changed, 78 insertions(+), 60 deletions(-) diff --git a/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php b/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php index 411d6394845d..06aa33286c6a 100644 --- a/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php +++ b/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php @@ -24,9 +24,9 @@ */ class AsseticBundle extends Bundle { - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addCompilerPass(new AssetManagerPass()); $container->addCompilerPass(new FilterManagerPass()); diff --git a/src/Symfony/Bundle/DoctrineBundle/DoctrineBundle.php b/src/Symfony/Bundle/DoctrineBundle/DoctrineBundle.php index de1d170543fd..38e61b1f260e 100644 --- a/src/Symfony/Bundle/DoctrineBundle/DoctrineBundle.php +++ b/src/Symfony/Bundle/DoctrineBundle/DoctrineBundle.php @@ -25,9 +25,9 @@ */ class DoctrineBundle extends Bundle { - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addCompilerPass(new RegisterEventListenersAndSubscribersPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); } diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/DependencyInjection/DoctrineMongoDBExtension.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/DependencyInjection/DoctrineMongoDBExtension.php index 0ba055fc51b1..4f03ad0ef715 100644 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/DependencyInjection/DoctrineMongoDBExtension.php +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/DependencyInjection/DoctrineMongoDBExtension.php @@ -402,6 +402,6 @@ public function getXsdValidationBasePath() */ public function getAlias() { - return 'doctrine_odm'; + return 'doctrine_mongo_db'; } } diff --git a/src/Symfony/Bundle/DoctrineMongoDBBundle/DoctrineMongoDBBundle.php b/src/Symfony/Bundle/DoctrineMongoDBBundle/DoctrineMongoDBBundle.php index 99e205e977a5..6c7ce9107072 100755 --- a/src/Symfony/Bundle/DoctrineMongoDBBundle/DoctrineMongoDBBundle.php +++ b/src/Symfony/Bundle/DoctrineMongoDBBundle/DoctrineMongoDBBundle.php @@ -27,9 +27,9 @@ */ class DoctrineMongoDBBundle extends Bundle { - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addCompilerPass(new RegisterEventListenersAndSubscribersPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); $container->addCompilerPass(new CreateProxyDirectoryPass(), PassConfig::TYPE_BEFORE_REMOVING); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index a8b92da72bc0..eb2748bc41c0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -506,6 +506,6 @@ public function getNamespace() public function getAlias() { - return 'app'; + return 'framework'; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index cf0248adcee7..59a00d7a5da7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -64,9 +64,9 @@ public function boot() } } - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addScope(new Scope('request')); diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index 1e5a2ba7d549..d0c6e7e1e0e8 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -22,9 +22,9 @@ */ class SecurityBundle extends Bundle { - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addCompilerPass(new AddSecurityVotersPass()); } diff --git a/src/Symfony/Bundle/TwigBundle/TwigBundle.php b/src/Symfony/Bundle/TwigBundle/TwigBundle.php index d27d85bcd2d6..4822145263e6 100644 --- a/src/Symfony/Bundle/TwigBundle/TwigBundle.php +++ b/src/Symfony/Bundle/TwigBundle/TwigBundle.php @@ -22,9 +22,9 @@ */ class TwigBundle extends Bundle { - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addCompilerPass(new TwigEnvironmentPass()); } diff --git a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php index eced6892bb52..bc31ce7049c8 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php @@ -85,6 +85,6 @@ public function getNamespace() public function getAlias() { - return 'webprofiler'; + return 'web_profiler'; } } diff --git a/src/Symfony/Bundle/ZendBundle/ZendBundle.php b/src/Symfony/Bundle/ZendBundle/ZendBundle.php index c06f2636ab74..4a5c36225a1b 100644 --- a/src/Symfony/Bundle/ZendBundle/ZendBundle.php +++ b/src/Symfony/Bundle/ZendBundle/ZendBundle.php @@ -22,9 +22,9 @@ */ class ZendBundle extends Bundle { - public function registerExtensions(ContainerBuilder $container) + public function build(ContainerBuilder $container) { - parent::registerExtensions($container); + parent::build($container); $container->addCompilerPass(new ZendLoggerWriterPass()); } diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index 17b5f75a73c7..be3c3f027532 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Console\Application; use Symfony\Component\Finder\Finder; @@ -41,6 +42,37 @@ public function shutdown() { } + /** + * Builds the bundle. + * + * 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 overriden to register compilation passes, + * other extensions, ... + * + * @param ContainerBuilder $container A ContainerBuilder instance + */ + 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); + } + } + /** * Gets the Bundle namespace. * @@ -96,33 +128,6 @@ final public function getName() return $this->name = false === $pos ? $name : substr($name, $pos + 1); } - /** - * Finds and registers Dependency Injection Container extensions. - * - * Override this method if your DIC extensions do not follow the conventions: - * - * * Extensions are in the 'DependencyInjection/' sub-directory - * * Extension class names ends with 'Extension' - * - * @param ContainerBuilder $container A ContainerBuilder instance - */ - public function registerExtensions(ContainerBuilder $container) - { - if (!$dir = realpath($this->getPath().'/DependencyInjection')) { - return; - } - - $finder = new Finder(); - $finder->files()->name('*Extension.php')->in($dir); - - $prefix = $this->getNamespace().'\\DependencyInjection'; - foreach ($finder as $file) { - $class = $prefix.strtr($file->getPath(), array($dir => '', '/' => '\\')).'\\'.$file->getBasename('.php'); - - $container->registerExtension(new $class()); - } - } - /** * Finds and registers Commands. * diff --git a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php index ba7f0ab6b647..96662f8841a0 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php +++ b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpKernel\Bundle; +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * BundleInterface. * @@ -28,6 +30,15 @@ function boot(); */ function shutdown(); + /** + * Builds the bundle. + * + * It is only ever called once when the cache is empty. + * + * @param ContainerBuilder $container A ContainerBuilder instance + */ + public function build(ContainerBuilder $container); + /** * Returns the bundle parent name. * diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index addaacd33981..214ba0080064 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -458,7 +458,7 @@ protected function buildContainer() $container = new ContainerBuilder($parameterBag); foreach ($this->bundles as $bundle) { - $bundle->registerExtensions($container); + $bundle->build($container); if ($this->debug) { $container->addObjectResource($bundle); diff --git a/src/Symfony/Component/HttpKernel/bootstrap.php b/src/Symfony/Component/HttpKernel/bootstrap.php index c82cb698555a..8d90613760a2 100644 --- a/src/Symfony/Component/HttpKernel/bootstrap.php +++ b/src/Symfony/Component/HttpKernel/bootstrap.php @@ -223,10 +223,12 @@ public function setContainer(ContainerInterface $container = null) } namespace Symfony\Component\HttpKernel\Bundle { +use Symfony\Component\DependencyInjection\ContainerBuilder; interface BundleInterface { function boot(); function shutdown(); + public function build(ContainerBuilder $container); function getParent(); function getName(); function getNamespace(); @@ -237,6 +239,7 @@ function getPath(); { use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Console\Application; use Symfony\Component\Finder\Finder; abstract class Bundle extends ContainerAware implements BundleInterface @@ -249,6 +252,18 @@ public function boot() public function shutdown() { } + 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); + } + } public function getNamespace() { if (null === $this->reflected) { @@ -276,19 +291,6 @@ final public function getName() $pos = strrpos($name, '\\'); return $this->name = false === $pos ? $name : substr($name, $pos + 1); } - public function registerExtensions(ContainerBuilder $container) - { - if (!$dir = realpath($this->getPath().'/DependencyInjection')) { - return; - } - $finder = new Finder(); - $finder->files()->name('*Extension.php')->in($dir); - $prefix = $this->getNamespace().'\\DependencyInjection'; - foreach ($finder as $file) { - $class = $prefix.strtr($file->getPath(), array($dir => '', '/' => '\\')).'\\'.$file->getBasename('.php'); - $container->registerExtension(new $class()); - } - } public function registerCommands(Application $application) { if (!$dir = realpath($this->getPath().'/Command')) { @@ -727,7 +729,7 @@ protected function buildContainer() $parameterBag = new ParameterBag($this->getKernelParameters()); $container = new ContainerBuilder($parameterBag); foreach ($this->bundles as $bundle) { - $bundle->registerExtensions($container); + $bundle->build($container); if ($this->debug) { $container->addObjectResource($bundle); } diff --git a/src/Symfony/Component/HttpKernel/bootstrap_cache.php b/src/Symfony/Component/HttpKernel/bootstrap_cache.php index bf2133767cff..9b659df04646 100644 --- a/src/Symfony/Component/HttpKernel/bootstrap_cache.php +++ b/src/Symfony/Component/HttpKernel/bootstrap_cache.php @@ -289,7 +289,7 @@ protected function buildContainer() $parameterBag = new ParameterBag($this->getKernelParameters()); $container = new ContainerBuilder($parameterBag); foreach ($this->bundles as $bundle) { - $bundle->registerExtensions($container); + $bundle->build($container); if ($this->debug) { $container->addObjectResource($bundle); }