Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7eeb6bf

Browse filesBrowse files
committed
Merge branch '5.3' into 5.4
* 5.3: [DependencyInjection] fix support for "new" in initializers on PHP 8.1 add translation for zh_TW 41830 missing translations for serbian sr latn Changed some translations to be more in line with native Serbian language [HttpFoundation] Fix ianaCodesReasonPhrasesProvider to consume a local file Add armenian translation for #41835 Add swedish translation for #41835 Added missing danish translations and fixed typo in validators.da.xlf
2 parents b26e100 + d6220d2 commit 7eeb6bf
Copy full SHA for 7eeb6bf

19 files changed

+601
-42
lines changed

‎src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+47-8Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class AutowirePass extends AbstractRecursivePass
4040
private $decoratedClass;
4141
private $decoratedId;
4242
private $methodCalls;
43+
private $defaultArgument;
4344
private $getPreviousValue;
4445
private $decoratedMethodIndex;
4546
private $decoratedMethodArgumentIndex;
@@ -48,6 +49,10 @@ class AutowirePass extends AbstractRecursivePass
4849
public function __construct(bool $throwOnAutowireException = true)
4950
{
5051
$this->throwOnAutowiringException = $throwOnAutowireException;
52+
$this->defaultArgument = new class() {
53+
public $value;
54+
public $names;
55+
};
5156
}
5257

5358
/**
@@ -62,6 +67,7 @@ public function process(ContainerBuilder $container)
6267
$this->decoratedClass = null;
6368
$this->decoratedId = null;
6469
$this->methodCalls = null;
70+
$this->defaultArgument->names = null;
6571
$this->getPreviousValue = null;
6672
$this->decoratedMethodIndex = null;
6773
$this->decoratedMethodArgumentIndex = null;
@@ -159,8 +165,9 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
159165
$this->decoratedId = $decoratedDefinition[1] ?? $this->currentId.'.inner';
160166
}
161167

168+
$patchedIndexes = [];
169+
162170
foreach ($this->methodCalls as $i => $call) {
163-
$this->decoratedMethodIndex = $i;
164171
[$method, $arguments] = $call;
165172

166173
if ($method instanceof \ReflectionFunctionAbstract) {
@@ -177,13 +184,39 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
177184
}
178185
}
179186

180-
$arguments = $this->autowireMethod($reflectionMethod, $arguments, $checkAttributes);
187+
$arguments = $this->autowireMethod($reflectionMethod, $arguments, $checkAttributes, $i);
181188

182189
if ($arguments !== $call[1]) {
183190
$this->methodCalls[$i][1] = $arguments;
191+
$patchedIndexes[] = $i;
184192
}
185193
}
186194

195+
// use named arguments to skip complex default values
196+
foreach ($patchedIndexes as $i) {
197+
$namedArguments = null;
198+
$arguments = $this->methodCalls[$i][1];
199+
200+
foreach ($arguments as $j => $value) {
201+
if ($namedArguments && !$value instanceof $this->defaultArgument) {
202+
unset($arguments[$j]);
203+
$arguments[$namedArguments[$j]] = $value;
204+
}
205+
if ($namedArguments || !$value instanceof $this->defaultArgument) {
206+
continue;
207+
}
208+
209+
if (\PHP_VERSION_ID >= 80100 && (\is_array($value->value) ? $value->value : \is_object($value->value))) {
210+
unset($arguments[$j]);
211+
$namedArguments = $value->names;
212+
} else {
213+
$arguments[$j] = $value->value;
214+
}
215+
}
216+
217+
$this->methodCalls[$i][1] = $arguments;
218+
}
219+
187220
return $this->methodCalls;
188221
}
189222

@@ -194,16 +227,19 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
194227
*
195228
* @throws AutowiringFailedException
196229
*/
197-
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, bool $checkAttributes): array
230+
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, bool $checkAttributes, int $methodIndex): array
198231
{
199232
$class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
200233
$method = $reflectionMethod->name;
201234
$parameters = $reflectionMethod->getParameters();
202235
if ($reflectionMethod->isVariadic()) {
203236
array_pop($parameters);
204237
}
238+
$this->defaultArgument->names = new \ArrayObject();
205239

206240
foreach ($parameters as $index => $parameter) {
241+
$this->defaultArgument->names[$index] = $parameter->name;
242+
207243
if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
208244
continue;
209245
}
@@ -241,7 +277,8 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
241277
// be false when isOptional() returns true. If the
242278
// argument *is* optional, allow it to be missing
243279
if ($parameter->isOptional()) {
244-
continue;
280+
--$index;
281+
break;
245282
}
246283
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
247284
$type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint';
@@ -250,7 +287,8 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
250287
}
251288

