ide_helper-8.x-2.x-dev/src/Handlers/PhpStormMetaCollector.php

src/Handlers/PhpStormMetaCollector.php
<?php

declare(strict_types = 1);

namespace Drupal\ide_helper\Handlers;

use Drupal\Component\Serialization\SerializationInterface;
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\ide_helper\Utils;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Webmozart\PathUtil\Path;

class PhpStormMetaCollector implements ContainerInjectionInterface {

  protected array $extensions = [];

  protected array $phpStormMeta = [];

  protected array $allServices = [];

  protected ModuleHandlerInterface $moduleHandler;

  protected EntityTypeManagerInterface $entityTypeManager;

  protected ConfigEntityStorageInterface $fieldStorageConfigStorage;

  protected FieldTypePluginManagerInterface $fieldTypePluginManager;

  protected SerializationInterface $yaml;

  protected string $drupalRoot = '';

  protected string $packageNamePrefix = 'drupal';

  public function getDrupalRoot(): string {
    return $this->drupalRoot;
  }

  protected function getDrupalRootWithFallback(): string {
    $drupalRoot = $this->getDrupalRoot();
    if (!$drupalRoot && defined('DRUPAL_ROOT')) {
      $drupalRoot = DRUPAL_ROOT;
    }

    return $drupalRoot ?: '.';
  }

  /**
   * @return $this
   */
  public function setDrupalRoot(string $value) {
    $this->drupalRoot = $value;

    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $entityTypeManager = $container->get('entity_type.manager');

    return new static(
      $container->get('module_handler'),
      $entityTypeManager,
      $entityTypeManager->getStorage('field_storage_config'),
      $container->get('plugin.manager.field.field_type'),
      $container->get('serialization.yaml'),
    );
  }

  public function __construct(
    ModuleHandlerInterface $moduleHandler,
    EntityTypeManagerInterface $entityTypeManager,
    ConfigEntityStorageInterface $fieldStorageConfigStorage,
    FieldTypePluginManagerInterface $fieldTypePluginManager,
    SerializationInterface $yaml
  ) {
    $this->moduleHandler = $moduleHandler;
    $this->entityTypeManager = $entityTypeManager;
    $this->fieldStorageConfigStorage = $fieldStorageConfigStorage;
    $this->fieldTypePluginManager = $fieldTypePluginManager;
    $this->yaml = $yaml;
  }

  public function collect(): array {
    return $this
      ->reset()
      ->initExtensions()
      ->processExtensions()
      ->processFields()
      ->phpStormMeta;
  }

  /**
   * @return $this
   */
  protected function reset() {
    $this->extensions = [];
    $this->phpStormMeta = [];

    return $this;
  }

  /**
   * @return $this
   */
  protected function initExtensions() {
    return $this
      ->initExtensionsEntityTypes()
      ->initExtensionsServices()
      ->initExtensionRouteNames();
  }

