Skip to content

Commit ae30d7c

Browse files
Merge branch '7.2' into 7.3
* 7.2: [DependencyInjection] Fix generating adapters of functional interfaces
2 parents ca0207c + ea3e4fb commit ae30d7c

File tree

6 files changed

+34
-14
lines changed

6 files changed

+34
-14
lines changed

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

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

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

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

src/Symfony/Component/DependencyInjection/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();

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