public function TextimageFactory::processTokens in Textimage 8.4
Same name and namespace in other branches
- 8.3 src/TextimageFactory.php \Drupal\textimage\TextimageFactory::processTokens()
Textimage tokens replacement.
Parameters
string $key: The Textimage token key within the main token [textimage:key:...]. Key can take 'uri' or 'url' values.
array $tokens: The tokens to resolve.
array $data: Token data array.
\Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata: The bubbleable metadata.
Return value
array An array of token replacements.
Overrides TextimageFactoryInterface::processTokens
File
- src/
TextimageFactory.php, line 281
Class
- TextimageFactory
- Provides a factory for Textimage.
Namespace
Drupal\textimageCode
public function processTokens($key, array $tokens, array $data, BubbleableMetadata $bubbleable_metadata) {
// @todo Not only node?
$node = isset($data['node']) ? $data['node'] : NULL;
// Need to avoid endless loops, that would occur if there are
// circular references in the tokens. Set static variables for
// the nesting level and the stack of fields accessed so far.
static $nesting_level;
static $field_stack;
if (!isset($nesting_level)) {
$nesting_level = 0;
$field_stack = [];
}
else {
$nesting_level++;
}
// Get tokens specific for the required key.
$sub_tokens = $this->token
->findWithPrefix($tokens, $key);
// Return immediately if none, or no node.
if (empty($sub_tokens) || !$node) {
$this
->rollbackStack($nesting_level, $field_stack);
return [];
}
// Loops through the tokens to resolve.
$replacements = [];
foreach ($sub_tokens as $sub_token => $original) {
// Clear current nesting level field stack.
unset($field_stack[$nesting_level]);
// Get token elements.
$sub_token_array = explode(':', $sub_token);
// Get requested field name, continue if missing.
$field_name = isset($sub_token_array[0]) ? $sub_token_array[0] : NULL;
if (!$field_name) {
continue;
}
// Check for recursion, i.e. the field is already engaged in a
// token resolution. Throw a TextimageTokenException in case.
if (in_array($field_name, $field_stack)) {
$this
->rollbackStack($nesting_level, $field_stack);
throw new TextimageTokenException($original);
}
// Set current requested field in the field stack.
$field_stack[$nesting_level] = $field_name;
// Get requested display mode, default to 'default'.
$display_mode = isset($sub_token_array[1]) ? $sub_token_array[1] ?: 'default' : 'default';
// Get requested sequence, default to NULL.
$index = isset($sub_token_array[2]) ? $sub_token_array[2] : NULL;
// Get field info, continue if missing.
if (!($field_info = $node
->getFieldDefinition($field_name))) {
continue;
}
// Get info on component providing formatting, continue if missing.
$entity_display = EntityViewDisplay::load('node.' . $node
->getType() . '.' . $display_mode);
if (!$entity_display) {
continue;
}
$entity_display_component = $entity_display
->getComponent($field_name);
if (empty($entity_display_component['type'])) {
continue;
}
// At this point, if Textimage is providing field formatting for the
// current field, we can proceed accessing the data needed to resolve
// the token.
if (in_array($entity_display_component['type'], [
'textimage_text_field_formatter',
'textimage_image_field_formatter',
])) {
// Get the image style used for the field formatting.
$image_style_name = isset($entity_display_component['settings']['image_style']) ? $entity_display_component['settings']['image_style'] : NULL;
if (!$image_style_name) {
continue;
}
$image_style = ImageStyle::load($image_style_name);
// Get the field items.
$items = $node
->get($field_name);
// Invoke Textimage API functions to return the token value requested.
if (in_array($field_info
->getFieldStorageDefinition()
->getTypeProvider(), [
'text',
'core',
])) {
$text = $this
->getTextFieldText($items);
if ($field_info
->getFieldStorageDefinition()
->getCardinality() != 1 && $entity_display_component['settings']['image_text_values'] == 'itemize') {
// Build separate image for each text value.
try {
$ret = [];
foreach ($text as $text_value) {
$textimage = $this
->get($bubbleable_metadata)
->setStyle($image_style)
->setTokenData($data)
->process($text_value);
$ret[] = $this
->getTokenReplacement($textimage, $key);
}
// Return a single URI/URL if requested, or a comma separated
// list of all the URIs/URLs generated.
if (!is_null($index) && isset($ret[$index])) {
$replacements[$original] = $ret[$index];
}
else {
$replacements[$original] = implode(',', $ret);
}
} catch (TextimageTokenException $e) {
// Callback ended up in circular loop, mark the failing token.
$replacements[$original] = str_replace('textimage', 'void-textimage', $original);
if ($nesting_level > 0) {
// Returns up in the nesting of iteration with the failing
// token.
$this
->rollbackStack($nesting_level, $field_stack);
throw new TextimageTokenException($e
->getToken());
}
else {
// Inform about the token failure.
$this->logger
->warning('Textimage token @token in node \'@node_title\' can not be resolved (circular reference). Remove the token to avoid this message.', [
'@token' => $original,
'@node_title' => $node
->getTitle(),
]);
}
}
}
else {
// Build single image with all text values.
try {
$textimage = $this
->get($bubbleable_metadata)
->setStyle($image_style)
->setTokenData($data)
->process($text);
$replacements[$original] = $this
->getTokenReplacement($textimage, $key);
} catch (TextimageTokenException $e) {
// Callback ended up in circular loop, mark the failing token.
$replacements[$original] = str_replace('textimage', 'void-textimage', $original);
if ($nesting_level > 0) {
// Returns up in the nesting of iteration with the failing
// token.
$this
->rollbackStack($nesting_level, $field_stack);
throw new TextimageTokenException($e
->getToken());
}
else {
// Inform about the token failure.
$this->logger
->warning('Textimage token @token in node \'@node_title\' can not be resolved (circular reference). Remove the token to avoid this message.', [
'@token' => $original,
'@node_title' => $node
->getTitle(),
]);
}
}
}
}
elseif ($field_info
->getFieldStorageDefinition()
->getTypeProvider() == 'image') {
// Image field. Get a separate Textimage from each of the images
// in the field.
try {
$ret = [];
foreach ($items as $item) {
// Get source image from the image field item.
$item_value = $item
->getValue();
$textimage = $this
->get($bubbleable_metadata)
->setStyle($image_style)
->setTokenData($data)
->setSourceImageFile($item->entity, $item_value['width'], $item_value['height'])
->process(NULL);
$ret[] = $this
->getTokenReplacement($textimage, $key);
}
// Return a single URI/URL if requested, or a comma separated
// list of all the URIs/URLs generated.
if (!is_null($index) && isset($ret[$index])) {
$replacements[$original] = $ret[$index];
}
else {
$replacements[$original] = implode(',', $ret);
}
} catch (TextimageTokenException $e) {
// Callback ended up in circular loop, mark the failing token.
$replacements[$original] = str_replace('textimage', 'void-textimage', $original);
if ($nesting_level > 0) {
// Returns up in the nesting of iteration with the failing token.
$this
->rollbackStack($nesting_level, $field_stack);
throw new TextimageTokenException($e
->getToken());
}
else {
// Inform about the token failure.
$this->logger
->warning('Textimage token @token in node \'@node_title\' can not be resolved (circular reference). Remove the token to avoid this message.', [
'@token' => $original,
'@node_title' => $node
->getTitle(),
]);
}
}
}
}
}
// Return to previous iteration.
$this
->rollbackStack($nesting_level, $field_stack);
return $replacements;
}