Skip to content

Commit

Permalink
slight compiler refactoring (RFC)
Browse files Browse the repository at this point in the history
  • Loading branch information
schmittjoh authored and fabpot committed Dec 20, 2010
1 parent 3dea789 commit 3b7f997
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 37 deletions.
30 changes: 30 additions & 0 deletions Compiler/CompilerPassInterface.php
@@ -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);
}
51 changes: 51 additions & 0 deletions Compiler/MergeExtensionConfigurationPass.php
@@ -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);
}
}
41 changes: 41 additions & 0 deletions Compiler/ResolveInterfaceInjectorsPass.php
@@ -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);
}
}
}
}
}
102 changes: 66 additions & 36 deletions ContainerBuilder.php
Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
*
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion InterfaceInjector.php
Expand Up @@ -16,7 +16,7 @@
/**
* InterfaceInjector is used for Interface Injection.
*
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
*/
class InterfaceInjector
{
Expand Down

0 comments on commit 3b7f997

Please sign in to comment.