Verified Commit 145af574 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3284502 by effulgentsia, alexpott: [regression] Drupal 9.4 breaks BC...

Issue #3284502 by effulgentsia, alexpott: [regression] Drupal 9.4 breaks BC via incorrect autoloading of \Drupal\Driver\* overrides of core db drivers
parent fe141d21
Loading
Loading
Loading
Loading
+18 −12
Original line number Diff line number Diff line
@@ -163,38 +163,44 @@ public static function initialize($app_root, $site_path, &$class_loader) {
    foreach ($databases as $key => $targets) {
      foreach ($targets as $target => $info) {
        // Backwards compatibility layer for Drupal 8 style database connection
        // arrays. Those do not have the 'autoload' key set for core database
        // drivers.
        if (empty($info['autoload'])) {
        // arrays. Those have the wrong 'namespace' key set, or not set at all
        // for core supported database drivers.
        if (empty($info['namespace']) || (strpos($info['namespace'], 'Drupal\\Core\\Database\\Driver\\') === 0)) {
          switch (strtolower($info['driver'])) {
            case 'mysql':
              $info['autoload'] = 'core/modules/mysql/src/Driver/Database/mysql/';
              $info['namespace'] = 'Drupal\\mysql\\Driver\\Database\\mysql';
              break;

            case 'pgsql':
              $info['autoload'] = 'core/modules/pgsql/src/Driver/Database/pgsql/';
              $info['namespace'] = 'Drupal\\pgsql\\Driver\\Database\\pgsql';
              break;

            case 'sqlite':
              $info['autoload'] = 'core/modules/sqlite/src/Driver/Database/sqlite/';
              $info['namespace'] = 'Drupal\\sqlite\\Driver\\Database\\sqlite';
              break;
          }
        }
        // Backwards compatibility layer for Drupal 8 style database connection
        // arrays. Those have the wrong 'namespace' key set, or not set at all
        // for core supported database drivers.
        if (empty($info['namespace']) || (strpos($info['namespace'], 'Drupal\\Core\\Database\\Driver\\') === 0)) {
        // arrays. Those do not have the 'autoload' key set for core database
        // drivers.
        if (empty($info['autoload'])) {
          switch (strtolower($info['driver'])) {
            case 'mysql':
              $info['namespace'] = 'Drupal\\mysql\\Driver\\Database\\mysql';
              if (trim($info['namespace'], '\\') === "Drupal\\mysql\\Driver\\Database\\mysql") {
                $info['autoload'] = "core/modules/mysql/src/Driver/Database/mysql/";
              }
              break;

            case 'pgsql':
              $info['namespace'] = 'Drupal\\pgsql\\Driver\\Database\\pgsql';
              if (trim($info['namespace'], '\\') === "Drupal\\pgsql\\Driver\\Database\\pgsql") {
                $info['autoload'] = "core/modules/pgsql/src/Driver/Database/pgsql/";
              }
              break;

            case 'sqlite':
              $info['namespace'] = 'Drupal\\sqlite\\Driver\\Database\\sqlite';
              if (trim($info['namespace'], '\\') === "Drupal\\sqlite\\Driver\\Database\\sqlite") {
                $info['autoload'] = "core/modules/sqlite/src/Driver/Database/sqlite/";
              }
              break;
          }
        }
+80 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

namespace Drupal\Tests\Core\Site;

use Composer\Autoload\ClassLoader;
use Drupal\Core\Database\Database;
use Drupal\Core\Site\Settings;
use Drupal\Tests\UnitTestCase;
use org\bovigo\vfs\vfsStream;
@@ -323,4 +325,82 @@ public function providerTestRealDeprecatedSettings(): array {
    ];
  }

  /**
   * Tests initialization performed for the $databases variable.
   *
   * @dataProvider providerTestDatabaseInfoInitialization
   */
  public function testDatabaseInfoInitialization(string $driver, ?string $namespace, ?string $autoload, string $expected_namespace, ?string $expected_autoload): void {
    $databases['mock'][$driver] = [
      'driver' => $driver,
      'prefix' => '',
    ];
    if (!is_null($namespace)) {
      $databases['mock'][$driver]['namespace'] = $namespace;
    }
    if (!is_null($autoload)) {
      $databases['mock'][$driver]['autoload'] = $autoload;
    }
    $settings_file_content = "<?php\n\$databases = " . var_export($databases, TRUE) . ";\n";

    $vfs_root = vfsStream::setup('root');
    $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root);
    vfsStream::newFile('settings.php')
      ->at($sites_directory)
      ->setContent($settings_file_content);

    $class_loader = $this->createMock(ClassLoader::class);
    if (!empty($expected_autoload)) {
      $class_loader->expects($this->once())
        ->method('addPsr4')
        ->with($expected_namespace . '\\', $expected_autoload);
    }
    else {
      $class_loader->expects($this->never())
        ->method('addPsr4');
    }

    Settings::initialize(vfsStream::url('root'), 'sites', $class_loader);

    $expected = [
      $driver => [
        'driver' => $driver,
        'namespace' => $expected_namespace,
        'prefix' => '',
      ],
    ];
    if (!is_null($expected_autoload)) {
      $expected[$driver]['autoload'] = $expected_autoload;
    }
    $this->assertEquals($expected, Database::getConnectionInfo('mock'));
  }

  /**
   * Provides data for testDatabaseInfoInitialization().
   */
  public function providerTestDatabaseInfoInitialization(): array {
    return [
      ['mysql', NULL, NULL, 'Drupal\\mysql\\Driver\\Database\\mysql', 'core/modules/mysql/src/Driver/Database/mysql/'],
      ['mysql', '', NULL, 'Drupal\\mysql\\Driver\\Database\\mysql', 'core/modules/mysql/src/Driver/Database/mysql/'],
      ['mysql', 'Drupal\\Core\\Database\\Driver\\mysql', NULL, 'Drupal\\mysql\\Driver\\Database\\mysql', 'core/modules/mysql/src/Driver/Database/mysql/'],
      ['mysql', 'Drupal\\mysql\\Driver\\Database\\mysql', NULL, 'Drupal\\mysql\\Driver\\Database\\mysql', 'core/modules/mysql/src/Driver/Database/mysql/'],
      ['mysql', 'Drupal\\Driver\\Database\\mysql', NULL, 'Drupal\\Driver\\Database\\mysql', NULL],
      ['mysql', 'Drupal\\mysql\\Driver\\Database\\mysql', 'modules/custom/mysql/src/Driver/Database/mysql/', 'Drupal\\mysql\\Driver\\Database\\mysql', 'modules/custom/mysql/src/Driver/Database/mysql/'],

      ['pgsql', NULL, NULL, 'Drupal\\pgsql\\Driver\\Database\\pgsql', 'core/modules/pgsql/src/Driver/Database/pgsql/'],
      ['pgsql', '', NULL, 'Drupal\\pgsql\\Driver\\Database\\pgsql', 'core/modules/pgsql/src/Driver/Database/pgsql/'],
      ['pgsql', 'Drupal\\Core\\Database\\Driver\\pgsql', NULL, 'Drupal\\pgsql\\Driver\\Database\\pgsql', 'core/modules/pgsql/src/Driver/Database/pgsql/'],
      ['pgsql', 'Drupal\\pgsql\\Driver\\Database\\pgsql', NULL, 'Drupal\\pgsql\\Driver\\Database\\pgsql', 'core/modules/pgsql/src/Driver/Database/pgsql/'],
      ['pgsql', 'Drupal\\Driver\\Database\\pgsql', NULL, 'Drupal\\Driver\\Database\\pgsql', NULL],
      ['pgsql', 'Drupal\\pgsql\\Driver\\Database\\pgsql', 'modules/custom/pgsql/src/Driver/Database/pgsql/', 'Drupal\\pgsql\\Driver\\Database\\pgsql', 'modules/custom/pgsql/src/Driver/Database/pgsql/'],

      ['sqlite', NULL, NULL, 'Drupal\\sqlite\\Driver\\Database\\sqlite', 'core/modules/sqlite/src/Driver/Database/sqlite/'],
      ['sqlite', '', NULL, 'Drupal\\sqlite\\Driver\\Database\\sqlite', 'core/modules/sqlite/src/Driver/Database/sqlite/'],
      ['sqlite', 'Drupal\\Core\\Database\\Driver\\sqlite', NULL, 'Drupal\\sqlite\\Driver\\Database\\sqlite', 'core/modules/sqlite/src/Driver/Database/sqlite/'],
      ['sqlite', 'Drupal\\sqlite\\Driver\\Database\\sqlite', NULL, 'Drupal\\sqlite\\Driver\\Database\\sqlite', 'core/modules/sqlite/src/Driver/Database/sqlite/'],
      ['sqlite', 'Drupal\\Driver\\Database\\sqlite', NULL, 'Drupal\\Driver\\Database\\sqlite', NULL],
      ['sqlite', 'Drupal\\sqlite\\Driver\\Database\\sqlite', 'modules/custom/sqlite/src/Driver/Database/sqlite/', 'Drupal\\sqlite\\Driver\\Database\\sqlite', 'modules/custom/sqlite/src/Driver/Database/sqlite/'],
    ];
  }

}