N°6934 - Symfony 6.4 - upgrade Symfony bundles to 6.4 (#580)

* Update Symfony lib to version ~6.4.0
* Update code missing return type
* Add an iTop general configuration entry to store application secret (Symfony mandatory parameter)
* Use dependency injection in ExceptionListener & UserProvider classes
This commit is contained in:
bdalsass
2023-12-05 13:56:56 +01:00
committed by GitHub
parent 863ab4560c
commit 27ce51ab07
1392 changed files with 44869 additions and 27799 deletions

View File

@@ -24,6 +24,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\Reference;
@@ -40,10 +41,7 @@ class XmlFileLoader extends FileLoader
protected $autoRegisterAliasesForSinglyImplementedInterfaces = false;
/**
* {@inheritdoc}
*/
public function load($resource, string $type = null)
public function load(mixed $resource, string $type = null): mixed
{
$path = $this->locator->locate($resource);
@@ -95,10 +93,7 @@ class XmlFileLoader extends FileLoader
}
}
/**
* {@inheritdoc}
*/
public function supports($resource, string $type = null)
public function supports(mixed $resource, string $type = null): bool
{
if (!\is_string($resource)) {
return false;
@@ -111,14 +106,14 @@ class XmlFileLoader extends FileLoader
return 'xml' === $type;
}
private function parseParameters(\DOMDocument $xml, string $file, \DOMNode $root = null)
private function parseParameters(\DOMDocument $xml, string $file, \DOMNode $root = null): void
{
if ($parameters = $this->getChildren($root ?? $xml->documentElement, 'parameters')) {
$this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file));
}
}
private function parseImports(\DOMDocument $xml, string $file, \DOMNode $root = null)
private function parseImports(\DOMDocument $xml, string $file, \DOMNode $root = null): void
{
$xpath = new \DOMXPath($xml);
$xpath->registerNamespace('container', self::NS);
@@ -134,7 +129,7 @@ class XmlFileLoader extends FileLoader
}
}
private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, \DOMNode $root = null)
private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, \DOMNode $root = null): void
{
$xpath = new \DOMXPath($xml);
$xpath->registerNamespace('container', self::NS);
@@ -184,7 +179,7 @@ class XmlFileLoader extends FileLoader
}
$excludes = [$service->getAttribute('exclude')];
}
$this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes);
$this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes, $file);
} else {
$this->setDefinition((string) $service->getAttribute('id'), $definition);
}
@@ -227,11 +222,11 @@ class XmlFileLoader extends FileLoader
$version = $deprecated[0]->getAttribute('version') ?: '';
if (!$deprecated[0]->hasAttribute('package')) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the node "deprecated" in "%s" is deprecated.', $file);
throw new InvalidArgumentException(sprintf('Missing attribute "package" at node "deprecated" in "%s".', $file));
}
if (!$deprecated[0]->hasAttribute('version')) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the node "deprecated" in "%s" is deprecated.', $file);
throw new InvalidArgumentException(sprintf('Missing attribute "version" at node "deprecated" in "%s".', $file));
}
$alias->setDeprecated($package, $version, $message);
@@ -258,7 +253,7 @@ class XmlFileLoader extends FileLoader
foreach (['class', 'public', 'shared', 'synthetic', 'abstract'] as $key) {
if ($value = $service->getAttribute($key)) {
$method = 'set'.$key;
$definition->$method($value = XmlUtils::phpize($value));
$definition->$method(XmlUtils::phpize($value));
}
}
@@ -286,12 +281,12 @@ class XmlFileLoader extends FileLoader
$package = $deprecated[0]->getAttribute('package') ?: '';
$version = $deprecated[0]->getAttribute('version') ?: '';
if ('' === $package) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the node "deprecated" in "%s" is deprecated.', $file);
if (!$deprecated[0]->hasAttribute('package')) {
throw new InvalidArgumentException(sprintf('Missing attribute "package" at node "deprecated" in "%s".', $file));
}
if ('' === $version) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the node "deprecated" in "%s" is deprecated.', $file);
if (!$deprecated[0]->hasAttribute('version')) {
throw new InvalidArgumentException(sprintf('Missing attribute "version" at node "deprecated" in "%s".', $file));
}
$definition->setDeprecated($package, $version, $message);
@@ -304,6 +299,11 @@ class XmlFileLoader extends FileLoader
$factory = $factories[0];
if ($function = $factory->getAttribute('function')) {
$definition->setFactory($function);
} elseif ($expression = $factory->getAttribute('expression')) {
if (!class_exists(Expression::class)) {
throw new \LogicException('The "expression" attribute cannot be used on factories without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
}
$definition->setFactory('@='.$expression);
} else {
if ($childService = $factory->getAttribute('service')) {
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
@@ -315,6 +315,14 @@ class XmlFileLoader extends FileLoader
}
}
if ($constructor = $service->getAttribute('constructor')) {
if (null !== $definition->getFactory()) {
throw new LogicException(sprintf('The "%s" service cannot declare a factory as well as a constructor.', $service->getAttribute('id')));
}
$definition->setFactory([null, $constructor]);
}
if ($configurators = $this->getChildren($service, 'configurator')) {
$configurator = $configurators[0];
if ($function = $configurator->getAttribute('function')) {
@@ -337,10 +345,14 @@ class XmlFileLoader extends FileLoader
$tags = $this->getChildren($service, 'tag');
foreach ($tags as $tag) {
$parameters = [];
$tagName = $tag->nodeValue;
$tagNameComesFromAttribute = $tag->childElementCount || '' === $tag->nodeValue;
if ('' === $tagName = $tagNameComesFromAttribute ? $tag->getAttribute('name') : $tag->nodeValue) {
throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', (string) $service->getAttribute('id'), $file));
}
$parameters = $this->getTagAttributes($tag, sprintf('The attribute name of tag "%s" for service "%s" in %s must be a non-empty string.', $tagName, (string) $service->getAttribute('id'), $file));
foreach ($tag->attributes as $name => $node) {
if ('name' === $name && '' === $tagName) {
if ($tagNameComesFromAttribute && 'name' === $name) {
continue;
}
@@ -351,10 +363,6 @@ class XmlFileLoader extends FileLoader
$parameters[$name] = XmlUtils::phpize($node->nodeValue);
}
if ('' === $tagName && '' === $tagName = $tag->getAttribute('name')) {
throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $service->getAttribute('id'), $file));
}
$definition->addTag($tagName, $parameters);
}
@@ -391,6 +399,52 @@ class XmlFileLoader extends FileLoader
$definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior);
}
if ($callable = $this->getChildren($service, 'from-callable')) {
if ($definition instanceof ChildDefinition) {
throw new InvalidArgumentException(sprintf('Attribute "parent" is unsupported when using "<from-callable>" on service "%s".', (string) $service->getAttribute('id')));
}
foreach ([
'Attribute "synthetic"' => 'isSynthetic',
'Attribute "file"' => 'getFile',
'Tag "<factory>"' => 'getFactory',
'Tag "<argument>"' => 'getArguments',
'Tag "<property>"' => 'getProperties',
'Tag "<configurator>"' => 'getConfigurator',
'Tag "<call>"' => 'getMethodCalls',
] as $key => $method) {
if ($definition->$method()) {
throw new InvalidArgumentException($key.sprintf(' is unsupported when using "<from-callable>" on service "%s".', (string) $service->getAttribute('id')));
}
}
$definition->setFactory(['Closure', 'fromCallable']);
if ('Closure' !== ($definition->getClass() ?? 'Closure')) {
$definition->setLazy(true);
} else {
$definition->setClass('Closure');
}
$callable = $callable[0];
if ($function = $callable->getAttribute('function')) {
$definition->setArguments([$function]);
} elseif ($expression = $callable->getAttribute('expression')) {
if (!class_exists(Expression::class)) {
throw new \LogicException('The "expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
}
$definition->setArguments(['@='.$expression]);
} else {
if ($childService = $callable->getAttribute('service')) {
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
} else {
$class = $callable->hasAttribute('class') ? $callable->getAttribute('class') : null;
}
$definition->setArguments([[$class, $callable->getAttribute('method') ?: '__invoke']]);
}
}
return $definition;
}
@@ -402,7 +456,7 @@ class XmlFileLoader extends FileLoader
private function parseFileToDOM(string $file): \DOMDocument
{
try {
$dom = XmlUtils::loadFile($file, [$this, 'validateSchema']);
$dom = XmlUtils::loadFile($file, $this->validateSchema(...));
} catch (\InvalidArgumentException $e) {
throw new InvalidArgumentException(sprintf('Unable to parse file "%s": ', $file).$e->getMessage(), $e->getCode(), $e);
}
@@ -415,7 +469,7 @@ class XmlFileLoader extends FileLoader
/**
* Processes anonymous services.
*/
private function processAnonymousServices(\DOMDocument $xml, string $file, \DOMNode $root = null)
private function processAnonymousServices(\DOMDocument $xml, string $file, \DOMNode $root = null): void
{
$definitions = [];
$count = 0;
@@ -480,6 +534,7 @@ class XmlFileLoader extends FileLoader
$key = $arg->getAttribute('key');
}
$trim = $arg->hasAttribute('trim') && XmlUtils::phpize($arg->getAttribute('trim'));
$onInvalid = $arg->getAttribute('on-invalid');
$invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
if ('ignore' == $onInvalid) {
@@ -490,7 +545,7 @@ class XmlFileLoader extends FileLoader
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
}
switch ($arg->getAttribute('type')) {
switch ($type = $arg->getAttribute('type')) {
case 'service':
if ('' === $arg->getAttribute('id')) {
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file));
@@ -510,38 +565,49 @@ class XmlFileLoader extends FileLoader
break;
case 'iterator':
$arg = $this->getArgumentsAsPhp($arg, $name, $file);
try {
$arguments[$key] = new IteratorArgument($arg);
} catch (InvalidArgumentException $e) {
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file));
}
$arguments[$key] = new IteratorArgument($arg);
break;
case 'closure':
case 'service_closure':
if ('' === $arg->getAttribute('id')) {
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_closure" has no or empty "id" attribute in "%s".', $name, $file));
if ('' !== $arg->getAttribute('id')) {
$arg = new Reference($arg->getAttribute('id'), $invalidBehavior);
} else {
$arg = $this->getArgumentsAsPhp($arg, $name, $file);
}
$arguments[$key] = new ServiceClosureArgument(new Reference($arg->getAttribute('id'), $invalidBehavior));
$arguments[$key] = match ($type) {
'service_closure' => new ServiceClosureArgument($arg),
'closure' => (new Definition('Closure'))
->setFactory(['Closure', 'fromCallable'])
->addArgument($arg),
};
break;
case 'service_locator':
$arg = $this->getArgumentsAsPhp($arg, $name, $file);
try {
$arguments[$key] = new ServiceLocatorArgument($arg);
} catch (InvalidArgumentException $e) {
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_locator" only accepts maps of type="service" references in "%s".', $name, $file));
if (isset($arg[0])) {
trigger_deprecation('symfony/dependency-injection', '6.3', 'Skipping "key" argument or using integers as values in a "service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.');
}
$arguments[$key] = new ServiceLocatorArgument($arg);
break;
case 'tagged':
case 'tagged_iterator':
case 'tagged_locator':
$type = $arg->getAttribute('type');
$forLocator = 'tagged_locator' === $type;
if (!$arg->getAttribute('tag')) {
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file));
}
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null);
$excludes = array_column($this->getChildren($arg, 'exclude'), 'nodeValue');
if ($arg->hasAttribute('exclude')) {
if (\count($excludes) > 0) {
throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
}
$excludes = [$arg->getAttribute('exclude')];
}
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null, $excludes, !$arg->hasAttribute('exclude-self') || XmlUtils::phpize($arg->getAttribute('exclude-self')));
if ($forLocator) {
$arguments[$key] = new ServiceLocatorArgument($arguments[$key]);
@@ -557,13 +623,13 @@ class XmlFileLoader extends FileLoader
$arguments[$key] = new AbstractArgument($arg->nodeValue);
break;
case 'string':
$arguments[$key] = $arg->nodeValue;
$arguments[$key] = $trim ? trim($arg->nodeValue) : $arg->nodeValue;
break;
case 'constant':
$arguments[$key] = \constant(trim($arg->nodeValue));
break;
default:
$arguments[$key] = XmlUtils::phpize($arg->nodeValue);
$arguments[$key] = XmlUtils::phpize($trim ? trim($arg->nodeValue) : $arg->nodeValue);
}
}
@@ -587,14 +653,36 @@ class XmlFileLoader extends FileLoader
return $children;
}
private function getTagAttributes(\DOMNode $node, string $missingName): array
{
$parameters = [];
$children = $this->getChildren($node, 'attribute');
foreach ($children as $childNode) {
if ('' === $name = $childNode->getAttribute('name')) {
throw new InvalidArgumentException($missingName);
}
if ($this->getChildren($childNode, 'attribute')) {
$parameters[$name] = $this->getTagAttributes($childNode, $missingName);
} else {
if (str_contains($name, '-') && !str_contains($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
$parameters[$normalizedName] = XmlUtils::phpize($childNode->nodeValue);
}
// keep not normalized key
$parameters[$name] = XmlUtils::phpize($childNode->nodeValue);
}
}
return $parameters;
}
/**
* Validates a documents XML schema.
*
* @return bool
*
* @throws RuntimeException When extension references a non-existent XSD file
*/
public function validateSchema(\DOMDocument $dom)
public function validateSchema(\DOMDocument $dom): bool
{
$schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')];
@@ -671,11 +759,6 @@ EOF
private function shouldEnableEntityLoader(): bool
{
// Version prior to 8.0 can be enabled without deprecation
if (\PHP_VERSION_ID < 80000) {
return true;
}
static $dom, $schema;
if (null === $dom) {
$dom = new \DOMDocument();
@@ -699,7 +782,7 @@ EOF
return !@$dom->schemaValidateSource($schema);
}
private function validateAlias(\DOMElement $alias, string $file)
private function validateAlias(\DOMElement $alias, string $file): void
{
foreach ($alias->attributes as $name => $node) {
if (!\in_array($name, ['alias', 'id', 'public'])) {
@@ -711,7 +794,7 @@ EOF
if (!$child instanceof \DOMElement || self::NS !== $child->namespaceURI) {
continue;
}
if (!\in_array($child->localName, ['deprecated'], true)) {
if ('deprecated' !== $child->localName) {
throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file));
}
}
@@ -722,7 +805,7 @@ EOF
*
* @throws InvalidArgumentException When no extension is found corresponding to a tag
*/
private function validateExtensions(\DOMDocument $dom, string $file)
private function validateExtensions(\DOMDocument $dom, string $file): void
{
foreach ($dom->documentElement->childNodes as $node) {
if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) {
@@ -731,7 +814,7 @@ EOF
// can it be handled by an extension?
if (!$this->container->hasExtension($node->namespaceURI)) {
$extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getNamespace(); }, $this->container->getExtensions()));
$extensionNamespaces = array_filter(array_map(fn (ExtensionInterface $ext) => $ext->getNamespace(), $this->container->getExtensions()));
throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? implode('", "', $extensionNamespaces) : 'none'));
}
}
@@ -740,7 +823,7 @@ EOF
/**
* Loads from an extension.
*/
private function loadFromExtensions(\DOMDocument $xml)
private function loadFromExtensions(\DOMDocument $xml): void
{
foreach ($xml->documentElement->childNodes as $node) {
if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) {
@@ -772,10 +855,8 @@ EOF
* * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
*
* @param \DOMElement $element A \DOMElement instance
*
* @return mixed
*/
public static function convertDomElementToArray(\DOMElement $element)
public static function convertDomElementToArray(\DOMElement $element): mixed
{
return XmlUtils::convertDomElementToArray($element);
}