class ModuleExtensionList

Same name in other branches
  1. 9 core/lib/Drupal/Core/Extension/ModuleExtensionList.php \Drupal\Core\Extension\ModuleExtensionList
  2. 10 core/lib/Drupal/Core/Extension/ModuleExtensionList.php \Drupal\Core\Extension\ModuleExtensionList
  3. 11.x core/lib/Drupal/Core/Extension/ModuleExtensionList.php \Drupal\Core\Extension\ModuleExtensionList

Provides a list of available modules.

@internal This class is not yet stable and therefore there are no guarantees that the internal implementations including constructor signature and protected properties / methods will not change over time. This will be reviewed after https://www.drupal.org/project/drupal/issues/2940481

Hierarchy

Expanded class hierarchy of ModuleExtensionList

15 files declare their use of ModuleExtensionList
AdminController.php in core/modules/system/src/Controller/AdminController.php
ConfigImporter.php in core/lib/Drupal/Core/Config/ConfigImporter.php
ConfigImportSubscriber.php in core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
ConfigSingleImportForm.php in core/modules/config/src/Form/ConfigSingleImportForm.php
ConfigSync.php in core/modules/config/src/Form/ConfigSync.php

... See full list

1 string reference to 'ModuleExtensionList'
core.services.yml in core/core.services.yml
core/core.services.yml
1 service uses ModuleExtensionList
extension.list.module in core/core.services.yml
Drupal\Core\Extension\ModuleExtensionList

File

core/lib/Drupal/Core/Extension/ModuleExtensionList.php, line 19

Namespace

Drupal\Core\Extension
View source
class ModuleExtensionList extends ExtensionList {
    use StringTranslationTrait;
    
    /**
     * {@inheritdoc}
     */
    protected $defaults = [
        'dependencies' => [],
        'description' => '',
        'package' => 'Other',
        'version' => NULL,
        'php' => DRUPAL_MINIMUM_PHP,
    ];
    
    /**
     * The config factory.
     *
     * @var \Drupal\Core\Config\ConfigFactoryInterface
     */
    protected $configFactory;
    
    /**
     * The profile list needed by this module list.
     *
     * @var \Drupal\Core\Extension\ExtensionList
     */
    protected $profileList;
    
    /**
     * Constructs a new ModuleExtensionList instance.
     *
     * @param string $root
     *   The app root.
     * @param string $type
     *   The extension type.
     * @param \Drupal\Core\Cache\CacheBackendInterface $cache
     *   The cache.
     * @param \Drupal\Core\Extension\InfoParserInterface $info_parser
     *   The info parser.
     * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
     *   The module handler.
     * @param \Drupal\Core\State\StateInterface $state
     *   The state.
     * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
     *   The config factory.
     * @param \Drupal\Core\Extension\ExtensionList $profile_list
     *   The site profile listing.
     * @param string $install_profile
     *   The install profile used by the site.
     * @param array[] $container_modules_info
     *   (optional) The module locations coming from the compiled container.
     */
    public function __construct($root, $type, CacheBackendInterface $cache, InfoParserInterface $info_parser, ModuleHandlerInterface $module_handler, StateInterface $state, ConfigFactoryInterface $config_factory, ExtensionList $profile_list, $install_profile, array $container_modules_info = []) {
        parent::__construct($root, $type, $cache, $info_parser, $module_handler, $state, $install_profile);
        $this->configFactory = $config_factory;
        $this->profileList = $profile_list;
        // Use the information from the container. This is an optimization.
        foreach ($container_modules_info as $module_name => $info) {
            $this->setPathname($module_name, $info['pathname']);
        }
    }
    
    /**
     * {@inheritdoc}
     */
    protected function getExtensionDiscovery() {
        $discovery = parent::getExtensionDiscovery();
        if ($active_profile = $this->getActiveProfile()) {
            $discovery->setProfileDirectories($this->getProfileDirectories($discovery));
        }
        return $discovery;
    }
    
    /**
     * Finds all installation profile paths.
     *
     * @param \Drupal\Core\Extension\ExtensionDiscovery $discovery
     *   The extension discovery.
     *
     * @return string[]
     *   Paths to all installation profiles.
     */
    protected function getProfileDirectories(ExtensionDiscovery $discovery) {
        $discovery->setProfileDirectories([]);
        $all_profiles = $discovery->scan('profile');
        $active_profile = $all_profiles[$this->installProfile];
        $profiles = array_intersect_key($all_profiles, $this->configFactory
            ->get('core.extension')
            ->get('module') ?: [
            $active_profile->getName() => 0,
        ]);
        $profile_directories = array_map(function (Extension $profile) {
            return $profile->getPath();
        }, $profiles);
        return $profile_directories;
    }
    
