datafield-1.x-dev/src/Hook/DataFieldTokensHooks.php
src/Hook/DataFieldTokensHooks.php
<?php
namespace Drupal\datafield\Hook;
use Drupal\Component\Utility\Html;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Hook tokens implementations for Data Field.
*/
class DataFieldTokensHooks implements ContainerInjectionInterface {
use StringTranslationTrait;
/**
* Constructs a new DataFieldHook object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* Entity type service.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
* Entity field service.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundleInformation
* Bundle Information service.
*/
public function __construct(
protected EntityTypeManagerInterface $entityTypeManager,
protected EntityFieldManagerInterface $entityFieldManager,
protected EntityTypeBundleInfoInterface $bundleInformation,
) {
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('entity_field.manager'),
$container->get('entity_type.bundle.info'),
);
}
/**
* Implements hook_token_info().
*/
#[Hook('token_info')]
public function tokenInfo($arg = []) {
$types = [];
$tokens = [];
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
if (!$entity_type->entityClassImplements(ContentEntityInterface::class)) {
continue;
}
// Build data field sub name tokens for all data fields.
$fields = $this->entityFieldManager->getFieldMap()[$entity_type_id] ?? [];
foreach ($fields as $field_name => $field) {
if ($field['type'] === 'data_field') {
$columns = [];
$field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, current($field['bundles']));
if (isset($field_definitions[$field_name])) {
$columns = $field_definitions[$field_name]->getSetting('field_settings');
}
$token_name = $entity_type_id . '-' . $field_name;
$types[$token_name] = [
'needs-data' => $token_name,
'nested' => TRUE,
'name' => $field_name,
'description' => $field_definitions[$field_name]?->getLabel() ?? '',
'module' => 'datafield',
];
foreach ($columns as $column => $subfield) {
$tokens[$token_name][$column] = [
'name' => $column,
'description' => $subfield['label'] ?? ucfirst($column),
'type' => $token_name,
];
}
}
}
}
return [
'types' => $types,
'tokens' => $tokens,
];
}
/**
* Implements hook_tokens().
*/
#[Hook('tokens')]
public function tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$replacements = [];
// Process entity with right type.
if (!empty($data[$type]) && $data[$type] instanceof ContentEntityInterface) {
$entity = $data[$type];
foreach ($tokens as $name => $original) {
// Analyse token [entity_type:field_name:subfield].
// Or with delta [entity_type:field_name:delta:subfield].
$parts = explode(':', $name);
$field_name = array_shift($parts);
$delta = is_numeric($parts[0] ?? NULL) ? (int) array_shift($parts) : 0;
$subfield = array_shift($parts);
if ($subfield && $entity->hasField($field_name)) {
$field = $entity->get($field_name);
if (isset($field[$delta]) && $field[$delta]->{$subfield} !== NULL) {
$value = $field[$delta]->{$subfield};
// Process default sanitize.
$replacements[$original] = !empty($options['sanitize']) ? Html::escape($value) : $value;
// Add cache dependency.
$bubbleable_metadata->addCacheableDependency($entity);
}
}
}
}
return $replacements;
}
}
