graphql_compose-1.0.0-beta20/modules/graphql_compose_metatags/src/Plugin/GraphQLCompose/FieldType/MetatagComputed.php
modules/graphql_compose_metatags/src/Plugin/GraphQLCompose/FieldType/MetatagComputed.php
<?php
declare(strict_types=1);
namespace Drupal\graphql_compose_metatags\Plugin\GraphQLCompose\FieldType;
use Drupal\graphql_compose\Attribute\FieldType;
use Drupal\Core\Entity\TranslatableInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\TypedData\TypedDataTrait;
use Drupal\graphql\GraphQL\Execution\FieldContext;
use Drupal\graphql_compose\Plugin\GraphQL\DataProducer\FieldProducerItemsInterface;
use Drupal\graphql_compose\Plugin\GraphQL\DataProducer\FieldProducerTrait;
use Drupal\graphql_compose\Plugin\GraphQLCompose\GraphQLComposeFieldTypeBase;
use Drupal\schema_metatag\SchemaMetatagManager;
use Drupal\typed_data\DataFetcherTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* {@inheritdoc}
*/
#[FieldType(
id: "metatag_computed",
type_sdl: "MetaTagUnion",
)]
class MetatagComputed extends GraphQLComposeFieldTypeBase implements FieldProducerItemsInterface, ContainerFactoryPluginInterface {
use TypedDataTrait;
use DataFetcherTrait;
use FieldProducerTrait;
/**
* Drupal renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected RendererInterface $renderer;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$instance = parent::create(
$container,
$configuration,
$plugin_id,
$plugin_definition
);
$instance->renderer = $container->get('renderer');
return $instance;
}
/**
* {@inheritdoc}
*/
public function resolveFieldItems(FieldItemListInterface $field, FieldContext $context): array {
// Fetch the entity directly from the field.
$entity = $field->getEntity();
// Get the language from context or fallback to the current language.
$langcode = $context->getContextLanguage() ?: $this->languageManager->getCurrentLanguage()->getId();
// Load the translated entity if required.
if ($langcode && $entity instanceof TranslatableInterface && $entity->hasTranslation($langcode) && $langcode !== $entity->language()->getId()) {
// Replace the field parent with the translated entity.
// This helps MetatagEntityFieldItemList when it uses $field->getEntity().
$entity = $entity->getTranslation($langcode);
$field->getParent()->setValue($entity);
$field->setLangcode($langcode);
}
// Render out meta tags.
$bubbleable = new BubbleableMetadata();
$render_context = new RenderContext();
$metatags = $this->renderer->executeInRenderContext(
$render_context,
fn () => $this->getDataFetcher()
->fetchDataByPropertyPath($entity->getTypedData(), 'metatag', $bubbleable)
->getValue()
) ?: [];
// Convert schema metatags into json+ld.
$this->addSchemaMetatags($metatags);
// Add any render metadata to the context.
if (!$render_context->isEmpty()) {
$context->addCacheableDependency($render_context->pop());
}
$context->addCacheableDependency($entity);
$context->addCacheableDependency($bubbleable);
return $metatags;
}
/**
* Add schema metatags to the list.
*
* @param array $metatags
* The list of metatags.
*/
protected function addSchemaMetatags(array &$metatags) {
if (!$this->moduleHandler->moduleExists('schema_metatag')) {
return;
}
// Find the schema metatags in the list.
$schema_metatags = array_filter($metatags,
fn ($item) => !empty($item['attributes']['schema_metatag'])
);
if (empty($schema_metatags)) {
return;
}
// Reduce the schema metatags from the list.
$metatags = array_diff_key($metatags, $schema_metatags);
// Change the data to match the manager structure.
$schema_metatags = array_map(
fn ($item) => [['#attributes' => $item['attributes']]],
$schema_metatags
);
// Add back in the combined schema json+ld metatag.
$content = SchemaMetatagManager::parseJsonld($schema_metatags);
$metatags[] = [
'tag' => 'script',
'content' => SchemaMetatagManager::encodeJsonld($content),
'attributes' => [
'type' => 'application/ld+json',
],
];
}
}
