Skip to content

Commit 98cec9b

Browse files
committed
Merge branch '5.1' into 5.2
* 5.1: Fix parameter order [DependencyInjection] Fix circular in DI with lazy + byContruct loop adjust Client::getProfile() typehint adjust KernelBrowser::getProfile() typehint fix: resolving pt translation issues Update VERSION for 3.4.47 Update CONTRIBUTORS for 3.4.47 Update CHANGELOG for 3.4.47 Add Romanian missing translations [DependencyInjection][Translator] Silent deprecation triggered by libxml_disable_entity_loader fix lexing strings containing escaped quotation characters prevent duplicated error message for file upload limits ignore the pattern attribute for textareas fix: solving pt-br translation issues
2 parents d7a2980 + 8b2ec9f commit 98cec9b

File tree

9 files changed

+283
-18
lines changed

9 files changed

+283
-18
lines changed

Compiler/AnalyzeServiceReferencesPass.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
15+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\ContainerInterface;
1718
use Symfony\Component\DependencyInjection\Definition;
@@ -35,6 +36,7 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass
3536
private $hasProxyDumper;
3637
private $lazy;
3738
private $byConstructor;
39+
private $byFactory;
3840
private $definitions;
3941
private $aliases;
4042

@@ -58,6 +60,7 @@ public function process(ContainerBuilder $container)
5860
$this->graph->clear();
5961
$this->lazy = false;
6062
$this->byConstructor = false;
63+
$this->byFactory = false;
6164
$this->definitions = $container->getDefinitions();
6265
$this->aliases = $container->getAliases();
6366

@@ -79,7 +82,7 @@ protected function processValue($value, bool $isRoot = false)
7982
$inExpression = $this->inExpression();
8083

