diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 1019270..2b1fca2 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -2182,6 +2182,16 @@ function install_write_profile($install_state) { 'value' => $install_state['parameters']['profile'], 'required' => TRUE, ); + } + // Add specified base_profile to the settings profile_directories. + if (!empty($install_state['profile_info']['base_profile']) && isset($install_state['profiles'][$install_state['profile_info']['base_profile']]) && empty(Settings::get('profile_directories'))) { + $path = $install_state['profiles'][$install_state['profile_info']['base_profile']]->getPath(); + $settings['settings']['profile_directories'] = (object) array( + 'value' => array($path), + 'required' => TRUE, + ); + } + if (!empty($settings)) { drupal_rewrite_settings($settings); } } diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 1c8068b..08826c3 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -744,6 +744,10 @@ protected function moduleData($module) { $profile_directories = array_map(function ($profile) { return $profile->getPath(); }, $profiles); + + // Allow additional profile directories to be added from settings.php. + // This provides support for "base profiles". + $profile_directories = array_merge(Settings::get('profile_directories', []), $profile_directories); $listing->setProfileDirectories($profile_directories); // Now find modules. diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php index 337629b..83d0b6b 100644 --- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php @@ -16,6 +16,13 @@ * $settings['extension_discovery_scan_tests'] = TRUE; * @endcode * to your settings.php. + * + * To add additional profile directories, add + * @code + * $settings['profile_directories'] = array(path); + * @encode + * to your settings.php. If multiple paths are specified, they are searched + * from last to first. */ class ExtensionDiscovery { @@ -250,6 +257,11 @@ public function setProfileDirectoriesFromSettings() { if ($profile) { $this->profileDirectories[] = drupal_get_path('profile', $profile); } + + // Allow additional profile directories to be added from settings.php. + // This provides support for "base profiles". + $this->profileDirectories = array_merge(Settings::get('profile_directories', []), $this->profileDirectories); + return $this; } diff --git a/core/modules/system/tests/src/Kernel/System/ExtensionDiscoveryProfilesTest.php b/core/modules/system/tests/src/Kernel/System/ExtensionDiscoveryProfilesTest.php new file mode 100644 index 0000000..9f0c03a --- /dev/null +++ b/core/modules/system/tests/src/Kernel/System/ExtensionDiscoveryProfilesTest.php @@ -0,0 +1,69 @@ +populateFilesystemStructure($filesystem); + + $vfs = vfsStream::setup('root', NULL, $filesystem); + $root = $vfs->url(); + + // Define the module files we will search for, and the directory precedence + // we expect. + $expected_directories = array( + // When both copies of the module are compatible with Drupal core, the + // copy in the profile directory takes precedence. + 'drupal_system_listing_compatible_test' => array( + 'core/profiles/testing/modules', + 'core/modules/system/tests/modules', + ), + ); + + // This test relies on two versions of the same module existing in + // different places in the filesystem. Without that, the test has no + // meaning, so assert their presence first. + foreach ($expected_directories as $module => $directories) { + foreach ($directories as $directory) { + $filename = "$directory/$module/$module.info.yml"; + $this->assertFileExists($root . $filename); + } + } + + // Now add the testing profile path to settings. + $settings = Settings::getAll(); + $settings['profile_directories'] = array ( + 0 => 'core/profiles/testing', + ); + new Settings($settings); + + // Now scan the directories and check that the files take precedence as + // expected. + $listing = new ExtensionDiscovery($root); + $files = $listing->scan('module'); + foreach ($expected_directories as $module => $directories) { + $expected_directory = array_shift($directories); + $expected_uri = "$expected_directory/$module/$module.info.yml"; + $this->assertEqual($files[$module]->getPathname(), $expected_uri, format_string('Module @actual was found at @expected.', array( + '@actual' => $files[$module]->getPathname(), + '@expected' => $expected_uri, + ))); + } + } +}