diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php index 39c4a771f57607eab037b5e99f04fa28e24e394b..c16f7d75da22ae04fe52576890e89cc6791f2773 100644 --- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php +++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php @@ -390,10 +390,32 @@ private function parseDefinition(string $id, $service, string $file, array $defa $definition->addTag($name, $tag); } - if (isset($service['decorates'])) { + if (null !== $decorates = $service['decorates'] ?? null) { + if ('' !== $decorates && '@' === $decorates[0]) { + throw new InvalidArgumentException(\sprintf('The value of the "decorates" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['decorates'], substr($decorates, 1))); + } + + $decorationOnInvalid = \array_key_exists('decoration_on_invalid', $service) ? $service['decoration_on_invalid'] : 'exception'; + if ('exception' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + } + elseif ('ignore' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } + elseif (null === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + } + elseif ('null' === $decorationOnInvalid) { + throw new InvalidArgumentException(\sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean null (without quotes) in "%s"?', $decorationOnInvalid, $id, $file)); + } + else { + throw new InvalidArgumentException(\sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean "exception", "ignore" or null in "%s"?', $decorationOnInvalid, $id, $file)); + } + $renameId = $service['decoration_inner_name'] ?? null; $priority = $service['decoration_priority'] ?? 0; - $definition->setDecoratedService($service['decorates'], $renameId, $priority); + + $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); } if (isset($service['autowire'])) { diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php index b4ed2ca57c3a42375ff822b771fc0677e4998466..717026fe3f46b7df8427b4ca520cd84453f42d89 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php @@ -200,6 +200,38 @@ public static function providerTestExceptions() { YAML, 'The service file "vfs://drupal/modules/example/example.yml" is not valid: it contains invalid root key(s) "do not". Services have to be added under "services" and Parameters under "parameters".', ], + 'decorates must be without @' => [<<<YAML + services: + example_service_1: + class: \Drupal\Core\ExampleClass + example_decoration: + class: \Drupal\Core\ExampleClass + decorates: "@example_service_1" + YAML, + 'The value of the "decorates" option for the "example_decoration" service must be the id of the service without the "@" prefix (replace "@example_service_1" with "example_service_1").', + ], + 'decorates_on_invalid may not be "null" with quotes' => [<<<YAML + services: + example_service_1: + class: \Drupal\Core\ExampleClass + example_decoration: + class: \Drupal\Core\ExampleClass + decorates: example_service_1 + decoration_on_invalid: "null" + YAML, + 'Invalid value "null" for attribute "decoration_on_invalid" on service "example_decoration". Did you mean null (without quotes) in "vfs://drupal/modules/example/example.yml"?', + ], + 'decoration_on_invalid must be valid' => [<<<YAML + services: + example_service_1: + class: \Drupal\Core\ExampleClass + example_decoration: + class: \Drupal\Core\ExampleClass + decorates: example_service_1 + decoration_on_invalid: foo + YAML, + 'Invalid value "foo" for attribute "decoration_on_invalid" on service "example_decoration". Did you mean "exception", "ignore" or null in "vfs://drupal/modules/example/example.yml"?', + ], ]; }