8000 [DependencyInjection] Optional class for class named services · symfony/symfony@6627e27 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6627e27

Browse files
committed
[DependencyInjection] Optional class for class named services
1 parent 923aaad commit 6627e27

File tree

6 files changed

+147
-3
lines changed

6 files changed

+147
-3
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8000
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\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
16+
/**
17+
* @author Martin Hasoň <martin.hason@gmail.com>
18+
*/
19+
class ClassNamedServicePass implements CompilerPassInterface
20+
{
21+
public function process(ContainerBuilder $container)
22+
{
23+
foreach ($container->getDefinitions() as $id => $definition) {
24+
if (null !== $definition->getClass()) {
25+
continue;
26+
}
27+
28+
foreach ($container->getOriginalIds($id) as $class) {
29+
if (class_exists($class)) {
30+
$definition->setClass($class);
31+
break;
32+
}
33+
}
34+
}
35+
}
36+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function __construct()
4141

4242
$this->optimizationPasses = array(array(
4343
new ExtensionCompilerPass(),
44+
new ClassNamedServicePass(),
4445
new ResolveDefinitionTemplatesPass(),
4546
new DecoratorServicePass(),
4647
new ResolveParameterPlaceHoldersPass(),

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
102102

103103
private $compiled = false;
104104

105+
private $originalIds = array();
106+
105107
/**
106108
* Sets the track resources flag.
107109
*
@@ -367,7 +369,7 @@ public function set($id, $service)
367369
throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a frozen container is not allowed.', $id));
368370
}
369371

370-
unset($this->definitions[$id], $this->aliasDefinitions[$id]);
372+
unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->originalIds[$id]);
371373

372374
parent::set($id, $service);
373375
}
@@ -379,7 +381,9 @@ public function set($id, $service)
379381
*/
380382
public function removeDefinition($id)
381383
{
382-
unset($this->definitions[strtolower($id)]);
384+
$id = strtolower($id);
385+
386+
unset($this->definitions[$id], $this->originalIds[$id]);
383387
}
384388

385389
/**
@@ -638,7 +642,7 @@ public function setAlias($alias, $id)
638642
throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
639643
}
640644

641-
unset($this->definitions[$alias]);
645+
unset($this->definitions[$alias], $this->originalIds[$alias]);
642646

643647
$this->aliasDefinitions[$alias] = $id;
644648
}
@@ -760,7 +764,10 @@ public function setDefinition($id, Definition $definition)
760764
throw new BadMethodCallException('Adding definition to a frozen container is not allowed');
761765
}
762766

767+
$originalId = $id;
763768
$id = strtolower($id);
769+
$this->originalIds[$id][] = $originalId;
770+
$this->originalIds[$id] = array_unique($this->originalIds[$id]);
764771

765772
unset($this->aliasDefinitions[$id]);
766773

@@ -1072,6 +1079,20 @@ public function getEnvCounters()
10721079
return $this->envCounters;
10731080
}
10741081

1082+
/**
1083+
* Returns the original ids for service.
1084+
*
1085+
* @param string $id The service identifier or alias
1086+
*
1087+
* @return string[] An array of all defined original service ids
1088+
*/
1089+
public function getOriginalIds($id)
1090+
{
1091+
$id = strtolower($id);
1092+
1093+
return isset($this->originalIds[$id]) ? $this->originalIds[$id] : array();
1094+
}
1095+
10751096
/**
10761097
* Returns the Service Conditionals.
10771098
*
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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\Component\DependencyInjection\Tests\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\ClassNamedServicePass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\DefinitionDecorator;
17+
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
18+
use Symfony\Component\DependencyInjection\Tests\Fixtures\EnhancedCaseSensitiveClass;
19+
20+
/**
21+
* @author Martin Hasoň <martin.hason@gmail.com>
22+
*/
23+
class ClassNamedServicePassTest extends \PHPUnit_Framework_TestCase
24+
{
25+
public function testProcess()
26+
{
27+
$container = new ContainerBuilder();
28+
29+
$unknown = $container->register('unknown_class');
30+
$class = $container->register(\stdClass::class);
31+
$autoloadClass = $container->register(CaseSensitiveClass::class);
32+
33+
$pass = new ClassNamedServicePass();
34+
$pass->process($container);
35+
36+
$this->assertNull($unknown->getClass());
37+
$this->assertEquals(\stdClass::class, $class->getClass());
38+
$this->assertEquals(CaseSensitiveClass::class, $autoloadClass->getClass());
39+
}
40+
41+
public function testCompile()
42+
{
43+
$container = new ContainerBuilder();
44+
45+
$container->register(\stdClass::class);
46+
$container->register(CaseSensitiveClass::class)->setDecoratedService(\stdClass::class);
47+
48+
$container->register('parent', CaseSensitiveClass::class);
49+
$container->setDefinition(EnhancedCaseSensitiveClass::class, new DefinitionDecorator('parent'));
50+
51+
$container->compile();
52+
53+
$this->assertEquals(CaseSensitiveClass::class, $container->getDefinition(CaseSensitiveClass::class)->getClass());
54+
$this->assertEquals(EnhancedCaseSensitiveClass::class, $container->getDefinition(EnhancedCaseSensitiveClass::class)->getClass());
55+
}
56+
}

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,16 @@ public function testAutowiring()
823823

824824
$this->assertEquals('a', (string) $container->getDefinition('b')->getArgument(0));
825825
}
826+
827+
public function testOriginalIds()
828+
{
829+
$container = new ContainerBuilder();
830+
831+
$container->register('Foo');
832+
833+
$this->assertEquals(array('Foo'), $container->getOriginalIds('foo'));
834+
$this->assertEmpty($container->getOriginalIds('unknown'));
835+
}
826836
}
827837

828838
class FooClass
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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\Component\DependencyInjection\Tests\Fixtures;
13+
14+
class CaseSensitiveClass
15+
{
16+
}
17+
18+
class EnhancedCaseSensitiveClass extends CaseSensitiveClass
19+
{
20+
}

0 commit comments

Comments
 (0)
0