Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
35 / 35 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
FootnoteMarkFormatter | |
100.00% |
35 / 35 |
|
100.00% |
3 / 3 |
12 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
linkRef | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
6 | |||
fetchCustomizedLinkLabel | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
5 |
1 | <?php |
2 | |
3 | namespace Cite; |
4 | |
5 | use MediaWiki\Parser\Sanitizer; |
6 | use Parser; |
7 | |
8 | /** |
9 | * Footnote markers in the context of the Cite extension are the numbers in the article text, e.g. |
10 | * [1], that can be hovered or clicked to be able to read the attached footnote. |
11 | * |
12 | * @license GPL-2.0-or-later |
13 | */ |
14 | class FootnoteMarkFormatter { |
15 | |
16 | /** @var array<string,string[]> In-memory cache for the cite_link_label_group-… link label lists */ |
17 | private array $linkLabels = []; |
18 | |
19 | private AnchorFormatter $anchorFormatter; |
20 | private ErrorReporter $errorReporter; |
21 | private ReferenceMessageLocalizer $messageLocalizer; |
22 | |
23 | public function __construct( |
24 | ErrorReporter $errorReporter, |
25 | AnchorFormatter $anchorFormatter, |
26 | ReferenceMessageLocalizer $messageLocalizer |
27 | ) { |
28 | $this->anchorFormatter = $anchorFormatter; |
29 | $this->errorReporter = $errorReporter; |
30 | $this->messageLocalizer = $messageLocalizer; |
31 | } |
32 | |
33 | /** |
34 | * Generate a link (<sup ...) for the <ref> element from a key |
35 | * and return XHTML ready for output |
36 | * |
37 | * @suppress SecurityCheck-DoubleEscaped |
38 | * @param Parser $parser |
39 | * @param string $group |
40 | * @param ReferenceStackItem $ref |
41 | * |
42 | * @return string |
43 | */ |
44 | public function linkRef( Parser $parser, string $group, ReferenceStackItem $ref ): string { |
45 | $label = $this->fetchCustomizedLinkLabel( $parser, $group, $ref->number ); |
46 | if ( $label === null ) { |
47 | $label = $this->messageLocalizer->localizeDigits( (string)$ref->number ); |
48 | if ( $group !== Cite::DEFAULT_GROUP ) { |
49 | $label = "$group $label"; |
50 | } |
51 | } |
52 | if ( isset( $ref->extendsIndex ) ) { |
53 | $label .= '.' . $this->messageLocalizer->localizeDigits( (string)$ref->extendsIndex ); |
54 | } |
55 | |
56 | $key = $ref->name ?? $ref->key; |
57 | // TODO: Use count without decrementing. |
58 | $count = $ref->name ? $ref->key . '-' . ( $ref->count - 1 ) : null; |
59 | $subkey = $ref->name ? '-' . $ref->key : null; |
60 | |
61 | return $parser->recursiveTagParse( |
62 | $this->messageLocalizer->msg( |
63 | 'cite_reference_link', |
64 | $this->anchorFormatter->backLinkTarget( $key, $count ), |
65 | $this->anchorFormatter->jumpLink( $key . $subkey ), |
66 | Sanitizer::safeEncodeAttribute( $label ) |
67 | )->plain() |
68 | ); |
69 | } |
70 | |
71 | /** |
72 | * Generate a custom format link for a group given an offset, e.g. |
73 | * the second <ref group="foo"> is b if $this->mLinkLabels["foo"] = |
74 | * [ 'a', 'b', 'c', ...]. |
75 | * Return an error if the offset > the # of array items |
76 | * |
77 | * @param Parser $parser |
78 | * @param string $group The group name |
79 | * @param int $number Expected to start at 1 |
80 | * |
81 | * @return string|null Returns null if no custom labels for this group exist |
82 | */ |
83 | private function fetchCustomizedLinkLabel( Parser $parser, string $group, int $number ): ?string { |
84 | if ( $group === Cite::DEFAULT_GROUP ) { |
85 | return null; |
86 | } |
87 | |
88 | $message = "cite_link_label_group-$group"; |
89 | if ( !array_key_exists( $group, $this->linkLabels ) ) { |
90 | $msg = $this->messageLocalizer->msg( $message ); |
91 | $this->linkLabels[$group] = $msg->isDisabled() ? [] : preg_split( '/\s+/', $msg->plain() ); |
92 | } |
93 | |
94 | // Expected behavior for groups without custom labels |
95 | if ( !$this->linkLabels[$group] ) { |
96 | return null; |
97 | } |
98 | |
99 | // Error message in case we run out of custom labels |
100 | return $this->linkLabels[$group][$number - 1] ?? $this->errorReporter->plain( |
101 | $parser, |
102 | 'cite_error_no_link_label_group', |
103 | $group, |
104 | $message |
105 | ); |
106 | } |
107 | |
108 | } |