Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. ExtensionDiscovery.php

function ExtensionDiscovery::scanDirectory

Same name in this branch
  1. 11.1.x core/lib/Drupal/Core/Extension/ExtensionDiscovery.php \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory()

Recursively scans a base directory for the extensions it contains.

Parameters

string $dir: A relative base directory path to scan, without trailing slash.

Return value

array An associative array whose keys are extension type names and whose values are associative arrays of \Drupal\Core\Extension\Extension objects, keyed by absolute path name.

See also

\mglaman\PHPStanDrupal\Drupal\RecursiveExtensionFilterIterator

1 call to ExtensionDiscovery::scanDirectory()
ExtensionDiscovery::scan in vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php
Discovers available extensions of a given type.

File

vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php, line 329

Class

ExtensionDiscovery

Namespace

mglaman\PHPStanDrupal\Drupal

Code

protected function scanDirectory($dir) : array {
    $files = [];
    // In order to scan top-level directories, absolute directory paths have to
    // be used (which also improves performance, since any configured PHP
    // include_paths will not be consulted). Retain the relative originating
    // directory being scanned, so relative paths can be reconstructed below
    // (all paths are expected to be relative to $this->root).
    $dir_prefix = $dir === '' ? '' : "{$dir}/";
    $absolute_dir = $dir === '' ? $this->root : $this->root . "/{$dir}";
    if (!is_dir($absolute_dir)) {
        return $files;
    }
    // Use Unix paths regardless of platform, skip dot directories, follow
    // symlinks (to allow extensions to be linked from elsewhere), and return
    // the RecursiveDirectoryIterator instance to have access to getSubPath(),
    // since SplFileInfo does not support relative paths.
    $flags = FilesystemIterator::UNIX_PATHS;
    $flags |= FilesystemIterator::SKIP_DOTS;
    $flags |= FilesystemIterator::FOLLOW_SYMLINKS;
    $flags |= FilesystemIterator::CURRENT_AS_SELF;
    $directory_iterator = new RecursiveDirectoryIterator($absolute_dir, $flags);
    // Allow directories specified in settings.php to be ignored. You can use
    // this to not check for files in common special-purpose directories. For
    // example, node_modules and bower_components. Ignoring irrelevant
    // directories is a performance boost.
    $ignore_directories = [
        'node_modules',
        'bower_components',
    ];
    // Filter the recursive scan to discover extensions only.
    // Important: Without a RecursiveFilterIterator, RecursiveDirectoryIterator
    // would recurse into the entire filesystem directory tree without any kind
    // of limitations.
    $filter = new RecursiveExtensionFilterIterator($directory_iterator, $ignore_directories);
    // The actual recursive filesystem scan is only invoked by instantiating the
    // RecursiveIteratorIterator.
    $iterator = new RecursiveIteratorIterator($filter, RecursiveIteratorIterator::LEAVES_ONLY, RecursiveIteratorIterator::CATCH_GET_CHILD);
    foreach ($iterator as $key => $fileinfo) {
        // All extension names in Drupal have to be valid PHP function names due
        // to the module hook architecture.
        if (preg_match(self::PHP_FUNCTION_PATTERN, $fileinfo->getBasename('.info.yml')) !== 1) {
            continue;
        }
        // This test module has a function declaration that conflicts with another module. Explicitly skip it.
        // @see https://www.drupal.org/project/drupal/issues/3020142
        // @todo remove when Drupal core fixed.
        if ($fileinfo->getBasename('.info.yml') === 'no_transitions_css') {
            continue;
        }
        // Determine extension type from info file.
        $type = false;
        $file = $fileinfo->openFile('r');
        while ($type === false && !$file->eof()) {
            if ($line = $file->fgets()) {
                preg_match('@^type:\\s*(\'|")?(\\w+)\\1?\\s*$@', $line, $matches);
                if (isset($matches[2])) {
                    $type = $matches[2];
                }
            }
        }
        if ($type === false) {
            continue;
        }
        $name = $fileinfo->getBasename('.info.yml');
        $pathname = $dir_prefix . $fileinfo->getSubPathname();
        // Determine whether the extension has a main extension file.
        // For theme engines, the file extension is .engine.
        if ($type === 'theme_engine') {
            $filename = $name . '.engine';
        }
        else {
            $filename = $name . '.' . $type;
        }
        if (!file_exists($this->root . '/' . dirname($pathname) . '/' . $filename)) {
            $filename = null;
        }
        $extension = new Extension($this->root, $type, $pathname, $filename);
        // Track the originating directory for sorting purposes.
        $extension->subpath = $fileinfo->getSubPath();
        $extension->origin = $dir;
        $files[$type][$key] = $extension;
    }
    return $files;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal