Security update for Core, with self-updated composer
[yaffs-website] / web / core / lib / Drupal / Core / Extension / ModuleInstaller.php
index f9500a5fc7db9c005b131c9511a92e1f0f8ab408..87924987c2c6ca0c3b0ccdb141ad0746840ab415 100644 (file)
@@ -136,6 +136,10 @@ class ModuleInstaller implements ModuleInstallerInterface {
           throw new ExtensionNameLengthException("Module name '$module' is over the maximum allowed length of " . DRUPAL_EXTENSION_NAME_MAX_LENGTH . ' characters');
         }
 
+        // Load a new config object for each iteration, otherwise changes made
+        // in hook_install() are not reflected in $extension_config.
+        $extension_config = \Drupal::configFactory()->getEditable('core.extension');
+
         // Check the validity of the default configuration. This will throw
         // exceptions if the configuration is not valid.
         $config_installer->checkConfigurationToInstall('module', $module);
@@ -190,6 +194,17 @@ class ModuleInstaller implements ModuleInstallerInterface {
         // Update the kernel to include it.
         $this->updateKernel($module_filenames);
 
+        // Replace the route provider service with a version that will rebuild
+        // if routes used during installation. This ensures that a module's
+        // routes are available during installation. This has to occur before
+        // any services that depend on it are instantiated otherwise those
+        // services will have the old route provider injected. Note that, since
+        // the container is rebuilt by updating the kernel, the route provider
+        // service is the regular one even though we are in a loop and might
+        // have replaced it before.
+        \Drupal::getContainer()->set('router.route_provider.old', \Drupal::service('router.route_provider'));
+        \Drupal::getContainer()->set('router.route_provider', \Drupal::service('router.route_provider.lazy_builder'));
+
         // Allow modules to react prior to the installation of a module.
         $this->moduleHandler->invokeAll('module_preinstall', [$module]);
 
@@ -279,10 +294,6 @@ class ModuleInstaller implements ModuleInstallerInterface {
         // @see https://www.drupal.org/node/2208429
         \Drupal::service('theme_handler')->refreshInfo();
 
-        // In order to make uninstalling transactional if anything uses routes.
-        \Drupal::getContainer()->set('router.route_provider.old', \Drupal::service('router.route_provider'));
-        \Drupal::getContainer()->set('router.route_provider', \Drupal::service('router.route_provider.lazy_builder'));
-
         // Allow the module to perform install tasks.
         $this->moduleHandler->invoke($module, 'install');
 
@@ -494,34 +505,30 @@ class ModuleInstaller implements ModuleInstallerInterface {
    *   The name of the module for which to remove all registered cache bins.
    */
   protected function removeCacheBins($module) {
-    // Remove any cache bins defined by a module.
     $service_yaml_file = drupal_get_path('module', $module) . "/$module.services.yml";
-    if (file_exists($service_yaml_file)) {
-      $definitions = Yaml::decode(file_get_contents($service_yaml_file));
-      if (isset($definitions['services'])) {
-        foreach ($definitions['services'] as $id => $definition) {
-          if (isset($definition['tags'])) {
-            foreach ($definition['tags'] as $tag) {
-              // This works for the default cache registration and even in some
-              // cases when a non-default "super" factory is used. That should
-              // be extremely rare.
-              if ($tag['name'] == 'cache.bin' && isset($definition['factory_service']) && isset($definition['factory_method']) && !empty($definition['arguments'])) {
-                try {
-                  $factory = \Drupal::service($definition['factory_service']);
-                  if (method_exists($factory, $definition['factory_method'])) {
-                    $backend = call_user_func_array([$factory, $definition['factory_method']], $definition['arguments']);
-                    if ($backend instanceof CacheBackendInterface) {
-                      $backend->removeBin();
-                    }
-                  }
-                }
-                catch (\Exception $e) {
-                  watchdog_exception('system', $e, 'Failed to remove cache bin defined by the service %id.', ['%id' => $id]);
-                }
-              }
-            }
+    if (!file_exists($service_yaml_file)) {
+      return;
+    }
+
+    $definitions = Yaml::decode(file_get_contents($service_yaml_file));
+
+    $cache_bin_services = array_filter(
+      isset($definitions['services']) ? $definitions['services'] : [],
+      function ($definition) {
+        $tags = isset($definition['tags']) ? $definition['tags'] : [];
+        foreach ($tags as $tag) {
+          if (isset($tag['name']) && ($tag['name'] == 'cache.bin')) {
+            return TRUE;
           }
         }
+        return FALSE;
+      }
+    );
+
+    foreach (array_keys($cache_bin_services) as $service_id) {
+      $backend = $this->kernel->getContainer()->get($service_id);
+      if ($backend instanceof CacheBackendInterface) {
+        $backend->removeBin();
       }
     }
   }