Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.75% |
30 / 32 |
|
87.50% |
7 / 8 |
CRAP | |
0.00% |
0 / 1 |
ErrorReporter | |
93.75% |
30 / 32 |
|
87.50% |
7 / 8 |
11.03 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
firstError | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
halfParsed | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
plain | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
msg | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
getInterfaceLanguageAndSplitCache | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
wrapInHtmlContainer | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
2 | |||
parseTypeAndIdFromMessageKey | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Cite; |
4 | |
5 | use Language; |
6 | use MediaWiki\Html\Html; |
7 | use MediaWiki\Parser\Sanitizer; |
8 | use Message; |
9 | use Parser; |
10 | use StatusValue; |
11 | |
12 | /** |
13 | * @license GPL-2.0-or-later |
14 | */ |
15 | class ErrorReporter { |
16 | |
17 | private ReferenceMessageLocalizer $messageLocalizer; |
18 | private ?Language $cachedInterfaceLanguage = null; |
19 | |
20 | public function __construct( ReferenceMessageLocalizer $messageLocalizer ) { |
21 | $this->messageLocalizer = $messageLocalizer; |
22 | } |
23 | |
24 | /** |
25 | * @deprecated Intermediate helper function. Long-term all errors should be rendered, not only |
26 | * the first one. |
27 | */ |
28 | public function firstError( Parser $parser, StatusValue $status ): string { |
29 | $error = $status->getErrors()[0]; |
30 | return $this->halfParsed( $parser, $error['message'], ...$error['params'] ); |
31 | } |
32 | |
33 | /** |
34 | * @param Parser $parser |
35 | * @param string $key Message name of the error or warning |
36 | * @param mixed ...$params |
37 | * |
38 | * @return string Half-parsed wikitext with extension's tags already being expanded |
39 | */ |
40 | public function halfParsed( Parser $parser, string $key, ...$params ): string { |
41 | $msg = $this->msg( $parser, $key, ...$params ); |
42 | $wikitext = $parser->recursiveTagParse( $msg->plain() ); |
43 | return $this->wrapInHtmlContainer( $wikitext, $key, $msg->getLanguage() ); |
44 | } |
45 | |
46 | /** |
47 | * @param Parser $parser |
48 | * @param string $key Message name of the error or warning |
49 | * @param mixed ...$params |
50 | * |
51 | * @return string Plain, unparsed wikitext |
52 | * @return-taint tainted |
53 | */ |
54 | public function plain( Parser $parser, string $key, ...$params ): string { |
55 | $msg = $this->msg( $parser, $key, ...$params ); |
56 | $wikitext = $msg->plain(); |
57 | return $this->wrapInHtmlContainer( $wikitext, $key, $msg->getLanguage() ); |
58 | } |
59 | |
60 | /** |
61 | * @param Parser $parser |
62 | * @param string $key |
63 | * @param mixed ...$params |
64 | * |
65 | * @return Message |
66 | */ |
67 | private function msg( Parser $parser, string $key, ...$params ): Message { |
68 | $language = $this->getInterfaceLanguageAndSplitCache( $parser ); |
69 | $msg = $this->messageLocalizer->msg( $key, ...$params )->inLanguage( $language ); |
70 | |
71 | [ $type ] = $this->parseTypeAndIdFromMessageKey( $msg->getKey() ); |
72 | |
73 | if ( $type === 'error' ) { |
74 | // Take care; this is a sideeffect that might not belong to this class. |
75 | $parser->addTrackingCategory( 'cite-tracking-category-cite-error' ); |
76 | } |
77 | |
78 | // Messages: cite_error, cite_warning |
79 | return $this->messageLocalizer->msg( "cite_$type", $msg->plain() )->inLanguage( $language ); |
80 | } |
81 | |
82 | /** |
83 | * Note the startling side effect of splitting ParserCache by user interface language! |
84 | */ |
85 | private function getInterfaceLanguageAndSplitCache( Parser $parser ): Language { |
86 | if ( !$this->cachedInterfaceLanguage ) { |
87 | $this->cachedInterfaceLanguage = $parser->getOptions()->getUserLangObj(); |
88 | } |
89 | return $this->cachedInterfaceLanguage; |
90 | } |
91 | |
92 | private function wrapInHtmlContainer( |
93 | string $wikitext, |
94 | string $key, |
95 | Language $language |
96 | ): string { |
97 | [ $type, $id ] = $this->parseTypeAndIdFromMessageKey( $key ); |
98 | $extraClass = $type === 'warning' |
99 | ? ' mw-ext-cite-warning-' . Sanitizer::escapeClass( $id ) |
100 | : ''; |
101 | |
102 | return Html::rawElement( |
103 | 'span', |
104 | [ |
105 | // The following classes are generated here: |
106 | // * mw-ext-cite-warning |
107 | // * mw-ext-cite-error |
108 | 'class' => "$type mw-ext-cite-$type" . $extraClass, |
109 | 'lang' => $language->getHtmlCode(), |
110 | 'dir' => $language->getDir(), |
111 | ], |
112 | $wikitext |
113 | ); |
114 | } |
115 | |
116 | /** |
117 | * @param string $messageKey Expected to be a message key like "cite_error_ref_numeric_key" |
118 | * |
119 | * @return string[] Two elements, e.g. "error" and "ref_too_many_keys" |
120 | */ |
121 | private function parseTypeAndIdFromMessageKey( string $messageKey ): array { |
122 | return array_slice( explode( '_', str_replace( '-', '_', $messageKey ), 3 ), 1 ); |
123 | } |
124 | |
125 | } |