diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php index 77ac5cfdcec7ec3d3fd67709610495e26fe25416..b370d8639adc20ac1b40a4c725ced95ab3f1752e 100644 --- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php +++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php @@ -476,8 +476,8 @@ private function validate($content, $file) throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file)); } - if ($invalid_keys = array_keys(array_diff_key($content, ['parameters' => 1, 'services' => 1]))) { - throw new InvalidArgumentException(sprintf('The service file "%s" is not valid: it contains invalid root key(s) "%s". Services have to be added under "services" and Parameters under "parameters".', $file, implode('", "', $invalid_keys))); + if ($invalid_keys = array_keys(array_diff_key($content, ['parameters' => 1, 'services' => 1, 'service_providers' => 1]))) { + throw new InvalidArgumentException(sprintf('The service file "%s" is not valid: it contains invalid root key(s) "%s". Services have to be added under "services", Parameters under "parameters", and service providers under "service_providers".', $file, implode('", "', $invalid_keys))); } return $content; diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index b475adb53fddedf8cbf1a3a03cedc9d3c7230b77..d684893b5d1b29b9606605c510ac08ec64a32bb4 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -23,6 +23,7 @@ use Drupal\Core\Installer\InstallerRedirectTrait; use Drupal\Core\Language\Language; use Drupal\Core\Security\RequestSanitizer; +use Drupal\Core\Serialization\Yaml; use Drupal\Core\Site\Settings; use Drupal\Core\Test\TestDatabase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -619,6 +620,7 @@ public function discoverServiceProviders() { $this->serviceProviderClasses['app']['core'] = 'Drupal\Core\CoreServiceProvider'; // Retrieve enabled modules and register their namespaces. + $file_cache = FileCacheFactory::get('container_yaml_loader'); if (!isset($this->moduleList)) { $extensions = $this->getConfigStorage()->read('core.extension'); // If core.extension configuration does not exist and we're not in the @@ -640,7 +642,7 @@ public function discoverServiceProviders() { $module_filenames = $this->getModuleFileNames(); $this->classLoaderAddMultiplePsr4($this->getModuleNamespacesPsr4($module_filenames)); - // Load each module's serviceProvider class. + // Load each module's service provider classes. foreach ($module_filenames as $module => $filename) { $camelized = ContainerBuilder::camelize($module); $name = "{$camelized}ServiceProvider"; @@ -648,9 +650,30 @@ public function discoverServiceProviders() { if (class_exists($class)) { $this->serviceProviderClasses['app'][$module] = $class; } + $filename = dirname($filename) . "/$module.services.yml"; if (is_file($filename)) { $this->serviceYamls['app'][$module] = $filename; + + // Load service providers from the $module.services.yml file. + if (!$content = $file_cache->get($filename)) { + $content = Yaml::decode(file_get_contents($filename)); + } + if (is_array($content) && isset($content['service_providers']) && is_array($content['service_providers'])) { + foreach ($content['service_providers'] as $index => $service_provider_class) { + $service_provider_class = trim($service_provider_class, '\\'); + $this->serviceProviderClasses['app']["$module:$index"] = $service_provider_class; + if ($service_provider_class === $class) { + // The deprecated implicit class name (*ServiceProvider) is listed + // explicitly under 'service_providers', in $module.services.yml. + unset($this->serviceProviderClasses['app'][$module]); + } + } + } + } + + if (!empty($this->serviceProviderClasses['app'][$module])) { + @trigger_error("Using implicit service providers is deprecated in drupal:11.2.0 and will be removed in drupal:12.0.0. Instead declare your $module module service provider class $class in $module.services.yml file. See https://www.drupal.org/node/2974194", E_USER_DEPRECATED); } } diff --git a/core/modules/file/file.services.yml b/core/modules/file/file.services.yml index 1812c5f0911d50cff3404d4f92c9f4255c7773b8..ffa46bbe4e4c0919e144195843ef891640926d86 100644 --- a/core/modules/file/file.services.yml +++ b/core/modules/file/file.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\file\FileServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/inline_form_errors/inline_form_errors.services.yml b/core/modules/inline_form_errors/inline_form_errors.services.yml index 0358ee160271402390563f3cc4dad2f317dfa571..9c6e678b2f9f02309c4736e9d137e9f92e7f1c8a 100644 --- a/core/modules/inline_form_errors/inline_form_errors.services.yml +++ b/core/modules/inline_form_errors/inline_form_errors.services.yml @@ -1,2 +1,5 @@ parameters: inline_form_errors.hooks_converted: true + +service_providers: + - Drupal\inline_form_errors\InlineFormErrorsServiceProvider diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml index 2fc8f9ada778d75ec29b52788bd9c597f2281678..0ff499ba59b539cfe8b51e066d1807a0f99d078f 100644 --- a/core/modules/language/language.services.yml +++ b/core/modules/language/language.services.yml @@ -1,6 +1,9 @@ parameters: language.hooks_converted: true +service_providers: + - Drupal\language\LanguageServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/layout_builder/layout_builder.services.yml b/core/modules/layout_builder/layout_builder.services.yml index 65c93652209b5e6f814d8756fb35264428a8539f..808660721de85c26894a3b2f7abb3338bb1feca2 100644 --- a/core/modules/layout_builder/layout_builder.services.yml +++ b/core/modules/layout_builder/layout_builder.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\layout_builder\LayoutBuilderServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/media/tests/modules/media_test_oembed/media_test_oembed.services.yml b/core/modules/media/tests/modules/media_test_oembed/media_test_oembed.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..f95ca641119de8c3bee8db073adfa765dc4b803f --- /dev/null +++ b/core/modules/media/tests/modules/media_test_oembed/media_test_oembed.services.yml @@ -0,0 +1,2 @@ +service_providers: + - Drupal\media_test_oembed\MediaTestOembedServiceProvider diff --git a/core/modules/media_library/media_library.services.yml b/core/modules/media_library/media_library.services.yml index 510769de9d6d526d70b937e94ca9aa714a52d541..0ca588b934ba7597845e9c63faeb6fc79879b8f8 100644 --- a/core/modules/media_library/media_library.services.yml +++ b/core/modules/media_library/media_library.services.yml @@ -1,6 +1,9 @@ parameters: media_library.hooks_converted: true +service_providers: + - Drupal\media_library\MediaLibraryServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml index e0d16a99459de9f4039a8e55f038aadc762c3753..be20d4ce1e00dba29a14d1f4987e07c4af7a2b41 100644 --- a/core/modules/migrate_drupal/migrate_drupal.services.yml +++ b/core/modules/migrate_drupal/migrate_drupal.services.yml @@ -1,6 +1,9 @@ parameters: migrate_drupal.hooks_converted: true +service_providers: + - Drupal\migrate_drupal\MigrateDrupalServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/mysql/mysql.services.yml b/core/modules/mysql/mysql.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..1b3cdd7903c880b83ed36b8a9e6f9630ca6d2849 --- /dev/null +++ b/core/modules/mysql/mysql.services.yml @@ -0,0 +1,2 @@ +service_providers: + - Drupal\mysql\MysqlServiceProvider diff --git a/core/modules/navigation/navigation.services.yml b/core/modules/navigation/navigation.services.yml index 5393be82b14ed1e84ff622776fd01cf492d72ad7..d06ae2ffd3614dbe37086eed301f63bdf98130e3 100644 --- a/core/modules/navigation/navigation.services.yml +++ b/core/modules/navigation/navigation.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\navigation\NavigationServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml index e5daad3542960b9ddeb5b45fcadab1599a4e6067..d6c6bf1b637271093fac9720e96faa7052516b2b 100644 --- a/core/modules/node/node.services.yml +++ b/core/modules/node/node.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\node\NodeServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/package_manager/tests/modules/package_manager_bypass/package_manager_bypass.services.yml b/core/modules/package_manager/tests/modules/package_manager_bypass/package_manager_bypass.services.yml index b5fea63ec7204ccd0759949c53896a28722e35ff..6e2624f40e11f23e94502490e4ae0da969c9d9db 100644 --- a/core/modules/package_manager/tests/modules/package_manager_bypass/package_manager_bypass.services.yml +++ b/core/modules/package_manager/tests/modules/package_manager_bypass/package_manager_bypass.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\package_manager_bypass\PackageManagerBypassServiceProvider + services: _defaults: autowire: true diff --git a/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml b/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml index bd41327d3159eae75be794868dfaaf1767c7f43c..2972ee744b9d743c537cc5de790b161a6d11d59d 100644 --- a/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml +++ b/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\package_manager_test_validation\PackageManagerTestValidationServiceProvider + services: package_manager_test_validation.subscriber: class: Drupal\package_manager_test_validation\EventSubscriber\TestSubscriber diff --git a/core/modules/rest/rest.services.yml b/core/modules/rest/rest.services.yml index aa249ed37825328d323e9445580944ffec913ec4..a0137c0cbfd92863c5858a35477d212d826c5867 100644 --- a/core/modules/rest/rest.services.yml +++ b/core/modules/rest/rest.services.yml @@ -1,6 +1,9 @@ parameters: rest.hooks_converted: true +service_providers: + - Drupal\rest\RestServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/serialization/serialization.services.yml b/core/modules/serialization/serialization.services.yml index 9dc3a849ce9a7e92570cd1c873cff4c3d8e058b0..df0cc7b83b3eea09aefa00ab9c078827f25c0482 100644 --- a/core/modules/serialization/serialization.services.yml +++ b/core/modules/serialization/serialization.services.yml @@ -1,6 +1,9 @@ parameters: serialization.hooks_converted: true +service_providers: + - Drupal\serialization\SerializationServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml b/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml index dc0ce1087ebd77f60091fea7aa557c1d0590c3b6..062a98062ab232210b31c25f724112ee1f993703 100644 --- a/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml +++ b/core/modules/system/tests/modules/accept_header_routing_test/accept_header_routing_test.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\accept_header_routing_test\AcceptHeaderRoutingTestServiceProvider + services: accept_header_matcher: class: Drupal\accept_header_routing_test\Routing\AcceptHeaderMatcher diff --git a/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.services.yml b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..a945e142b0923831f9fccdc8cd8911a3655151b3 --- /dev/null +++ b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.services.yml @@ -0,0 +1,2 @@ +service_providers: + - Drupal\container_rebuild_test\ContainerRebuildTestServiceProvider diff --git a/core/modules/system/tests/modules/drupal_kernel_module_service_providers/drupal_kernel_module_service_providers.info.yml b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/drupal_kernel_module_service_providers.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..d89ae7804f176781626900f03018519d92741c91 --- /dev/null +++ b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/drupal_kernel_module_service_providers.info.yml @@ -0,0 +1,6 @@ +name: 'Drupal kernel module service providers' +type: module +description: '' +package: Testing +version: VERSION +core: 8.x diff --git a/core/modules/system/tests/modules/drupal_kernel_module_service_providers/drupal_kernel_module_service_providers.services.yml b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/drupal_kernel_module_service_providers.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..15ce7b0022cdebd35a8ccf1f048480b48c51314c --- /dev/null +++ b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/drupal_kernel_module_service_providers.services.yml @@ -0,0 +1,2 @@ +service_providers: + - Drupal\drupal_kernel_module_service_providers\DrupalKernelModuleServiceProvidersServiceProvider2 diff --git a/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/DrupalKernelModuleServiceProvidersServiceProvider.php b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/DrupalKernelModuleServiceProvidersServiceProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..cf6c62e15be14fe0616b07f895fcdc599fc5e8de --- /dev/null +++ b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/DrupalKernelModuleServiceProvidersServiceProvider.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\drupal_kernel_module_service_providers; + +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\DependencyInjection\ServiceProviderInterface; + +class DrupalKernelModuleServiceProvidersServiceProvider implements ServiceProviderInterface { + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container): void { + $container->register('drupal_kernel_module_service_providers.test_0', TestService::class); + } + +} diff --git a/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/DrupalKernelModuleServiceProvidersServiceProvider2.php b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/DrupalKernelModuleServiceProvidersServiceProvider2.php new file mode 100644 index 0000000000000000000000000000000000000000..cd52764c66bfdf4ea6c278179db2a7f2c2c7e979 --- /dev/null +++ b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/DrupalKernelModuleServiceProvidersServiceProvider2.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\drupal_kernel_module_service_providers; + +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\DependencyInjection\ServiceProviderInterface; + +class DrupalKernelModuleServiceProvidersServiceProvider2 implements ServiceProviderInterface { + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container): void { + $container->register('drupal_kernel_module_service_providers.test_1', TestService::class); + } + +} diff --git a/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/TestService.php b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/TestService.php new file mode 100644 index 0000000000000000000000000000000000000000..8a445535ad8881f94d87eaebe2211c5c53beb85b --- /dev/null +++ b/core/modules/system/tests/modules/drupal_kernel_module_service_providers/src/TestService.php @@ -0,0 +1,9 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\drupal_kernel_module_service_providers; + +class TestService { + +} diff --git a/core/modules/system/tests/modules/error_service_test/error_service_test.services.yml b/core/modules/system/tests/modules/error_service_test/error_service_test.services.yml index c2a56334caf58f8d2eaef2fa0da71d38a0ba56b5..d83c35bd4dd525fc1463541518dedbd9060aa533 100644 --- a/core/modules/system/tests/modules/error_service_test/error_service_test.services.yml +++ b/core/modules/system/tests/modules/error_service_test/error_service_test.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\error_service_test\ErrorServiceTestServiceProvider + services: http_middleware.monkeys: class: Drupal\error_service_test\MonkeysInTheControlRoom diff --git a/core/modules/system/tests/modules/menu_test/menu_test.services.yml b/core/modules/system/tests/modules/menu_test/menu_test.services.yml index e1a0aa059bceee5206f5d9164d524dec12479f5f..5c35e8c03338287e5810e77ac7c2cc8f5c1fc3df 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.services.yml +++ b/core/modules/system/tests/modules/menu_test/menu_test.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\menu_test\MenuTestServiceProvider + services: theme.negotiator.test_theme: class: Drupal\menu_test\Theme\TestThemeNegotiator diff --git a/core/modules/system/tests/modules/module_test/module_test.services.yml b/core/modules/system/tests/modules/module_test/module_test.services.yml index 58fe6bf765c69e755183037d408dd074ffe49dbb..f7285602e92186659a8bd349b09c03d17fc2cce4 100644 --- a/core/modules/system/tests/modules/module_test/module_test.services.yml +++ b/core/modules/system/tests/modules/module_test/module_test.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\module_test\ModuleTestServiceProvider + services: # Tests module uninstall plugin.manager.module_test.cache_clear_test: diff --git a/core/modules/system/tests/modules/router_test_directory/router_test.services.yml b/core/modules/system/tests/modules/router_test_directory/router_test.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..c1eecba9be6820e28ea928779674ac7fc9e73cf5 --- /dev/null +++ b/core/modules/system/tests/modules/router_test_directory/router_test.services.yml @@ -0,0 +1,2 @@ +service_providers: + - Drupal\router_test\RouterTestServiceProvider diff --git a/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml b/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml index 6cefdedb3b53d52128f45bf065d0f9fb12520b76..2b93c9456ee04f0f51d7f5d765ae90bd93621844 100644 --- a/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml +++ b/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\service_provider_test\ServiceProviderTestServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/modules/workspaces/workspaces.services.yml b/core/modules/workspaces/workspaces.services.yml index f124d5e376c3f745d800dfc2770968d0d1dbe96f..55196000f6d9d7b7808f144c10c23caac19aca05 100644 --- a/core/modules/workspaces/workspaces.services.yml +++ b/core/modules/workspaces/workspaces.services.yml @@ -1,3 +1,6 @@ +service_providers: + - Drupal\workspaces\WorkspacesServiceProvider + services: _defaults: autoconfigure: true diff --git a/core/tests/Drupal/KernelTests/Core/DrupalKernel/ImplicitServiceProvidersDeprecationTest.php b/core/tests/Drupal/KernelTests/Core/DrupalKernel/ImplicitServiceProvidersDeprecationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8964317da64e0d0deb8bccd6fa5280721f190195 --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/DrupalKernel/ImplicitServiceProvidersDeprecationTest.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\KernelTests\Core\DrupalKernel; + +use Drupal\drupal_kernel_module_service_providers\TestService; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests the deprecation of implicit service providers. + * + * @group DrupalKernel + * @group legacy + */ +class ImplicitServiceProvidersDeprecationTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['drupal_kernel_module_service_providers']; + + /** + * Tests the deprecation of implicit service providers. + * + * @expectedDeprecation Using implicit service providers is deprecated in drupal:11.2.0 and will be removed in drupal:12.0.0. Instead declare your drupal_kernel_module_service_providers module service provider class Drupal\drupal_kernel_module_service_providers\DrupalKernelModuleServiceProvidersServiceProvider in drupal_kernel_module_service_providers.services.yml file. See https://www.drupal.org/node/2974194 + */ + public function testDeprecation():void { + $this->assertInstanceOf(TestService::class, $this->container->get('drupal_kernel_module_service_providers.test_0')); + $this->assertInstanceOf(TestService::class, $this->container->get('drupal_kernel_module_service_providers.test_1')); + } + +} diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php index 717026fe3f46b7df8427b4ca520cd84453f42d89..5c717ba40fd7c257e958e62214a464a0da514160 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php @@ -44,6 +44,8 @@ class: \Drupal\Core\ExampleClass example_service_closure: class: \Drupal\Core\ExampleClass arguments: [!service_closure '@example_service_1']" +service_providers: + - \Drupal\Core\CoreServiceProvider YAML; vfsStream::setup('drupal', NULL, [