diff --git a/src/negative_test/drupal-services/drupal-services-autoconfigure.yml b/src/negative_test/drupal-services/drupal-services-autoconfigure.yml new file mode 100644 index 00000000000..294d5a9ac0f --- /dev/null +++ b/src/negative_test/drupal-services/drupal-services-autoconfigure.yml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=../../schemas/json/drupal-services.json +services: + #Defines a service with autoconfiguration but uses string. + Drupal\Test\Negative\WithAutoconfigure\String: + autoconfigure: 'ok' + + #Defines a service with autoconfiguration but uses integer. + Drupal\Test\Negative\WithAutoconfigure\Integer: + autoconfigure: 1 diff --git a/src/negative_test/drupal-services/drupal-services-autowire.yml b/src/negative_test/drupal-services/drupal-services-autowire.yml new file mode 100644 index 00000000000..a0415c98648 --- /dev/null +++ b/src/negative_test/drupal-services/drupal-services-autowire.yml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=../../schemas/json/drupal-services.json +services: + # Defines a service with autowiring but string instead of boolean. + test.negative.with.autowiring.string: + class: Drupal\Example\WithAutowiring + autowire: 'yes' + + # Defines a service with autowiring but string instead of boolean. + test.negative.with.autowiring.integer: + class: Drupal\Example\WithAutowiring + autowire: 1 diff --git a/src/negative_test/drupal-services/drupal-services-decoration.yml b/src/negative_test/drupal-services/drupal-services-decoration.yml new file mode 100644 index 00000000000..d9d284db0dd --- /dev/null +++ b/src/negative_test/drupal-services/drupal-services-decoration.yml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=../../schemas/json/drupal-services.json +services: + # Wrong type: decoration_priority must be an integer, not a string. + test.negative.decoration_priority_string: + class: Drupal\test\Invalid + decorates: test.decorated_service + decoration_priority: 'high' + arguments: [] + + # Invalid enum value: not one of exception/ignore/null. + test.negative.decoration_on_invalid_bad_value: + class: Drupal\test\Invalid + decorates: test.does_not_exist + decoration_on_invalid: maybe + arguments: [] + + # The exact pitfall from the null-quoting issue: an unquoted null + # becomes YAML's null type, not the schema's string enum member. + test.negative.decoration_on_invalid_unquoted_null: + class: Drupal\test\Invalid + decorates: test.does_not_exist + decoration_on_invalid: null + arguments: [] + + # Wrong type: decoration_inner_name must be a string, not a service + # reference array or object. + test.negative.decoration_inner_name_wrong_type: + class: Drupal\test\Invalid + decorates: test.decorated_service + decoration_inner_name: ['not', 'a', 'string'] + arguments: [] + + # Typo/misspelled key: additionalProperties is false on the service + # object, so this should be rejected outright. + test.negative.decoration_typo: + class: Drupal\test\Invalid + decorates: test.decorated_service + decoration_priorty: 5 + arguments: [] diff --git a/src/schemas/json/drupal-services.json b/src/schemas/json/drupal-services.json index 5d7925f4a2f..f9ccde4bc9e 100644 --- a/src/schemas/json/drupal-services.json +++ b/src/schemas/json/drupal-services.json @@ -44,6 +44,19 @@ "title": "Service name to decorate", "type": "string" }, + "decoration_priority": { + "title": "Priority of this decorator relative to others decorating the same service", + "type": "integer" + }, + "decoration_inner_name": { + "title": "Overrides the default '.inner' name for the decorated inner service", + "type": "string" + }, + "decoration_on_invalid": { + "title": "Behavior when the decorated service does not exist", + "type": "string", + "enum": ["exception", "ignore", "null"] + }, "deprecated": { "title": "A flag indicating that the service is deprecated", "type": "string" @@ -80,6 +93,14 @@ "type": "string" } }, + "autowire": { + "title": "Service dependencies can be autowired", + "type": "boolean" + }, + "autoconfigure": { + "title": "Service handler can be automatically configured", + "type": "boolean" + }, "tags": { "title": "List of tags tell Drupal that your service can be processed in some special way", "examples": [ diff --git a/src/test/drupal-services/drupal-services.yml b/src/test/drupal-services/drupal-services.yml index f0eba38dcb1..512baae5f15 100644 --- a/src/test/drupal-services/drupal-services.yml +++ b/src/test/drupal-services/drupal-services.yml @@ -12,5 +12,65 @@ services: # Defines an alias shortcut. Drupal\Example\WithModuleHandler: '@example.with_module_handler' + # Defines a service with autowiring. + example.with.autowiring: + class: Drupal\Example\WithAutowiring + autowire: true + + #Defines a service with autoconfiguration. + Drupal\Example\WithAutoconfigure: + autoconfigure: true + + # decoration_priority: controls stacking order when multiple decorators + # target the same service. Accepts any integer, including negative. + test.decorator.high_priority: + class: Drupal\test\HighPriorityDecorator + decorates: test.decorated_service + decoration_priority: 10 + arguments: ['@test.decorator.high_priority.inner'] + + test.decorator.negative_priority: + class: Drupal\test\NegativePriorityDecorator + decorates: test.decorated_service + decoration_priority: -5 + arguments: ['@test.decorator.negative_priority.inner'] + + # decoration_inner_name: overrides the default '.inner' name used + # to reference the decorated service. + test.decorator.custom_inner_name: + class: Drupal\test\CustomInnerNameDecorator + decorates: test.decorated_service + decoration_inner_name: test.decorator.custom_inner_name.original + arguments: ['@test.decorator.custom_inner_name.original'] + + # decoration_on_invalid: each of the three valid Symfony behaviors. + test.decorator.on_invalid_exception: + class: Drupal\test\OnInvalidExceptionDecorator + decorates: test.does_not_exist + decoration_on_invalid: exception + arguments: ['@test.decorator.on_invalid_exception.inner'] + + test.decorator.on_invalid_ignore: + class: Drupal\test\OnInvalidIgnoreDecorator + decorates: test.does_not_exist + decoration_on_invalid: ignore + arguments: ['@test.decorator.on_invalid_ignore.inner'] + + test.decorator.on_invalid_null: + class: Drupal\test\OnInvalidNullDecorator + decorates: test.does_not_exist + decoration_on_invalid: 'null' + arguments: ['@test.decorator.on_invalid_null.inner'] + + # Combined case: all four decoration options used together, as they + # might realistically appear in a single service definition. + test.decorator.full_combination: + class: Drupal\test\FullDecorator + decorates: test.decorated_service + decoration_priority: 5 + decoration_inner_name: test.decorator.full_combination.original + decoration_on_invalid: ignore + arguments: ['@test.decorator.full_combination.original'] + parameters: example.parameter: TRUE