Commit f838dbc8 authored by catch's avatar catch
Browse files

Issue #3129534 by daffie, anmolgoyal74, mondrake, naresh_bavaskar, Beakerboy,...

Issue #3129534 by daffie, anmolgoyal74, mondrake, naresh_bavaskar, Beakerboy, catch, alexpott, quietone: Automatically enable the module that is providing the current database driver
parent d722e9d7
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -556,6 +556,12 @@ services:
      - { name: module_install.uninstall_validator }
    arguments: ['@string_translation', '@extension.list.module', '@extension.list.theme']
    lazy: true
  database_driver_uninstall_validator:
    class: Drupal\Core\Extension\DatabaseDriverUninstallValidator
    tags:
      - { name: module_install.uninstall_validator }
    arguments: ['@string_translation', '@extension.list.module', '@database']
    lazy: true
  theme_handler:
    class: Drupal\Core\Extension\ThemeHandler
    arguments: ['%app.root%', '@config.factory', '@extension.list.theme']
+13 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
use Drupal\Component\Utility\OpCodeCache;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Database\Database;
use Drupal\Core\Extension\Dependency;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Installer\InstallerKernel;
@@ -619,6 +620,18 @@ function drupal_install_system($install_state) {
    ->set('profile', $install_state['parameters']['profile'])
    ->save();

  $connection = Database::getConnection();
  $provider = $connection->getProvider();
  // When the database driver is provided by a module, then install that module.
  // This module must be installed before any other module, as it must be able
  // to override any call to hook_schema() or any "backend_overridable" service.
  if ($provider !== 'core') {
    $autoload = $connection->getConnectionOptions()['autoload'] ?? '';
    if (($pos = strpos($autoload, 'src/Driver/Database/')) !== FALSE) {
      $kernel->getContainer()->get('module_installer')->install([$provider], FALSE);
    }
  }

  // Install System module.
  $kernel->getContainer()->get('module_installer')->install(['system'], FALSE);

+18 −0
Original line number Diff line number Diff line
@@ -1950,4 +1950,22 @@ public static function createUrlFromConnectionOptions(array $connection_options)
    return $db_url;
  }

  /**
   * Get the module name of the module that is providing the database driver.
   *
   * @return string
   *   The module name of the module that is providing the database driver, or
   *   "core" when the driver is not provided as part of a module.
   */
  public function getProvider(): string {
    [$first, $second] = explode('\\', $this->connectionOptions['namespace'], 3);

    // The namespace for Drupal modules is Drupal\MODULE_NAME, and the module
    // name must be all lowercase. Second-level namespaces containing uppercase
    // letters (e.g., "Core", "Component", "Driver") are not modules.
    // @see \Drupal\Core\DrupalKernel::getModuleNamespacesPsr4()
    // @see https://www.drupal.org/docs/8/creating-custom-modules/naming-and-placing-your-drupal-8-module#s-name-your-module
    return ($first === 'Drupal' && strtolower($second) === $second) ? $second : 'core';
  }

}
+68 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Core\Extension;

use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Database;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;

/**
 * Ensures installed modules providing a database driver are not uninstalled.
 */
class DatabaseDriverUninstallValidator implements ModuleUninstallValidatorInterface {

  use StringTranslationTrait;

  /**
   * The module extension list.
   *
   * @var \Drupal\Core\Extension\ModuleExtensionList
   */
  protected $moduleExtensionList;

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $connection;

  /**
   * Constructs a new DatabaseDriverUninstallValidator.
   *
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
   *   The module extension list.
   * @param \Drupal\Core\Database\Connection $connection
   *   The database connection.
   */
  public function __construct(TranslationInterface $string_translation, ModuleExtensionList $extension_list_module, Connection $connection) {
    $this->stringTranslation = $string_translation;
    $this->moduleExtensionList = $extension_list_module;
    $this->connection = $connection;
  }

  /**
   * {@inheritdoc}
   */
  public function validate($module) {
    $reasons = [];

    // @todo Remove the next line of code in
    // https://www.drupal.org/project/drupal/issues/3129043.
    $this->connection = Database::getConnection();

    // When the database driver is provided by a module, then that module
    // cannot be uninstalled.
    if ($module === $this->connection->getProvider()) {
      $module_name = $this->moduleExtensionList->get($module)->info['name'];
      $reasons[] = $this->t("The module '@module_name' is providing the database driver '@driver_name'.",
        ['@module_name' => $module_name, '@driver_name' => $this->connection->driver()]);
    }

    return $reasons;
  }

}
+88 −0
Original line number Diff line number Diff line
<?php
// @codingStandardsIgnoreFile

/**
 * This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\Core\Extension\DatabaseDriverUninstallValidator' "core/lib/Drupal/Core".
 */

namespace Drupal\Core\ProxyClass\Extension {

    /**
     * Provides a proxy class for \Drupal\Core\Extension\DatabaseDriverUninstallValidator.
     *
     * @see \Drupal\Component\ProxyBuilder
     */
    class DatabaseDriverUninstallValidator implements \Drupal\Core\Extension\ModuleUninstallValidatorInterface
    {

        use \Drupal\Core\DependencyInjection\DependencySerializationTrait;

        /**
         * The id of the original proxied service.
         *
         * @var string
         */
        protected $drupalProxyOriginalServiceId;

        /**
         * The real proxied service, after it was lazy loaded.
         *
         * @var \Drupal\Core\Extension\DatabaseDriverUninstallValidator
         */
        protected $service;

        /**
         * The service container.
         *
         * @var \Symfony\Component\DependencyInjection\ContainerInterface
         */
        protected $container;

        /**
         * Constructs a ProxyClass Drupal proxy object.
         *
         * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
         *   The container.
         * @param string $drupal_proxy_original_service_id
         *   The service ID of the original service.
         */
        public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
        {
            $this->container = $container;
            $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
        }

        /**
         * Lazy loads the real service from the container.
         *
         * @return object
         *   Returns the constructed real service.
         */
        protected function lazyLoadItself()
        {
            if (!isset($this->service)) {
                $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
            }

            return $this->service;
        }

        /**
         * {@inheritdoc}
         */
        public function validate($module)
        {
            return $this->lazyLoadItself()->validate($module);
        }

        /**
         * {@inheritdoc}
         */
        public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationInterface $translation)
        {
            return $this->lazyLoadItself()->setStringTranslation($translation);
        }

    }

}
Loading