8184
if ($value instanceof ArgumentInterface) {
82-
$this->lazy = true;
85+
$this->lazy = !$this->byFactory || !$value instanceof IteratorArgument;
8386
parent::processValue($value->getValues());
8487
$this->lazy = $lazy;
8588

@@ -129,7 +132,11 @@ protected function processValue($value, bool $isRoot = false)
129132

130133
$byConstructor = $this->byConstructor;
131134
$this->byConstructor = $isRoot || $byConstructor;
135+
136+
$byFactory = $this->byFactory;
137+
$this->byFactory = true;
132138
$this->processValue($value->getFactory());
139+
$this->byFactory = $byFactory;
133140
$this->processValue($value->getArguments());
134141

135142
$properties = $value->getProperties();

Dumper/PhpDumper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ private function collectCircularReferences(string $sourceId, array $edges, array
440440
foreach ($edges as $edge) {
441441
$node = $edge->getDestNode();
442442
$id = $node->getId();
443-
if (!($definition = $node->getValue()) instanceof Definition || $sourceId === $id || ($edge->isLazy() && ($this->proxyDumper ?? $this->getProxyDumper())->isProxyCandidate($definition)) || $edge->isWeak()) {
443+
if ($sourceId === $id || !$node->getValue() instanceof Definition || $edge->isLazy() || $edge->isWeak()) {
444444
continue;
445445
}
446446

Loader/XmlFileLoader.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,21 +624,50 @@ public function validateSchema(\DOMDocument $dom)
624624
EOF
625625
;
626626

627-
if (\LIBXML_VERSION < 20900) {
627+
if ($this->shouldEnableEntityLoader()) {
628628
$disableEntities = libxml_disable_entity_loader(false);
629629
$valid = @$dom->schemaValidateSource($source);
630630
libxml_disable_entity_loader($disableEntities);
631631
} else {
632632
$valid = @$dom->schemaValidateSource($source);
633633
}
634-
635634
foreach ($tmpfiles as $tmpfile) {
636635
@unlink($tmpfile);
637636
}
638637

639638
return $valid;
640639
}
641640

641+
private function shouldEnableEntityLoader(): bool
642+
{
643+
// Version prior to 8.0 can be enabled without deprecation
644+
if (\PHP_VERSION_ID < 80000) {
645+
return true;
646+
}
647+
648+
static $dom, $schema;
649+
if (null === $dom) {
650+
$dom = new \DOMDocument();
651+
$dom->loadXML('<?xml version="1.0"?><test/>');
652+
653+
$tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
654+
register_shutdown_function(static function () use ($tmpfile) {
655+
@unlink($tmpfile);
656+
});
657+
$schema = '<?xml version="1.0" encoding="utf-8"?>
658+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
659+
<xsd:include schemaLocation="file:///'.str_replace('\\', '/', $tmpfile).'" />
660+
</xsd:schema>';
661+
file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
662+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
663+
<xsd:element name="test" type="testType" />
664+
<xsd:complexType name="testType"/>
665+
</xsd:schema>');
666+
}
667+
668+
return !@$dom->schemaValidateSource($schema);
669+
}
670+
642671
private function validateAlias(\DOMElement $alias, string $file)
643672
{
644673
foreach ($alias->attributes as $name => $node) {

Tests/ContainerBuilderTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,12 +1395,18 @@ public function testAlmostCircular($visibility)
13951395
$container = include __DIR__.'/Fixtures/containers/container_almost_circular.php';
13961396
$container->compile();
13971397

1398+
$entityManager = $container->get('doctrine.entity_manager');
1399+
$this->assertEquals(new \stdClass(), $entityManager);
1400+
13981401
$pA = $container->get('pA');
13991402
$this->assertEquals(new \stdClass(), $pA);
14001403

14011404
$logger = $container->get('monolog.logger');
14021405
$this->assertEquals(new \stdClass(), $logger->handler);
14031406

1407+
$logger_inline = $container->get('monolog_inline.logger');
1408+
$this->assertEquals(new \stdClass(), $logger_inline->handler);
1409+
14041410
$foo = $container->get('foo');
14051411
$this->assertSame($foo, $foo->bar->foobar->foo);
14061412

Tests/Dumper/PhpDumperTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,12 +1054,18 @@ public function testAlmostCircular($visibility)
10541054

10551055
$container = new $container();
10561056

1057+
$entityManager = $container->get('doctrine.entity_manager');
1058+
$this->assertEquals(new \stdClass(), $entityManager);
1059+
10571060
$pA = $container->get('pA');
10581061
$this->assertEquals(new \stdClass(), $pA);
10591062

10601063
$logger = $container->get('monolog.logger');
10611064
$this->assertEquals(new \stdClass(), $logger->handler);
10621065

1066+
$logger_inline = $container->get('monolog_inline.logger');
1067+
$this->assertEquals(new \stdClass(), $logger_inline->handler);
1068+
10631069
$foo = $container->get('foo');
10641070
$this->assertSame($foo, $foo->bar->foobar->foo);
10651071

Tests/Fixtures/containers/container_almost_circular.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
34
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
45
use Symfony\Component\DependencyInjection\ContainerBuilder;
56
use Symfony\Component\DependencyInjection\Definition;
@@ -9,6 +10,20 @@
910
$public = 'public' === $visibility;
1011
$container = new ContainerBuilder();
1112

13+
// factory with lazy injection
14+
15+
$container->register('doctrine.config', 'stdClass')->setPublic(false)
16+
->setProperty('resolver', new Reference('doctrine.entity_listener_resolver'))
17+
->setProperty('flag', 'ok');
18+
19+
$container->register('doctrine.entity_manager', 'stdClass')->setPublic(true)
20+
->setFactory([FactoryChecker::class, 'create'])
21+
->addArgument(new Reference('doctrine.config'));
22+
$container->register('doctrine.entity_listener_resolver', 'stdClass')->setPublic($public)
23+
->addArgument(new IteratorArgument([new Reference('doctrine.listener')]));
24+
$container->register('doctrine.listener', 'stdClass')->setPublic($public)
25+
->addArgument(new Reference('doctrine.entity_manager'));
26+
1227
// multiple path detection
1328

1429
$container->register('pA', 'stdClass')->setPublic(true)
@@ -42,6 +57,27 @@
4257
$container->register('monolog.logger_2', 'stdClass')->setPublic($public)
4358
->setProperty('handler', new Reference('mailer.transport'));
4459

60+
// monolog-like + handler that require monolog with inlined factory
61+
62+
$container->register('monolog_inline.logger', 'stdClass')->setPublic(true)
63+
->setProperty('handler', new Reference('mailer_inline.mailer'));
64+
65+
$container->register('mailer_inline.mailer', 'stdClass')->setPublic(false)
66+
->addArgument(
67+
(new Definition('stdClass'))
68+
->setFactory([new Reference('mailer_inline.transport_factory'), 'create'])
69+
);
70+
71+
$container->register('mailer_inline.transport_factory', FactoryCircular::class)->setPublic($public)
72+
->addArgument(new TaggedIteratorArgument('mailer_inline.transport'));
73+
74+
$container->register('mailer_inline.transport_factory.amazon', 'stdClass')->setPublic($public)
75+
->addArgument(new Reference('monolog_inline.logger_2'))
76+
->addTag('mailer.transport');
77+
78+
$container->register('monolog_inline.logger_2', 'stdClass')->setPublic($public)
79+
->setProperty('handler', new Reference('mailer_inline.mailer'));
80+
4581
// same visibility for deps
4682

4783
$container->register('foo', FooCircular::class)->setPublic(true)

Tests/Fixtures/includes/classes.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ public function create()
128128
}
129129
}
130130

131+
class FactoryChecker
132+
{
133+
public static function create($config)
134+
{
135+
if (!isset($config->flag)) {
136+
throw new \LogicException('The injected config must contain a "flag" property.');
137+
}
138+
139+
return new stdClass();
140+
}
141+
}
142+
131143
class FoobarCircular
132144
{
133145
public function __construct(FooCircular $foo)

Tests/Fixtures/php/services_almost_circular_private.php

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function __construct()
2525
'baz6' => 'getBaz6Service',
2626
'connection' => 'getConnectionService',
2727
'connection2' => 'getConnection2Service',
28+
'doctrine.entity_manager' => 'getDoctrine_EntityManagerService',
2829
'foo' => 'getFooService',
2930
'foo2' => 'getFoo2Service',
3031
'foo5' => 'getFoo5Service',
@@ -37,6 +38,7 @@ public function __construct()
3738
'manager2' => 'getManager2Service',
3839
'manager3' => 'getManager3Service',
3940
'monolog.logger' => 'getMonolog_LoggerService',
41+
'monolog_inline.logger' => 'getMonologInline_LoggerService',
4042
'pA' => 'getPAService',
4143
'root' => 'getRootService',
4244
'subscriber' => 'getSubscriberService',
@@ -69,6 +71,9 @@ public function getRemovedIds(): array
6971
'connection4' => true,
7072
'dispatcher' => true,
7173
'dispatcher2' => true,
74+
'doctrine.config' => true,
75+
'doctrine.entity_listener_resolver' => true,
76+
'doctrine.listener' => true,
7277
'foo4' => true,
7378
'foobar' => true,
7479
'foobar2' => true,
@@ -82,8 +87,12 @@ public function getRemovedIds(): array
8287
'mailer.transport' => true,
8388
'mailer.transport_factory' => true,
8489
'mailer.transport_factory.amazon' => true,
90+
'mailer_inline.mailer' => true,
91+
'mailer_inline.transport_factory' => true,
92+
'mailer_inline.transport_factory.amazon' => true,
8593
'manager4' => true,
8694
'monolog.logger_2' => true,
95+
'monolog_inline.logger_2' => true,
8796
'multiuse1' => true,
8897
'pB' => true,
8998
'pC' => true,
@@ -182,6 +191,22 @@ protected function getConnection2Service()
182191
return $instance;
183192
}
184193

194+
/**
195+
* Gets the public 'doctrine.entity_manager' shared service.
196+
*
197+
* @return \stdClass
198+
*/
199+
protected function getDoctrine_EntityManagerService()
200+
{
201+
$a = new \stdClass();
202+
$a->resolver = new \stdClass(new RewindableGenerator(function () {
203+
yield 0 => ($this->privates['doctrine.listener'] ?? $this->getDoctrine_ListenerService());
204+
}, 1));
205+
$a->flag = 'ok';
206+
207+
return $this->services['doctrine.entity_manager'] = \FactoryChecker::create($a);
208+
}
209+
185210
/**
186211
* Gets the public 'foo' shared service.
187212
*
@@ -375,6 +400,20 @@ protected function getMonolog_LoggerService()
375400
return $instance;
376401
}
377402

403+
/**
404+
* Gets the public 'monolog_inline.logger' shared service.
405+
*
406+
* @return \stdClass
407+
*/
408+
protected function getMonologInline_LoggerService()
409+
{
410+
$this->services['monolog_inline.logger'] = $instance = new \stdClass();
411+
412+
$instance->handler = ($this->privates['mailer_inline.mailer'] ?? $this->getMailerInline_MailerService());
413+
414+
return $instance;
415+
}
416+
378417
/**
379418
* Gets the public 'pA' shared service.
380419
*
@@ -445,6 +484,16 @@ protected function getBar6Service()
445484
return $this->privates['bar6'] = new \stdClass($a);
446485
}
447486

487+
/**
488+
* Gets the private 'doctrine.listener' shared service.
489+
*
490+
* @return \stdClass
491+
*/
492+
protected function getDoctrine_ListenerService()
493+
{
494+
return $this->privates['doctrine.listener'] = new \stdClass(($this->services['doctrine.entity_manager'] ?? $this->getDoctrine_EntityManagerService()));
495+
}
496+
448497
/**
449498
* Gets the private 'level5' shared service.
450499
*
@@ -470,7 +519,8 @@ protected function getMailer_TransportService()
470519
{
471520
return $this->privates['mailer.transport'] = (new \FactoryCircular(new RewindableGenerator(function () {
472521
yield 0 => ($this->privates['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService());
473-
}, 1)))->create();
522+
yield 1 => $this->getMailerInline_TransportFactory_AmazonService();
523+
}, 2)))->create();
474524
}
475525

476526
/**
@@ -489,6 +539,31 @@ protected function getMailer_TransportFactory_AmazonService()
489539
return $instance;
490540
}
491541

542+
/**
543+
* Gets the private 'mailer_inline.mailer' shared service.
544+
*
545+
* @return \stdClass
546+
*/
547+
protected function getMailerInline_MailerService()
548+
{
549+
return $this->privates['mailer_inline.mailer'] = new \stdClass((new \FactoryCircular(new RewindableGenerator(function () {
550+
return new \EmptyIterator();
551+
}, 0)))->create());
552+
}
553+
554+
/**
555+
* Gets the private 'mailer_inline.transport_factory.amazon' shared service.
556+
*
557+
* @return \stdClass
558+
*/
559+
protected function getMailerInline_TransportFactory_AmazonService()
560+
{
561+
$a = new \stdClass();
562+
$a->handler = ($this->privates['mailer_inline.mailer'] ?? $this->getMailerInline_MailerService());
563+
564+
return new \stdClass($a);
565+
}
566+
492567
/**
493568
* Gets the private 'manager4' shared service.
494569
*

0 commit comments

Comments
 (0)