DatabaseDriver.php

Same filename in other branches
  1. 10 core/lib/Drupal/Core/Extension/DatabaseDriver.php

Namespace

Drupal\Core\Extension

File

core/lib/Drupal/Core/Extension/DatabaseDriver.php

View source
<?php

namespace Drupal\Core\Extension;

use Composer\Autoload\ClassLoader;
use Drupal\Core\Database\Install\Tasks;

/**
 * Defines a database driver extension object.
 */
class DatabaseDriver extends Extension {
    
    /**
     * The container class loader.
     */
    private ClassLoader $classLoader;
    
    /**
     * The install tasks object instance of the database driver.
     */
    private Tasks $installTasks;
    
    /**
     * Constructs a new DatabaseDriver object.
     *
     * @param string $root
     *   The app root.
     * @param \Drupal\Core\Extension\Extension $module
     *   The module containing the database driver.
     * @param string $driverName
     *   The database driver name.
     * @param \Drupal\Core\Extension\Extension[] $discoveredModules
     *   The modules discovered in the installation.
     */
    public function __construct(string $root, Extension $module, string $driverName, array $discoveredModules) {
        $this->root = $root;
        $this->type = 'database_driver';
    }
    
    /**
     * Returns the Extension object of the module containing the database driver.
     *
     * @return \Drupal\Core\Extension\Extension
     *   The Extension object of the module containing the database driver.
     */
    public function getModule() : Extension {
        return $this->module;
    }
    
    /**
     * Returns the name of the database driver.
     *
     * @return string
     *   The name of the database driver.
     */
    public function getDriverName() : string {
        return $this->driverName;
    }
    
    /**
     * Returns the PHP namespace of the database driver.
     *
     * @return string
     *   The PHP namespace of the database driver.
     */
    public function getNamespace() : string {
        return "Drupal\\" . $this->getModule()
            ->getName() . "\\Driver\\Database\\" . $this->getDriverName();
    }
    
    /**
     * {@inheritdoc}
     */
    public function getName() {
        return $this->getNamespace();
    }
    
    /**
     * {@inheritdoc}
     */
    public function getPath() {
        return $this->getModule()
            ->getPath() . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Driver' . DIRECTORY_SEPARATOR . 'Database' . DIRECTORY_SEPARATOR . $this->getDriverName();
    }
    
    /**
     * {@inheritdoc}
     */
    public function load() {
        if (!isset($this->classLoader)) {
            if (\Drupal::hasContainer() && \Drupal::hasService('class_loader')) {
                $this->classLoader = \Drupal::service('class_loader');
            }
            else {
                $this->classLoader = (require DRUPAL_ROOT . '/autoload.php');
            }
            $this->classLoader
                ->addPsr4($this->getNamespace() . '\\', $this->getPath());
            foreach ($this->getAutoloadInfo()['dependencies'] ?? [] as $dependency) {
                $this->classLoader
                    ->addPsr4($dependency['namespace'] . '\\', $dependency['autoload']);
            }
        }
        return TRUE;
    }
    
    /**
     * Returns the install tasks object instance of this database driver.
     *
     * @return \Drupal\Core\Database\Install\Tasks
     *   The install tasks object instance.
     */
    public function getInstallTasks() : Tasks {
        if (!isset($this->installTasks)) {
            $this->load();
            $installTasksClass = $this->getNamespace() . "\\Install\\Tasks";
            $this->installTasks = new $installTasksClass();
        }
        return $this->installTasks;
    }
    // phpcs:disable
    
    /**
     * Returns an array with the driver's autoload information.
     *
     * The module that provides the database driver should add the driver's
     * namespace to Composer's autoloader. However, since the database connection
     * must be established before Drupal adds the module's entire namespace to the
     * autoloader, the database connection info array includes an "autoload" key
     * containing the autoload directory for the driver's namespace. For requests
     * that connect to the database via a connection info array, the value of the
     * "autoload" key is automatically added to the autoloader.
     *
     * This method can be called to find the default value of that key when the
     * database connection info array isn't available. This includes:
     * - Console commands and test runners that connect to a database specified
     *   by a database URL rather than a connection info array.
     * - During installation, prior to the connection info array being written to
     *   settings.php.
     *
     * This method returns an array with the driver's namespace and autoload
     * directory that must be added to the autoloader, as well as those of any
     * dependency specified in the driver's module.info.yml file, in the format
     * @code
     * [
     *   'autoload' => 'path_to_modules/module_a/src/Driver/Database/driver_1/',
     *   'namespace' => 'Drupal\\module_a\\Driver\\Database\\driver_1',
     *   'dependencies' => [
     *     'module_x' => [
     *       'autoload' => 'path_to_modules/module_x/src/',
     *       'namespace' => 'Drupal\\module_x',
     *     ],
     *   ],
     * ]
     * @endcode
     *
     * @return array{
     *     'autoload': string,
     *     'namespace': string,
     *     'dependencies': array<string, array{'autoload': string, 'namespace': string}>,
     *   }
     */
    // phpcs:enable
    public function getAutoloadInfo() : array {
        $this->getModuleInfo();
        $autoloadInfo = [
            'namespace' => $this->getNamespace(),
            'autoload' => $this->getPath() . DIRECTORY_SEPARATOR,
        ];
        foreach ($this->info['dependencies'] ?? [] as $dependency) {
            $dependencyData = Dependency::createFromString($dependency);
            $dependencyName = $dependencyData->getName();
            if (empty($this->discoveredModules[$dependencyName])) {
                throw new \RuntimeException(sprintf("Cannot find the module '%s' that is required by module '%s'", $dependencyName, $this->getModule()
                    ->getName()));
            }
            $autoloadInfo['dependencies'][$dependencyName] = [
                'namespace' => "Drupal\\{$dependencyName}",
                'autoload' => $this->discoveredModules[$dependencyName]
                    ->getPath() . '/src/',
            ];
        }
        return $autoloadInfo;
    }
    
    /**
     * {@inheritdoc}
     */
    public function isExperimental() : bool {
        $this->getModuleInfo();
        return parent::isExperimental();
    }
    
    /**
     * {@inheritdoc}
     */
    public function isObsolete() : bool {
        $this->getModuleInfo();
        return parent::isObsolete();
    }
    
    /**
     * Gets the content of the info.yml file of the driver's module, as an array.
     *
     * The info array is saved in the $info property.
     *
     * @throws \Drupal\Core\Extension\InfoParserException
     *   Exception thrown if there is a parsing error or the .info.yml file does
     *   not contain a required key.
     */
    private function getModuleInfo() : void {
        if (!isset($this->info)) {
            $infoParser = new InfoParser($this->root);
            $this->info = $infoParser->parse($this->getModule()
                ->getPathname());
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function getPathname() {
        throw new \LogicException(__METHOD__ . '() is not implemented');
    }
    
    /**
     * {@inheritdoc}
     */
    public function getFilename() {
        throw new \LogicException(__METHOD__ . '() is not implemented');
    }
    
    /**
     * {@inheritdoc}
     */
    public function getExtensionPathname() {
        throw new \LogicException(__METHOD__ . '() is not implemented');
    }
    
    /**
     * {@inheritdoc}
     */
    public function getExtensionFilename() {
        throw new \LogicException(__METHOD__ . '() is not implemented');
    }

}

Classes

Title Deprecated Summary
DatabaseDriver Defines a database driver extension object.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.