webprofiler-10.0.x-dev/src/Entity/EntityTypeManagerWrapper.php

src/Entity/EntityTypeManagerWrapper.php
<?php

declare(strict_types=1);

namespace Drupal\webprofiler\Entity;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityViewBuilderInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\PhpStorage\PhpStorageFactory;
use Drupal\Core\StringTranslation\TranslationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Wrap the entity type manager service to collect loaded and rendered entities.
 */
class EntityTypeManagerWrapper extends EntityTypeManager implements EntityTypeManagerInterface {

  /**
   * Loaded entities.
   *
   * @var array
   */
  private array $loaded;

  /**
   * Rendered entities.
   *
   * @var array
   */
  private array $rendered;

  /**
   * The original entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   *
   * @phpstan-ignore-next-line
   */
  private EntityTypeManagerInterface $entityManager;

  /**
   * EntityTypeManagerWrapper constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
   *   The original entity manager service.
   * @param \Traversable $namespaces
   *   An object that implements \Traversable which contains the root paths
   *   keyed by the corresponding namespace to look for plugin implementations.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache backend to use.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation.
   * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
   *   The class resolver.
   * @param \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository
   *   The entity last installed schema repository.
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The container.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_manager,
    \Traversable $namespaces,
    ModuleHandlerInterface $module_handler,
    CacheBackendInterface $cache,
    TranslationInterface $string_translation,
    ClassResolverInterface $class_resolver,
    EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository,
    ContainerInterface $container,
  ) {
    $this->entityManager = $entity_manager;

    $this->setCacheBackend($cache, 'entity_type', ['entity_types']);
    $this->alterInfo('entity_type');

    parent::__construct($namespaces, $module_handler, $cache, $string_translation, $class_resolver, $entity_last_installed_schema_repository, $container);
  }

  /**
   * {@inheritdoc}
   */
  public function getStorage($entity_type_id) {
    /** @var \Drupal\Core\Entity\EntityStorageInterface $handler */
    $handler = $this->getHandler($entity_type_id, 'storage');
    $entity_kind = ($handler instanceof ConfigEntityStorageInterface) ? 'config' : 'content';

    if (!isset($this->loaded[$entity_kind][$entity_type_id])) {
      $handler = $this->getStorageDecorator($entity_type_id, $handler);
      $this->loaded[$entity_kind][$entity_type_id] = $handler;
    }
    else {
      $handler = $this->loaded[$entity_kind][$entity_type_id];
    }

    return $handler;
  }

  /**
   * {@inheritdoc}
   */
  public function getViewBuilder($entity_type_id) {
    /** @var \Drupal\Core\Entity\EntityViewBuilderInterface $handler */
    $handler = $this->getHandler($entity_type_id, 'view_builder');

    if ($handler instanceof EntityViewBuilderInterface) {
      if (!isset($this->rendered[$entity_type_id])) {
        $handler = new EntityViewBuilderDecorator($handler);
        $this->rendered[$entity_type_id] = $handler;
      }
      else {
        $handler = $this->rendered[$entity_type_id];
      }
    }

    return $handler;
  }

  /**
   * Return loaded entities.
   *
   * @param string $entity_kind
   *   The kind of the entity: config or content.
   * @param string $entity_type
   *   The entity's type.
   *
   * @return ConfigEntityStorageDecorator|null
   *   Loaded entities.
   */
  public function getLoaded(string $entity_kind, string $entity_type): ConfigEntityStorageDecorator|NULL {
    return $this->loaded[$entity_kind][$entity_type] ?? NULL;
  }

  /**
   * Return rendered entities.
   *
   * @param string $entity_type
   *   The entity's type.
   *
   * @return EntityViewBuilderDecorator|null
   *   Rendered entities.
   */
  public function getRendered(string $entity_type): EntityViewBuilderDecorator|NULL {
    return $this->rendered[$entity_type] ?? NULL;
  }

  /**
   * Prevents the service container from being serialized.
   *
   * @return string[]
   *   The properties to serialize.
   */
  public function __sleep(): array {
    return ['loaded', 'rendered'];
  }

  /**
   * Restores the service container after serialization.
   */
  public function setContainer(?ContainerInterface $container = NULL): void {
    $this->container = $container;
  }

  /**
   * Return a decorator for the storage handler.
   *
   * @param string $entity_type
   *   The entity's type.
   * @param object $handler
   *   The original storage handler.
   *
   * @return object
   *   A decorator for the storage handler.
   */
  private function getStorageDecorator(string $entity_type, object $handler): object {
    // Loaded this way to avoid circular references.
    /** @var \Drupal\webprofiler\DecoratorGeneratorInterface $decoratorGenerator */
    // @phpstan-ignore-next-line
    $decoratorGenerator = \Drupal::service('webprofiler.config_entity_storage_decorator_generator');

    $decorators = $decoratorGenerator->getDecorators();

    $storage = PhpStorageFactory::get('webprofiler');
    if ($handler instanceof ConfigEntityStorageInterface) {
      if (\array_key_exists($entity_type, $decorators)) {
        $storage->load($entity_type);
        if (!\class_exists($decorators[$entity_type])) {
          try {
            $decoratorGenerator->generate();
            $storage->load($entity_type);
          }
          catch (\Exception $e) {
            return $handler;
          }
        }

        return new $decorators[$entity_type]($handler);
      }

      return new ConfigEntityStorageDecorator($handler);
    }

    return $handler;
  }

}

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

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