drupal_static_autoloader-01.0/src/Autoloader.php

src/Autoloader.php
<?php declare(strict_types=1);

namespace mglaman\DrupalStaticAutoloader;

use DrupalFinder\DrupalFinder;
use mglaman\DrupalStaticAutoloader\Drupal\ExtensionDiscovery;
use mglaman\DrupalStaticAutoloader\Drupal\Extension;

final class Autoloader
{

  /**
   * @var string
   */
    private $drupalRoot;

  /**
   * @var string
   */
    private $drupalVendorRoot;

  /**
   * @var \Composer\Autoload\ClassLoader
   */
    private $autoloader;

  /**
   * @var \mglaman\DrupalStaticAutoloader\Drupal\ExtensionDiscovery
   */
    private $extensionDiscovery;

    // Taken from drupal_phpunit_get_extension_namespaces.
    private const PHPUNIT_TEST_SUITES = ['Unit', 'Kernel', 'Functional', 'Build', 'FunctionalJavascript'];

    public static function getLoader(string $root): self
    {
        return new self($root);
    }

    public function __construct(string $root)
    {
        if (!is_readable($root)) {
            throw new \InvalidArgumentException("Unable to read $root");
        }
        $finder = new DrupalFinder();
        $finder->locateRoot($root);
        $drupalRoot = $finder->getDrupalRoot();
        $drupalVendorRoot = $finder->getVendorDir();
        if (! (bool) $drupalRoot || ! (bool) $drupalVendorRoot) {
            throw new \InvalidArgumentException("Unable to detect Drupal at $root");
        }
        $this->drupalRoot = $drupalRoot;
        $this->drupalVendorRoot = $drupalVendorRoot;
        $this->autoloader = include $drupalVendorRoot . '/autoload.php';
    }

    public function register(): void
    {
        $this->loadLegacyIncludes();

        $this->extensionDiscovery = new ExtensionDiscovery($this->drupalRoot);

      // Discover all available profiles.
        $profiles = $this->extensionDiscovery->scan('profile');
        $profile_directories = array_map(static function (Extension $profile) : string {
            return $profile->getPath();
        }, $profiles);
        $this->extensionDiscovery->setProfileDirectories($profile_directories);

        $this->registerExtensions('module');
        $this->registerExtensions('theme');
        $this->registerExtensions('profile');
        $this->registerExtensions('theme_engine');

        $this->registerTestNamespaces();
        $this->loadDrushIncludes();
    }

    private function registerExtensions(string $type)
    {
        if ($type !== 'module' && $type !== 'theme' && $type !== 'profile' && $type !== 'theme_engine') {
            throw new \InvalidArgumentException("Must be 'module' or 'theme' but got $type");
        }
        // Tracks implementations of hook_hook_info for loading of those files.
        $hook_info_implementations = [];

        $extensions = $this->extensionDiscovery->scan($type);
        foreach ($extensions as $extension_name => $extension) {
            $extension_path = $this->drupalRoot . '/' . $extension->getPath();
            $this->autoloader->addPsr4("Drupal\\{$extension_name}\\", $extension_path . '/src');

            // @see drupal_phpunit_get_extension_namespaces().
            $test_dir = $extension_path . '/tests/src';
            foreach (self::PHPUNIT_TEST_SUITES as $suite_name) {
                $suite_dir = $test_dir . '/' . $suite_name;
                if (is_dir($suite_dir)) {
                    $this->autoloader->addPsr4("Drupal\\Tests\\$extension_name\\$suite_name\\", $suite_dir);
                }
            }
            // Extensions can have a \Drupal\extension\Traits namespace for
            // cross-suite trait code.
            $trait_dir = $test_dir . '/Traits';
            if (is_dir($trait_dir)) {
                $this->autoloader->addPsr4('Drupal\\Tests\\' . $extension_name . '\\Traits\\', $trait_dir);
            }

            $this->loadExtension($extension);

            // Load schema and post_update files.
            if (file_exists($extension_path . '/' . $extension_name . '.install')) {
                // These are ignored as they cause crashes.
                $ignored_install_files = ['entity_test', 'entity_test_update', 'update_test_schema'];
                if (!in_array($extension_name, $ignored_install_files, true)) {
                    require_once $extension_path . '/' . $extension_name . '.install';
                }
            }
            if (file_exists($extension_path . '/' . $extension_name . '.post_update.php')) {
                require_once $extension_path . '/' . $extension_name . '.post_update.php';
            }

            // Mimics the buildHookInfo method in the module handler.
            // @see \Drupal\Core\Extension\ModuleHandler::buildHookInfo
            if ($type === 'module' || $type === 'profile') {
                $hook_info_function = $extension_name . '_hook_info';
                if (function_exists($hook_info_function)) {
                    $result = $hook_info_function();
                    if (is_array($result)) {
                        $groups = array_unique(array_values(array_map(static function (array $hook_info) {
                            return $hook_info['group'];
                        }, $result)));
                        // We do not need the full array structure, we only care
                        // about the group name for loading files.
                        $hook_info_implementations[] = $groups;
                    }
                }
            }
        }

        // Iterate over hook_hook_info implementations and load those files.
        if (count($hook_info_implementations) > 0) {
            $hook_info_implementations = array_merge(...$hook_info_implementations);
            foreach ($hook_info_implementations as $hook_info_group) {
                foreach ($extensions as $extension_name => $extension) {
                    $include_file = $this->drupalRoot . '/' . $extension->getPath() . '/' . $extension_name . '.' . $hook_info_group . '.inc';
                    if (file_exists($include_file)) {
                        include_once $include_file;
                    }
                }
            }
        }
    }