252289
// specifically pass the default value
253-
$arguments[$index] = $parameter->getDefaultValue();
290+
$arguments[$index] = clone $this->defaultArgument;
291+
$arguments[$index]->value = $parameter->getDefaultValue();
254292

255293
continue;
256294
}
@@ -260,7 +298,8 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
260298
$failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
261299

262300
if ($parameter->isDefaultValueAvailable()) {
263-
$value = $parameter->getDefaultValue();
301+
$value = clone $this->defaultArgument;
302+
$value->value = $parameter->getDefaultValue();
264303
} elseif (!$parameter->allowsNull()) {
265304
throw new AutowiringFailedException($this->currentId, $failureMessage);
266305
}
@@ -281,6 +320,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
281320
} else {
282321
$arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass);
283322
$this->getPreviousValue = $getValue;
323+
$this->decoratedMethodIndex = $methodIndex;
284324
$this->decoratedMethodArgumentIndex = $index;
285325

286326
continue;
@@ -292,8 +332,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
292332

293333
if ($parameters && !isset($arguments[++$index])) {
294334
while (0 <= --$index) {
295-
$parameter = $parameters[$index];
296-
if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) {
335+
if (!$arguments[$index] instanceof $this->defaultArgument) {
297336
break;
298337
}
299338
unset($arguments[$index]);

‎src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ protected function processValue($value, bool $isRoot = false)
3939
}
4040

4141
$i = 0;
42+
$hasNamedArgs = false;
4243
foreach ($value->getArguments() as $k => $v) {
44+
if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
45+
$hasNamedArgs = true;
46+
continue;
47+
}
48+
4349
if ($k !== $i++) {
4450
if (!\is_int($k)) {
4551
$msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k);
@@ -57,11 +63,27 @@ protected function processValue($value, bool $isRoot = false)
5763
throw new RuntimeException($msg);
5864
}
5965
}
66+
67+
if ($hasNamedArgs) {
68+
$msg = sprintf('Invalid constructor argument for service "%s": cannot use positional argument after named argument. Check your service definition.', $this->currentId);
69+
$value->addError($msg);
70+
if ($this->throwExceptions) {
71+
throw new RuntimeException($msg);
72+
}
73+
74+
break;
75+
}
6076
}
6177

6278
foreach ($value->getMethodCalls() as $methodCall) {
6379
$i = 0;
80+
$hasNamedArgs = false;
6481
foreach ($methodCall[1] as $k => $v) {
82+
if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
83+
$hasNamedArgs = true;
84+
continue;
85+
}
86+
6587
if ($k !== $i++) {
6688
if (!\is_int($k)) {
6789
$msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k);
@@ -79,6 +101,16 @@ protected function processValue($value, bool $isRoot = false)
79101
throw new RuntimeException($msg);
80102
}
81103
}
104+
105+
if ($hasNamedArgs) {
106+
$msg = sprintf('Invalid argument for method call "%s" of service "%s": cannot use positional argument after named argument. Check your service definition.', $methodCall[0], $this->currentId);
107+
$value->addError($msg);
108+
if ($this->throwExceptions) {
109+
throw new RuntimeException($msg);
110+
}
111+
112+
break;
113+
}
82114
}
83115
}
84116

‎src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public function process(ContainerBuilder $container)
110110
protected function processValue($value, bool $isRoot = false)
111111
{
112112
if ($value instanceof ArgumentInterface) {
113-
// Reference found in ArgumentInterface::getValues() are not inlineable
113+
// References found in ArgumentInterface::getValues() are not inlineable
114114
return $value;
115115
}
116116

‎src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,8 @@ private function addServiceMethodCalls(Definition $definition, string $variableN
739739
$calls = '';
740740
foreach ($definition->getMethodCalls() as $k => $call) {
741741
$arguments = [];
742-
foreach ($call[1] as $value) {
743-
$arguments[] = $this->dumpValue($value);
742+
foreach ($call[1] as $i => $value) {
743+
$arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value);
744744
}
745745

746746
$witherAssignation = '';
@@ -1132,8 +1132,8 @@ private function addNewInstance(Definition $definition, string $return = '', str
11321132
}
11331133

11341134
$arguments = [];
1135-
foreach ($definition->getArguments() as $value) {
1136-
$arguments[] = $this->dumpValue($value);
1135+
foreach ($definition->getArguments() as $i => $value) {
1136+
$arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value);
11371137
}
11381138

11391139
if (null !== $definition->getFactory()) {

‎src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckArgumentsValidityPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckArgumentsValidityPassTest.php
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,22 @@ public function testProcess()
4646
*/
4747
public function testException(array $arguments, array $methodCalls)
4848
{
49-
$this->expectException(RuntimeException::class);
5049
$container = new ContainerBuilder();
5150
$definition = $container->register('foo');
5251
$definition->setArguments($arguments);
5352
$definition->setMethodCalls($methodCalls);
5453

5554
$pass = new CheckArgumentsValidityPass();
55+
$this->expectException(RuntimeException::class);
5656
$pass->process($container);
5757
}
5858

5959
public function definitionProvider()
6060
{
6161
return [
62-
[[null, 'a' => 'a'], []],
62+
[['a' => 'a', null], []],
6363
[[1 => 1], []],
64-
[[], [['baz', [null, 'a' => 'a']]]],
64+
[[], [['baz', ['a' => 'a', null]]]],
6565
[[], [['baz', [1 => 1]]]],
6666
];
6767
}
@@ -70,7 +70,7 @@ public function testNoException()
7070
{
7171
$container = new ContainerBuilder();
7272
$definition = $container->register('foo');
73-
$definition->setArguments([null, 'a' => 'a']);
73+
$definition->setArguments(['a' => 'a', null]);
7474

7575
$pass = new CheckArgumentsValidityPass(false);
7676
$pass->process($container);

‎src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
4646
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4747
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
48+
use Symfony\Component\DependencyInjection\Tests\Fixtures\NewInInitializer;
4849
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
4950
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
5051
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
@@ -1207,6 +1208,24 @@ public function testDumpHandlesObjectClassNames()
12071208
$this->assertInstanceOf(\stdClass::class, $container->get('bar'));
12081209
}
12091210

1211+
/**
1212+
* @requires PHP 8.1
1213+
*/
1214+
public function testNewInInitializer()
1215+
{
1216+
$container = new ContainerBuilder();
1217+
$container
1218+
->register('foo', NewInInitializer::class)
1219+
->setPublic(true)
1220+
->setAutowired(true)
1221+
->setArguments(['$bar' => 234]);
1222+
1223+
$container->compile();
1224+
1225+
$dumper = new PhpDumper($container);
1226+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_new_in_initializer.php', $dumper->dump());
1227+
}
1228+
12101229
/**
12111230
* @requires PHP 8.1
12121231
*/
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
class NewInInitializer
6+
{
7+
public function __construct($foo = new \stdClass(), $bar = 123)
8+
{
9+
}
10+
}
+59Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
7+
use Symfony\Component\DependencyInjection\Exception\LogicException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* This class has been auto-generated
14+
* by the Symfony Dependency Injection Component.
15+
*
16+
* @final
17+
*/
18+
class ProjectServiceContainer extends Container
19+
{
20+
private $parameters = [];
21+
22+
public function __construct()
23+
{
24+
$this->services = $this->privates = [];
25+
$this->methodMap = [
26+
'foo' => 'getFooService',
27+
];
28+
29+
$this->aliases = [];
30+
}
31+
32+
public function compile(): void
33+
{
34+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
35+
}
36+
37+
public function isCompiled(): bool
38+
{
39+
return true;
40+
}
41+
42+
public function getRemovedIds(): array
43+
{
44+
return [
45+
'Psr\\Container\\ContainerInterface' => true,
46+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
47+
];
48+
}
49+
50+
/**
51+
* Gets the public 'foo' shared autowired service.
52+
*
53+
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\NewInInitializer
54+
*/
55+
protected function getFooService()
56+
{
57+
return $this->services['foo'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\NewInInitializer(bar: 234);
58+
}
59+
}

‎src/Symfony/Component/HttpFoundation/Response.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Response.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class Response
138138
*
139139
* The list of codes is complete according to the
140140
* {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry}
141-
* (last updated 2016-03-01).
141+
* (last updated 2018-09-21).
142142
*
143143
* Unless otherwise noted, the status code is defined in RFC2616.
144144
*

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.