Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
FormattedNameTokenReplacement
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
6 / 6
17
100.00% covered (success)
100.00%
1 / 1
 resolve
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
3
 loadNameFieldList
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 addFieldCacheMetadata
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 attachFormatCacheMetadata
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 nameItemAtDelta
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 formatItem
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\name\Utility;
6
7use Drupal\Core\Cache\CacheableDependencyInterface;
8use Drupal\Core\Entity\ContentEntityInterface;
9use Drupal\Core\Entity\EntityTypeManagerInterface;
10use Drupal\Core\Field\FieldItemListInterface;
11use Drupal\Core\Render\BubbleableMetadata;
12use Drupal\name\Plugin\Field\FieldType\NameItem;
13use Drupal\name\Service\NameFormatterInterface;
14
15/**
16 * Computes formatted name field token replacement text.
17 *
18 * @internal
19 */
20final class FormattedNameTokenReplacement {
21
22  /**
23   * Computes replacement text for a formatted name field token.
24   */
25  public static function resolve(
26    ContentEntityInterface $entity,
27    string $field_name,
28    int $delta,
29    string $format_id,
30    array $options,
31    BubbleableMetadata $bubbleable_metadata,
32    EntityTypeManagerInterface $entity_type_manager,
33    NameFormatterInterface $name_formatter,
34  ): string {
35    $items = self::loadNameFieldList($entity, $field_name);
36    if ($items === NULL) {
37      return '';
38    }
39    self::addFieldCacheMetadata($entity, $items, $bubbleable_metadata);
40    self::attachFormatCacheMetadata(
41      $format_id,
42      $bubbleable_metadata,
43      $entity_type_manager,
44    );
45    $item = self::nameItemAtDelta($items, $delta);
46    if ($item === NULL) {
47      return '';
48    }
49    return self::formatItem($item, $format_id, $options, $name_formatter);
50  }
51
52  /**
53   * Loads a name field item list when the field exists and is a name field.
54   */
55  private static function loadNameFieldList(
56    ContentEntityInterface $entity,
57    string $field_name,
58  ): ?FieldItemListInterface {
59    if (!$entity->hasField($field_name)) {
60      return NULL;
61    }
62    $items = $entity->get($field_name);
63    if ($items->getFieldDefinition()->getType() !== 'name') {
64      return NULL;
65    }
66    return $items;
67  }
68
69  /**
70   * Adds entity and field list cache metadata to bubbleable metadata.
71   */
72  private static function addFieldCacheMetadata(
73    ContentEntityInterface $entity,
74    FieldItemListInterface $items,
75    BubbleableMetadata $bubbleable_metadata,
76  ): void {
77    $bubbleable_metadata->addCacheableDependency($entity);
78    if ($items instanceof CacheableDependencyInterface) {
79      $bubbleable_metadata->addCacheableDependency($items);
80    }
81  }
82
83  /**
84   * Loads the requested name format (or default) and adds cache metadata.
85   */
86  private static function attachFormatCacheMetadata(
87    string $format_id,
88    BubbleableMetadata $bubbleable_metadata,
89    EntityTypeManagerInterface $entity_type_manager,
90  ): void {
91    $format_storage = $entity_type_manager->getStorage('name_format');
92    $used_format = $format_storage->load($format_id)
93      ?: $format_storage->load('default');
94    if ($used_format) {
95      $bubbleable_metadata->addCacheableDependency($used_format);
96    }
97  }
98
99  /**
100   * Returns the name item at a delta when the list is non-empty and in range.
101   */
102  private static function nameItemAtDelta(
103    FieldItemListInterface $items,
104    int $delta,
105  ): ?NameItem {
106    $delta_is_out_of_range = (
107      $items->isEmpty() || $delta < 0 || $delta >= $items->count()
108    );
109    if ($delta_is_out_of_range) {
110      return NULL;
111    }
112    $item = $items->get($delta);
113    if (!($item instanceof NameItem)) {
114      return NULL;
115    }
116    return $item;
117  }
118
119  /**
120   * Formats a single name field item with the configured name formatter.
121   */
122  private static function formatItem(
123    NameItem $item,
124    string $format_id,
125    array $options,
126    NameFormatterInterface $name_formatter,
127  ): string {
128    return (string) $name_formatter->format(
129      $item->filteredArray(),
130      $format_id,
131      $options['langcode'] ?? NULL,
132    );
133  }
134
135}