Skip to content

Commit 23c6d5e

Browse files
[DI] Allow autoconfiguring bindings
1 parent 5d6f100 commit 23c6d5e

File tree

8 files changed

+80
-4
lines changed

8 files changed

+80
-4
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Bridge\Monolog\Processor\ProcessorInterface;
15+
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
20+
21+
/**
22+
* Adds a rule to bind "security.actual_token_storage" to ProcessorInterface instances.
23+
*
24+
* @author Nicolas Grekas <p@tchwork.com>
25+
*/
26+
class RegisterForAutoconfigurationPass implements CompilerPassInterface
27+
{
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function process(ContainerBuilder $container)
32+
{
33+
if ($container->has('security.actual_token_storage')) {
34+
$processorAutoconfiguration = $container->registerForAutoconfiguration(ProcessorInterface::class);
35+
$processorAutoconfiguration->setBindings($processorAutoconfiguration->getBindings() + array(
36+
TokenStorageInterface::class => new BoundArgument(new Reference('security.actual_token_storage'), false),
37+
));
38+
}
39+
}
40+
}

src/Symfony/Bundle/SecurityBundle/SecurityBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
1515
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterCsrfTokenClearingLogoutHandlerPass;
16+
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterForAutoconfigurationPass;
1617
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginFactory;
1718
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginLdapFactory;
1819
use Symfony\Component\HttpKernel\Bundle\Bundle;
@@ -64,5 +65,6 @@ public function build(ContainerBuilder $container)
6465
$container->addCompilerPass(new AddSecurityVotersPass());
6566
$container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING);
6667
$container->addCompilerPass(new RegisterCsrfTokenClearingLogoutHandlerPass());
68+
$container->addCompilerPass(new RegisterForAutoconfigurationPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 200);
6769
}
6870
}

src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ final class BoundArgument implements ArgumentInterface
2222
private $identifier;
2323
private $used;
2424

25-
public function __construct($value)
25+
public function __construct($value, bool $trackUsage = true)
2626
{
2727
$this->value = $value;
28-
$this->identifier = ++self::$sequence;
28+
if ($trackUsage) {
29+
$this->identifier = ++self::$sequence;
30+
} else {
31+
$this->used = true;
32+
}
2933
}
3034

3135
/**

src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
6262
$parent = $shared = null;
6363
$instanceofTags = array();
6464
$instanceofCalls = array();
65+
$instanceofBindings = array();
6566

6667
foreach ($conditionals as $interface => $instanceofDefs) {
6768
if ($interface !== $class && (!$container->getReflectionClass($class, false))) {
@@ -79,13 +80,15 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
7980
$parent = '.instanceof.'.$interface.'.'.$key.'.'.$id;
8081
$container->setDefinition($parent, $instanceofDef);
8182
$instanceofTags[] = $instanceofDef->getTags();
83+
$instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings;
8284

8385
foreach ($instanceofDef->getMethodCalls() as $methodCall) {
8486
$instanceofCalls[] = $methodCall;
8587
}
8688

8789
$instanceofDef->setTags(array());
8890
$instanceofDef->setMethodCalls(array());
91+
$instanceofDef->setBindings(array());
8992

9093
if (isset($instanceofDef->getChanges()['shared'])) {
9194
$shared = $instanceofDef->isShared();
@@ -123,7 +126,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
123126
}
124127

125128
$definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls()));
126-
$definition->setBindings($bindings);
129+
$definition->setBindings($bindings + $instanceofBindings);
127130

128131
// reset fields with "merge" behavior
129132
$abstract

src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class InstanceofConfigurator extends AbstractServiceConfigurator
2626
use Traits\PublicTrait;
2727
use Traits\ShareTrait;
2828
use Traits\TagTrait;
29+
use Traits\BindTrait;
2930

3031
/**
3132
* Defines an instanceof-conditional to be applied to following service definitions.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class YamlFileLoader extends FileLoader
9393
'calls' => 'calls',
9494
'tags' => 'tags',
9595
'autowire' => 'autowire',
96+
'bind' => 'bind',
9697
);
9798

9899
private static $defaultsKeywords = array(

src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
142142
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
143143
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
144+
<xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
144145
</xsd:choice>
145146
<xsd:attribute name="id" type="xsd:string" use="required" />
146147
<xsd:attribute name="shared" type="boolean" />

src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass;
1818
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
1919
use Symfony\Component\DependencyInjection\ContainerBuilder;
20+
use Symfony\Component\DependencyInjection\Reference;
2021

2122
class ResolveInstanceofConditionalsPassTest extends TestCase
2223
{
@@ -270,7 +271,30 @@ public function testMergeReset()
270271
$this->assertTrue($abstract->isAbstract());
271272
}
272273

273-
public function testBindings()
274+
public function testProcessForAutoconfiguredBindings()
275+
{
276+
$container = new ContainerBuilder();
277+
278+
$container->registerForAutoconfiguration(self::class)
279+
->setBindings(array(
280+
'$foo' => new BoundArgument(234, false),
281+
parent::class => new BoundArgument(new Reference('foo'), false),
282+
));
283+
284+
$container->register('foo', self::class)
285+
->setAutoconfigured(true)
286+
->setBindings(array('$foo' => new BoundArgument(123, false)));
287+
288+
(new ResolveInstanceofConditionalsPass())->process($container);
289+
290+
$expected = array(
291+
'$foo' => new BoundArgument(123, false),
292+
parent::class => new BoundArgument(new Reference('foo'), false),
293+
);
294+
$this->assertEquals($expected, $container->findDefinition('foo')->getBindings());
295+
}
296+
297+
public function testBindingsOnInstanceofConditionals()
274298
{
275299
$container = new ContainerBuilder();
276300
$def = $container->register('foo', self::class)->setBindings(array('$toto' => 123));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy