Permalink
Browse files

slight compiler refactoring (RFC)

  • Loading branch information...
1 parent 5e94807 commit a2105d44aad351e2e1d302e7a385883428480a96 @schmittjoh schmittjoh committed with fabpot Dec 14, 2010
@@ -0,0 +1,30 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * Interface that must be implemented by compilation passes
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+interface CompilerPassInterface
+{
+ /**
+ * You can modify the container here before it is dumped to PHP code.
+ *
+ * @param ContainerBuilder $container
+ * @return void
+ */
+ function process(ContainerBuilder $container);
+}
@@ -0,0 +1,51 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * Merges extension configs into the container builder
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class MergeExtensionConfigurationPass implements CompilerPassInterface
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $parameters = $container->getParameterBag()->all();
+ $definitions = $container->getDefinitions();
+ $aliases = $container->getAliases();
+
+ foreach ($container->getExtensionConfigs() as $name => $configs) {
+ list($namespace, $tag) = explode(':', $name);
+
+ $extension = $container->getExtension($namespace);
+
+ $tmpContainer = new ContainerBuilder($container->getParameterBag());
+ $tmpContainer->addObjectResource($extension);
+ foreach ($configs as $config) {
+ $extension->load($tag, $config, $tmpContainer);
+ }
+
+ $container->merge($tmpContainer);
+ }
+
+ $container->setExtensionConfigs(array());
+ $container->addDefinitions($definitions);
+ $container->addAliases($aliases);
+ $container->getParameterBag()->add($parameters);
+ }
+}
@@ -0,0 +1,41 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * Resolves interface injectors and inlines them as method calls
+ *
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ */
+class ResolveInterfaceInjectorsPass implements CompilerPassInterface
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ foreach ($container->getDefinitions() as $definition) {
+ foreach ($container->getInterfaceInjectors() as $injector) {
+ if (null !== $definition->getFactoryService()) {
+ continue;
+ }
+ $defClass = $container->getParameterBag()->resolveValue($definition->getClass());
+ $definition->setClass($defClass);
+ if ($injector->supports($defClass)) {
+ $injector->processDefinition($definition);
+ }
+ }
+ }
+ }
+}
@@ -2,10 +2,14 @@
namespace Symfony\Component\DependencyInjection;
+use Symfony\Component\DependencyInjection\Compiler\ResolveInterfaceInjectorsPass;
+use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
-use Symfony\Component\DependencyInjection\Resource\ResourceInterface;
-use Symfony\Component\DependencyInjection\Resource\FileResource;
use Symfony\Component\DependencyInjection\InterfaceInjector;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
+use Symfony\Component\DependencyInjection\Resource\FileResource;
+use Symfony\Component\DependencyInjection\Resource\ResourceInterface;
/*
* This file is part of the Symfony framework.
@@ -31,6 +35,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
protected $resources = array();
protected $extensionConfigs = array();
protected $injectors = array();
+ protected $compilerPasses;
+
+ /**
+ * Constructor
+ * @param ParameterBagInterface $parameterBag
+ */
+ public function __construct(ParameterBagInterface $parameterBag = null)
+ {
+ parent::__construct($parameterBag);
+
+ $passes = array();
+ $passes[] = new MergeExtensionConfigurationPass();
+ $passes[] = new ResolveInterfaceInjectorsPass();
+ $this->compilerPasses = $passes;
+ }
/**
* Registers an extension.
@@ -127,6 +146,38 @@ public function loadFromExtension($extension, $tag, array $values = array())
return $this;
}
+ /**
+ * Adds a compiler pass at the end of the current passes
+ *
+ * @param CompilerPassInterface $pass
+ * @return void
+ */
+ public function addCompilerPass(CompilerPassInterface $pass)
+ {
+ $this->compilerPasses[] = $pass;
+ }
+
+ /**
+ * Returns the currently registered compiler passes
+ *
+ * @return array
+ */
+ public function getCompilerPasses()
+ {
+ return $this->compilerPasses;
+ }
+
+ /**
+ * Overwrites all existing passes
+ *
+ * @param array $passes
+ * @return void
+ */
+ public function setCompilerPasses(array $passes)
+ {
+ $this->compilerPasses = $passes;
+ }
+
/**
* Sets a service.
*
@@ -267,6 +318,17 @@ public function getExtensionConfigs()
return $this->extensionConfigs;
}
+ /**
+ * Sets the extension configs array
+ *
+ * @param array $config
+ * @return void
+ */
+ public function setExtensionConfigs(array $config)
+ {
+ $this->extensionConfigs = $config;
+ }
+
/**
* Freezes the container.
*
@@ -279,40 +341,8 @@ public function getExtensionConfigs()
*/
public function freeze()
{
- $parameters = $this->parameterBag->all();
- $definitions = $this->definitions;
- $aliases = $this->aliases;
-
- foreach ($this->extensionConfigs as $name => $configs) {
- list($namespace, $tag) = explode(':', $name);
-
- $extension = $this->getExtension($namespace);
-
- $container = new self($this->parameterBag);
- $container->addObjectResource($extension);
- foreach ($configs as $config) {
- $extension->load($tag, $config, $container);
- }
-
- $this->merge($container);
- }
-
- $this->extensionConfigs = array();
- $this->addDefinitions($definitions);
- $this->addAliases($aliases);
- $this->parameterBag->add($parameters);
-
- foreach ($this->definitions as $definition) {
- foreach ($this->injectors as $injector) {
- if (null !== $definition->getFactoryService()) {
- continue;
- }
- $defClass = $this->parameterBag->resolveValue($definition->getClass());
- $definition->setClass($defClass);
- if ($injector->supports($defClass)) {
- $injector->processDefinition($definition);
- }
- }
+ foreach ($this->compilerPasses as $pass) {
+ $pass->process($this);
}
parent::freeze();
@@ -16,7 +16,7 @@
/**
* InterfaceInjector is used for Interface Injection.
*
- * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
*/
class InterfaceInjector
{

0 comments on commit a2105d4

Please sign in to comment.