    private function loadExtension(Extension $extension): void
    {
        try {
            $extension->load();
        } catch (\Throwable $e) {
          // Something prevented the extension file from loading.
          // This can happen when drupal_get_path or drupal_get_filename are used outside of the scope of a function.
        }
    }

    private function loadLegacyIncludes(): void
    {
        $this->loadIncludesByDirectory('drupal/core', $this->drupalRoot . '/core/includes');
    }

    private function loadDrushIncludes()
    {
        if (class_exists(\Drush\Drush::class)) {
            $reflect = new \ReflectionClass(\Drush\Drush::class);
            if ($reflect->getFileName() !== false) {
                $levels = 2;
                if (\Drush\Drush::getMajorVersion() < 9) {
                    $levels = 3;
                }
                $drushDir = dirname($reflect->getFileName(), $levels);
                $this->loadIncludesByDirectory('drush/drush', $drushDir);
            }
        }
    }

    private function loadIncludesByDirectory(string $package, string $absolute_path): void
    {
        $flags = \FilesystemIterator::UNIX_PATHS;
        $flags |= \FilesystemIterator::SKIP_DOTS;
        $flags |= \FilesystemIterator::FOLLOW_SYMLINKS;
        $flags |= \FilesystemIterator::CURRENT_AS_SELF;
        $directory_iterator = new \RecursiveDirectoryIterator($absolute_path, $flags);
        $iterator = new \RecursiveIteratorIterator(
            $directory_iterator,
            \RecursiveIteratorIterator::LEAVES_ONLY,
            // Suppress filesystem errors in case a directory cannot be accessed.
            \RecursiveIteratorIterator::CATCH_GET_CHILD
        );

        foreach ($iterator as $fileinfo) {
            // Check if this file was added as an autoloaded file in a
            // composer.json file.
            //
            // @see \Composer\Autoload\AutoloadGenerator::getFileIdentifier().
            $autoloadFileIdentifier = md5($package . ':includes/' . $fileinfo->getFilename());
            if (isset($GLOBALS['__composer_autoload_files'][$autoloadFileIdentifier])) {
                continue;
            }
            if ($fileinfo->getExtension() === 'inc') {
                require_once $fileinfo->getPathname();
            }
        }
    }

  /**
   * @see drupal_phpunit_populate_class_loader
   */
    private function registerTestNamespaces()
    {
      // Start with classes in known locations.
        $dir = $this->drupalRoot . '/core/tests';
        $this->autoloader->add('Drupal\\BuildTests', $dir);
        $this->autoloader->add('Drupal\\Tests', $dir);
        $this->autoloader->add('Drupal\\TestSite', $dir);
        $this->autoloader->add('Drupal\\KernelTests', $dir);
        $this->autoloader->add('Drupal\\FunctionalTests', $dir);
        $this->autoloader->add('Drupal\\FunctionalJavascriptTests', $dir);
        $this->autoloader->add('Drupal\\TestTools', $dir);
    }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc