8000 bug #47564 [DependencyInjection] Fix lazy-proxying final classes (nic… · symfony/symfony@8075c68 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8075c68

Browse files
bug #47564 [DependencyInjection] Fix lazy-proxying final classes (nicolas-grekas)
This PR was merged into the 6.2 branch. Discussion ---------- [DependencyInjection] Fix lazy-proxying final classes | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #47563 | License | MIT | Doc PR | - Commits ------- 9ca3cb1 [DependencyInjection] Fix lazy-proxying final classes
2 parents 8a66294 + 9ca3cb1 commit 8075c68

File tree

4 files changed

+54
-15
lines changed

4 files changed

+54
-15
lines changed

src/Symfony/Component/DependencyInjection/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']) &&am 10000 p; !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;

src/Symfony/Component/DependencyInjection/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
}

src/Symfony/Component/VarExporter/ProxyHelper.php

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,7 @@ public static function generateLazyProxy(?\ReflectionClass $class, array $interf
191191
$methods = ['initializeLazyObject' => implode('', $body).' }'] + $methods;
192192
}
193193
$body = $methods ? "\n".implode("\n\n", $methods)."\n" : '';
194-
195-
if ($class) {
196-
$propertyScopes = substr(self::exportPropertyScopes($class->name), 1, -6);
197-
$body = <<<EOPHP
198-
199-
private const LAZY_OBJECT_PROPERTY_SCOPES = [
200-
'lazyObjectReal' => [self::class, 'lazyObjectReal', null],
201-
"\\0".self::class."\\0lazyObjectReal" => [self::class, 'lazyObjectReal', null],{$propertyScopes}
202-
];
203-
{$body}
204-
EOPHP;
205-
}
194+
$propertyScopes = $class ? substr(self::exportPropertyScopes($class->name), 1, -6) : '';
206195

207196
return <<<EOPHP
208197
{$parent} implements \\{$interfaces}
@@ -211,6 +200,11 @@ public static function generateLazyProxy(?\ReflectionClass $class, array $interf
211200
212201
private {$readonly}int \$lazyObjectId;
213202
private {$readonly}{$type} \$lazyObjectReal;
203+
204+
private const LAZY_OBJECT_PROPERTY_SCOPES = [
205+
'lazyObjectReal' => [self::class, 'lazyObjectReal', null],
206+
"\\0".self::class."\\0lazyObjectReal" => [self::class, 'lazyObjectReal', null],{$propertyScopes}
207+
];
214208
{$body}}
215209
216210
// Help opcache.preload discover always-needed symbols

src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ public function testGenerateLazyProxyForInterfaces()
122122
private int $lazyObjectId;
123123
private \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1&\Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 $lazyObjectReal;
124124
125+
private const LAZY_OBJECT_PROPERTY_SCOPES = [
126+
'lazyObjectReal' => [self::class, 'lazyObjectReal', null],
127+
"\0".self::class."\0lazyObjectReal" => [self::class, 'lazyObjectReal', null],
128+
];
129+
125130
public function initializeLazyObject(): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1&\Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2
126131
{
127132
if (isset($this->lazyObjectReal)) {

0 commit comments

Comments
 (0)
0