Skip to content
Snippets Groups Projects

Provide a version parameter to entity by id queries to provide the latest or...

Files
4
 
<?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\RevisionableStorageInterface;
 
use Drupal\Core\Entity\TranslatableInterface;
 
use Drupal\Core\Entity\TranslatableRevisionableStorageInterface;
 
use Drupal\Core\Language\LanguageManagerInterface;
 
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 
use Drupal\graphql\GraphQL\Execution\FieldContext;
 
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
 
use Drupal\graphql_compose\Plugin\GraphQLCompose\SchemaType\VersionType;
 
use Symfony\Component\DependencyInjection\ContainerInterface;
 
 
/**
 
* The entity version fallback.
 
*
 
* @DataProducer(
 
* id = "entity_version_fallback",
 
* name = @Translation("Entity revision fallback"),
 
* description = @Translation("Returns the entity by version (i.e. latest or working-copy) with optional fallback."),
 
* produces = @ContextDefinition("entity",
 
* label = @Translation("Versioned entity")
 
* ),
 
* consumes = {
 
* "entity" = @ContextDefinition("entity",
 
* label = @Translation("Entity")
 
* ),
 
* "version" = @ContextDefinition("string",
 
* label = @Translation("version"),
 
* required = FALSE
 
* ),
 
* "langcode" = @ContextDefinition("string",
 
* label = @Translation("langcode"),
 
* required = FALSE
 
* ),
 
* "fallback" = @ContextDefinition("boolean",
 
* label = @Translation("Return same entity as fallback"),
 
* required = FALSE
 
* )
 
* }
 
* )
 
*/
 
class EntityVersionFallback extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
 
 
/**
 
* The entity type manager.
 
*
 
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
 
*/
 
protected $entityTypeManager;
 
 
/**
 
* The language manager.
 
*
 
* @var \Drupal\Core\Language\LanguageManagerInterface
 
*/
 
protected $languageManager;
 
 
/**
 
* Constructs a EntityTranslationRevisionFallback.
 
*
 
* @param array $configuration
 
* The plugin configuration.
 
* @param string $plugin_id
 
* The plugin id.
 
* @param array $plugin_definition
 
* The plugin definition.
 
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
 
* The entity type manager.
 
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
 
* The language manager.
 
*/
 
public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager) {
 
parent::__construct($configuration, $plugin_id, $plugin_definition);
 
 
$this->entityTypeManager = $entity_type_manager;
 
$this->languageManager = $language_manager;
 
}
 
 
/**
 
* {@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('language_manager')
 
);
 
}
 
 
/**
 
* Returns the entity for a given revision and translation.
 
*
 
* @param \Drupal\Core\Entity\EntityInterface $entity
 
* The entity.
 
* @param string|null $version
 
* The version.
 
* @param string|null $langcode
 
* The entity langcode.
 
* @param bool|null $fallback
 
* Flag to indicate whether to fallback to original entity.
 
* @param \Drupal\graphql\GraphQL\Execution\FieldContext $context
 
* The GraphQL context.
 
*
 
* @return \Drupal\Core\Entity\EntityInterface|null
 
* The revised entity.
 
*/
 
public function resolve(EntityInterface $entity, ?string $version, ?string $langcode, ?bool $fallback, FieldContext $context) {
 
// If the version value is null or 'working-copy' just return the entity.
 
if ($version !== VersionType::WORKING_COPY) {
 
return $entity;
 
}
 
 
if ($entity instanceof RevisionableInterface && $entity->getEntityType()->isRevisionable()) {
 
if ($version_id = $this->getRevisionId($entity, $langcode)) {
 
$entity = $this->getRevisionStorage($entity)->loadRevision($version_id);
 
if ($langcode && $entity instanceof TranslatableInterface && $entity->hasTranslation($langcode)) {
 
$entity = $entity->getTranslation($langcode);
 
}
 
$entity->addCacheContexts(["static:version:{$version_id}"]);
 
/** @var \Drupal\Core\Access\AccessResultInterface $accessResult */
 
$accessResult = $entity->access('view', NULL, TRUE);
 
$context->addCacheableDependency($accessResult);
 
if (!$accessResult->isAllowed()) {
 
return NULL;
 
}
 
$context->setContextValue('version', $version_id);
 
return $entity;
 
}
 
}
 
 
// Fallback to the current entity.
 
if ($fallback) {
 
return $entity;
 
}
 
 
return NULL;
 
}
 
 
/**
 
* Get the revision id for an entity.
 
*
 
* @param \Drupal\Core\Entity\EntityInterface $entity
 
* The revisable entity.
 
* @param string|null $langcode
 
* The entity langcode.
 
*
 
* @return int|string|null
 
* Returns the revision id OTHERWISE null.
 
*/
 
protected function getRevisionId(EntityInterface $entity, ?string $langcode) : int|string|null {
 
$entity_storage = $this->getRevisionStorage($entity);
 
$version_id = NULL;
 
if ($entity_storage instanceof RevisionableStorageInterface) {
 
$entity_id = $entity->id();
 
if ($entity_storage instanceof TranslatableRevisionableStorageInterface) {
 
$version_id = $entity_storage->getLatestTranslationAffectedRevisionId(
 
$entity_id,
 
$langcode ?? $this->languageManager->getDefaultLanguage()->getId(),
 
);
 
}
 
else {
 
$version_id = $entity_storage->getLatestRevisionId($entity_id);
 
}
 
}
 
 
return $version_id;
 
}
 
 
/**
 
* Provides the storage interface.
 
*
 
* @param \Drupal\Core\Entity\RevisionableInterface $entity
 
* The entity.
 
*
 
* @return \Drupal\Core\Entity\RevisionableStorageInterface
 
* The revisionable storage interface.
 
*/
 
protected function getRevisionStorage(RevisionableInterface $entity) : RevisionableStorageInterface {
 
return $this->entityTypeManager->getStorage($entity->getEntityTypeId());
 
}
 
 
}
Loading