diff --git a/core/core.services.yml b/core/core.services.yml index 3243691b26a7a9b7ebcacfdc53538a32bd6097b9..7aaba677456e9a43d15939981e48a7af87daa986 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -60,6 +60,8 @@ parameters: queue.config: suspendMaximumWait: 30.0 services: + _defaults: + autoconfigure: true # Simple cache contexts, directly derived from the request context. cache_context.ip: class: Drupal\Core\Cache\Context\IpCacheContext @@ -292,8 +294,6 @@ services: arguments: [discovery] cache_router_rebuild_subscriber: class: Drupal\Core\EventSubscriber\CacheRouterRebuildSubscriber - tags: - - { name: event_subscriber } page_cache_request_policy: class: Drupal\Core\PageCache\DefaultRequestPolicy arguments: ['@session_configuration'] @@ -332,14 +332,11 @@ services: config.factory: class: Drupal\Core\Config\ConfigFactory tags: - - { name: event_subscriber } - { name: service_collector, tag: 'config.factory.override', call: addOverride } arguments: ['@config.storage', '@event_dispatcher', '@config.typed'] Drupal\Core\Config\ConfigFactoryInterface: '@config.factory' config.importer_subscriber: class: Drupal\Core\Config\Importer\FinalMissingContentSubscriber - tags: - - { name: event_subscriber } config.installer: class: Drupal\Core\Config\ConfigInstaller arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher', '%install_profile%', '@extension.path.resolver'] @@ -416,12 +413,8 @@ services: database.replica_kill_switch: class: Drupal\Core\Database\ReplicaKillSwitch arguments: ['@settings', '@datetime.time', '@session'] - tags: - - { name: event_subscriber } Drupal\Core\Database\ReplicaKillSwitch: '@database.replica_kill_switch' - Drupal\Core\Database\EventSubscriber\StatementExecutionSubscriber: - tags: - - { name: event_subscriber } + Drupal\Core\Database\EventSubscriber\StatementExecutionSubscriber: ~ datetime.time: class: Drupal\Component\Datetime\Time arguments: ['@request_stack'] @@ -692,8 +685,6 @@ services: entity_route_subscriber: class: Drupal\Core\EventSubscriber\EntityRouteProviderSubscriber arguments: ['@entity_type.manager'] - tags: - - { name: event_subscriber } entity.definition_update_manager: class: Drupal\Core\Entity\EntityDefinitionUpdateManager arguments: ['@entity_type.manager', '@entity.last_installed_schema.repository', '@entity_field.manager', '@entity_type.listener', '@field_storage_definition.listener'] @@ -721,8 +712,6 @@ services: entity.bundle_config_import_validator: class: Drupal\Core\Entity\Event\BundleConfigImportValidate arguments: ['@config.manager', '@entity_type.manager'] - tags: - - { name: event_subscriber } entity.autocomplete_matcher: class: Drupal\Core\Entity\EntityAutocompleteMatcher arguments: ['@plugin.manager.entity_reference_selection'] @@ -988,19 +977,14 @@ services: class: Drupal\Core\Routing\RouteProvider arguments: ['@database', '@state', '@path.current', '@cache.data', '@path_processor_manager', '@cache_tags.invalidator', 'router', '@language_manager'] tags: - - { name: event_subscriber } - { name: backend_overridable } Drupal\Core\Routing\RouteProviderInterface: '@router.route_provider' router.route_provider.lazy_builder: class: Drupal\Core\Routing\RouteProviderLazyBuilder arguments: ['@router.route_provider', '@router.builder'] - tags: - - { name: event_subscriber } router.route_preloader: class: Drupal\Core\Routing\RoutePreloader arguments: ['@router.route_provider', '@state', '@cache.bootstrap'] - tags: - - { name: 'event_subscriber' } url_generator.non_bubbling: class: Drupal\Core\Routing\UrlGenerator arguments: ['@router.route_provider', '@path_processor_manager', '@route_processor_manager', '@request_stack', '%filter_protocols%'] @@ -1043,13 +1027,9 @@ services: router.path_roots_subscriber: class: Drupal\Core\EventSubscriber\PathRootsSubscriber arguments: ['@state'] - tags: - - { name: event_subscriber } entity.query.config: class: Drupal\Core\Config\Entity\Query\QueryFactory arguments: ['@config.factory', '@keyvalue', '@config.manager'] - tags: - - { name: event_subscriber } entity.query.sql: class: Drupal\Core\Entity\Query\Sql\QueryFactory arguments: ['@database'] @@ -1080,8 +1060,6 @@ services: menu.rebuild_subscriber: class: Drupal\Core\EventSubscriber\MenuRouterRebuildSubscriber arguments: ['@lock', '@plugin.manager.menu.link', '@database', '@database.replica_kill_switch', '@logger.channel.menu'] - tags: - - { name: event_subscriber } path.matcher: class: Drupal\Core\Path\PathMatcher arguments: ['@config.factory', '@current_route_match'] @@ -1126,8 +1104,6 @@ services: Drupal\Core\ParamConverter\ParamConverterManagerInterface: '@paramconverter_manager' paramconverter_subscriber: class: Drupal\Core\EventSubscriber\ParamConverterSubscriber - tags: - - { name: event_subscriber } arguments: ['@paramconverter_manager'] paramconverter.entity: class: Drupal\Core\ParamConverter\EntityConverter @@ -1148,8 +1124,6 @@ services: lazy: true route_subscriber.module: class: Drupal\Core\EventSubscriber\ModuleRouteSubscriber - tags: - - { name: event_subscriber } arguments: ['@module_handler'] resolver_manager.entity: class: Drupal\Core\Entity\EntityResolverManager @@ -1157,25 +1131,18 @@ services: Drupal\Core\Entity\EntityResolverManager: '@resolver_manager.entity' route_subscriber.entity: class: Drupal\Core\EventSubscriber\EntityRouteAlterSubscriber - tags: - - { name: event_subscriber } arguments: ['@resolver_manager.entity'] ajax_response.subscriber: class: Drupal\Core\EventSubscriber\AjaxResponseSubscriber arguments: ['@ajax_response.attachments_processor'] - tags: - - { name: event_subscriber } form_ajax_subscriber: class: Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber arguments: ['@form_ajax_response_builder', '@string_translation', '@messenger'] - tags: - - { name: event_subscriber } route_enhancer.param_conversion: class: Drupal\Core\Routing\Enhancer\ParamConversionEnhancer arguments: ['@paramconverter_manager'] tags: - { name: route_enhancer, priority: 5000 } - - { name: event_subscriber } route_enhancer.form: class: Drupal\Core\Routing\Enhancer\FormRouteEnhancer tags: @@ -1195,28 +1162,18 @@ services: - { name: route_enhancer } route_special_attributes_subscriber: class: Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber - tags: - - { name: event_subscriber } route_http_method_subscriber: class: Drupal\Core\EventSubscriber\RouteMethodSubscriber - tags: - - { name: event_subscriber } psr_response_view_subscriber: class: Drupal\Core\EventSubscriber\PsrResponseSubscriber arguments: ['@psr7.http_foundation_factory'] - tags: - - { name: event_subscriber } # Main content view subscriber plus the renderers it uses. main_content_view_subscriber: class: Drupal\Core\EventSubscriber\MainContentViewSubscriber arguments: ['@class_resolver', '@current_route_match', '%main_content_renderers%'] - tags: - - { name: event_subscriber } renderer_non_html: class: Drupal\Core\EventSubscriber\RenderArrayNonHtmlSubscriber - tags: - - { name: event_subscriber } main_content_renderer.html: class: Drupal\Core\Render\MainContent\HtmlRenderer arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler', '@renderer', '@render_cache', '%renderer.config%', '@theme.manager'] @@ -1262,14 +1219,10 @@ services: Drupal\Core\Form\FormAjaxResponseBuilderInterface: '@form_ajax_response_builder' router_listener: class: Symfony\Component\HttpKernel\EventListener\RouterListener - tags: - - { name: event_subscriber } arguments: ['@router', '@request_stack', '@router.request_context', NULL] options_request_listener: class: Drupal\Core\EventSubscriber\OptionsRequestSubscriber arguments: ['@router.route_provider'] - tags: - - { name: event_subscriber } bare_html_page_renderer: class: Drupal\Core\Render\BareHtmlPageRenderer arguments: ['@renderer', '@html_response.attachments_processor'] @@ -1346,20 +1299,12 @@ services: maintenance_mode_subscriber: class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer', '@messenger', '@event_dispatcher'] - tags: - - { name: event_subscriber } route_access_response_subscriber: class: Drupal\Core\EventSubscriber\RouteAccessResponseSubscriber - tags: - - { name: event_subscriber } client_error_response_subscriber: class: Drupal\Core\EventSubscriber\ClientErrorResponseSubscriber - tags: - - { name: event_subscriber } anonymous_user_response_subscriber: class: Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber - tags: - - { name: event_subscriber } arguments: ['@current_user'] ajax_response.attachments_processor: class: Drupal\Core\Ajax\AjaxResponseAttachmentsProcessor @@ -1369,86 +1314,53 @@ services: arguments: ['@asset.resolver', '@config.factory', '@asset.css.collection_renderer', '@asset.js.collection_renderer', '@request_stack', '@renderer', '@module_handler', '@language_manager'] html_response.subscriber: class: Drupal\Core\EventSubscriber\HtmlResponseSubscriber - tags: - - { name: event_subscriber } arguments: ['@html_response.attachments_processor'] finish_response_subscriber: class: Drupal\Core\EventSubscriber\FinishResponseSubscriber - tags: - - { name: event_subscriber } arguments: ['@language_manager', '@config.factory', '@page_cache_request_policy', '@page_cache_response_policy', '@cache_contexts_manager', '%http.response.debug_cacheability_headers%'] response_generator_subscriber: class: Drupal\Core\EventSubscriber\ResponseGeneratorSubscriber - tags: - - { name: event_subscriber } redirect_response_subscriber: class: Drupal\Core\EventSubscriber\RedirectResponseSubscriber arguments: ['@unrouted_url_assembler', '@router.request_context'] - tags: - - { name: event_subscriber } redirect_leading_slashes_subscriber: class: Drupal\Core\EventSubscriber\RedirectLeadingSlashesSubscriber - tags: - - { name: event_subscriber } request_close_subscriber: class: Drupal\Core\EventSubscriber\RequestCloseSubscriber - tags: - - { name: event_subscriber } arguments: ['@module_handler'] config_import_subscriber: class: Drupal\Core\EventSubscriber\ConfigImportSubscriber tags: - - { name: event_subscriber } - { name: service_collector, tag: 'module_install.uninstall_validator', call: addUninstallValidator } arguments: ['@theme_handler', '@extension.list.module'] config_snapshot_subscriber: class: Drupal\Core\EventSubscriber\ConfigSnapshotSubscriber - tags: - - { name: event_subscriber } arguments: ['@config.manager', '@config.storage', '@config.storage.snapshot'] config_exclude_modules_subscriber: class: Drupal\Core\EventSubscriber\ExcludedModulesEventSubscriber arguments: ['@config.storage', '@settings', '@config.manager'] - tags: - - { name: event_subscriber } exception.needs_installer: class: Drupal\Core\EventSubscriber\ExceptionDetectNeedsInstallSubscriber arguments: ['@database'] - tags: - - { name: event_subscriber } exception.default_json: class: Drupal\Core\EventSubscriber\ExceptionJsonSubscriber - tags: - - { name: event_subscriber } exception.default_html: class: Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber - tags: - - { name: event_subscriber } arguments: ['@http_kernel', '@logger.channel.php', '@redirect.destination', '@router.no_access_checks'] exception.final: class: Drupal\Core\EventSubscriber\FinalExceptionSubscriber - tags: - - { name: event_subscriber } arguments: ['@config.factory'] exception.logger: class: Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber - tags: - - { name: event_subscriber } arguments: ['@logger.factory'] exception.custom_page_html: class: Drupal\Core\EventSubscriber\CustomPageExceptionHtmlSubscriber - tags: - - { name: event_subscriber } arguments: ['@config.factory', '@http_kernel', '@logger.channel.php', '@redirect.destination', '@router.no_access_checks', '@access_manager'] exception.fast_404_html: class: Drupal\Core\EventSubscriber\Fast404ExceptionHtmlSubscriber - tags: - - { name: event_subscriber } arguments: ['@config.factory', '@cache_tags.invalidator'] exception.enforced_form_response: class: Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber - tags: - - { name: event_subscriber } route_processor_manager: class: Drupal\Core\RouteProcessor\RouteProcessorManager tags: @@ -1521,8 +1433,6 @@ services: - { name: stream_wrapper, scheme: temporary } kernel_destruct_subscriber: class: Drupal\Core\EventSubscriber\KernelDestructionSubscriber - tags: - - { name: event_subscriber } calls: - [setContainer, ['@service_container']] image.toolkit.manager: @@ -1598,8 +1508,6 @@ services: authentication_subscriber: class: Drupal\Core\EventSubscriber\AuthenticationSubscriber arguments: ['@authentication', '@current_user'] - tags: - - { name: event_subscriber } account_switcher: class: Drupal\Core\Session\AccountSwitcher arguments: ['@current_user', '@session_handler.write_safe'] @@ -1797,13 +1705,9 @@ services: early_rendering_controller_wrapper_subscriber: class: Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber arguments: ['@http_kernel.controller.argument_resolver', '@renderer'] - tags: - - { name: event_subscriber } # Placeholder strategies for rendering placeholders. html_response.placeholder_strategy_subscriber: class: Drupal\Core\EventSubscriber\HtmlResponsePlaceholderStrategySubscriber - tags: - - { name: event_subscriber } arguments: ['@placeholder_strategy'] placeholder_strategy: class: Drupal\Core\Render\Placeholder\ChainedPlaceholderStrategy @@ -1827,8 +1731,6 @@ services: update.post_update_registry: class: Drupal\Core\Update\UpdateRegistry factory: ['@update.post_update_registry_factory', create] - tags: - - { name: event_subscriber } update.post_update_registry_factory: class: Drupal\Core\Update\UpdateRegistryFactory parent: container.trait @@ -1838,12 +1740,8 @@ services: response_filter.active_link: class: Drupal\Core\EventSubscriber\ActiveLinkResponseFilter arguments: ['@current_user', '@path.current', '@path.matcher', '@language_manager'] - tags: - - { name: event_subscriber } response_filter.rss.relative_url: class: Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter - tags: - - { name: event_subscriber } messenger: class: Drupal\Core\Messenger\Messenger arguments: ['@session.flash_bag', '@page_cache_kill_switch'] diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php index bd0db8db8103791d9677889a5bf740fb79b902ef..0db7124a4a57efa0c882a444a03012d47b8da4b2 100644 --- a/core/lib/Drupal/Core/CoreServiceProvider.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -27,6 +27,7 @@ use Drupal\Core\Render\MainContent\MainContentRenderersPass; use Drupal\Core\Site\Settings; use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ServiceProvider class for mandatory core services. @@ -97,6 +98,8 @@ public function register(ContainerBuilder $container) { $container->addCompilerPass(new DeprecatedServicePass()); + $container->registerForAutoconfiguration(EventSubscriberInterface::class) + ->addTag('event_subscriber'); } /** diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php index 36cd99d586db4a189dd2b30f3731bfb61d727610..a1b81d261e7ce587f789094293dcdf7e242eef95 100644 --- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php +++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php @@ -36,6 +36,7 @@ class YamlFileLoader 'public' => 'public', 'tags' => 'tags', 'autowire' => 'autowire', + 'autoconfigure' => 'autoconfigure', ]; /** @@ -254,6 +255,9 @@ private function parseDefinition(string $id, $service, string $file, array $defa if (isset($defaults['autowire'])) { $definition->setAutowired($defaults['autowire']); } + if (isset($defaults['autoconfigure'])) { + $definition->setAutoconfigured($defaults['autoconfigure']); + } $definition->setChanges([]); diff --git a/core/misc/cspell/dictionary.txt b/core/misc/cspell/dictionary.txt index 24deec2a21881425e2a58d3916868789634f3d58..70822a08a57074c5ee9f29935eae09f3f9620aea 100644 --- a/core/misc/cspell/dictionary.txt +++ b/core/misc/cspell/dictionary.txt @@ -56,6 +56,9 @@ autocompletefocus autocompletesearch autocompleteselect autocompleting +autoconfiguration +autoconfigure +autoconfigured autocreate autocreated autocreation diff --git a/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutoconfigurationTest.php b/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutoconfigurationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1c6b943750c895a49386b5199c20ae239fa8da15 --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutoconfigurationTest.php @@ -0,0 +1,39 @@ +<?php + +namespace Drupal\KernelTests\Core\DependencyInjection; + +use Drupal\Core\Serialization\Yaml; +use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests autoconfiguration of services. + * + * @group DependencyInjection + */ +class AutoconfigurationTest extends KernelTestBase { + + use FileSystemModuleDiscoveryDataProviderTrait; + + /** + * Tests that core services do not use tags if autoconfiguration is enabled. + */ + public function testCoreServiceTags(): void { + $filenames = array_map(fn($module) => "core/modules/{$module[0]}/{$module[0]}.services.yml", $this->coreModuleListDataProvider()); + $filenames[] = 'core/core.services.yml'; + foreach (array_filter($filenames, 'file_exists') as $filename) { + $services = Yaml::decode(file_get_contents($filename))['services']; + if (!empty($services['_defaults']['autoconfigure'])) { + foreach ($services as $id => $service) { + if (is_array($service) && isset($service['tags'])) { + foreach ($service['tags'] as $tag) { + $tag_name = is_string($tag) ? $tag : $tag['name']; + $this->assertNotEquals('event_subscriber', $tag_name, "Service '$id' in $filename should not be tagged with 'event_subscriber'."); + } + } + } + } + } + } + +} diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php index 54d996bd07b6813143d65fb5da4d832b93e17180..06e40a0e3c54cf590b9103fd9c750a0dfa5404fb 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php @@ -91,7 +91,7 @@ public function providerTestExceptions() { _defaults: invalid: string YAML, - 'The configuration key "invalid" cannot be used to define a default value in "vfs://drupal/modules/example/example.yml". Allowed keys are "public", "tags", "autowire".', + 'The configuration key "invalid" cannot be used to define a default value in "vfs://drupal/modules/example/example.yml". Allowed keys are "public", "tags", "autowire", "autoconfigure".', ], 'default tags must be an array' => [<<<YAML services: