Skip to content

Commit 321ccff

Browse files
committed
fix: check factory definition
1 parent cd7d7c2 commit 321ccff

File tree

2 files changed

+40
-32
lines changed

2 files changed

+40
-32
lines changed
Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<?php
22

3-
declare(strict_types=1);
4-
53
/*
64
* This file is part of the Symfony package.
75
*
@@ -14,6 +12,7 @@
1412
namespace Symfony\Component\DependencyInjection\Compiler;
1513

1614
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Definition;
1716
use Symfony\Component\DependencyInjection\Exception\IncorrectServiceClassException;
1817
use Symfony\Component\DependencyInjection\Reference;
1918

@@ -22,42 +21,52 @@ class CheckServiceClassExistsPass implements CompilerPassInterface
2221
public function process(ContainerBuilder $container): void
2322
{
2423
foreach ($container->getDefinitions() as $id => $definition) {
25-
if ($definition->isSynthetic()) {
26-
continue;
27-
}
28-
29-
if ($factory = $definition->getFactory()) {
30-
$this->checkFactory($container, $factory, $id);
31-
continue;
32-
}
33-
34-
$class = $container->getParameterBag()->resolveValue($definition->getClass());
35-
$message = \sprintf('class "%s" defined for service "%s" does not exist.', $class, $id);
24+
$this->validateDefinition($container, $definition, $id);
25+
}
26+
}
3627

37-
try {
38-
$ref = $container->getReflectionClass($class, true);
28+
private function checkFactory(ContainerBuilder $container, array|string $factory, string $id): void
29+
{
30+
if (\is_array($factory)) {
31+
$object = $factory[0] ?? null;
3932

40-
if (null === $ref) {
41-
throw new IncorrectServiceClassException($message);
42-
}
43-
} catch (\ReflectionException $e) {
44-
throw new IncorrectServiceClassException($message, previous: $e);
33+
if ($object instanceof Definition) {
34+
$this->validateDefinition($container, $object, "{$id} (factory)");
35+
} elseif (!\is_string($object)) {
36+
// We only check strings and Definition, References and null values are checked elsewhere.
37+
return;
4538
}
4639
}
40+
41+
try {
42+
\Closure::fromCallable($factory);
43+
} catch (\TypeError) {
44+
throw new IncorrectServiceClassException(\sprintf('Factory "%s" for service "%s" is invalid, please check for typos.', \is_string($factory) ? $factory : implode('::', $factory), $id));
45+
}
4746
}
4847

49-
private function checkFactory(ContainerBuilder $container, array|string $factory, string $id): void
48+
private function validateDefinition(ContainerBuilder $container, Definition $definition, string $id): void
5049
{
51-
if (\is_array($factory) && $factory[0] instanceof Reference && $container->hasDefinition((string) $factory[0])) {
50+
if ($definition->isSynthetic()) {
51+
return;
52+
}
53+
54+
if ($factory = $definition->getFactory()) {
55+
$this->checkFactory($container, $factory, $id);
5256
return;
5357
}
5458

55-
$factory = \is_array($factory) ? array_map('strval', $factory) : $container->getParameterBag()->resolveValue($factory);
59+
$class = $definition->getClass();
60+
$message = \sprintf('class "%s" defined for service "%s" does not exist.', $class, $id);
5661

5762
try {
58-
\Closure::fromCallable($factory);
59-
} catch (\TypeError) {
60-
throw new IncorrectServiceClassException(\sprintf('Factory "%s" for service "%s" is invalid, please check for typos.', \is_string($factory) ? $factory : implode('::', $factory), $id));
63+
$ref = $container->getReflectionClass($class, true);
64+
65+
if (null === $ref) {
66+
throw new IncorrectServiceClassException($message);
67+
}
68+
} catch (\ReflectionException $e) {
69+
throw new IncorrectServiceClassException($message, previous: $e);
6170
}
6271
}
6372
}

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\DependencyInjection\Compiler\CheckServiceClassExistsPass;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Definition;
1718
use Symfony\Component\DependencyInjection\Exception\IncorrectServiceClassException;
18-
use Symfony\Component\DependencyInjection\Reference;
1919

2020
class CheckServiceClassExistsPassTest extends TestCase
2121
{
@@ -33,14 +33,13 @@ public function testProcess()
3333
(new CheckServiceClassExistsPass())->process($container);
3434
}
3535

36-
public function testProcessParameterClass()
36+
public function testInvalidFactoryDefinition()
3737
{
3838
$this->expectException(IncorrectServiceClassException::class);
39-
$this->expectExceptionMessage('class "App\Servoces\MyService" defined for service "foo" does not exist.');
39+
$this->expectExceptionMessage('class "My\ClassWithTypo" defined for service "foo (factory)" does not exist.');
4040

4141
$container = new ContainerBuilder();
42-
$container->setParameter('service_class', 'App\Servoces\MyService');
43-
$container->register('foo', '%service_class%');
42+
$container->register('foo')->setFactory([new Definition('My\ClassWithTypo'), 'create']);
4443

4544
(new CheckServiceClassExistsPass())->process($container);
4645
}
@@ -51,7 +50,7 @@ public function testProcessWithFactory()
5150
$this->expectExceptionMessage('Factory "My\MissingClass::create" for service "foo" is invalid, please check for typos.');
5251

5352
$container = new ContainerBuilder();
54-
$container->register('foo')->setFactory([new Reference('My\MissingClass'), 'create']);
53+
$container->register('foo')->setFactory(['My\MissingClass', 'create']);
5554

5655
(new CheckServiceClassExistsPass())->process($container);
5756
}

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