    /**
     * Gets the processed active profile object, or null.
     *
     * @return \Drupal\Core\Extension\Extension|null
     *   The active profile, if there is one.
     */
    protected function getActiveProfile() {
        $profiles = $this->profileList
            ->getList();
        if ($this->installProfile && isset($profiles[$this->installProfile])) {
            return $profiles[$this->installProfile];
        }
        return NULL;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function doScanExtensions() {
        $extensions = parent::doScanExtensions();
        $profiles = $this->profileList
            ->getList();
        // Modify the active profile object that was previously added to the module
        // list.
        if ($this->installProfile && isset($profiles[$this->installProfile])) {
            $extensions[$this->installProfile] = $profiles[$this->installProfile];
        }
        return $extensions;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function doList() {
        // Find modules.
        $extensions = parent::doList();
        // It is possible that a module was marked as required by
        // hook_system_info_alter() and modules that it depends on are not required.
        foreach ($extensions as $extension) {
            $this->ensureRequiredDependencies($extension, $extensions);
        }
        // Add status, weight, and schema version.
        $installed_modules = $this->configFactory
            ->get('core.extension')
            ->get('module') ?: [];
        foreach ($extensions as $name => $module) {
            $module->weight = isset($installed_modules[$name]) ? $installed_modules[$name] : 0;
            $module->status = (int) isset($installed_modules[$name]);
            $module->schema_version = SCHEMA_UNINSTALLED;
        }
        $extensions = $this->moduleHandler
            ->buildModuleDependencies($extensions);
        if ($this->installProfile && $extensions[$this->installProfile]) {
            $active_profile = $extensions[$this->installProfile];
            // Installation profile hooks are always executed last.
            $active_profile->weight = 1000;
            // Installation profiles are hidden by default, unless explicitly
            // specified otherwise in the .info.yml file.
            if (!isset($active_profile->info['hidden'])) {
                $active_profile->info['hidden'] = TRUE;
            }
            // The installation profile is required.
            $active_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($active_profile->info['distribution']['name'])) {
                $active_profile->info['distribution']['name'] = 'Drupal';
            }
        }
        return $extensions;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function getInstalledExtensionNames() {
        return array_keys($this->moduleHandler
            ->getModuleList());
    }
    
    /**
     * Marks dependencies of required modules as 'required', recursively.
     *
     * @param \Drupal\Core\Extension\Extension $module
     *   The module extension object.
     * @param \Drupal\Core\Extension\Extension[] $modules
     *   Extension objects for all available modules.
     */
    protected function ensureRequiredDependencies(Extension $module, array $modules = []) {
        if (!empty($module->info['required'])) {
            foreach ($module->info['dependencies'] as $dependency) {
                $dependency_name = Dependency::createFromString($dependency)->getName();
                if (!isset($modules[$dependency_name]->info['required'])) {
                    $modules[$dependency_name]->info['required'] = TRUE;
                    $modules[$dependency_name]->info['explanation'] = $this->t('Dependency of required module @module', [
                        '@module' => $module->info['name'],
                    ]);
                    // Ensure any dependencies it has are required.
                    $this->ensureRequiredDependencies($modules[$dependency_name], $modules);
                }
            }
        }
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
ExtensionList::$addedPathNames protected property A list of extension folder names directly added in code (not discovered).
ExtensionList::$cache protected property The cache.
ExtensionList::$extensionInfo protected property Static caching for extension info.
ExtensionList::$extensions protected property The cached extensions.
ExtensionList::$infoParser protected property The info parser.
ExtensionList::$installProfile protected property The install profile used by the site.
ExtensionList::$moduleHandler protected property The module handler.
ExtensionList::$pathNames protected property A list of extension folder names keyed by extension name.
ExtensionList::$root protected property The app root.
ExtensionList::$state protected property The state store.
ExtensionList::$type protected property The type of the extension: "module", "theme" or "profile".
ExtensionList::checkIncompatibility public function Tests the compatibility of an extension.
ExtensionList::createExtensionInfo protected function Creates the info value for an extension object. 1
ExtensionList::exists public function Determines if an extension exists in the filesystem.
ExtensionList::get public function Returns a single extension.
ExtensionList::getAllAvailableInfo public function Returns an array of info files information of available extensions.
ExtensionList::getAllInstalledInfo public function Returns an array of info files information of installed extensions.
ExtensionList::getExtensionInfo public function Returns information about a specified extension.
ExtensionList::getInfoCacheId protected function Returns the extension info cache ID.
ExtensionList::getList public function Returns all available extensions.
ExtensionList::getListCacheId protected function Returns the extension list cache ID.
ExtensionList::getName public function Returns the human-readable name of the extension.
ExtensionList::getPath public function Gets the path to an extension of a specific type (module, theme, etc.).
ExtensionList::getPathname public function Gets the info file path for an extension.
ExtensionList::getPathnames public function Returns a list of extension file paths keyed by machine name.
ExtensionList::getPathnamesCacheId protected function Returns the extension filenames cache ID.
ExtensionList::recalculateInfo protected function Generates the information from .info.yml files for extensions of this type.
ExtensionList::recalculatePathnames protected function Generates a sorted list of .info.yml file locations for all extensions.
ExtensionList::reset public function Resets the stored extension list. 1
ExtensionList::setPathname public function Sets the pathname for an extension.
ModuleExtensionList::$configFactory protected property The config factory.
ModuleExtensionList::$defaults protected property Default values to be merged into *.info.yml file arrays. Overrides ExtensionList::$defaults
ModuleExtensionList::$profileList protected property The profile list needed by this module list.
ModuleExtensionList::doList protected function Builds the list of extensions. Overrides ExtensionList::doList
ModuleExtensionList::doScanExtensions protected function Scans the available extensions. Overrides ExtensionList::doScanExtensions
ModuleExtensionList::ensureRequiredDependencies protected function Marks dependencies of required modules as 'required', recursively.
ModuleExtensionList::getActiveProfile protected function Gets the processed active profile object, or null.
ModuleExtensionList::getExtensionDiscovery protected function Returns the extension discovery. Overrides ExtensionList::getExtensionDiscovery
ModuleExtensionList::getInstalledExtensionNames protected function Returns a list of machine names of installed extensions. Overrides ExtensionList::getInstalledExtensionNames
ModuleExtensionList::getProfileDirectories protected function Finds all installation profile paths.
ModuleExtensionList::__construct public function Constructs a new ModuleExtensionList instance. Overrides ExtensionList::__construct
StringTranslationTrait::$stringTranslation protected property The string translation service.
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.

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