Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 398cfdd

Browse files
committed
[DependencyInjection] Add custom container configurators
1 parent 170ab63 commit 398cfdd

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
2727
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
2828
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
29+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
2930
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
3031
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
3132
use Symfony\Component\Config\Resource\ClassExistenceResource;
@@ -123,6 +124,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
123124
private $removedIds = array();
124125
private $alreadyLoading = array();
125126

127+
/**
128+
* @var callable[] configurator class name => callable
129+
*/
130+
private $containerConfiguratorFactories;
131+
126132
public function __construct(ParameterBagInterface $parameterBag = null)
127133
{
128134
parent::__construct($parameterBag);
@@ -222,6 +228,36 @@ public function hasExtension($name)
222228
return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
223229
}
224230

231+
/**
232+
* @param callable $factory function (ContainerConfigurator $c) { .... }
233+
*/
234+
public function registerContainerConfiguratorFactory(string $configuratorClassName, callable $factory)
235+
{
236+
if (!class_exists($configuratorClassName)) {
237+
throw new \LogicException(sprintf('Container configurator class %s does not exist.', $configuratorClassName));
238+
}
239+
240+
if (isset($this->containerConfiguratorFactories[$configuratorClassName])) {
241+
throw new \LogicException(sprintf('Container configurator factory for %s was already registered.', $configuratorClassName));
242+
}
243+
244+
$this->containerConfiguratorFactories[$configuratorClassName] = $factory;
245+
}
246+
247+
/**
248+
* @param string $configuratorClassName
249+
*
250+
* @return mixed
251+
*/
252+
public function getContainerConfigurator(string $configuratorClassName, ContainerConfigurator $configurator)
253+
{
254+
if (!isset($this->containerConfiguratorFactories[$configuratorClassName])) {
255+
throw new \LogicException(sprintf('Container configurator factory for %s does not exist.', $configuratorClassName));
256+
}
257+
258+
return call_user_func($this->containerConfiguratorFactories[$configuratorClassName], $configurator);
259+
}
260+
225261
/**
226262
* Returns an array of resources loaded to build this configuration.
227263
*

src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,20 @@ public function load($resource, $type = null)
4444
$callback = $load($path);
4545

4646
if ($callback instanceof \Closure) {
47-
$callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this);
47+
$method = new \ReflectionFunction($callback);
48+
49+
if (0 === $method->getNumberOfParameters()) {
50+
throw new \LogicException('Closure in %s:%d must have at least 1 argument.', $path, $method->getStartLine());
51+
}
52+
53+
$configurator = new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource);
54+
$configuratorClass = $method->getParameters()[0]->getClass()->name;
55+
56+
if (ContainerConfigurator::class !== $configuratorClass) {
57+
$configurator = $this->container->getContainerConfigurator($configuratorClass, $configurator);
58+
}
59+
60+
$callback($configurator, $this->container, $this);
4861
}
4962
}
5063

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
6+
7+
final class FooContainerConfigurator
8+
{
9+
private $configurator;
10+
11+
public function __construct(ContainerConfigurator $configurator)
12+
{
13+
$this->configurator = $configurator;
14+
}
15+
16+
public function foo()
17+
{
18+
$this->configurator->parameters()->set('foo', 'bar');
19+
}
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooContainerConfigurator;
4+
5+
return function (FooContainerConfigurator $c) {
6+
$c->foo();
7+
};

src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
1616
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
1717
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
18+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
1819
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
1920
use Symfony\Component\Config\FileLocator;
21+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooContainerConfigurator;
2022

2123
class PhpFileLoaderTest extends TestCase
2224
{
@@ -74,6 +76,23 @@ public function provideConfig()
7476
yield array('php7');
7577
}
7678

79+
public function testCustomContainerConfigurator()
80+
{
81+
$container = new ContainerBuilder();
82+
$container->registerContainerConfiguratorFactory(
83+
FooContainerConfigurator::class,
84+
function (ContainerConfigurator $c) {
85+
return new FooContainerConfigurator($c);
86+
}
87+
);
88+
89+
$fixtures = realpath(__DIR__.'/../Fixtures');
90+
$loader = new PhpFileLoader($container, new FileLocator());
91+
$loader->load($fixtures.'/config/custom_configurator.php');
92+
93+
$this->assertEquals('bar', $container->getParameter('foo'));
94+
}
95+
7796
/**
7897
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
7998
* @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.

0 commit comments

Comments
 (0)