Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
NameFormatParser
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
9 / 9
10
100.00% covered (success)
100.00%
1 / 1
 format
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 applyModifiers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 closingBracketPosition
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isModifierChar
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isConditionChar
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 resolveTokenValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 applyConditions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 pieceConditionMet
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 processBracketGroup
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\name\Utility;
6
7/**
8 * Facade: converts a token map and a format string into a plain string.
9 *
10 * The format-string parsing pipeline is split across three focused utility
11 * classes. This class re-exports their public APIs as static methods to
12 * preserve backwards compatibility for code that calls NameFormatParser
13 * directly and for NameFormatParserService subclasses.
14 *
15 * Pipeline: NameFormatTokens::build() (components to token map),
16 * NameFormatLexer::tokenize() (format string to pieces), and
17 * NameFormatAssembler::assemble() (pieces to plain string).
18 *
19 * @see \Drupal\name\Utility\NameFormatLexer
20 * @see \Drupal\name\Utility\NameFormatModifiers
21 * @see \Drupal\name\Utility\NameFormatAssembler
22 * @see \Drupal\name\Utility\NameFormatTokens
23 */
24final class NameFormatParser {
25
26  /**
27   * Default word-boundary pattern used by the B/b modifiers.
28   *
29   * Re-exported from NameFormatModifiers for backwards compatibility.
30   */
31  const BOUNDARY_REGEXP = NameFormatModifiers::BOUNDARY_REGEXP;
32
33  /**
34   * Converts a format string and token map into a formatted string.
35   *
36   * Escaped backslashes in the format string are neutralized to a tab
37   * placeholder before tokenization; any remaining literal double-backslashes
38   * in assembled token values are also converted by the assembler.
39   *
40   * @param string $format
41   *   The name format pattern.
42   * @param array $tokens
43   *   Token map as returned by NameFormatTokens::build().
44   *
45   * @return string
46   *   The formatted string.
47   */
48  public static function format(string $format, array $tokens): string {
49    if (empty($format)) {
50      return '';
51    }
52
53    // Neutralize escaped backslashes so the tokenizer does not treat them
54    // as escape prefixes.
55    $format = str_replace('\\\\', "\t", $format);
56
57    return NameFormatAssembler::assemble(
58      NameFormatLexer::tokenize($format, $tokens),
59    );
60  }
61
62  /**
63   * Applies case, trim, escape, and word-split modifiers to a string.
64   *
65   * Delegates to NameFormatModifiers::apply().
66   *
67   * @param string $string
68   *   The value to modify.
69   * @param string $modifiers
70   *   A sequence of modifier characters (L, U, F, G, T, S, B, b).
71   * @param string $boundary_regexp
72   *   Word-boundary pattern used by B and b.
73   *
74   * @return string
75   *   The modified string.
76   */
77  public static function applyModifiers(
78    string $string,
79    string $modifiers,
80    string $boundary_regexp = self::BOUNDARY_REGEXP,
81  ): string {
82    return NameFormatModifiers::apply($string, $modifiers, $boundary_regexp);
83  }
84
85  /**
86   * Returns the closing bracket position matching the first opening bracket.
87   *
88   * Delegates to NameFormatLexer::closingBracketPosition().
89   *
90   * @param string $string
91   *   The string starting with the opening bracket character.
92   *
93   * @return int|false
94   *   The zero-based position of the closing bracket, or FALSE when not found.
95   */
96  public static function closingBracketPosition(string $string): int|false {
97    return NameFormatLexer::closingBracketPosition($string);
98  }
99
100  /**
101   * Returns TRUE when the character is a modifier.
102   *
103   * Delegates to NameFormatLexer::isModifierChar().
104   *
105   * @param string $char
106   *   A single format character.
107   *
108   * @return bool
109   *   TRUE when the character is a modifier, otherwise FALSE.
110   */
111  public static function isModifierChar(string $char): bool {
112    return NameFormatLexer::isModifierChar($char);
113  }
114
115  /**
116   * Returns TRUE when the character is a condition flag.
117   *
118   * Delegates to NameFormatLexer::isConditionChar().
119   *
120   * @param string $char
121   *   A single format character.
122   *
123   * @return bool
124   *   TRUE when the character is a condition, otherwise FALSE.
125   */
126  public static function isConditionChar(string $char): bool {
127    return NameFormatLexer::isConditionChar($char);
128  }
129
130  /**
131   * Resolves a single format character to its token value.
132   *
133   * Delegates to NameFormatTokens::resolveValue().
134   *
135   * @param string $char
136   *   A single format character.
137   * @param array $tokens
138   *   The token map.
139   *
140   * @return string
141   *   The resolved value or the original character.
142   */
143  public static function resolveTokenValue(string $char, array $tokens): string {
144    return NameFormatTokens::resolveValue($char, $tokens);
145  }
146
147  /**
148   * Applies conditional inclusion rules to a list of pieces.
149   *
150   * Delegates to NameFormatAssembler::assemble().
151   *
152   * @param array[] $pieces
153   *   Each piece is an array with 'value' and 'conditions' keys.
154   *
155   * @return string
156   *   The assembled output string.
157   */
158  public static function applyConditions(array $pieces): string {
159    return NameFormatAssembler::assemble($pieces);
160  }
161
162  /**
163   * Returns TRUE when the piece's conditions are satisfied by its neighbors.
164   *
165   * Delegates to NameFormatAssembler::pieceConditionMet().
166   *
167   * @param string $conditions
168   *   Accumulated condition characters for the piece.
169   * @param string|false $last_component
170   *   The preceding piece value, or FALSE when there is none.
171   * @param string|false $next_component
172   *   The following piece value, or FALSE when there is none.
173   *
174   * @return bool
175   *   TRUE when the conditions match the surrounding pieces.
176   */
177  public static function pieceConditionMet(
178    string $conditions,
179    string|false $last_component,
180    string|false $next_component,
181  ): bool {
182    return NameFormatAssembler::pieceConditionMet(
183      $conditions,
184      $last_component,
185      $next_component,
186    );
187  }
188
189  /**
190   * Processes a bracketed segment or preserves an unmatched bracket.
191   *
192   * Delegates to NameFormatLexer::processBracketGroup().
193   *
194   * @param string $format
195   *   The full format string being parsed.
196   * @param int $position
197   *   The current position of the bracket character.
198   * @param array $tokens
199   *   The token map.
200   * @param string $modifiers
201   *   Accumulated modifier characters.
202   * @param string $conditions
203   *   Accumulated condition characters.
204   *
205   * @return array{piece: array, advance: int}
206   *   The assembled piece and the number of extra characters to advance past.
207   */
208  public static function processBracketGroup(
209    string $format,
210    int $position,
211    array $tokens,
212    string $modifiers,
213    string $conditions,
214  ): array {
215    return NameFormatLexer::processBracketGroup(
216      $format,
217      $position,
218      $tokens,
219      $modifiers,
220      $conditions,
221    );
222  }
223
224}