Skip to content

Commit 3192e7f

Browse files
[DependencyInjection] Fix lazy-proxying final classes
1 parent e056066 commit 3192e7f

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

LazyProxy/PhpDumper/LazyServiceDumper.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,13 @@ public function getProxyCode(Definition $definition, string $id = null): string
123123
if (!interface_exists($tag['interface']) && !class_exists($tag['interface'], false)) {
124124
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": several "proxy" tags found but "%s" is not an interface.', $id ?? $definition->getClass(), $tag['interface']));
125125
}
126+
if (!is_a($class->name, $tag['interface'], true)) {
127+
throw new InvalidArgumentException(sprintf('Invalid "proxy" tag for service "%s": class "%s" doesn\'t implement "%s".', $id ?? $definition->getClass(), $definition->getClass(), $tag['interface']));
128+
}
126129
$interfaces[] = new \ReflectionClass($tag['interface']);
127130
}
128131

129-
if (1 === \count($interfaces) && !$interfaces[0]->isInterface()) {
130-
$class = array_pop($interfaces);
131-
}
132+
$class = 1 === \count($interfaces) && !$interfaces[0]->isInterface() ? array_pop($interfaces) : null;
132133
} elseif ($class->isInterface()) {
133134
$interfaces = [$class];
134135
$class = null;

Tests/LazyProxy/PhpDumper/LazyServiceDumperTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Psr\Container\ContainerInterface;
1616
use Symfony\Component\DependencyInjection\Definition;
17+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1718
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyServiceDumper;
1819

1920
class LazyServiceDumperTest extends TestCase
@@ -26,4 +27,42 @@ public function testProxyInterface()
2627
$this->assertTrue($dumper->isProxyCandidate($definition));
2728
$this->assertStringContainsString('function get(', $dumper->getProxyCode($definition));
2829
}
30+
31+
public function testFinalClassInterface()
32+
{
33+
$dumper = new LazyServiceDumper();
34+
$definition = (new Definition(TestContainer::class))
35+
->setLazy(true)
36+
->addTag('proxy', ['interface' => ContainerInterface::class]);
37+
38+
$this->assertTrue($dumper->isProxyCandidate($definition));
39+
$this->assertStringContainsString('function get(', $dumper->getProxyCode($definition));
40+
}
41+
42+
public function testInvalidClass()
43+
{
44+
$dumper = new LazyServiceDumper();
45+
$definition = (new Definition(\stdClass::class))
46+
->setLazy(true)
47+
->addTag('proxy', ['interface' => ContainerInterface::class]);
48+
49+
$this->assertTrue($dumper->isProxyCandidate($definition));
50+
51+
$this->expectException(InvalidArgumentException::class);
52+
$this->expectExceptionMessage('Invalid "proxy" tag for service "stdClass": class "stdClass" doesn\'t implement "Psr\Container\ContainerInterface".');
53+
$dumper->getProxyCode($definition);
54+
}
55+
}
56+
57+
final class TestContainer implements ContainerInterface
58+
{
59+
public function has(string $key): bool
60+
{
61+
return true;
62+
}
63+
64+
public function get(string $key): string
65+
{
66+
return $key;
67+
}
2968
}

0 commit comments

Comments
 (0)