class 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
- class \Drupal\Core\Extension\ExtensionList- class \Drupal\Core\Extension\ModuleExtensionList uses \Drupal\Core\StringTranslation\StringTranslationTrait extends \Drupal\Core\Extension\ExtensionList
 
Expanded class hierarchy of ModuleExtensionList
26 files declare their use of ModuleExtensionList
- AdminController.php in core/modules/ system/ src/ Controller/ AdminController.php 
- CKEditor.php in core/modules/ ckeditor/ src/ Plugin/ Editor/ CKEditor.php 
- CKEditorPluginBase.php in core/modules/ ckeditor/ src/ CKEditorPluginBase.php 
- ConfigImporter.php in core/lib/ Drupal/ Core/ Config/ ConfigImporter.php 
- ConfigImportSubscriber.php in core/lib/ Drupal/ Core/ EventSubscriber/ ConfigImportSubscriber.php 
1 string reference to 'ModuleExtensionList'
- core.services.yml in core/core.services.yml 
- core/core.services.yml
1 service uses ModuleExtensionList
File
- 
              core/lib/ Drupal/ Core/ Extension/ ModuleExtensionList.php, line 20 
Namespace
Drupal\Core\ExtensionView 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 ($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 = $installed_modules[$name] ?? 0;
      $module->status = (int) isset($installed_modules[$name]);
      $module->schema_version = UpdateHookRegistry::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. | ||
| ExtensionList::sortByName | public static | function | Array sorting callback; sorts extensions by their name. | ||
| 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. | 3 | |
| 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.
