graphql_compose-1.0.0-beta20/src/Plugin/GraphQL/DataProducer/EntityLoadRevision.php

src/Plugin/GraphQL/DataProducer/EntityLoadRevision.php
<?php

declare(strict_types=1);

namespace Drupal\graphql_compose\Plugin\GraphQL\DataProducer;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\Entity\TranslatableRevisionableStorageInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\graphql\Attribute\DataProducer;
use Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer;
use Drupal\graphql\GraphQL\Execution\FieldContext;
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
use Drupal\graphql_compose\EntityTranslateTrait;
use GraphQL\Deferred;
use GraphQL\Error\UserError;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Loads the entity by revision.
 */
#[DataProducer(
  id: "entity_load_revision",
  name: new TranslatableMarkup("Load entity revision"),
  description: new TranslatableMarkup("The entity belonging to the current url."),
  produces: new ContextDefinition(
    data_type: "entity",
    label: new TranslatableMarkup("Entity"),
  ),
  consumes: [
    "entity" => new ContextDefinition(
      data_type: "entity",
      label: new TranslatableMarkup("The entity to load revisions from"),
    ),
    "identifier" => new ContextDefinition(
      data_type: "any",
      label: new TranslatableMarkup("Revision ID"),
      required: FALSE,
    ),
    "language" => new ContextDefinition(
      data_type: "string",
      label: new TranslatableMarkup("Language code"),
      required: FALSE,
    ),
  ],
)]
class EntityLoadRevision extends DataProducerPluginBase implements ContainerFactoryPluginInterface {

  use EntityTranslateTrait;

  /**
   * The latest revision identifiers.
   */
  const REVISION_LATEST = [
    'latest',
    'newest',
    'working',
    'working-copy',
  ];

  /**
   * The current revision identifiers.
   */
  const REVISION_CURRENT = [
    'active',
    'current',
    'default',
  ];

  /**
   * Constructs a \Drupal\Component\Plugin\PluginBase object.
   *
   * @param array $configuration
   *   The plugin configuration array.
   * @param string $pluginId
   *   The plugin id.
   * @param mixed $pluginDefinition
   *   The plugin definition array.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The language manager service.
   * @param \Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer $entityRevisionBuffer
   *   The entity revision buffer service.
   */
  public function __construct(
    array $configuration,
    $pluginId,
    $pluginDefinition,
    protected EntityTypeManagerInterface $entityTypeManager,
    protected EntityRevisionBuffer $entityRevisionBuffer,
  ) {
    parent::__construct($configuration, $pluginId, $pluginDefinition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('graphql.buffer.entity_revision'),
    );
  }

  /**
   * Resolve the entity revision.
   *
   * @param \Drupal\Core\Entity\EntityInterface|null $entity
   *   The entity to load revisions from.
   * @param int|string|null $identifier
   *   The revision ID to load.
   * @param string|null $language
   *   The language code to use.
   * @param \Drupal\graphql\GraphQL\Execution\FieldContext $context
   *   Cache context.
   */
  public function resolve(?EntityInterface $entity, int|string|null $identifier, ?string $language, FieldContext $context): Deferred|EntityInterface|null {

    if (is_string($identifier)) {
      $identifier = strtolower($identifier);
    }

    if (!$identifier || in_array($identifier, self::REVISION_CURRENT)) {
      return $entity;
    }

    if (!$entity instanceof RevisionableInterface) {
      return $entity;
    }

    $entity_id = $entity->id();
    $entity_type_id = $entity->getEntityTypeId();

    // Get the current or preferred language.
    $langcode = $this->getCurrentLanguage($context, $language, LanguageInterface::TYPE_INTERFACE);

    // Quickly resolve the latest revision.
    if (in_array($identifier, self::REVISION_LATEST)) {
      /** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
      $storage = $this->entityTypeManager->getStorage($entity_type_id);

      $identifier = ($storage instanceof TranslatableRevisionableStorageInterface)
        ? $storage->getLatestTranslationAffectedRevisionId($entity_id, $langcode)
        : $storage->getLatestRevisionId($entity_id);
    }

    // Still did not get a valid revision identifier.
    if (!$identifier || !is_numeric($identifier)) {
      return NULL;
    }

    // Add the entity to the buffer.
    $resolver = $this->entityRevisionBuffer->add($entity_type_id, (int) $identifier);

    return new Deferred(function () use ($resolver, $langcode, $entity_id, $entity_type_id, $context) {

      /** @var \Drupal\Core\Entity\RevisionableInterface|null $revision */
      if (!$revision = $resolver()) {
        // Add cache list tags to invalidate the cache.
        $entity_type = $this->entityTypeManager->getDefinition($entity_type_id, FALSE);
        if ($entity_type) {
          $context->addCacheTags($entity_type->getListCacheTags());
        }

        $context->addCacheTags(['4xx-response']);
        return NULL;
      }

      // Check the revision belongs to the entity.
      if ($revision->id() !== $entity_id) {
        throw new UserError('The requested revision does not belong to the requested entity.');
      }

      $context->setContextValue('revision', $revision->getRevisionId());
      $revision = $this->getTranslation($revision, $langcode);
      if (!$revision instanceof EntityInterface) {
        return NULL;
      }

      // Check revision access.
      $access = $revision->access('view', NULL, TRUE);
      $context->addCacheableDependency($access);

      return $access->isAllowed() ? $revision : NULL;
    });
  }

}

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

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