diff -u b/core/core.services.yml b/core/core.services.yml --- b/core/core.services.yml +++ b/core/core.services.yml @@ -500,7 +500,7 @@ lazy: true profile_handler: class: Drupal\Core\Extension\ProfileHandler - arguments: ['@info_parser'] + arguments: ['@app.root', '@info_parser'] theme_handler: class: Drupal\Core\Extension\ThemeHandler arguments: ['@app.root', '@config.factory', '@module_handler', '@state', '@info_parser'] diff -u b/core/includes/install.core.inc b/core/includes/install.core.inc --- b/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -442,7 +442,10 @@ } // Ensure all profile directories are registered. $profile_handler = \Drupal::service('profile_handler'); - $profile_directories = $profile_handler->getProfileDependencies($profile); + $profiles = $profile_handler->getProfiles($profile); + $profile_directories = array_map(function($extension) { + return $extension->getPath(); + }, $profiles); $listing->setProfileDirectories($profile_directories); } @@ -1556,7 +1559,7 @@ */ function install_install_profile(&$install_state) { $profile_handler = \Drupal::service('profile_handler'); - $profiles = $profile_handler->getProfileDependencies(); + $profiles = $profile_handler->getProfiles(); // Install all the profiles. \Drupal::service('module_installer')->install(array_keys($profiles), FALSE); diff -u b/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php --- b/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -473,7 +473,7 @@ // Install profiles can not have config clashes. Configuration that // has the same name as a module's configuration will be used instead. - $profiles = $this->profileHandler->getProfileDependencies(); + $profiles = $this->profileHandler->getProfiles(); if (!isset($profiles[$name])) { // Throw an exception if the module being installed contains configuration // that already exists. Additionally, can not continue installing more diff -u b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php --- b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php +++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php @@ -118,15 +118,10 @@ // this by replacing the config file path from the module/theme with the // install profile version if there are any duplicates. if (isset($profile)) { - if (!isset($profile_list)) { - $profile_list = $listing->scan('profile'); - } - $profile_names = \Drupal::service('profile_handler')->getProfileDependencies($profile); - foreach ($profile_names as $profile_name => $profile_path) { - if (isset($profile_list[$profile_name])) { - $profile_folders = $this->getComponentNames(array($profile_list[$profile_name])); - $this->folders = $profile_folders + $this->folders; - } + $profiles = \Drupal::service('profile_handler')->getProfiles($profile); + foreach ($profiles as $extension) { + $profile_folders = $this->getComponentNames(array($extension)); + $this->folders = $profile_folders + $this->folders; } } } diff -u b/core/lib/Drupal/Core/Config/InstallStorage.php b/core/lib/Drupal/Core/Config/InstallStorage.php --- b/core/lib/Drupal/Core/Config/InstallStorage.php +++ b/core/lib/Drupal/Core/Config/InstallStorage.php @@ -156,17 +156,17 @@ // @todo Remove as part of https://www.drupal.org/node/2186491 $listing = new ExtensionDiscovery(\Drupal::root()); $profiles = $listing->scan('profile'); - foreach ($profiles as $profile_name => $profile_object) { + foreach ($profiles as $profile_name => $extension) { // Prime the drupal_get_filename() static cache with the profile info // file location so we can use drupal_get_path() on the active profile // during the module scan. // @todo Remove as part of https://www.drupal.org/node/2186491 - drupal_get_filename('profile', $profile_name, $profile_object->getPathname()); + drupal_get_filename('profile', $profile_name, $extension->getPathname()); } // Now that we can fetch the path, get dependent profiles and add the extensions - $profile_names = \Drupal::service('profile_handler')->getProfileDependencies(); - foreach ($profile_names as $profile_name => $profile_path) { - $this->folders += $this->getComponentNames(array($profiles[$profile_name])); + $profiles = \Drupal::service('profile_handler')->getProfiles(); + foreach ($profiles as $extension) { + $this->folders += $this->getComponentNames(array($extension)); } // @todo Remove as part of https://www.drupal.org/node/2186491 $this->folders += $this->getComponentNames($listing->scan('module')); diff -u b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php --- b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php @@ -253,7 +253,11 @@ // (@drupalKernel::moduleData) so check if profile_handler is available. if (\Drupal::hasService('profile_handler')) { $profile_handler = \Drupal::service('profile_handler'); - $this->profileDirectories = array_merge($profile_handler->getProfileDependencies($profile), $this->profileDirectories); + $profiles = $profile_handler->getProfiles($profile); + $profile_directories = array_map(function($extension) { + return $extension->getPath(); + }, $profiles); + $this->profileDirectories = array_merge($profile_directories, $this->profileDirectories); } else { $this->profileDirectories[] = drupal_get_path('profile', $profile); diff -u b/core/lib/Drupal/Core/Extension/ProfileHandler.php b/core/lib/Drupal/Core/Extension/ProfileHandler.php --- b/core/lib/Drupal/Core/Extension/ProfileHandler.php +++ b/core/lib/Drupal/Core/Extension/ProfileHandler.php @@ -17,6 +17,13 @@ protected static $cache = array(); /** + * The app root. + * + * @var string + */ + protected $root; + + /** * The info parser to parse the profile.info.yml files. * * @var \Drupal\Core\Extension\InfoParserInterface @@ -26,22 +33,29 @@ /** * Constructs a new ProfileHandler. * + * @param string $root + * The app root. * @param \Drupal\Core\Extension\InfoParserInterface $info_parser * The info parser to parse the profile.info.yml files. */ - public function __construct(InfoParserInterface $info_parser) { + public function __construct($root, InfoParserInterface $info_parser) { + $this->root = $root; $this->infoParser = $info_parser; } /** * {@inheritdoc} */ - public function getProfileDependencies($profile = NULL) { + public function getProfiles($profile = NULL) { + static $weight; + if (empty($profile)) { $profile = drupal_get_profile(); } if (!isset(static::$cache[$profile])) { $profiles = array(); + // Starting weight for profiles ensures their hooks run last. + $weight = 1000; // Check if a valid profile name was given. if (!empty($profile)) { // We can't use install_profile_info() because that could trigger an @@ -49,15 +63,39 @@ $profile_path = drupal_get_path('profile', $profile); $profile_file = $profile_path . "/$profile.info.yml"; $profile_info = $this->infoParser->parse($profile_file); + $type = $profile_info['type']; // Check of the profile has a base profile and if so add it - recursion. $base_profile_name = !empty($profile_info['base profile']['name']) ? $profile_info['base profile']['name'] : (!empty($profile_info['base profile']) ? $profile_info['base profile'] : ''); if ($base_profile_name) { - $profiles += $this->getProfileDependencies($base_profile_name); + $profiles += $this->getProfiles($base_profile_name); + $weight++; + } + + $filename = file_exists($profile_path . "/$profile.$type") ? "$profile.$type" : NULL; + $extension = new Extension($this->root, $type, $profile_file, $filename); + + // Installation profiles are hidden by default, unless explicitly specified + // otherwise in the .info.yml file. + if (!isset($profile_info['hidden'])) { + $profile_info['hidden'] = TRUE; + } + + // The installation profile is required, if it's a valid module. + $profile_info['required'] = TRUE; + // Add a default distribution name if the profile did not provide one. + // @see install_profile_info() + // @see drupal_install_profile_distribution_name() + if (!isset($profile_info['distribution']['name'])) { + $profile_info['distribution']['name'] = 'Drupal'; } + + $extension->info = $profile_info; + $extension->weight = $weight; + // Add requested profile as last one. - $profiles[$profile] = $profile_path; + $profiles[$profile] = $extension; } static::$cache[$profile] = $profiles; } diff -u b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php --- b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php +++ b/core/lib/Drupal/Core/Extension/ProfileHandlerInterface.php @@ -15,9 +15,9 @@ * * @return array - * List of dependent installation profiles paths keys by profile name + * List of installation profile extensions keyed by profile name * in descending order of their dependencies. * (parent profiles first, main profile last) */ - public function getProfileDependencies($profile = NULL); + public function getProfiles($profile = NULL); } diff -u b/core/modules/system/system.module b/core/modules/system/system.module --- b/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -963,27 +963,20 @@ // module scan as the module scan requires knowing what the active profile is. // @todo Remove as part of https://www.drupal.org/node/2186491. $profiles = $listing->scan('profile'); - foreach ($profiles as $profile_name => $profile) { + foreach ($profiles as $profile_name => $extension) { // Prime the drupal_get_filename() static cache with the profile info file // location so we can use drupal_get_path() on the active profile during // the module scan. // @todo Remove as part of https://www.drupal.org/node/2186491. - drupal_get_filename('profile', $profile_name, $profile->getPathname()); + drupal_get_filename('profile', $profile_name, $extension->getPathname()); } // Find modules. $modules = $listing->scan('module'); - $profile = drupal_get_profile(); - $profile_names = array_keys(\Drupal::service('profile_handler')->getProfileDependencies($profile)); - // Include the installation profile in modules that are loaded. - $weight = 1000; - foreach ($profile_names as $profile_name) { - $modules[$profile_name] = $profiles[$profile_name]; - // Installation profile hooks are always executed last. - $modules[$profile_name]->weight = $weight; - $weight++; - } + // Find profiles. + $profiles = \Drupal::service('profile_handler')->getProfiles(); + $modules = array_merge($modules, $profiles); // Set defaults for module info. $defaults = array( @@ -997,7 +990,9 @@ // Read info files for each module. foreach ($modules as $key => $module) { // Look for the info file. - $module->info = \Drupal::service('info_parser')->parse($module->getPathname()); + if (empty($module->info)) { + $module->info = \Drupal::service('info_parser')->parse($module->getPathname()); + } // Add the info file modification time, so it becomes available for // contributed modules to use for ordering module lists. @@ -1006,12 +1001,6 @@ // Merge in defaults and save. $modules[$key]->info = $module->info + $defaults; - // Installation profiles are hidden by default, unless explicitly specified - // otherwise in the .info.yml file. - if (in_array($key, $profile_names) && !isset($modules[$key]->info['hidden'])) { - $modules[$key]->info['hidden'] = TRUE; - } - // Invoke hook_system_info_alter() to give installed modules a chance to // modify the data in the .info.yml files if necessary. // @todo Remove $type argument, obsolete with $module->getType(). @@ -1025,18 +1014,6 @@ _system_rebuild_module_data_ensure_required($module, $modules); } - - if ($profile && isset($modules[$profile])) { - // The installation profile is required, if it's a valid module. - $modules[$profile]->info['required'] = TRUE; - // Add a default distribution name if the profile did not provide one. - // @see install_profile_info() - // @see drupal_install_profile_distribution_name() - if (!isset($modules[$profile]->info['distribution']['name'])) { - $modules[$profile]->info['distribution']['name'] = 'Drupal'; - } - } - return $modules; }