diff --git a/core/includes/update.inc b/core/includes/update.inc index 3659caf..881adcd 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -103,10 +103,9 @@ function update_prepare_d8_bootstrap() { $settings['cache']['default'] = 'cache.backend.memory'; new Settings($settings); - // Enable UpdateBundle service overrides. While the container_bundles array - // does not need a key, let's use so it can be removed once the upgrade are - // finished. @see update_flush_all_caches() - $GLOBALS['conf']['container_bundles']['UpdateBundle'] = 'Drupal\Core\DependencyInjection\UpdateBundle'; + // Enable UpdateServiceProvider service overrides. + // @see update_flush_all_caches() + $GLOBALS['conf']['container_service_providers']['UpdateServiceProvider'] = 'Drupal\Core\DependencyInjection\UpdateServiceProvider'; // Check whether settings.php needs to be rewritten. $settings_exist = !empty($GLOBALS['config_directories']); diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index bb4368c..1fa80fc 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -19,8 +19,8 @@ * * The container is built by the kernel and passed in to this class which stores * it statically. The container always contains the services from - * \Drupal\Core\CoreBundle, the bundles of enabled modules and any other bundles - * defined in $GLOBALS['conf']['container_bundles']. + * \Drupal\Core\CoreServiceProvider, the service providers of enabled modules and any other + * service providers defined in $GLOBALS['conf']['container_service_providers']. * * This class exists only to support legacy code that cannot be dependency * injected. If your code needs it, consider refactoring it to be object diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreServiceProvider.php similarity index 88% rename from core/lib/Drupal/Core/CoreBundle.php rename to core/lib/Drupal/Core/CoreServiceProvider.php index 9af0c74..5c04a32 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -2,12 +2,15 @@ /** * @file - * Definition of Drupal\Core\CoreBundle. + * Definition of Drupal\Core\CoreServiceProvider. */ namespace Drupal\Core; use Drupal\Core\Cache\ListCacheBinsPass; +use Drupal\Core\DependencyInjection\ServiceProviderInterface; +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass; use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass; use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass; use Drupal\Core\DependencyInjection\Compiler\RegisterMatchersPass; @@ -18,16 +21,14 @@ use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass; use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass; use Drupal\Core\DependencyInjection\Compiler\RegisterBreadcrumbBuilderPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Scope; -use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\Compiler\PassConfig; /** - * Bundle class for mandatory core services. + * ServiceProvider class for mandatory core services. * * This is where Drupal core registers all of its compiler passes. * The service definitions themselves are in core/core.services.yml with a @@ -36,12 +37,12 @@ * Modules wishing to register services to the container should use * modulename.services.yml in their respective directories. */ -class CoreBundle extends Bundle { +class CoreServiceProvider implements ServiceProviderInterface { /** - * Implements \Symfony\Component\HttpKernel\Bundle\BundleInterface::build(). + * {@inheritdoc} */ - public function build(ContainerBuilder $container) { + public function register(ContainerBuilder $container) { // The 'request' scope and service enable services to depend on the Request // object and get reconstructed when the request object changes (e.g., // during a subrequest). @@ -67,6 +68,16 @@ public function build(ContainerBuilder $container) { // Add the compiler pass that will process the tagged breadcrumb builder // services. $container->addCompilerPass(new RegisterBreadcrumbBuilderPass()); + // Add the compiler pass that lets service providers modify existing + // service definitions. + $container->addCompilerPass(new ModifyServiceDefinitionsPass()); + } + + /** + * {@inheritdoc} + */ + public function alter(ContainerBuilder $container) { + } /** diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/ModifyServiceDefinitionsPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/ModifyServiceDefinitionsPass.php new file mode 100644 index 0000000..a00cc25 --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/ModifyServiceDefinitionsPass.php @@ -0,0 +1,35 @@ +has('kernel')) { + return; + } + $kernel = $container->get('kernel'); + if (!is_a($kernel, 'Drupal\Core\DrupalKernel')) { + return; + } + $providers = $kernel->getServiceProviders(); + foreach ($providers as $provider) { + $provider->alter($container); + } + } + +} diff --git a/core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php b/core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php new file mode 100644 index 0000000..8614e32 --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php @@ -0,0 +1,26 @@ +register('lock', 'Drupal\Core\Lock\NullLockBackend'); @@ -40,4 +40,8 @@ public function build(SymfonyContainerBuilder $container) { ->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic'); } + public function alter(ContainerBuilder $container) { + + } + } diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 6d7d4fa..c74ee06 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -9,7 +9,7 @@ use Drupal\Component\PhpStorage\PhpStorageFactory; use Drupal\Core\Config\BootstrapConfigStorageFactory; -use Drupal\Core\CoreBundle; +use Drupal\Core\CoreServiceProvider; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\YamlFileLoader; use Symfony\Component\ClassLoader\ClassLoader; @@ -22,11 +22,14 @@ * The DrupalKernel class is the core of Drupal itself. * * This class is responsible for building the Dependency Injection Container and - * also deals with the registration of bundles. It allows registered bundles to - * add their services to the container. Core provides the CoreBundle, which adds - * the services required for all core subsystems. Each module can then add its - * own bundle, i.e. a subclass of Symfony\Component\HttpKernel\Bundle, to - * register services to the container. + * also deals with the registration of service providers. It allows registered + * service providers to add their services to the container. Core provides the + * CoreServiceProvider, which, in addition to registering any core services that + * cannot be registered in the core.services.yaml file, adds any compiler passes + * needed by core, e.g. for processing tagged services. Each module can add its + * own service provider, i.e. a class implementing + * Drupal\Core\DependencyInjection\ServiceProvider, to register services to the + * container, or modify existing services. */ class DrupalKernel extends Kernel implements DrupalKernelInterface { @@ -80,11 +83,11 @@ class DrupalKernel extends Kernel implements DrupalKernelInterface { protected $configStorage; /** - * The list of the classnames of the bundles in this kernel. + * The list of the classnames of the service providers in this kernel. * * @var array */ - protected $bundleClasses; + protected $serviceProviderClasses; /** * Whether the container can be dumped. @@ -108,6 +111,13 @@ class DrupalKernel extends Kernel implements DrupalKernelInterface { protected $serviceYamls; /** + * The array of registered service providers. + * + * @var array + */ + protected $serviceProviders; + + /** * Constructs a DrupalKernel object. * * @param string $environment @@ -122,7 +132,7 @@ class DrupalKernel extends Kernel implements DrupalKernelInterface { * (optional) The classloader is only used if $storage is not given or * the load from storage fails and a container rebuild is required. In * this case, the loaded modules will be registered with this loader in - * order to be able to find the module bundles. + * order to be able to find the module serviceProviders. * @param bool $allow_dumping * (optional) FALSE to stop the container from being written to or read * from disk. Defaults to TRUE. @@ -172,21 +182,25 @@ public function boot() { } } + public function registerBundles() { + // We do not support symfony bundles + } + /** - * Returns an array of available bundles. + * Returns an array of available serviceProviders. * * @return array - * The available bundles. + * The available serviceProviders. */ - public function registerBundles() { + public function registerServiceProviders() { $this->configStorage = BootstrapConfigStorageFactory::get(); - $bundles = array( - new CoreBundle(), + $serviceProviders = array( + 'CoreServiceProvider' => new CoreServiceProvider(), ); $this->serviceYamls = array( 'core/core.services.yml' ); - $this->bundleClasses = array('Drupal\Core\CoreBundle'); + $this->serviceProviderClasses = array('Drupal\Core\CoreServiceProvider'); // Ensure we know what modules are enabled and that their namespaces are // registered. @@ -197,13 +211,14 @@ public function registerBundles() { $module_filenames = $this->getModuleFileNames(); $this->registerNamespaces($this->getModuleNamespaces($module_filenames)); - // Load each module's bundle class. + // Load each module's serviceProvider class. foreach ($this->moduleList as $module => $weight) { $camelized = ContainerBuilder::camelize($module); - $class = "Drupal\\{$module}\\{$camelized}Bundle"; + $name = "{$camelized}ServiceProvider"; + $class = "Drupal\\{$module}\\{$name}"; if (class_exists($class)) { - $bundles[] = new $class(); - $this->bundleClasses[] = $class; + $serviceProviders[$name] = new $class(); + $this->serviceProviderClasses[] = $class; } $filename = dirname($module_filenames[$module]) . "/$module.services.yml"; if (file_exists($filename)) { @@ -211,18 +226,18 @@ public function registerBundles() { } } - // Add site specific or test bundles. - if (!empty($GLOBALS['conf']['container_bundles'])) { - foreach ($GLOBALS['conf']['container_bundles'] as $class) { - $bundles[] = new $class(); - $this->bundleClasses[] = $class; + // Add site specific or test service providers. + if (!empty($GLOBALS['conf']['container_service_providers'])) { + foreach ($GLOBALS['conf']['container_service_providers'] as $name => $class) { + $serviceProviders[$name] = new $class(); + $this->serviceProviderClasses[] = $class; } } // Add site specific or test YAMLs. if (!empty($GLOBALS['conf']['container_yamls'])) { $this->serviceYamls = array_merge($this->serviceYamls, $GLOBALS['conf']['container_yamls']); } - return $bundles; + return $serviceProviders; } /** @@ -269,7 +284,7 @@ public function updateModules(array $module_list, array $module_filenames = arra } // If we haven't yet booted, we don't need to do anything: the new module // list will take effect when boot() is called. If we have already booted, - // then reboot in order to refresh the bundle list and container. + // then reboot in order to refresh the serviceProvider list and container. if ($this->booted) { $this->booted = FALSE; $this->boot(); @@ -371,6 +386,7 @@ protected function initializeContainer() { } $this->container->set('kernel', $this); + // Set the class loader which was registered as a synthetic service. $this->container->set('class_loader', $this->classLoader); // If we have a request set it back to the new container. @@ -416,9 +432,10 @@ protected function persistServices(array $persist) { * @return ContainerBuilder The compiled service container */ protected function buildContainer() { - $this->initializeBundles(); + $this->initializeServiceProviders(); $container = $this->getContainerBuilder(); - $container->setParameter('container.bundles', $this->bundleClasses); + $container->set('kernel', $this); + $container->setParameter('container.service_providers', $this->serviceProviderClasses); $container->setParameter('container.modules', $this->getModuleFileNames()); // Get a list of namespaces and put it onto the container. @@ -443,8 +460,8 @@ protected function buildContainer() { foreach ($this->serviceYamls as $filename) { $yaml_loader->load($filename); } - foreach ($this->bundles as $bundle) { - $bundle->build($container); + foreach ($this->serviceProviders as $provider) { + $provider->register($container); } // Identify all services whose instances should be persisted when rebuilding @@ -464,6 +481,32 @@ protected function buildContainer() { } /** + * Registers all service providers to the kernel. + * + * @throws \LogicException + */ + protected function initializeServiceProviders() { + $this->serviceProviders = array(); + + foreach ($this->registerServiceProviders() as $name => $provider) { + if (isset($this->serviceProviders[$name])) { + throw new \LogicException(sprintf('Trying to register two service providers with the same name "%s"', $name)); + } + $this->serviceProviders[$name] = $provider; + } + } + + /** + * Getter for the serviceProviders property. + * + * @return ServiceProvider[] + * An associative array of ServiceProvider objects, keyed by name. + */ + public function getServiceProviders() { + return $this->serviceProviders; + } + + /** * Gets a new ContainerBuilder instance used to build the service container. * * @return ContainerBuilder diff --git a/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestBundle.php b/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestBundle.php deleted file mode 100644 index b711507..0000000 --- a/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestBundle.php +++ /dev/null @@ -1,28 +0,0 @@ -getDefinition('language_manager'); - $definition->setClass('Drupal\language_test\LanguageTestManager'); - } - -} - diff --git a/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestServiceProvider.php b/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestServiceProvider.php new file mode 100644 index 0000000..e177a46 --- /dev/null +++ b/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestServiceProvider.php @@ -0,0 +1,35 @@ +getDefinition('language_manager'); + $definition->setClass('Drupal\language_test\LanguageTestManager'); + } + +} + diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php index 2c80dcd..8a79ed2 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php @@ -90,7 +90,7 @@ protected function setUp() { // Build a minimal, partially mocked environment for unit tests. $this->containerBuild(drupal_container()); // Make sure it survives kernel rebuilds. - $GLOBALS['conf']['container_bundles'][] = 'Drupal\simpletest\TestBundle'; + $GLOBALS['conf']['container_service_providers']['TestServiceProvider'] = 'Drupal\simpletest\TestServiceProvider'; \Drupal::state()->set('system.module.files', $this->moduleFiles); \Drupal::state()->set('system.theme.files', $this->themeFiles); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index d3ba7b3..6fc7d24 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -684,7 +684,7 @@ protected function verbose($message) { * methods during debugging. */ public function run(array $methods = array()) { - TestBundle::$currentTest = $this; + TestServiceProvider::$currentTest = $this; $simpletest_config = config('simpletest.settings'); $class = get_class($this); @@ -756,7 +756,7 @@ public function run(array $methods = array()) { } } } - TestBundle::$currentTest = NULL; + TestServiceProvider::$currentTest = NULL; // Clear out the error messages and restore error handler. drupal_get_messages(); restore_error_handler(); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBundle.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBundle.php deleted file mode 100644 index 7e2fd2f..0000000 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBundle.php +++ /dev/null @@ -1,24 +0,0 @@ -containerBuild($container); - } - } - -} diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestServiceProvider.php b/core/modules/simpletest/lib/Drupal/simpletest/TestServiceProvider.php new file mode 100644 index 0000000..cdc07b4 --- /dev/null +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestServiceProvider.php @@ -0,0 +1,31 @@ +containerBuild($container); + } + } + + /** + * {@inheritdoc} + */ + function alter(ContainerBuilder $container) { + + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php index b613121..8a1cb68 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php @@ -114,7 +114,7 @@ protected function setUp() { // Build a minimal, partially mocked environment for unit tests. $this->containerBuild(drupal_container()); // Make sure it survives kernel rebuilds. - $conf['container_bundles'][] = 'Drupal\simpletest\TestBundle'; + $conf['container_service_providers']['TestServiceProvider'] = 'Drupal\simpletest\TestServiceProvider'; // Change the database prefix. // All static variables need to be reset before the database prefix is diff --git a/core/update.php b/core/update.php index b73e3ce..3b6afe3 100644 --- a/core/update.php +++ b/core/update.php @@ -186,7 +186,7 @@ function update_helpful_links() { * while updates are running. */ function update_flush_all_caches() { - unset($GLOBALS['conf']['container_bundles']['UpdateBundle']); + unset($GLOBALS['conf']['container_service_providers']['UpdateServiceProvider']); Drupal::service('kernel')->updateModules(Drupal::moduleHandler()->getModuleList()); // No updates to run, so caches won't get flushed later. Clear them now.