You are here

public function ExtensionDiscovery::scan in Drupal 8

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Extension/ExtensionDiscovery.php \Drupal\Core\Extension\ExtensionDiscovery::scan()

Discovers available extensions of a given type.

Finds all extensions (modules, themes, etc) that exist on the site. It searches in several locations. For instance, to discover all available modules:

$listing = new ExtensionDiscovery(\Drupal::root());
$modules = $listing
  ->scan('module');

The following directories will be searched (in the order stated):

  • the core directory; i.e., /core
  • the installation profile directory; e.g., /core/profiles/standard
  • the legacy site-wide directory; i.e., /sites/all
  • the site-wide directory; i.e., /
  • the site-specific directory; e.g., /sites/example.com

To also find test modules, add

$settings['extension_discovery_scan_tests'] = TRUE;

to your settings.php.

The information is returned in an associative array, keyed by the extension name (without .info.yml extension). Extensions found later in the search will take precedence over extensions found earlier - unless they are not compatible with the current version of Drupal core.

Parameters

string $type: The extension type to search for. One of 'profile', 'module', 'theme', or 'theme_engine'.

bool $include_tests: (optional) Whether to explicitly include or exclude test extensions. By default, test extensions are only discovered when in a test environment.

Return value

\Drupal\Core\Extension\Extension[] An associative array of Extension objects, keyed by extension name.

File

core/lib/Drupal/Core/Extension/ExtensionDiscovery.php, line 152

Class

ExtensionDiscovery
Discovers available extensions in the filesystem.

Namespace

Drupal\Core\Extension

Code

public function scan($type, $include_tests = NULL) {

  // Determine the installation profile directories to scan for extensions,
  // unless explicit profile directories have been set. Exclude profiles as we
  // cannot have profiles within profiles.
  if (!isset($this->profileDirectories) && $type != 'profile') {
    $this
      ->setProfileDirectoriesFromSettings();
  }

  // Search the core directory.
  $searchdirs[static::ORIGIN_CORE] = 'core';

  // Search the legacy sites/all directory.
  $searchdirs[static::ORIGIN_SITES_ALL] = 'sites/all';

  // Search for contributed and custom extensions in top-level directories.
  // The scan uses a whitelist to limit recursion to the expected extension
  // type specific directory names only.
  $searchdirs[static::ORIGIN_ROOT] = '';

  // Simpletest uses the regular built-in multi-site functionality of Drupal
  // for running web tests. As a consequence, extensions of the parent site
  // located in a different site-specific directory are not discovered in a
  // test site environment, because the site directories are not the same.
  // Therefore, add the site directory of the parent site to the search paths,
  // so that contained extensions are still discovered.
  // @see \Drupal\simpletest\WebTestBase::setUp()
  if ($parent_site = Settings::get('test_parent_site')) {
    $searchdirs[static::ORIGIN_PARENT_SITE] = $parent_site;
  }

  // Find the site-specific directory to search. Since we are using this
  // method to discover extensions including profiles, we might be doing this
  // at install time. Therefore Kernel service is not always available, but is
  // preferred.
  if (\Drupal::hasService('kernel')) {
    $searchdirs[static::ORIGIN_SITE] = \Drupal::service('site.path');
  }
  else {
    $searchdirs[static::ORIGIN_SITE] = $this->sitePath ?: DrupalKernel::findSitePath(Request::createFromGlobals());
  }

  // Unless an explicit value has been passed, manually check whether we are
  // in a test environment, in which case test extensions must be included.
  // Test extensions can also be included for debugging purposes by setting a
  // variable in settings.php.
  if (!isset($include_tests)) {
    $include_tests = Settings::get('extension_discovery_scan_tests') || drupal_valid_test_ua();
  }
  $files = [];
  foreach ($searchdirs as $dir) {

    // Discover all extensions in the directory, unless we did already.
    if (!isset(static::$files[$this->root][$dir][$include_tests])) {
      static::$files[$this->root][$dir][$include_tests] = $this
        ->scanDirectory($dir, $include_tests);
    }

    // Only return extensions of the requested type.
    if (isset(static::$files[$this->root][$dir][$include_tests][$type])) {
      $files += static::$files[$this->root][$dir][$include_tests][$type];
    }
  }

  // If applicable, filter out extensions that do not belong to the current
  // installation profiles.
  $files = $this
    ->filterByProfileDirectories($files);

  // Sort the discovered extensions by their originating directories.
  $origin_weights = array_flip($searchdirs);
  $files = $this
    ->sort($files, $origin_weights);

  // Process and return the list of extensions keyed by extension name.
  return $this
    ->process($files);
}