diff --git a/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php b/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php index d43d814ebd38b..d666e74f4bb07 100644 --- a/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php +++ b/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php @@ -14,7 +14,6 @@ use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\BaseNode; use Symfony\Component\Config\Definition\BooleanNode; -use Symfony\Component\Config\Definition\Builder\ExprBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; @@ -127,24 +126,18 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n $class->addRequire($childClass); $this->classes[] = $childClass; - $hasNormalizationClosures = $this->hasNormalizationClosures($node); $comment = $this->getComment($node); - if ($hasNormalizationClosures) { - $comment = sprintf(" * @template TValue\n * @param TValue \$value\n%s", $comment); - $comment .= sprintf(' * @return %s|$this'."\n", $childClass->getFqcn()); - $comment .= sprintf(' * @psalm-return (TValue is array ? %s : static)'."\n ", $childClass->getFqcn()); - } - if ('' !== $comment) { - $comment = "/**\n$comment*/\n"; - } + $comment = sprintf(" * @template TValue\n * @param TValue \$value\n%s", $comment); + $comment .= sprintf(' * @return %s|$this'."\n", $childClass->getFqcn()); + $comment .= sprintf(' * @psalm-return (TValue is array ? %s : static)'."\n ", $childClass->getFqcn()); + $comment = "/**\n$comment*/\n"; $property = $class->addProperty( $node->getName(), - $this->getType($childClass->getFqcn(), $hasNormalizationClosures) + $childClass->getFqcn().'|scalar' ); - $nodeTypes = $this->getParameterTypes($node); - $body = $hasNormalizationClosures ? ' -COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static + $body = ' +COMMENTpublic function NAME(mixed $value = []): CLASS|static { if (!\is_array($value)) { $this->_usedProperties[\'PROPERTY\'] = true; @@ -160,26 +153,10 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); } - return $this->PROPERTY; -}' : ' -COMMENTpublic function NAME(array $value = []): CLASS -{ - if (null === $this->PROPERTY) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = new CLASS($value); - } elseif (0 < \func_num_args()) { - throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); - } - return $this->PROPERTY; }'; $class->addUse(InvalidConfigurationException::class); - $class->addMethod($node->getName(), $body, [ - 'COMMENT' => $comment, - 'PROPERTY' => $property->getName(), - 'CLASS' => $childClass->getFqcn(), - 'PARAM_TYPE' => \in_array('mixed', $nodeTypes, true) ? 'mixed' : implode('|', $nodeTypes), - ]); + $class->addMethod($node->getName(), $body, ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn()]); $this->buildNode($node, $childClass, $this->getSubNamespace($childClass)); } @@ -216,21 +193,19 @@ private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuild $methodName = $name; $hasNormalizationClosures = $this->hasNormalizationClosures($node) || $this->hasNormalizationClosures($prototype); - $nodeParameterTypes = $this->getParameterTypes($node); - $prototypeParameterTypes = $this->getParameterTypes($prototype); - if (!$prototype instanceof ArrayNode || ($prototype instanceof PrototypedArrayNode && $prototype->getPrototype() instanceof ScalarNode)) { + $parameterType = $this->getParameterType($prototype); + if (null !== $parameterType || $prototype instanceof ScalarNode) { $class->addUse(ParamConfigurator::class); $property = $class->addProperty($node->getName()); if (null === $key = $node->getKeyAttribute()) { // This is an array of values; don't use singular name - $nodeTypesWithoutArray = array_filter($nodeParameterTypes, static fn ($type) => 'array' !== $type); $body = ' /** - * @param ParamConfigurator|listEXTRA_TYPE $value + * @param PHPDOC_TYPE $value * * @return $this */ -public function NAME(PARAM_TYPE $value): static +public function NAME(TYPE $value): static { $this->_usedProperties[\'PROPERTY\'] = true; $this->PROPERTY = $value; @@ -240,9 +215,8 @@ public function NAME(PARAM_TYPE $value): static $class->addMethod($node->getName(), $body, [ 'PROPERTY' => $property->getName(), - 'PROTOTYPE_TYPE' => implode('|', $prototypeParameterTypes), - 'EXTRA_TYPE' => $nodeTypesWithoutArray ? '|'.implode('|', $nodeTypesWithoutArray) : '', - 'PARAM_TYPE' => \in_array('mixed', $nodeParameterTypes, true) ? 'mixed' : 'ParamConfigurator|'.implode('|', $nodeParameterTypes), + 'TYPE' => $hasNormalizationClosures ? 'mixed' : 'ParamConfigurator|array', + 'PHPDOC_TYPE' => $hasNormalizationClosures ? 'mixed' : sprintf('ParamConfigurator|list', '' === $parameterType ? 'mixed' : $parameterType), ]); } else { $body = ' @@ -259,7 +233,7 @@ public function NAME(string $VAR, TYPE $VALUE): static $class->addMethod($methodName, $body, [ 'PROPERTY' => $property->getName(), - 'TYPE' => \in_array('mixed', $prototypeParameterTypes, true) ? 'mixed' : 'ParamConfigurator|'.implode('|', $prototypeParameterTypes), + 'TYPE' => 'mixed', 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value', ]); @@ -277,22 +251,18 @@ public function NAME(string $VAR, TYPE $VALUE): static $property = $class->addProperty( $node->getName(), - $this->getType($childClass->getFqcn().'[]', $hasNormalizationClosures) + $childClass->getFqcn().'[]|scalar' ); $comment = $this->getComment($node); - if ($hasNormalizationClosures) { - $comment = sprintf(" * @template TValue\n * @param TValue \$value\n%s", $comment); - $comment .= sprintf(' * @return %s|$this'."\n", $childClass->getFqcn()); - $comment .= sprintf(' * @psalm-return (TValue is array ? %s : static)'."\n ", $childClass->getFqcn()); - } - if ('' !== $comment) { - $comment = "/**\n$comment*/\n"; - } + $comment = sprintf(" * @template TValue\n * @param TValue \$value\n%s", $comment); + $comment .= sprintf(' * @return %s|$this'."\n", $childClass->getFqcn()); + $comment .= sprintf(' * @psalm-return (TValue is array ? %s : static)'."\n ", $childClass->getFqcn()); + $comment = "/**\n$comment*/\n"; if (null === $key = $node->getKeyAttribute()) { - $body = $hasNormalizationClosures ? ' -COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static + $body = ' +COMMENTpublic function NAME(mixed $value = []): CLASS|static { $this->_usedProperties[\'PROPERTY\'] = true; if (!\is_array($value)) { @@ -301,23 +271,12 @@ public function NAME(string $VAR, TYPE $VALUE): static return $this; } - return $this->PROPERTY[] = new CLASS($value); -}' : ' -COMMENTpublic function NAME(array $value = []): CLASS -{ - $this->_usedProperties[\'PROPERTY\'] = true; - return $this->PROPERTY[] = new CLASS($value); }'; - $class->addMethod($methodName, $body, [ - 'COMMENT' => $comment, - 'PROPERTY' => $property->getName(), - 'CLASS' => $childClass->getFqcn(), - 'PARAM_TYPE' => \in_array('mixed', $nodeParameterTypes, true) ? 'mixed' : implode('|', $nodeParameterTypes), - ]); + $class->addMethod($methodName, $body, ['COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn()]); } else { - $body = $hasNormalizationClosures ? ' -COMMENTpublic function NAME(string $VAR, PARAM_TYPE $VALUE = []): CLASS|static + $body = ' +COMMENTpublic function NAME(string $VAR, mixed $VALUE = []): CLASS|static { if (!\is_array($VALUE)) { $this->_usedProperties[\'PROPERTY\'] = true; @@ -333,17 +292,6 @@ public function NAME(string $VAR, TYPE $VALUE): static throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); } - return $this->PROPERTY[$VAR]; -}' : ' -COMMENTpublic function NAME(string $VAR, array $VALUE = []): CLASS -{ - if (!isset($this->PROPERTY[$VAR])) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY[$VAR] = new CLASS($VALUE); - } elseif (1 < \func_num_args()) { - throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); - } - return $this->PROPERTY[$VAR]; }'; $class->addUse(InvalidConfigurationException::class); @@ -352,7 +300,6 @@ public function NAME(string $VAR, TYPE $VALUE): static 'CLASS' => $childClass->getFqcn(), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value', - 'PARAM_TYPE' => \in_array('mixed', $prototypeParameterTypes, true) ? 'mixed' : implode('|', $prototypeParameterTypes), ]); } @@ -380,33 +327,35 @@ public function NAME($value): static $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'COMMENT' => $comment]); } - private function getParameterTypes(NodeInterface $node): array + private function getParameterType(NodeInterface $node): ?string { - $paramTypes = []; - if ($node instanceof BaseNode) { - $types = $node->getNormalizedTypes(); - if (\in_array(ExprBuilder::TYPE_ANY, $types, true)) { - $paramTypes[] = 'mixed'; - } - if (\in_array(ExprBuilder::TYPE_STRING, $types, true)) { - $paramTypes[] = 'string'; - } - } if ($node instanceof BooleanNode) { - $paramTypes[] = 'bool'; - } elseif ($node instanceof IntegerNode) { - $paramTypes[] = 'int'; - } elseif ($node instanceof FloatNode) { - $paramTypes[] = 'float'; - } elseif ($node instanceof EnumNode) { - $paramTypes[] = 'mixed'; - } elseif ($node instanceof ArrayNode) { - $paramTypes[] = 'array'; - } elseif ($node instanceof VariableNode) { - $paramTypes[] = 'mixed'; + return 'bool'; + } + + if ($node instanceof IntegerNode) { + return 'int'; } - return array_unique($paramTypes); + if ($node instanceof FloatNode) { + return 'float'; + } + + if ($node instanceof EnumNode) { + return ''; + } + + if ($node instanceof PrototypedArrayNode && $node->getPrototype() instanceof ScalarNode) { + // This is just an array of variables + return 'array'; + } + + if ($node instanceof VariableNode) { + // mixed + return ''; + } + + return null; } private function getComment(BaseNode $node): string @@ -428,8 +377,11 @@ private function getComment(BaseNode $node): string if ($node instanceof EnumNode) { $comment .= sprintf(' * @param ParamConfigurator|%s $value', implode('|', array_unique(array_map(fn ($a) => !$a instanceof \UnitEnum ? var_export($a, true) : '\\'.ltrim(var_export($a, true), '\\'), $node->getValues()))))."\n"; } else { - $parameterTypes = $this->getParameterTypes($node); - $comment .= ' * @param ParamConfigurator|'.implode('|', $parameterTypes).' $value'."\n"; + $parameterType = $this->getParameterType($node); + if (null === $parameterType || '' === $parameterType) { + $parameterType = 'mixed'; + } + $comment .= ' * @param ParamConfigurator|'.$parameterType.' $value'."\n"; } } else { foreach ((array) ($node->getExample() ?? []) as $example) { @@ -592,9 +544,4 @@ private function hasNormalizationClosures(NodeInterface $node): bool return [] !== $r->getValue($node); } - - private function getType(string $classType, bool $hasNormalizationClosures): string - { - return $classType.($hasNormalizationClosures ? '|scalar' : ''); - } } diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index 85f0f7eebd30b..e34cde2fbe762 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -32,7 +32,6 @@ abstract class BaseNode implements NodeInterface protected $name; protected $parent; protected $normalizationClosures = []; - protected $normalizedTypes = []; protected $finalValidationClosures = []; protected $allowOverwrite = true; protected $required = false; @@ -236,28 +235,6 @@ public function setNormalizationClosures(array $closures) $this->normalizationClosures = $closures; } - /** - * Sets the list of types supported by normalization. - * - * see ExprBuilder::TYPE_* constants. - * - * @return void - */ - public function setNormalizedTypes(array $types) - { - $this->normalizedTypes = $types; - } - - /** - * Gets the list of types supported by normalization. - * - * see ExprBuilder::TYPE_* constants. - */ - public function getNormalizedTypes(): array - { - return $this->normalizedTypes; - } - /** * Sets the closures used for final validation. * diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index 3ada5c5503405..ba3f4e729f6a7 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -374,7 +374,7 @@ protected function createNode(): NodeInterface if ($this->default) { if (!\is_array($this->defaultValue)) { - throw new \InvalidArgumentException(sprintf('%s: the default value of an array node has to be an array.', $node->getPath())); + throw new \InvalidArgumentException(sprintf('"%s": the default value of an array node has to be an array.', $node->getPath())); } $node->setDefaultValue($this->defaultValue); @@ -406,7 +406,6 @@ protected function createNode(): NodeInterface if (isset($this->normalization)) { $node->setNormalizationClosures($this->normalization->before); - $node->setNormalizedTypes($this->normalization->declaredTypes); $node->setXmlRemappings($this->normalization->remappings); } diff --git a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php index 9cb44148121e6..38ae79be72b19 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php @@ -21,14 +21,7 @@ */ class ExprBuilder { - public const TYPE_ANY = 'any'; - public const TYPE_STRING = 'string'; - public const TYPE_NULL = 'null'; - public const TYPE_ARRAY = 'array'; - protected $node; - - public $allowedTypes; public $ifPart; public $thenPart; @@ -45,7 +38,6 @@ public function __construct(NodeDefinition $node) public function always(\Closure $then = null): static { $this->ifPart = static fn () => true; - $this->allowedTypes = self::TYPE_ANY; if (null !== $then) { $this->thenPart = $then; @@ -64,7 +56,6 @@ public function always(\Closure $then = null): static public function ifTrue(\Closure $closure = null): static { $this->ifPart = $closure ?? static fn ($v) => true === $v; - $this->allowedTypes = self::TYPE_ANY; return $this; } @@ -77,7 +68,6 @@ public function ifTrue(\Closure $closure = null): static public function ifString(): static { $this->ifPart = \is_string(...); - $this->allowedTypes = self::TYPE_STRING; return $this; } @@ -90,7 +80,6 @@ public function ifString(): static public function ifNull(): static { $this->ifPart = \is_null(...); - $this->allowedTypes = self::TYPE_NULL; return $this; } @@ -103,7 +92,6 @@ public function ifNull(): static public function ifEmpty(): static { $this->ifPart = static fn ($v) => empty($v); - $this->allowedTypes = self::TYPE_ANY; return $this; } @@ -116,7 +104,6 @@ public function ifEmpty(): static public function ifArray(): static { $this->ifPart = \is_array(...); - $this->allowedTypes = self::TYPE_ARRAY; return $this; } @@ -129,7 +116,6 @@ public function ifArray(): static public function ifInArray(array $array): static { $this->ifPart = static fn ($v) => \in_array($v, $array, true); - $this->allowedTypes = self::TYPE_ANY; return $this; } @@ -142,7 +128,6 @@ public function ifInArray(array $array): static public function ifNotInArray(array $array): static { $this->ifPart = static fn ($v) => !\in_array($v, $array, true); - $this->allowedTypes = self::TYPE_ANY; return $this; } @@ -155,7 +140,6 @@ public function ifNotInArray(array $array): static public function castToArray(): static { $this->ifPart = static fn ($v) => !\is_array($v); - $this->allowedTypes = self::TYPE_ANY; $this->thenPart = static fn ($v) => [$v]; return $this; diff --git a/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php index 0e362d9fa3c90..59f92ffc6864b 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php @@ -20,7 +20,6 @@ class NormalizationBuilder { protected $node; public $before = []; - public $declaredTypes = []; public $remappings = []; public function __construct(NodeDefinition $node) diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php index 00622f162ad0e..aa975b859ef06 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php @@ -42,12 +42,23 @@ public function source(string $source_class, mixed $value): static } /** + * @template TValue + * @param TValue $value * looks for translation in old fashion way * @deprecated The child node "books" at path "translator" is deprecated. - */ - public function books(array $value = []): \Symfony\Config\AddToList\Translator\BooksConfig + * @return \Symfony\Config\AddToList\Translator\BooksConfig|$this + * @psalm-return (TValue is array ? \Symfony\Config\AddToList\Translator\BooksConfig : static) + */ + public function books(mixed $value = []): \Symfony\Config\AddToList\Translator\BooksConfig|static { - if (null === $this->books) { + if (!\is_array($value)) { + $this->_usedProperties['books'] = true; + $this->books = $value; + + return $this; + } + + if (!$this->books instanceof \Symfony\Config\AddToList\Translator\BooksConfig) { $this->_usedProperties['books'] = true; $this->books = new \Symfony\Config\AddToList\Translator\BooksConfig($value); } elseif (0 < \func_num_args()) { @@ -73,7 +84,7 @@ public function __construct(array $value = []) if (array_key_exists('books', $value)) { $this->_usedProperties['books'] = true; - $this->books = new \Symfony\Config\AddToList\Translator\BooksConfig($value['books']); + $this->books = \is_array($value['books']) ? new \Symfony\Config\AddToList\Translator\BooksConfig($value['books']) : $value['books']; unset($value['books']); } @@ -92,7 +103,7 @@ public function toArray(): array $output['sources'] = $this->sources; } if (isset($this->_usedProperties['books'])) { - $output['books'] = $this->books->toArray(); + $output['books'] = $this->books instanceof \Symfony\Config\AddToList\Translator\BooksConfig ? $this->books->toArray() : $this->books; } return $output; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php index a8b0adb28b5f2..d5a247343058a 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php @@ -16,9 +16,22 @@ class AddToListConfig implements \Symfony\Component\Config\Builder\ConfigBuilder private $messenger; private $_usedProperties = []; - public function translator(array $value = []): \Symfony\Config\AddToList\TranslatorConfig + /** + * @template TValue + * @param TValue $value + * @return \Symfony\Config\AddToList\TranslatorConfig|$this + * @psalm-return (TValue is array ? \Symfony\Config\AddToList\TranslatorConfig : static) + */ + public function translator(mixed $value = []): \Symfony\Config\AddToList\TranslatorConfig|static { - if (null === $this->translator) { + if (!\is_array($value)) { + $this->_usedProperties['translator'] = true; + $this->translator = $value; + + return $this; + } + + if (!$this->translator instanceof \Symfony\Config\AddToList\TranslatorConfig) { $this->_usedProperties['translator'] = true; $this->translator = new \Symfony\Config\AddToList\TranslatorConfig($value); } elseif (0 < \func_num_args()) { @@ -28,9 +41,22 @@ public function translator(array $value = []): \Symfony\Config\AddToList\Transla return $this->translator; } - public function messenger(array $value = []): \Symfony\Config\AddToList\MessengerConfig + /** + * @template TValue + * @param TValue $value + * @return \Symfony\Config\AddToList\MessengerConfig|$this + * @psalm-return (TValue is array ? \Symfony\Config\AddToList\MessengerConfig : static) + */ + public function messenger(mixed $value = []): \Symfony\Config\AddToList\MessengerConfig|static { - if (null === $this->messenger) { + if (!\is_array($value)) { + $this->_usedProperties['messenger'] = true; + $this->messenger = $value; + + return $this; + } + + if (!$this->messenger instanceof \Symfony\Config\AddToList\MessengerConfig) { $this->_usedProperties['messenger'] = true; $this->messenger = new \Symfony\Config\AddToList\MessengerConfig($value); } elseif (0 < \func_num_args()) { @@ -49,13 +75,13 @@ public function __construct(array $value = []) { if (array_key_exists('translator', $value)) { $this->_usedProperties['translator'] = true; - $this->translator = new \Symfony\Config\AddToList\TranslatorConfig($value['translator']); + $this->translator = \is_array($value['translator']) ? new \Symfony\Config\AddToList\TranslatorConfig($value['translator']) : $value['translator']; unset($value['translator']); } if (array_key_exists('messenger', $value)) { $this->_usedProperties['messenger'] = true; - $this->messenger = new \Symfony\Config\AddToList\MessengerConfig($value['messenger']); + $this->messenger = \is_array($value['messenger']) ? new \Symfony\Config\AddToList\MessengerConfig($value['messenger']) : $value['messenger']; unset($value['messenger']); } @@ -68,10 +94,10 @@ public function toArray(): array { $output = []; if (isset($this->_usedProperties['translator'])) { - $output['translator'] = $this->translator->toArray(); + $output['translator'] = $this->translator instanceof \Symfony\Config\AddToList\TranslatorConfig ? $this->translator->toArray() : $this->translator; } if (isset($this->_usedProperties['messenger'])) { - $output['messenger'] = $this->messenger->toArray(); + $output['messenger'] = $this->messenger instanceof \Symfony\Config\AddToList\MessengerConfig ? $this->messenger->toArray() : $this->messenger; } return $output; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php index d019ecf81bb76..9ef9909ba206b 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php @@ -16,9 +16,22 @@ class NodeInitialValuesConfig implements \Symfony\Component\Config\Builder\Confi private $messenger; private $_usedProperties = []; - public function someCleverName(array $value = []): \Symfony\Config\NodeInitialValues\SomeCleverNameConfig + /** + * @template TValue + * @param TValue $value + * @return \Symfony\Config\NodeInitialValues\SomeCleverNameConfig|$this + * @psalm-return (TValue is array ? \Symfony\Config\NodeInitialValues\SomeCleverNameConfig : static) + */ + public function someCleverName(mixed $value = []): \Symfony\Config\NodeInitialValues\SomeCleverNameConfig|static { - if (null === $this->someCleverName) { + if (!\is_array($value)) { + $this->_usedProperties['someCleverName'] = true; + $this->someCleverName = $value; + + return $this; + } + + if (!$this->someCleverName instanceof \Symfony\Config\NodeInitialValues\SomeCleverNameConfig) { $this->_usedProperties['someCleverName'] = true; $this->someCleverName = new \Symfony\Config\NodeInitialValues\SomeCleverNameConfig($value); } elseif (0 < \func_num_args()) { @@ -28,9 +41,22 @@ public function someCleverName(array $value = []): \Symfony\Config\NodeInitialVa return $this->someCleverName; } - public function messenger(array $value = []): \Symfony\Config\NodeInitialValues\MessengerConfig + /** + * @template TValue + * @param TValue $value + * @return \Symfony\Config\NodeInitialValues\MessengerConfig|$this + * @psalm-return (TValue is array ? \Symfony\Config\NodeInitialValues\MessengerConfig : static) + */ + public function messenger(mixed $value = []): \Symfony\Config\NodeInitialValues\MessengerConfig|static { - if (null === $this->messenger) { + if (!\is_array($value)) { + $this->_usedProperties['messenger'] = true; + $this->messenger = $value; + + return $this; + } + + if (!$this->messenger instanceof \Symfony\Config\NodeInitialValues\MessengerConfig) { $this->_usedProperties['messenger'] = true; $this->messenger = new \Symfony\Config\NodeInitialValues\MessengerConfig($value); } elseif (0 < \func_num_args()) { @@ -49,13 +75,13 @@ public function __construct(array $value = []) { if (array_key_exists('some_clever_name', $value)) { $this->_usedProperties['someCleverName'] = true; - $this->someCleverName = new \Symfony\Config\NodeInitialValues\SomeCleverNameConfig($value['some_clever_name']); + $this->someCleverName = \is_array($value['some_clever_name']) ? new \Symfony\Config\NodeInitialValues\SomeCleverNameConfig($value['some_clever_name']) : $value['some_clever_name']; unset($value['some_clever_name']); } if (array_key_exists('messenger', $value)) { $this->_usedProperties['messenger'] = true; - $this->messenger = new \Symfony\Config\NodeInitialValues\MessengerConfig($value['messenger']); + $this->messenger = \is_array($value['messenger']) ? new \Symfony\Config\NodeInitialValues\MessengerConfig($value['messenger']) : $value['messenger']; unset($value['messenger']); } @@ -68,10 +94,10 @@ public function toArray(): array { $output = []; if (isset($this->_usedProperties['someCleverName'])) { - $output['some_clever_name'] = $this->someCleverName->toArray(); + $output['some_clever_name'] = $this->someCleverName instanceof \Symfony\Config\NodeInitialValues\SomeCleverNameConfig ? $this->someCleverName->toArray() : $this->someCleverName; } if (isset($this->_usedProperties['messenger'])) { - $output['messenger'] = $this->messenger->toArray(); + $output['messenger'] = $this->messenger instanceof \Symfony\Config\NodeInitialValues\MessengerConfig ? $this->messenger->toArray() : $this->messenger; } return $output; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php index 1794ede72e18c..b2e0854b6b97c 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php @@ -24,11 +24,11 @@ class ScalarNormalizedTypesConfig implements \Symfony\Component\Config\Builder\C private $_usedProperties = []; /** - * @param ParamConfigurator|list|string $value + * @param mixed $value * * @return $this */ - public function simpleArray(ParamConfigurator|string|array $value): static + public function simpleArray(mixed $value): static { $this->_usedProperties['simpleArray'] = true; $this->simpleArray = $value; @@ -39,7 +39,7 @@ public function simpleArray(ParamConfigurator|string|array $value): static /** * @return $this */ - public function keyedArray(string $name, ParamConfigurator|string|array $value): static + public function keyedArray(string $name, mixed $value): static { $this->_usedProperties['keyedArray'] = true; $this->keyedArray[$name] = $value; @@ -116,9 +116,22 @@ public function keyedListObject(string $class, mixed $value = []): \Symfony\Conf return $this->keyedListObject[$class]; } - public function nested(array $value = []): \Symfony\Config\ScalarNormalizedTypes\NestedConfig + /** + * @template TValue + * @param TValue $value + * @return \Symfony\Config\ScalarNormalizedTypes\NestedConfig|$this + * @psalm-return (TValue is array ? \Symfony\Config\ScalarNormalizedTypes\NestedConfig : static) + */ + public function nested(mixed $value = []): \Symfony\Config\ScalarNormalizedTypes\NestedConfig|static { - if (null === $this->nested) { + if (!\is_array($value)) { + $this->_usedProperties['nested'] = true; + $this->nested = $value; + + return $this; + } + + if (!$this->nested instanceof \Symfony\Config\ScalarNormalizedTypes\NestedConfig) { $this->_usedProperties['nested'] = true; $this->nested = new \Symfony\Config\ScalarNormalizedTypes\NestedConfig($value); } elseif (0 < \func_num_args()) { @@ -167,7 +180,7 @@ public function __construct(array $value = []) if (array_key_exists('nested', $value)) { $this->_usedProperties['nested'] = true; - $this->nested = new \Symfony\Config\ScalarNormalizedTypes\NestedConfig($value['nested']); + $this->nested = \is_array($value['nested']) ? new \Symfony\Config\ScalarNormalizedTypes\NestedConfig($value['nested']) : $value['nested']; unset($value['nested']); } @@ -195,7 +208,7 @@ public function toArray(): array $output['keyed_list_object'] = array_map(fn ($v) => $v instanceof \Symfony\Config\ScalarNormalizedTypes\KeyedListObjectConfig ? $v->toArray() : $v, $this->keyedListObject); } if (isset($this->_usedProperties['nested'])) { - $output['nested'] = $this->nested->toArray(); + $output['nested'] = $this->nested instanceof \Symfony\Config\ScalarNormalizedTypes\NestedConfig ? $this->nested->toArray() : $this->nested; } return $output;