  /**
   * @return $this
   */
  protected function initExtensionsEntityTypes() {
    foreach ($this->entityTypeManager->getDefinitions() as $entityTypeDefinition) {
      $originalClass = $entityTypeDefinition->getOriginalClass();
      $extensionNameFull = $this->getExtensionNameFull(Utils::extensionNameFromFqn($originalClass));
      $this->extensions[$extensionNameFull]['entityTypes'][$entityTypeDefinition->id()] = $entityTypeDefinition;
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function initExtensionsServices() {
    $drupalRoot = $this->getDrupalRootWithFallback();
    $services = $this->yaml->decode(file_get_contents("$drupalRoot/core/core.services.yml"));
    $coreNameFull = $this->getExtensionNameFull('Core');
    $this->extensions[$coreNameFull]['services'] = $services['services'];
    $this->allServices = $services['services'];
    foreach ($this->moduleHandler->getModuleList() as $extension) {
      $path = $extension->getPath();
      $extensionName = $extension->getName();
      $extensionNameFull = $this->getExtensionNameFull($extensionName);
      $fileName = Path::join($drupalRoot, $path, "$extensionName.services.yml");
      if (!file_exists($fileName)) {
        continue;
      }

      $services = $this->yaml->decode(file_get_contents($fileName));
      if (!empty($services['services'])) {
        $this->allServices += $services['services'];
        $this->extensions[$extensionNameFull]['services'] = $services['services'];
      }
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function processExtensions() {
    foreach (array_keys($this->extensions) as $extensionNameFull) {
      $this->processExtension($extensionNameFull);
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function processExtension(string $extensionNameFull) {
    return $this
      ->processExtensionEntityTypes($extensionNameFull)
      ->processExtensionServices($extensionNameFull)
      ->processExtensionRouteNames($extensionNameFull);
  }

  /**
   * @return $this
   */
  protected function initExtensionRouteNames() {
    $drupalRoot = $this->getDrupalRoot();
    foreach ($this->moduleHandler->getModuleList() as $extension) {
      $path = $extension->getPath();
      $extensionName = $extension->getName();
      $extensionNameFull = $this->getExtensionNameFull($extensionName);
      $fileName = "$drupalRoot/$path/$extensionName.routing.yml";
      if (!file_exists($fileName)) {
        continue;
      }

      $this->extensions[$extensionNameFull]['routing'] = $this->yaml->decode(file_get_contents($fileName));
      unset($this->extensions[$extensionNameFull]['routing']['route_callbacks']);
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function processExtensionEntityTypes(string $extensionNameFull) {
    if (empty($this->extensions[$extensionNameFull]['entityTypes'])) {
      return $this;
    }

    $handlers = [
      [
        'name' => 'storage',
        'base' => 'Storage',
        'method' => 'getStorage(0)',
      ],
      [
        'name' => 'access',
        'base' => 'AccessControlHandler',
        'method' => 'getAccessControlHandler(0)',
      ],
      [
        'name' => 'list_builder',
        'base' => 'ListBuilder',
        'method' => 'getListBuilder(0)',
      ],
      [
        'name' => 'view_builder',
        'base' => 'ViewBuilder',
        'method' => 'getViewBuilder(0)',
      ],
    ];

    /** @var \Drupal\Core\Entity\EntityTypeInterface $entityType */
    foreach ($this->extensions[$extensionNameFull]['entityTypes'] as $entityType) {
      foreach ($handlers as $handler) {
        if (!$entityType->hasHandlerClass($handler['name'])) {
          continue;
        }

        $handlerClass = $entityType->getHandlerClass($handler['name']);
        $handlerInterface = Utils::getServiceHandlerInterface($handlerClass, $handler['base']);
        $this->addOverride(
          $extensionNameFull,
          EntityTypeManagerInterface::class,
          $handler['method'],
          [
            $entityType->id() => $handlerInterface ?: $handlerClass,
          ],
        );
      }
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function processExtensionServices(string $extensionNameFull) {
    if (empty($this->extensions[$extensionNameFull]['services'])) {
      return $this;
    }

    foreach ($this->extensions[$extensionNameFull]['services'] as $serviceName => $service) {
      $serviceClass = Utils::serviceClass($service, $this->allServices);
      if ($serviceClass) {
        $serviceClassName = Utils::classNameFromFqn($serviceClass);
        $this->addOverride(
          $extensionNameFull,
          ContainerInterface::class,
          'get(0)',
          [
            $serviceName => Utils::getServiceHandlerInterface($serviceClass, $serviceClassName) ?: $serviceClass,
          ],
        );

        $this->addOverride(
          $extensionNameFull,
          \Drupal::class,
          'service(0)',
          [
            $serviceName => Utils::getServiceHandlerInterface($serviceClass, $serviceClassName) ?: $serviceClass,
          ],
        );
      }
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function processExtensionRouteNames(string $extensionNameFull) {
    if (empty($this->extensions[$extensionNameFull]['routing'])) {
      return $this;
    }

    foreach (array_keys($this->extensions[$extensionNameFull]['routing']) as $routeName) {
      $this->addOverride(
        $extensionNameFull,
        Url::class,
        'fromRoute(0)',
        [
          $routeName => Url::class,
        ],
      );

      $this->addOverride(
        $extensionNameFull,
        Link::class,
        'createFromRoute(1)',
        [
          $routeName => Link::class,
        ],
      );
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function processFields() {
    /** @var \Drupal\field\Entity\FieldStorageConfig[] $fields */
    $fields = $this->fieldStorageConfigStorage->loadMultiple();
    $entityTypes = $this->entityTypeManager->getDefinitions();
    $fieldTypes = $this->fieldTypePluginManager->getDefinitions();

    $defaultFieldItemListInterface = FieldItemListInterface::class;
    foreach ($fields as $field) {
      $entityType = $entityTypes[$field->getTargetEntityTypeId()];
      $fieldName = $field->getName();
      $fieldType = $fieldTypes[$field->getType()];

      $entityTypeClass = $entityType->getClass();
      $entityTypeInterface = Utils::getServiceHandlerInterface($entityTypeClass, '');

      $fieldItemListInterface = Utils::getServiceHandlerInterface($fieldType['list_class'], '');
      if ($fieldItemListInterface === $defaultFieldItemListInterface) {
        continue;
      }

      $extensionNameFull = $this->getExtensionNameFull('field.fields');

      $this->addOverride(
        $extensionNameFull,
        $entityTypeInterface,
        'get(0)',
        [
          $fieldName => $fieldItemListInterface,
        ],
      );
    }

    return $this;
  }

  /**
   * @return $this
   */
  protected function addOverride(string $extensionNameFull, string $class, string $method, array $map) {
    $key = "$class::$method";
    if (!isset($this->phpStormMeta[$extensionNameFull]['overrides'][$key])) {
      $this->phpStormMeta[$extensionNameFull]['overrides'][$key] = [
        'class' => $class,
        'method' => $method,
        'map' => [],
      ];
    }

    $this->phpStormMeta[$extensionNameFull]['overrides'][$key]['map'] += $map;

    return $this;
  }

  protected function getExtensionNameFull(string $extensionName): string {
    return "{$this->packageNamePrefix}.{$extensionName}";
  }

}

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

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