8000 Merge branch '6.0' into 6.1 · symfony/symfony@123b165 · GitHub
[go: up one dir, main page]

Skip to content

Commit 123b165

Browse files
committed
Merge branch '6.0' into 6.1
2 parents 06c534c + 154637b commit 123b165

File tree

50 files changed

+1360
-287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1360
-287
lines changed

src/Symfony/Component/Config/Builder/ClassBuilder.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function build(): string
6565
}
6666
$require .= sprintf('require_once __DIR__.\DIRECTORY_SEPARATOR.\'%s\';', implode('\'.\DIRECTORY_SEPARATOR.\'', $path))."\n";
6767
}
68-
$use = '';
68+
$use = $require ? "\n" : '';
6969
foreach (array_keys($this->use) as $statement) {
7070
$use .= sprintf('use %s;', $statement)."\n";
7171
}
@@ -78,17 +78,15 @@ public function build(): string
7878
foreach ($this->methods as $method) {
7979
$lines = explode("\n", $method->getContent());
8080
foreach ($lines as $line) {
81-
$body .= ' '.$line."\n";
81+
$body .= ($line ? ' '.$line : '')."\n";
8282
}
8383
}
8484

8585
$content = strtr('<?php
8686
8787
namespace NAMESPACE;
8888
89-
REQUIRE
90-
USE
91-
89+
REQUIREUSE
9290
/**
9391
* This class is automatically generated to help in creating a config.
9492
*/

src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php

Lines changed: 138 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,49 @@ private function buildNode(NodeInterface $node, ClassBuilder $class, string $nam
130130

131131
private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $namespace): void
132132
{
133-
if ('' !== $comment = $this->getComment($node)) {
134-
$comment = "/**\n$comment*/\n";
135-
}
136-
137133
$childClass = new ClassBuilder($namespace, $node->getName());
138134
$childClass->setAllowExtraKeys($node->shouldIgnoreExtraKeys());
139135
$class->addRequire($childClass);
140136
$this->classes[] = $childClass;
141137

142-
$property = $class->addProperty($node->getName(), $childClass->getFqcn());
143-
$body = '
138+
$hasNormalizationClosures = $this->hasNormalizationClosures($node);
139+
$comment = $this->getComment($node);
140+
if ($hasNormalizationClosures) {
141+
$comment .= sprintf(' * @return %s|$this'."\n ", $childClass->getFqcn());
142+
}
143+
if ('' !== $comment) {
144+
$comment = "/**\n$comment*/\n";
145+
}
146+
147+
$property = $class->addProperty(
148+
$node->getName(),
149+
$this->getType($childClass->getFqcn(), $hasNormalizationClosures)
150+
);
151+
$body = $hasNormalizationClosures ? '
152+
COMMENTpublic function NAME(mixed $value = []): CLASS|static
153+
{
154+
if (!\is_array($value)) {
155+
$this->_usedProperties[\'PROPERTY\'] = true;
156+
$this->PROPERTY = $value;
157+
158+
return $this;
159+
}
160+
161+
if (!$this->PROPERTY instanceof CLASS) {
162+
$this->_usedProperties[\'PROPERTY\'] = true;
163+
$this->PROPERTY = new CLASS($value);
164+
} elseif (0 < \func_num_args()) {
165+
throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
166+
}
167+
168+
return $this->PROPERTY;
169+
}' : '
144170
COMMENTpublic function NAME(array $value = []): CLASS
145171
{
146172
if (null === $this->PROPERTY) {
147173
$this->_usedProperties[\'PROPERTY\'] = true;
148174
$this->PROPERTY = new CLASS($value);
149-
} elseif ([] !== $value) {
175+
} elseif (0 < \func_num_args()) {
150176
throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
151177
}
152178
@@ -176,14 +202,19 @@ public function NAME(mixed $valueDEFAULT): static
176202
177203
return $this;
178204
}';
179-
$class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'COMMENT' => $comment, 'DEFAULT' => $node->hasDefaultValue() ? ' = '.var_export($node->getDefaultValue(), true) : '']);
205+
$class->addMethod($node->getName(), $body, [
206+
'PROPERTY' => $property->getName(),
207+
'COMMENT' => $comment,
208+
'DEFAULT' => $node->hasDefaultValue() ? ' = '.var_export($node->getDefaultValue(), true) : '',
209+
]);
180210
}
181211

182212
private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuilder $class, string $namespace): void
183213
{
184214
$name = $this->getSingularName($node);
185215
$prototype = $node->getPrototype();
186216
$methodName = $name;
217+
$hasNormalizationClosures = $this->hasNormalizationClosures($node) || $this->hasNormalizationClosures($prototype);
187218

188219
$parameterType = $this->getParameterType($prototype);
189220
if (null !== $parameterType || $prototype instanceof ScalarNode) {
@@ -193,19 +224,23 @@ private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuild
193224
// This is an array of values; don't use singular name
194225
$body = '
195226
/**
196-
* @param ParamConfigurator|list<ParamConfigurator|TYPE> $value
227+
* @param PHPDOC_TYPE $value
197228
*
198229
* @return $this
199230
*/
200-
public function NAME(ParamConfigurator|array $value): static
231+
public function NAME(TYPE $value): static
201232
{
202233
$this->_usedProperties[\'PROPERTY\'] = true;
203234
$this->PROPERTY = $value;
204235
205236
return $this;
206237
}';
207238

208-
$class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'TYPE' => '' === $parameterType ? 'mixed' : $parameterType]);
239+
$class->addMethod($node->getName(), $body, [
240+
'PROPERTY' => $property->getName(),
241+
'TYPE' => $hasNormalizationClosures ? 'mixed' : 'ParamConfigurator|array',
242+
'PHPDOC_TYPE' => $hasNormalizationClosures ? 'mixed' : sprintf('ParamConfigurator|list<ParamConfigurator|%s>', '' === $parameterType ? 'mixed' : $parameterType),
243+
]);
209244
} else {
210245
$body = '
211246
/**
@@ -219,7 +254,12 @@ public function NAME(string $VAR, TYPE $VALUE): static
219254
return $this;
220255
}';
221256

222-
$class->addMethod($methodName, $body, ['PROPERTY' => $property->getName(), 'TYPE' => '' === $parameterType ? 'mixed' : 'ParamConfigurator|'.$parameterType, 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value']);
257+
$class->addMethod($methodName, $body, [
258+
'PROPERTY' => $property->getName(),
259+
'TYPE' => $hasNormalizationClosures || '' === $parameterType ? 'mixed' : 'ParamConfigurator|'.$parameterType,
260+
'VAR' => '' === $key ? 'key' : $key,
261+
'VALUE' => 'value' === $key ? 'data' : 'value',
262+
]);
223263
}
224264

225265
return;
@@ -231,14 +271,33 @@ public function NAME(string $VAR, TYPE $VALUE): static
231271
}
232272
$class->addRequire($childClass);
233273
$this->classes[] = $childClass;
234-
$property = $class->addProperty($node->getName(), $childClass->getFqcn().'[]');
235274

236-
if ('' !== $comment = $this->getComment($node)) {
275+
$property = $class->addProperty(
276+
$node->getName(),
277+
$this->getType($childClass->getFqcn().'[]', $hasNormalizationClosures)
278+
);
279+
280+
$comment = $this->getComment($node);
281+
if ($hasNormalizationClosures) {
282+
$comment .= sprintf(' * @return %s|$this'."\n ", $childClass->getFqcn());
283+
}
284+
if ('' !== $comment) {
237285
$comment = "/**\n$comment*/\n";
238286
}
239287

240288
if (null === $key = $node->getKeyAttribute()) {
241-
$body = '
289+
$body = $hasNormalizationClosures ? '
290+
COMMENTpublic function NAME(mixed $value = []): CLASS|static
291+
{
292+
$this->_usedProperties[\'PROPERTY\'] = true;
293+
if (!\is_array($value)) {
294+
$this->PROPERTY[] = $value;
295+
296+
return $this;
297+
}
298+
299+
return $this->PROPERTY[] = new CLASS($value);
300+
}' : '
242301
COMMENTpublic function NAME(array $value = []): CLASS
243302
{
244303
$this->_usedProperties[\'PROPERTY\'] = true;
@@ -247,22 +306,43 @@ public function NAME(string $VAR, TYPE $VALUE): static
247306
}';
248307
$class->addMethod($methodName, $body, ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn()]);
249308
} else {
250-
$body = '
251-
COMMENTpublic function NAME(string $VAR, array $VALUE = []): CLASS
309+
$body = $hasNormalizationClosures ? '
310+
COMMENTpublic function NAME(string $VAR, mixed $VALUE = []): CLASS|static
252311
{
253-
if (!isset($this->PROPERTY[$VAR])) {
312+
if (!\is_array($VALUE)) {
254313
$this->_usedProperties[\'PROPERTY\'] = true;
314+
$this->PROPERTY[$VAR] = $VALUE;
255315
256-
return $this->PROPERTY[$VAR] = new CLASS($VALUE);
316+
return $this;
257317
}
258-
if ([] === $VALUE) {
259-
return $this->PROPERTY[$VAR];
318+
319+
if (!isset($this->PROPERTY[$VAR]) || !$this->PROPERTY[$VAR] instanceof CLASS) {
320+
$this->_usedProperties[\'PROPERTY\'] = true;
321+
$this->PROPERTY[$VAR] = new CLASS($VALUE);
322+
} elseif (1 < \func_num_args()) {
323+
throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
260324
}
261325
262-
throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
326+
return $this->PROPERTY[$VAR];
327+
}' : '
328+
COMMENTpublic function NAME(string $VAR, array $VALUE = []): CLASS
329+
{
330+
if (!isset($this->PROPERTY[$VAR])) {
331+
$this->_usedProperties[\'PROPERTY\'] = true;
332+
$this->PROPERTY[$VAR] = new CLASS($VALUE);
333+
} elseif (1 < \func_num_args()) {
334+
throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\');
335+
}
336+
337+
return $this->PROPERTY[$VAR];
263338
}';
264339
$class->addUse(InvalidConfigurationException::class);
265-
$class->addMethod($methodName, $body, ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value']);
340+
$class->addMethod($methodName, $body, [
341+
'COMMENT' => $comment, 'PROPERTY' => $property->getName(),
342+
'CLASS' => $childClass->getFqcn(),
343+
'VAR' => '' === $key ? 'key' : $key,
344+
'VALUE' => 'value' === $key ? 'data' : 'value',
345+
]);
266346
}
267347

268348
$this->buildNode($prototype, $childClass, $namespace.'\\'.$childClass->getName());
@@ -393,16 +473,22 @@ private function buildToArray(ClassBuilder $class): void
393473
$code = '$this->PROPERTY';
394474
if (null !== $p->getType()) {
395475
if ($p->isArray()) {
396-
$code = 'array_map(function ($v) { return $v->toArray(); }, $this->PROPERTY)';
476+
$code = $p->areScalarsAllowed()
477+
? 'array_map(function ($v) { return $v instanceof CLASS ? $v->toArray() : $v; }, $this->PROPERTY)'
478+
: 'array_map(function ($v) { return $v->toArray(); }, $this->PROPERTY)'
479+
;
397480
} else {
398-
$code = '$this->PROPERTY->toArray()';
481+
$code = $p->areScalarsAllowed()
482+
? '$this->PROPERTY instanceof CLASS ? $this->PROPERTY->toArray() : $this->PROPERTY'
483+
: '$this->PROPERTY->toArray()'
484+
;
399485
}
400486
}
401487

402488
$body .= strtr('
403489
if (isset($this->_usedProperties[\'PROPERTY\'])) {
404490
$output[\'ORG_NAME\'] = '.$code.';
405-
}', ['PROPERTY' => $p->getName(), 'ORG_NAME' => $p->getOriginalName()]);
491+
}', ['PROPERTY' => $p->getName(), 'ORG_NAME' => $p->getOriginalName(), 'CLASS' => $p->getType()]);
406492
}
407493

408494
$extraKeys = $class->shouldAllowExtraKeys() ? ' + $this->_extraKeys' : '';
@@ -423,9 +509,15 @@ private function buildConstructor(ClassBuilder $class): void
423509
$code = '$value[\'ORG_NAME\']';
424510
if (null !== $p->getType()) {
425511
if ($p->isArray()) {
426-
$code = 'array_map(function ($v) { return new '.$p->getType().'($v); }, $value[\'ORG_NAME\'])';
512+
$code = $p->areScalarsAllowed()
513+
? 'array_map(function ($v) { return \is_array($v) ? new '.$p->getType().'($v) : $v; }, $value[\'ORG_NAME\'])'
514+
: 'array_map(function ($v) { return new '.$p->getType().'($v); }, $value[\'ORG_NAME\'])'
515+
;
427516
} else {
428-
$code = 'new '.$p->getType().'($value[\'ORG_NAME\'])';
517+
$code = $p->areScalarsAllowed()
518+
? '\is_array($value[\'ORG_NAME\']) ? new '.$p->getType().'($value[\'ORG_NAME\']) : $value[\'ORG_NAME\']'
519+
: 'new '.$p->getType().'($value[\'ORG_NAME\'])'
520+
;
429521
}
430522
}
431523

@@ -453,8 +545,7 @@ private function buildConstructor(ClassBuilder $class): void
453545

454546
$class->addMethod('__construct', '
455547
public function __construct(array $value = [])
456-
{
457-
'.$body.'
548+
{'.$body.'
458549
}');
459550
}
460551

@@ -486,4 +577,21 @@ private function getSubNamespace(ClassBuilder $rootClass): string
486577
{
487578
return sprintf('%s\\%s', $rootClass->getNamespace(), substr($rootClass->getName(), 0, -6));
488579
}
580+
581+
private function hasNormalizationClosures(NodeInterface $node): bool
582+
{
583+
try {
584+
$r = new \ReflectionProperty($node, '< 10000 span class=pl-s>normalizationClosures');
585+
} catch (\ReflectionException) {
586+
return false;
587+
}
588+
$r->setAccessible(true);
589+
590+
return [] !== $r->getValue($node);
591+
}
592+
593+
private function getType(string $classType, bool $hasNormalizationClosures): string
594+
{
595+
return $classType.($hasNormalizationClosures ? '|scalar' : '');
596+
}
489597
}

src/Symfony/Component/Config/Builder/Property.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Property
2323
private string $name;
2424
private string $originalName;
2525
private bool $array = false;
26+
private bool $scalarsAllowed = false;
2627
private ?string $type = null;
2728
private ?string $content = null;
2829

@@ -47,6 +48,11 @@ public function setType(string $type): void
4748
$this->array = false;
4849
$this->type = $type;
4950

51+
if (str_ends_with($type, '|scalar')) {
52+
$this->scalarsAllowed = true;
53+
$this->type = $type = substr($type, 0, -7);
54+
}
55+
5056
if (str_ends_with($type, '[]')) {
5157
$this->array = true;
5258
$this->type = substr($type, 0, -2);
@@ -72,4 +78,9 @@ public function isArray(): bool
7278
{
7379
return $this->array;
7480
}
81+
82+
public function areScalarsAllowed(): bool
83+
{
84+
return $this->scalarsAllowed;
85+
}
7586
}

src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList.config.php

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

3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
312
use Symfony\Config\AddToListConfig;
413

514
return static function (AddToListConfig $config) {

src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList.output.php

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

3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
312
return [
413
'translator' => [
514
'fallbacks' => ['sv', 'fr', 'es'],

src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList.php

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

3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
312
namespace Symfony\Component\Config\Tests\Builder\Fixtures;
413

514
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

0 commit comments

Comments
 (0)
0