Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
10.93% |
20 / 183 |
|
7.55% |
4 / 53 |
CRAP | |
0.00% |
0 / 1 |
MockSiteConfig | |
10.93% |
20 / 183 |
|
7.55% |
4 / 53 |
3735.32 | |
0.00% |
0 / 1 |
__construct | |
80.00% |
12 / 15 |
|
0.00% |
0 / 1 |
4.13 | |||
getLinterSiteConfig | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
allowedExternalImagePrefixes | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
baseURI | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
exportMetadataToHeadBcp47 | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
redirectRegexp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
categoryRegexp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
bswRegexp | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
canonicalNamespaceId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
namespaceId | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
namespaceName | |
66.67% |
4 / 6 |
|
0.00% |
0 / 1 |
3.33 | |||
namespaceHasSubpages | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
namespaceCase | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
specialPageLocalName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setInterwikiMagic | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
interwikiMagic | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
interwikiMap | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
iwp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
legalTitleChars | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
linkPrefixRegex | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
linkTrail | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
linkTrailRegex | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
langBcp47 | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
mainPageLinkTarget | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getMWConfigValue | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
20 | |||
rtl | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
langConverterEnabledBcp47 | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
script | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
scriptpath | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
server | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
timezoneOffset | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
variantsFor | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
30 | |||
widthOption | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getVariableIDs | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
haveComputedFunctionSynonyms | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
updateFunctionSynonym | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getMagicWords | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
2 | |||
getMagicWordMatcher | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getParameterizedAliasMatcher | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
30 | |||
getNonNativeExtensionTags | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
2 | |||
getMaxTemplateDepth | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSpecialPageAliases | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getSpecialNSAliases | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getProtocols | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
fakeTimestamp | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setFakeTimestamp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setTimezoneOffset | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
scrubBidiChars | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNoFollowConfig | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getExternalLinkTarget | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
metrics | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
incrementCounter | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
observeTiming | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace Wikimedia\Parsoid\Mocks; |
5 | |
6 | use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface; |
7 | use Monolog\Formatter\LineFormatter; |
8 | use Monolog\Handler\ErrorLogHandler; |
9 | use Monolog\Logger; |
10 | use Wikimedia\Bcp47Code\Bcp47Code; |
11 | use Wikimedia\Bcp47Code\Bcp47CodeValue; |
12 | use Wikimedia\Parsoid\Config\SiteConfig; |
13 | use Wikimedia\Parsoid\Config\StubMetadataCollector; |
14 | use Wikimedia\Parsoid\Core\ContentMetadataCollector; |
15 | use Wikimedia\Parsoid\Core\LinkTarget; |
16 | use Wikimedia\Parsoid\DOM\Document; |
17 | use Wikimedia\Parsoid\Utils\Title; |
18 | use Wikimedia\Parsoid\Utils\Utils; |
19 | |
20 | class MockSiteConfig extends SiteConfig { |
21 | |
22 | /** @var ?int Unix timestamp */ |
23 | private $fakeTimestamp = 946782245; // 2000-01-02T03:04:05Z |
24 | |
25 | /** @var int */ |
26 | private $timezoneOffset = 0; // UTC |
27 | |
28 | /** @var bool */ |
29 | private $interwikiMagic = true; |
30 | |
31 | /** @var array */ |
32 | private $linterOverrides = []; |
33 | |
34 | private const NAMESPACE_MAP = [ |
35 | 'media' => -2, |
36 | 'special' => -1, |
37 | '' => 0, |
38 | 'talk' => 1, |
39 | 'user' => 2, |
40 | 'user_talk' => 3, |
41 | // Last one will be used by namespaceName |
42 | 'project' => 4, 'wp' => 4, 'wikipedia' => 4, |
43 | 'project_talk' => 5, 'wt' => 5, 'wikipedia_talk' => 5, |
44 | 'file' => 6, |
45 | 'file_talk' => 7, |
46 | 'template' => 10, |
47 | 'template_talk' => 11, |
48 | 'help' => 12, |
49 | 'category' => 14, |
50 | 'category_talk' => 15, |
51 | ]; |
52 | |
53 | /** @var array<int,bool> */ |
54 | protected $namespacesWithSubpages = []; |
55 | |
56 | /** @var array */ |
57 | protected $interwikiMap = []; |
58 | |
59 | /** @var int */ |
60 | private $maxDepth = 40; |
61 | |
62 | /** @var string|null */ |
63 | private $linkPrefixRegex = null; |
64 | |
65 | /** @var string|bool */ |
66 | private $externalLinkTarget; |
67 | |
68 | public function __construct( array $opts ) { |
69 | parent::__construct(); |
70 | |
71 | if ( isset( $opts['linting'] ) ) { |
72 | $this->linterEnabled = $opts['linting']; |
73 | } |
74 | if ( isset( $opts['maxDepth'] ) ) { |
75 | $this->maxDepth = $opts['maxDepth']; |
76 | } |
77 | if ( isset( $opts['linterOverrides'] ) ) { |
78 | $this->linterOverrides = $opts['linterOverrides']; |
79 | } |
80 | $this->linkPrefixRegex = $opts['linkPrefixRegex'] ?? null; |
81 | $this->linkTrailRegex = $opts['linkTrailRegex'] ?? '/^([a-z]+)/sD'; // enwiki default |
82 | $this->externalLinkTarget = $opts['externallinktarget'] ?? false; |
83 | |
84 | // Use Monolog's PHP console handler |
85 | $logger = new Logger( "Parsoid CLI" ); |
86 | $handler = new ErrorLogHandler(); |
87 | $handler->setFormatter( new LineFormatter( '%message%' ) ); |
88 | $logger->pushHandler( $handler ); |
89 | $this->setLogger( $logger ); |
90 | } |
91 | |
92 | public function getLinterSiteConfig(): array { |
93 | return $this->linterOverrides + parent::getLinterSiteConfig(); |
94 | } |
95 | |
96 | public function allowedExternalImagePrefixes(): array { |
97 | return []; |
98 | } |
99 | |
100 | public function baseURI(): string { |
101 | return '//my.wiki.example/wikix/'; |
102 | } |
103 | |
104 | /** |
105 | * @inheritDoc |
106 | */ |
107 | public function exportMetadataToHeadBcp47( |
108 | Document $document, |
109 | ContentMetadataCollector $metadata, |
110 | string $defaultTitle, |
111 | Bcp47Code $lang |
112 | ): void { |
113 | '@phan-var StubMetadataCollector $metadata'; // @var StubMetadataCollector $metadata |
114 | $moduleLoadURI = $this->server() . $this->scriptpath() . '/load.php'; |
115 | // Look for a displaytitle. |
116 | $displayTitle = $metadata->getPageProperty( 'displaytitle' ) ?? |
117 | // Use the default title, properly escaped |
118 | Utils::escapeHtml( $defaultTitle ); |
119 | $this->exportMetadataHelper( |
120 | $document, |
121 | $moduleLoadURI, |
122 | $metadata->getModules(), |
123 | $metadata->getModuleStyles(), |
124 | $metadata->getJsConfigVars(), |
125 | $displayTitle, |
126 | $lang |
127 | ); |
128 | } |
129 | |
130 | public function redirectRegexp(): string { |
131 | return '/(?i:#REDIRECT)/'; |
132 | } |
133 | |
134 | public function categoryRegexp(): string { |
135 | return '/Category/'; |
136 | } |
137 | |
138 | public function bswRegexp(): string { |
139 | return '/' . |
140 | 'NOGLOBAL|DISAMBIG|NOCOLLABORATIONHUBTOC|nocollaborationhubtoc|NOTOC|notoc|' . |
141 | 'NOGALLERY|nogallery|FORCETOC|forcetoc|TOC|toc|NOEDITSECTION|noeditsection|' . |
142 | 'NOTITLECONVERT|notitleconvert|NOTC|notc|NOCONTENTCONVERT|nocontentconvert|' . |
143 | 'NOCC|nocc|NEWSECTIONLINK|NONEWSECTIONLINK|HIDDENCAT|INDEX|NOINDEX|STATICREDIRECT' . |
144 | '/'; |
145 | } |
146 | |
147 | /** @inheritDoc */ |
148 | public function canonicalNamespaceId( string $name ): ?int { |
149 | return self::NAMESPACE_MAP[$name] ?? null; |
150 | } |
151 | |
152 | /** @inheritDoc */ |
153 | public function namespaceId( string $name ): ?int { |
154 | $name = Utils::normalizeNamespaceName( $name ); |
155 | return self::NAMESPACE_MAP[$name] ?? null; |
156 | } |
157 | |
158 | /** @inheritDoc */ |
159 | public function namespaceName( int $ns ): ?string { |
160 | static $map = null; |
161 | if ( $map === null ) { |
162 | $map = array_flip( self::NAMESPACE_MAP ); |
163 | } |
164 | if ( !isset( $map[$ns] ) ) { |
165 | return null; |
166 | } |
167 | return ucwords( strtr( $map[$ns], '_', ' ' ) ); |
168 | } |
169 | |
170 | /** @inheritDoc */ |
171 | public function namespaceHasSubpages( int $ns ): bool { |
172 | return !empty( $this->namespacesWithSubpages[$ns] ); |
173 | } |
174 | |
175 | /** @inheritDoc */ |
176 | public function namespaceCase( int $ns ): string { |
177 | return 'first-letter'; |
178 | } |
179 | |
180 | /** @inheritDoc */ |
181 | public function specialPageLocalName( string $alias ): ?string { |
182 | return null; |
183 | } |
184 | |
185 | public function setInterwikiMagic( bool $val ): void { |
186 | $this->interwikiMagic = $val; |
187 | } |
188 | |
189 | public function interwikiMagic(): bool { |
190 | return $this->interwikiMagic; |
191 | } |
192 | |
193 | public function interwikiMap(): array { |
194 | return $this->interwikiMap; |
195 | } |
196 | |
197 | public function iwp(): string { |
198 | return 'mywiki'; |
199 | } |
200 | |
201 | public function legalTitleChars(): string { |
202 | return ' %!"$&\'()*,\-.\/0-9:;=?@A-Z\\\\^_`a-z~\x80-\xFF+'; |
203 | } |
204 | |
205 | public function linkPrefixRegex(): ?string { |
206 | return $this->linkPrefixRegex; |
207 | } |
208 | |
209 | protected function linkTrail(): string { |
210 | // @phan-suppress-previous-line PhanPluginNeverReturnMethod |
211 | throw new \BadMethodCallException( |
212 | 'Should not be used. linkTrailRegex() is overridden here.' ); |
213 | } |
214 | |
215 | public function linkTrailRegex(): ?string { |
216 | return $this->linkTrailRegex; |
217 | } |
218 | |
219 | public function langBcp47(): Bcp47Code { |
220 | return new Bcp47CodeValue( 'en' ); |
221 | } |
222 | |
223 | public function mainPageLinkTarget(): LinkTarget { |
224 | return Title::newFromText( 'Main Page', $this ); |
225 | } |
226 | |
227 | /** @inheritDoc */ |
228 | public function getMWConfigValue( string $key ) { |
229 | switch ( $key ) { |
230 | case 'CiteResponsiveReferences': |
231 | return true; |
232 | case 'CiteResponsiveReferencesThreshold': |
233 | return 10; |
234 | default: |
235 | return null; |
236 | } |
237 | } |
238 | |
239 | public function rtl(): bool { |
240 | return false; |
241 | } |
242 | |
243 | /** @inheritDoc */ |
244 | public function langConverterEnabledBcp47( Bcp47Code $lang ): bool { |
245 | return $lang->toBcp47Code() === 'sr'; |
246 | } |
247 | |
248 | public function script(): string { |
249 | return '/wx/index.php'; |
250 | } |
251 | |
252 | public function scriptpath(): string { |
253 | return '/wx'; |
254 | } |
255 | |
256 | public function server(): string { |
257 | return '//my.wiki.example'; |
258 | } |
259 | |
260 | public function timezoneOffset(): int { |
261 | return $this->timezoneOffset; |
262 | } |
263 | |
264 | /** @inheritDoc */ |
265 | public function variantsFor( Bcp47Code $lang ): ?array { |
266 | switch ( $lang->toBcp47Code() ) { |
267 | case 'sr': |
268 | return [ |
269 | 'base' => new Bcp47CodeValue( 'sr' ), |
270 | 'fallbacks' => [ |
271 | new Bcp47CodeValue( 'sr-Cyrl' ) |
272 | ] |
273 | ]; |
274 | case 'sr-Cyrl': |
275 | return [ |
276 | 'base' => new Bcp47CodeValue( 'sr' ), |
277 | 'fallbacks' => [ |
278 | new Bcp47CodeValue( 'sr' ) |
279 | ] |
280 | ]; |
281 | case 'sr-Latn': |
282 | return [ |
283 | 'base' => new Bcp47CodeValue( 'sr' ), |
284 | 'fallbacks' => [ |
285 | new Bcp47CodeValue( 'sr' ) |
286 | ] |
287 | ]; |
288 | default: |
289 | return null; |
290 | } |
291 | } |
292 | |
293 | public function widthOption(): int { |
294 | return 220; |
295 | } |
296 | |
297 | /** @inheritDoc */ |
298 | protected function getVariableIDs(): array { |
299 | return []; // None for now |
300 | } |
301 | |
302 | /** @inheritDoc */ |
303 | protected function haveComputedFunctionSynonyms(): bool { |
304 | return false; |
305 | } |
306 | |
307 | /** @inheritDoc */ |
308 | protected function updateFunctionSynonym( string $func, string $magicword, bool $caseSensitive ): void { |
309 | /* Nothing for now. Look at src/Config/Api/SiteConfig when mocking is needed. */ |
310 | } |
311 | |
312 | /** @inheritDoc */ |
313 | protected function getMagicWords(): array { |
314 | return [ |
315 | 'toc' => [ 0, '__TOC__' ], |
316 | 'img_thumbnail' => [ 1, 'thumb' ], |
317 | 'img_framed' => [ 1, 'frame', 'framed' ], |
318 | 'img_frameless' => [ 1, 'frameless' ], |
319 | 'img_manualthumb' => [ 1, 'thumbnail=$1', 'thumb=$1' ], |
320 | 'img_none' => [ 1, 'none' ], |
321 | 'img_left' => [ 1, 'left' ], |
322 | 'img_right' => [ 1, 'right' ], |
323 | // T345026: 'sub' should follow 'img_sub' to match dewikivoyage |
324 | 'img_sub' => [ 1, 'sub' ], |
325 | 'sub' => [ 0, 'sub' ], |
326 | 'notoc' => [ 0, '__NOTOC__' ], |
327 | 'timedmedia_loop' => [ 0, 'loop' ], |
328 | 'timedmedia_muted' => [ 0, 'muted' ], |
329 | ]; |
330 | } |
331 | |
332 | /** @inheritDoc */ |
333 | public function getMagicWordMatcher( string $id ): string { |
334 | if ( $id === 'toc' ) { |
335 | return '/^TOC$/'; |
336 | } else { |
337 | return '/(?!)/'; |
338 | } |
339 | } |
340 | |
341 | /** @inheritDoc */ |
342 | public function getParameterizedAliasMatcher( array $words ): callable { |
343 | $paramMWs = [ |
344 | 'img_lossy' => "/^(?:(?i:lossy\=(.*?)))$/uS", |
345 | 'timedmedia_thumbtime' => "/^(?:(?i:thumbtime\=(.*?)))$/uS", |
346 | 'timedmedia_starttime' => "/^(?:(?i:start\=(.*?)))$/uS", |
347 | 'timedmedia_endtime' => "/^(?:(?i:end\=(.*?)))$/uS", |
348 | 'timedmedia_disablecontrols' => "/^(?:(?i:disablecontrols\=(.*?)))$/uS", |
349 | 'img_manualthumb' => "/^(?:(?:thumbnail\=(.*?)|thumb\=(.*?)))$/uS", |
350 | 'img_width' => "/^(?:(?:(.*?)px))$/uS", |
351 | 'img_lang' => "/^(?:(?:lang\=(.*?)))$/uS", |
352 | 'img_page' => "/^(?:(?:page\=(.*?)|page (.*?)))$/uS", |
353 | 'img_upright' => "/^(?:(?:upright\=(.*?)|upright (.*?)))$/uS", |
354 | 'img_link' => "/^(?:(?:link\=(.*?)))$/uS", |
355 | 'img_alt' => "/^(?:(?:alt\=(.*?)))$/uS", |
356 | 'img_class' => "/^(?:(?:class\=(.*?)))$/uS" |
357 | ]; |
358 | $regexes = array_intersect_key( $paramMWs, array_flip( $words ) ); |
359 | return static function ( $text ) use ( $regexes ) { |
360 | /** |
361 | * $name is the canonical magic word name |
362 | * $re has patterns for matching aliases |
363 | */ |
364 | foreach ( $regexes as $name => $re ) { |
365 | if ( preg_match( $re, $text, $m ) ) { |
366 | unset( $m[0] ); |
367 | |
368 | // Ex. regexp here is, /^(?:(?:|vinculo\=(.*?)|enlace\=(.*?)|link\=(.*?)))$/uS |
369 | // Check all the capture groups for a value, if not, it's safe to return an |
370 | // empty string since we did get a match. |
371 | foreach ( $m as $v ) { |
372 | if ( $v !== '' ) { |
373 | return [ 'k' => $name, 'v' => $v ]; |
374 | } |
375 | } |
376 | return [ 'k' => $name, 'v' => '' ]; |
377 | } |
378 | } |
379 | return null; |
380 | }; |
381 | } |
382 | |
383 | /** @inheritDoc */ |
384 | protected function getNonNativeExtensionTags(): array { |
385 | return [ |
386 | 'indicator' => true, |
387 | 'timeline' => true, |
388 | 'hiero' => true, |
389 | 'charinsert' => true, |
390 | 'inputbox' => true, |
391 | 'source' => true, |
392 | 'syntaxhighlight' => true, |
393 | 'section' => true, |
394 | 'score' => true, |
395 | 'templatedata' => true, |
396 | 'math' => true, |
397 | 'ce' => true, |
398 | 'chem' => true, |
399 | 'graph' => true, |
400 | 'maplink' => true, |
401 | 'categorytree' => true, |
402 | 'templatestyles' => true |
403 | ]; |
404 | } |
405 | |
406 | /** @inheritDoc */ |
407 | public function getMaxTemplateDepth(): int { |
408 | return $this->maxDepth; |
409 | } |
410 | |
411 | /** @inheritDoc */ |
412 | protected function getSpecialPageAliases( string $specialPage ): array { |
413 | if ( $specialPage === 'Booksources' ) { |
414 | return [ 'Booksources', 'BookSources' ]; // Mock value |
415 | } else { |
416 | throw new \BadMethodCallException( 'Not implemented' ); |
417 | } |
418 | } |
419 | |
420 | /** @inheritDoc */ |
421 | protected function getSpecialNSAliases(): array { |
422 | return [ "Special", "special" ]; // Mock value |
423 | } |
424 | |
425 | /** @inheritDoc */ |
426 | protected function getProtocols(): array { |
427 | return [ "http:", "https:", "irc:", "ircs:", "news:", "ftp:", "mailto:", "gopher:", "//" ]; |
428 | } |
429 | |
430 | public function fakeTimestamp(): ?int { |
431 | return $this->fakeTimestamp; |
432 | } |
433 | |
434 | /** |
435 | * Set the fake timestamp for testing |
436 | * @param ?int $ts Unix timestamp |
437 | */ |
438 | public function setFakeTimestamp( ?int $ts ): void { |
439 | $this->fakeTimestamp = $ts; |
440 | } |
441 | |
442 | /** |
443 | * Set the timezone offset for testing |
444 | * @param int $offset Offset from UTC |
445 | */ |
446 | public function setTimezoneOffset( int $offset ): void { |
447 | $this->timezoneOffset = $offset; |
448 | } |
449 | |
450 | public function scrubBidiChars(): bool { |
451 | return true; |
452 | } |
453 | |
454 | /** @inheritDoc */ |
455 | public function getNoFollowConfig(): array { |
456 | return [ |
457 | 'nofollow' => true, |
458 | 'nsexceptions' => [ 1 ], |
459 | 'domainexceptions' => [ 'www.example.com' ] |
460 | ]; |
461 | } |
462 | |
463 | /** @inheritDoc */ |
464 | public function getExternalLinkTarget() { |
465 | return $this->externalLinkTarget; |
466 | } |
467 | |
468 | /** @var ?MockMetrics */ |
469 | private $metrics; |
470 | |
471 | /** @inheritDoc */ |
472 | public function metrics(): ?StatsdDataFactoryInterface { |
473 | if ( $this->metrics === null ) { |
474 | $this->metrics = new MockMetrics(); |
475 | } |
476 | return $this->metrics; |
477 | } |
478 | |
479 | /** |
480 | * Increment a counter metric |
481 | * @param string $name |
482 | * @param array $labels |
483 | * @param float $amount |
484 | * @return void |
485 | */ |
486 | public function incrementCounter( string $name, array $labels, float $amount = 1 ): void { |
487 | // We don't use the labels for now, using MockMetrics instead |
488 | $this->metrics->increment( $name ); |
489 | } |
490 | |
491 | /** |
492 | * Record a timing metric |
493 | * @param string $name |
494 | * @param float $value |
495 | * @param array $labels |
496 | * @return void |
497 | */ |
498 | public function observeTiming( string $name, float $value, array $labels ): void { |
499 | // We don't use the labels for now, using MockMetrics instead |
500 | $this->metrics->timing( $name, $value ); |
501 | } |
502 | } |