Skip to content

Commit 07d502f

Browse files
Merge branch '7.2' into 7.3
* 7.2: [DependencyInjection] Fix generating adapters of functional interfaces
2 parents 1013115 + a7ec591 commit 07d502f

File tree

6 files changed

+34
-14
lines changed

6 files changed

+34
-14
lines changed

Argument/LazyClosure.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,22 @@ public function __get(mixed $name): mixed
4040
}
4141

4242
if (isset($this->initializer)) {
43-
$this->service = ($this->initializer)();
43+
if (\is_string($service = ($this->initializer)())) {
44+
$service = (new \ReflectionClass($service))->newInstanceWithoutConstructor();
45+
}
46+
$this->service = $service;
4447
unset($this->initializer);
4548
}
4649

4750
return $this->service;
4851
}
4952

50-
public static function getCode(string $initializer, array $callable, Definition $definition, ContainerBuilder $container, ?string $id): string
53+
public static function getCode(string $initializer, array $callable, string $class, ContainerBuilder $container, ?string $id): string
5154
{
5255
$method = $callable[1];
53-
$asClosure = 'Closure' === ($definition->getClass() ?: 'Closure');
5456

55-
if ($asClosure) {
57+
if ($asClosure = 'Closure' === $class) {
5658
$class = ($callable[0] instanceof Reference ? $container->findDefinition($callable[0]) : $callable[0])->getClass();
57-
} else {
58-
$class = $definition->getClass();
5959
}
6060

6161
$r = $container->getReflectionClass($class);

ContainerBuilder.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,14 +1109,15 @@ private function createService(Definition $definition, array &$inlineServices, b
11091109
}
11101110

11111111
if (\is_array($callable) && (
1112-
$callable[0] instanceof Reference
1112+
'Closure' !== $class
1113+
|| $callable[0] instanceof Reference
11131114
|| $callable[0] instanceof Definition && !isset($inlineServices[spl_object_hash($callable[0])])
11141115
)) {
11151116
$initializer = function () use ($callable, &$inlineServices) {
11161117
return $this->doResolveServices($callable[0], $inlineServices);
11171118
};
11181119

1119-
$proxy = eval('return '.LazyClosure::getCode('$initializer', $callable, $definition, $this, $id).';');
1120+
$proxy = eval('return '.LazyClosure::getCode('$initializer', $callable, $class, $this, $id).';');
11201121
$this->shareService($definition, $proxy, $id, $inlineServices);
11211122

11221123
return $proxy;

Dumper/PhpDumper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,13 +1184,13 @@ private function addNewInstance(Definition $definition, string $return = '', ?st
11841184
throw new RuntimeException(\sprintf('Cannot dump definition because of invalid factory method (%s).', $callable[1] ?: 'n/a'));
11851185
}
11861186

1187-
if (['...'] === $arguments && ($definition->isLazy() || 'Closure' !== ($definition->getClass() ?? 'Closure')) && (
1187+
if (['...'] === $arguments && ('Closure' !== ($class = $definition->getClass() ?: 'Closure') || $definition->isLazy() && (
11881188
$callable[0] instanceof Reference
11891189
|| ($callable[0] instanceof Definition && !$this->definitionVariables->contains($callable[0]))
1190-
)) {
1190+
))) {
11911191
$initializer = 'fn () => '.$this->dumpValue($callable[0]);
11921192

1193-
return $return.LazyClosure::getCode($initializer, $callable, $definition, $this->container, $id).$tail;
1193+
return $return.LazyClosure::getCode($initializer, $callable, $class, $this->container, $id).$tail;
11941194
}
11951195

11961196
if ($callable[0] instanceof Reference

Tests/Argument/LazyClosureTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ public function testThrowsWhenNotUsingInterface()
3333
$this->expectException(\RuntimeException::class);
3434
$this->expectExceptionMessage('Cannot create adapter for service "foo" because "Symfony\Component\DependencyInjection\Tests\Argument\LazyClosureTest" is not an interface.');
3535

36-
LazyClosure::getCode('foo', [new \stdClass(), 'bar'], new Definition(self::class), new ContainerBuilder(), 'foo');
36+
LazyClosure::getCode('foo', [new \stdClass(), 'bar'], self::class, new ContainerBuilder(), 'foo');
3737
}
3838

3939
public function testThrowsOnNonFunctionalInterface()
4040
{
4141
$this->expectException(\RuntimeException::class);
4242
$this->expectExceptionMessage('Cannot create adapter for service "foo" because interface "Symfony\Component\DependencyInjection\Tests\Argument\NonFunctionalInterface" doesn\'t have exactly one method.');
4343

44-
LazyClosure::getCode('foo', [new \stdClass(), 'bar'], new Definition(NonFunctionalInterface::class), new ContainerBuilder(), 'foo');
44+
LazyClosure::getCode('foo', [new \stdClass(), 'bar'], NonFunctionalInterface::class, new ContainerBuilder(), 'foo');
4545
}
4646

4747
public function testThrowsOnUnknownMethodInInterface()
4848
{
4949
$this->expectException(\RuntimeException::class);
5050
$this->expectExceptionMessage('Cannot create lazy closure for service "bar" because its corresponding callable is invalid.');
5151

52-
LazyClosure::getCode('bar', [new Definition(FunctionalInterface::class), 'bar'], new Definition(\Closure::class), new ContainerBuilder(), 'bar');
52+
LazyClosure::getCode('bar', [new Definition(FunctionalInterface::class), 'bar'], \Closure::class, new ContainerBuilder(), 'bar');
5353
}
5454
}
5555

Tests/ContainerBuilderTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
use Symfony\Component\DependencyInjection\Reference;
5151
use Symfony\Component\DependencyInjection\ServiceLocator;
5252
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
53+
use Symfony\Component\DependencyInjection\Tests\Compiler\MyCallable;
5354
use Symfony\Component\DependencyInjection\Tests\Compiler\SingleMethodInterface;
5455
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
5556
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
@@ -532,6 +533,19 @@ public function testClosureProxy()
532533
$this->assertInstanceOf(Foo::class, $container->get('closure_proxy')->theMethod());
533534
}
534535

536+
public function testClosureProxyWithStaticMethod()
537+
{
538+
$container = new ContainerBuilder();
539+
$container->register('closure_proxy', SingleMethodInterface::class)
540+
->setPublic('true')
541+
->setFactory(['Closure', 'fromCallable'])
542+
->setArguments([[MyCallable::class, 'theMethodImpl']]);
543+
$container->compile();
544+
545+
$this->assertInstanceOf(SingleMethodInterface::class, $container->get('closure_proxy'));
546+
$this->assertSame(124, $container->get('closure_proxy')->theMethod());
547+
}
548+
535549
public function testCreateServiceClass()
536550
{
537551
$builder = new ContainerBuilder();

Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,11 @@ class MyCallable
462462
public function __invoke(): void
463463
{
464464
}
465+
466+
public static function theMethodImpl(): int
467+
{
468+
return 124;
469+
}
465470
}
466471

467472
class MyInlineService

0 commit comments

Comments
 (0)