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

Skip to content

Commit 064bee1

Browse files
committed
Fix IDs in ServiceLocator
1 parent eed0ae4 commit 064bee1

File tree

2 files changed

+73
-28
lines changed

2 files changed

+73
-28
lines changed

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

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
3737
$value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container));
3838
}
3939

40-
return self::register($this->container, $value->getValues());
40+
return self::register($this->container, $this->replaceNumericServiceLocatorKeys($value->getValues()));
4141
}
4242

4343
if ($value instanceof Definition) {
@@ -62,26 +62,15 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
6262
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId));
6363
}
6464

65-
$i = 0;
65+
$services = $this->replaceNumericServiceLocatorKeys($services);
6666

6767
foreach ($services as $k => $v) {
6868
if ($v instanceof ServiceClosureArgument) {
6969
continue;
7070
}
7171

72-
if ($i === $k) {
73-
if ($v instanceof Reference) {
74-
unset($services[$k]);
75-
$k = (string) $v;
76-
}
77-
++$i;
78-
} elseif (\is_int($k)) {
79-
$i = null;
80-
}
81-
8272
$services[$k] = new ServiceClosureArgument($v);
8373
}
84-
ksort($services);
8574

8675
$value->setArgument(0, $services);
8776

@@ -100,6 +89,39 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
10089
return new Reference($id);
10190
}
10291

92+
/**
93+
* Replaces numeric service IDs with service names.
94+
*
95+
* @param array<array-key, mixed> $services
96+
*
97+
* @return array<string, mixed>
98+
*/
99+
private function replaceNumericServiceLocatorKeys(array $services): array
100+
{
101+
$i = 0;
102+
103+
foreach ($services as $k => $v) {
104+
if ($i === $k && $v instanceof Reference) {
105+
unset($services[$k]);
106+
$k = (string) $v;
107+
++$i;
108+
} elseif (\is_int($k)) {
109+
/**
110+
* Not consecutive numbers, so stop replacing names but continue the loop.
111+
*
112+
* @see ServiceLocatorTagPassTest::testInheritedKeyOverwritesPreviousServiceWithKey
113+
*/
114+
$i = null;
115+
}
116+
117+
$services[$k] = $v;
118+
}
119+
120+
ksort($services);
121+
122+
return $services;
123+
}
124+
103125
public static function register(ContainerBuilder $container, array $map, string $callerId = null): Reference
104126
{
105127
foreach ($map as $k => $v) {

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

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
2222
use Symfony\Component\DependencyInjection\Reference;
2323
use Symfony\Component\DependencyInjection\ServiceLocator;
24-
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
2524
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
2625
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition2;
2726

@@ -62,8 +61,8 @@ public function testProcessValue()
6261
{
6362
$container = new ContainerBuilder();
6463

65-
$container->register('bar', CustomDefinition::class);
66-
$container->register('baz', CustomDefinition::class);
64+
$container->register('bar', TestDefinition1::class);
65+
$container->register('baz', TestDefinition2::class);
6766

6867
$container->register('foo', ServiceLocator::class)
6968
->setArguments([[
@@ -79,9 +78,33 @@ public function testProcessValue()
7978
/** @var ServiceLocator $locator */
8079
$locator = $container->get('foo');
8180

82-
$this->assertSame(CustomDefinition::class, $locator('bar')::class);
83-
$this->assertSame(CustomDefinition::class, $locator('baz')::class);
84-
$this->assertSame(CustomDefinition::class, $locator('some.service')::class);
81+
$this->assertInstanceOf(TestDefinition1::class, $locator('bar'));
82+
$this->assertInstanceOf(TestDefinition2::class, $locator('baz'));
83+
$this->assertInstanceOf(TestDefinition1::class, $locator('some.service'));
84+
}
85+
86+
public function testProcessLocatorArgumentValue()
87+
{
88+
$container = new ContainerBuilder();
89+
90+
$container->register('bar', TestDefinition1::class);
91+
$container->register('baz', TestDefinition2::class);
92+
93+
$container->register('foo', Locator::class)
94+
->addArgument(new ServiceLocatorArgument([
95+
new Reference('bar'),
96+
'some.service' => new Reference('bar'),
97+
new Reference('baz'),
98+
]));
99+
100+
(new ServiceLocatorTagPass())->process($container);
101+
102+
/** @var ServiceLocator $locator */
103+
$locator = $container->get('foo')->locator;
104+
105+
$this->assertInstanceOf(TestDefinition1::class, $locator('bar'));
106+
$this->assertInstanceOf(TestDefinition1::class, $locator('some.service'));
107+
$this->assertInstanceOf(TestDefinition2::class, $locator('baz'));
85108
}
86109

87110
public function testServiceWithKeyOverwritesPreviousInheritedKey()
@@ -104,7 +127,7 @@ public function testServiceWithKeyOverwritesPreviousInheritedKey()
104127
/** @var ServiceLocator $locator */
105128
$locator = $container->get('foo');
106129

107-
$this->assertSame(TestDefinition2::class, $locator('bar')::class);
130+
$this->assertInstanceOf(TestDefinition2::class, $locator('bar'));
108131
}
109132

110133
public function testInheritedKeyOverwritesPreviousServiceWithKey()
@@ -128,8 +151,8 @@ public function testInheritedKeyOverwritesPreviousServiceWithKey()
128151
/** @var ServiceLocator $locator */
129152
$locator = $container->get('foo');
130153

131-
$this->assertSame(TestDefinition1::class, $locator('bar')::class);
132-
$this->assertSame(TestDefinition2::class, $locator(16)::class);
154+
$this->assertInstanceOf(TestDefinition1::class, $locator('bar'));
155+
$this->assertInstanceOf(TestDefinition2::class, $locator(16));
133156
}
134157

135158
public function testBindingsAreCopied()
@@ -164,8 +187,8 @@ public function testTaggedServices()
164187
/** @var ServiceLocator $locator */
165188
$locator = $container->get('foo');
166189

167-
$this->assertSame(TestDefinition1::class, $locator('bar')::class);
168-
$this->assertSame(TestDefinition2::class, $locator('baz')::class);
190+
$this->assertInstanceOf(TestDefinition1::class, $locator('bar'));
191+
$this->assertInstanceOf(TestDefinition2::class, $locator('baz'));
169192
}
170193

171194
public function testIndexedByServiceIdWithDecoration()
@@ -184,19 +207,19 @@ public function testIndexedByServiceIdWithDecoration()
184207

185208
$container->setDefinition(Service::class, $service);
186209

187-
$decorated = new Definition(Decorated::class);
210+
$decorated = new Definition(DecoratedService::class);
188211
$decorated->setPublic(true);
189212
$decorated->setDecoratedService(Service::class);
190213

191-
$container->setDefinition(Decorated::class, $decorated);
214+
$container->setDefinition(DecoratedService::class, $decorated);
192215

193216
$container->compile();
194217

195218
/** @var ServiceLocator $locator */
196219
$locator = $container->get(Locator::class)->locator;
197220
static::assertTrue($locator->has(Service::class));
198-
static::assertFalse($locator->has(Decorated::class));
199-
static::assertInstanceOf(Decorated::class, $locator->get(Service::class));
221+
static::assertFalse($locator->has(DecoratedService::class));
222+
static::assertInstanceOf(DecoratedService::class, $locator->get(Service::class));
200223
}
201224

202225
public function testDefinitionOrderIsTheSame()

0 commit comments

Comments
 (0)