Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
TokenFieldSubTypeResolver
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
3 / 3
13
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
7
 candidateKeys
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 isValidSubType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\name\Utility;
6
7/**
8 * Resolves Token field chain sub-type ids for name fields.
9 *
10 * @internal
11 */
12final class TokenFieldSubTypeResolver {
13
14  /**
15   * Resolves Token field chain sub-type for a name field, if registered.
16   *
17   * @param array $info
18   *   Full token info from hook_token_info_alter().
19   * @param string $entity_type_id
20   *   Entity type id (e.g. node).
21   * @param string $field_name
22   *   Field machine name.
23   *
24   * @return string|null
25   *   Token type id for the field item subtree, or NULL.
26   */
27  public static function resolve(array $info, string $entity_type_id, string $field_name): ?string {
28    $entity_tokens_missing = (
29      !isset($info['tokens'][$entity_type_id]) || !is_array($info['tokens'][$entity_type_id])
30    );
31    if ($entity_tokens_missing) {
32      return NULL;
33    }
34    $tokens = $info['tokens'][$entity_type_id];
35    foreach (self::candidateKeys($tokens, $field_name) as $candidate) {
36      $sub_type = $tokens[$candidate]['type'] ?? NULL;
37      $sub_type_is_empty = ($sub_type === NULL || $sub_type === '');
38      if ($sub_type_is_empty) {
39        continue;
40      }
41      if (self::isValidSubType($info, $sub_type)) {
42        return $sub_type;
43      }
44    }
45    return NULL;
46  }
47
48  /**
49   * Builds token keys that may declare a field item sub-type.
50   *
51   * @param array<string, mixed> $entity_tokens
52   *   Tokens registered for the entity type.
53   * @param string $field_name
54   *   Field machine name.
55   *
56   * @return list<string>
57   *   Candidate token keys, field name first.
58   */
59  public static function candidateKeys(array $entity_tokens, string $field_name): array {
60    $candidates = [$field_name];
61    $pattern = '/^' . preg_quote($field_name, '/') . ':\d+$/';
62    $token_keys = array_keys($entity_tokens);
63    foreach ($token_keys as $token_key) {
64      if ($token_key === $field_name) {
65        continue;
66      }
67      if (preg_match($pattern, $token_key)) {
68        $candidates[] = $token_key;
69      }
70    }
71    return $candidates;
72  }
73
74  /**
75   * Whether a sub-type has a registered token subtree.
76   */
77  private static function isValidSubType(array $info, string $sub_type): bool {
78    return isset($info['tokens'][$sub_type]) && is_array($info['tokens'][$sub_type]);
79  }
80
81}