Skip to content

Commit a2105d4

Browse files
schmittjohfabpot
authored andcommitted
slight compiler refactoring (RFC)
1 parent 5e94807 commit a2105d4

File tree

5 files changed

+189
-37
lines changed

5 files changed

+189
-37
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\ContainerBuilder;
6+
7+
/*
8+
* This file is part of the Symfony framework.
9+
*
10+
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
11+
*
12+
* This source file is subject to the MIT license that is bundled
13+
* with this source code in the file LICENSE.
14+
*/
15+
16+
/**
17+
* Interface that must be implemented by compilation passes
18+
*
19+
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
20+
*/
21+
interface CompilerPassInterface
22+
{
23+
/**
24+
* You can modify the container here before it is dumped to PHP code.
25+
*
26+
* @param ContainerBuilder $container
27+
* @return void
28+
*/
29+
function process(ContainerBuilder $container);
30+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\ContainerBuilder;
6+
7+
/*
8+
* This file is part of the Symfony framework.
9+
*
10+
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
11+
*
12+
* This source file is subject to the MIT license that is bundled
13+
* with this source code in the file LICENSE.
14+
*/
15+
16+
/**
17+
* Merges extension configs into the container builder
18+
*
19+
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
20+
*/
21+
class MergeExtensionConfigurationPass implements CompilerPassInterface
22+
{
23+
/**
24+
* {@inheritDoc}
25+
*/
26+
public function process(ContainerBuilder $container)
27+
{
28+
$parameters = $container->getParameterBag()->all();
29+
$definitions = $container->getDefinitions();
30+
$aliases = $container->getAliases();
31+
32+
foreach ($container->getExtensionConfigs() as $name => $configs) {
33+
list($namespace, $tag) = explode(':', $name);
34+
35+
$extension = $container->getExtension($namespace);
36+
37+
$tmpContainer = new ContainerBuilder($container->getParameterBag());
38+
$tmpContainer->addObjectResource($extension);
39+
foreach ($configs as $config) {
40+
$extension->load($tag, $config, $tmpContainer);
41+
}
42+
43+
$container->merge($tmpContainer);
44+
}
45+
46+
$container->setExtensionConfigs(array());
47+
$container->addDefinitions($definitions);
48+
$container->addAliases($aliases);
49+
$container->getParameterBag()->add($parameters);
50+
}
51+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\ContainerBuilder;
6+
7+
/*
8+
* This file is part of the Symfony framework.
9+
*
10+
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
11+
*
12+
* This source file is subject to the MIT license that is bundled
13+
* with this source code in the file LICENSE.
14+
*/
15+
16+
/**
17+
* Resolves interface injectors and inlines them as method calls
18+
*
19+
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
20+
*/
21+
class ResolveInterfaceInjectorsPass implements CompilerPassInterface
22+
{
23+
/**
24+
* {@inheritDoc}
25+
*/
26+
public function process(ContainerBuilder $container)
27+
{
28+
foreach ($container->getDefinitions() as $definition) {
29+
foreach ($container->getInterfaceInjectors() as $injector) {
30+
if (null !== $definition->getFactoryService()) {
31+
continue;
32+
}
33+
$defClass = $container->getParameterBag()->resolveValue($definition->getClass());
34+
$definition->setClass($defClass);
35+
if ($injector->supports($defClass)) {
36+
$injector->processDefinition($definition);
37+
}
38+
}
39+
}
40+
}
41+
}

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22

33
namespace Symfony\Component\DependencyInjection;
44

5+
use Symfony\Component\DependencyInjection\Compiler\ResolveInterfaceInjectorsPass;
6+
use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass;
7+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
58
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
6-
use Symfony\Component\DependencyInjection\Resource\ResourceInterface;
7-
use Symfony\Component\DependencyInjection\Resource\FileResource;
89
use Symfony\Component\DependencyInjection\InterfaceInjector;
10+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
use Symfony\Component\DependencyInjection\Resource\FileResource;
12+
use Symfony\Component\DependencyInjection\Resource\ResourceInterface;
913

1014
/*
1115
* This file is part of the Symfony framework.
@@ -31,6 +35,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
3135
protected $resources = array();
3236
protected $extensionConfigs = array();
3337
protected $injectors = array();
38+
protected $compilerPasses;
39+
40+
/**
41+
* Constructor
42+
* @param ParameterBagInterface $parameterBag
43+
*/
44+
public function __construct(ParameterBagInterface $parameterBag = null)
45+
{
46+
parent::__construct($parameterBag);
47+
48+
$passes = array();
49+
$passes[] = new MergeExtensionConfigurationPass();
50+
$passes[] = new ResolveInterfaceInjectorsPass();
51+
$this->compilerPasses = $passes;
52+
}
3453

3554
/**
3655
* Registers an extension.
@@ -127,6 +146,38 @@ public function loadFromExtension($extension, $tag, array $values = array())
127146
return $this;
128147
}
129148

149+
/**
150+
* Adds a compiler pass at the end of the current passes
151+
*
152+
* @param CompilerPassInterface $pass
153+
* @return void
154+
*/
155+
public function addCompilerPass(CompilerPassInterface $pass)
156+
{
157+
$this->compilerPasses[] = $pass;
158+
}
159+
160+
/**
161+
* Returns the currently registered compiler passes
162+
*
163+
* @return array
164+
*/
165+
public function getCompilerPasses()
166+
{
167+
return $this->compilerPasses;
168+
}
169+
170+
/**
171+
* Overwrites all existing passes
172+
*
173+
* @param array $passes
174+
* @return void
175+
*/
176+
public function setCompilerPasses(array $passes)
177+
{
178+
$this->compilerPasses = $passes;
179+
}
180+
130181
/**
131182
* Sets a service.
132183
*
@@ -267,6 +318,17 @@ public function getExtensionConfigs()
267318
return $this->extensionConfigs;
268319
}
269320

321+
/**
322+
* Sets the extension configs array
323+
*
324+
* @param array $config
325+
* @return void
326+
*/
327+
public function setExtensionConfigs(array $config)
328+
{
329+
$this->extensionConfigs = $config;
330+
}
331+
270332
/**
271333
* Freezes the container.
272334
*
@@ -279,40 +341,8 @@ public function getExtensionConfigs()
279341
*/
280342
public function freeze()
281343
{
282-
$parameters = $this->parameterBag->all();
283-
$definitions = $this->definitions;
284-
$aliases = $this->aliases;
285-
286-
foreach ($this->extensionConfigs as $name => $configs) {
287-
list($namespace, $tag) = explode(':', $name);
288-
289-
$extension = $this->getExtension($namespace);
290-
291-
$container = new self($this->parameterBag);
292-
$container->addObjectResource($extension);
293-
foreach ($configs as $config) {
294-
$extension->load($tag, $config, $container);
295-
}
296-
297-
$this->merge($container);
298-
}
299-
300-
$this->extensionConfigs = array();
301-
$this->addDefinitions($definitions);
302-
$this->addAliases($aliases);
303-
$this->parameterBag->add($parameters);
304-
305-
foreach ($this->definitions as $definition) {
306-
foreach ($this->injectors as $injector) {
307-
if (null !== $definition->getFactoryService()) {
308-
continue;
309-
}
310-
$defClass = $this->parameterBag->resolveValue($definition->getClass());
311-
$definition->setClass($defClass);
312-
if ($injector->supports($defClass)) {
313-
$injector->processDefinition($definition);
314-
}
315-
}
344+
foreach ($this->compilerPasses as $pass) {
345+
$pass->process($this);
316346
}
317347

318348
parent::freeze();

src/Symfony/Component/DependencyInjection/InterfaceInjector.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/**
1717
* InterfaceInjector is used for Interface Injection.
1818
*
19-
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
19+
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
2020
*/
2121
class InterfaceInjector
2222
{

0 commit comments

Comments
 (0)