Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
86.51% |
2231 / 2579 |
|
58.00% |
87 / 150 |
CRAP | |
0.00% |
0 / 1 |
| Parser | |
86.54% |
2231 / 2578 |
|
58.00% |
87 / 150 |
2560.67 | |
0.00% |
0 / 1 |
| __construct | |
96.30% |
26 / 27 |
|
0.00% |
0 / 1 |
2 | |||
| __destruct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
| __clone | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| firstCallInit | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| clearState | |
100.00% |
32 / 32 |
|
100.00% |
1 / 1 |
1 | |||
| resetOutput | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| getParseTime | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
2 | |||
| parse | |
92.86% |
52 / 56 |
|
0.00% |
0 / 1 |
9.03 | |||
| makeLimitReport | |
98.28% |
57 / 58 |
|
0.00% |
0 / 1 |
9 | |||
| recursiveTagParse | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| recursiveTagParseFully | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| parseExtensionTagAsTopLevelDoc | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| preprocess | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
2.01 | |||
| recursivePreprocess | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| getPreloadText | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
| setUser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setTitle | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getTitle | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setPage | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
| getPage | |
40.00% |
2 / 5 |
|
0.00% |
0 / 1 |
4.94 | |||
| getOutputType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setOutputType | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
| getOutput | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getOptions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setOptions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| nextLinkID | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setLinkID | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getTargetLanguage | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
| getUserIdentity | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getPreprocessor | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getLinkRenderer | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| getMagicWordFactory | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getContentLanguage | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getBadFileLookup | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| extractTagsAndParams | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
56 | |||
| getStripList | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getStripState | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| insertStripItem | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| handleTables | |
99.14% |
115 / 116 |
|
0.00% |
0 / 1 |
33 | |||
| internalParse | |
93.55% |
29 / 31 |
|
0.00% |
0 / 1 |
4.00 | |||
| getTargetLanguageConverter | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| getContentLanguageConverter | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| getHookContainer | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getNamespaceInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getMiserMode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getHookRunner | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| internalParseHalfParsed | |
100.00% |
28 / 28 |
|
100.00% |
1 / 1 |
7 | |||
| handleMagicLinks | |
91.30% |
21 / 23 |
|
0.00% |
0 / 1 |
2.00 | |||
| magicLinkCallback | |
96.30% |
52 / 54 |
|
0.00% |
0 / 1 |
16 | |||
| makeFreeExternalLink | |
100.00% |
35 / 35 |
|
100.00% |
1 / 1 |
9 | |||
| handleHeadings | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
2 | |||
| handleAllQuotes | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
| doQuotes | |
98.28% |
114 / 116 |
|
0.00% |
0 / 1 |
46 | |||
| handleExternalLinks | |
97.22% |
35 / 36 |
|
0.00% |
0 / 1 |
7 | |||
| getExternalLinkRel | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| getExternalLinkAttribs | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
| normalizeLinkUrl | |
100.00% |
40 / 40 |
|
100.00% |
1 / 1 |
11 | |||
| normalizeUrlComponent | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
| maybeMakeExternalImage | |
44.83% |
13 / 29 |
|
0.00% |
0 / 1 |
65.54 | |||
| handleInternalLinks | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| handleInternalLinks2 | |
96.73% |
148 / 153 |
|
0.00% |
0 / 1 |
48 | |||
| makeKnownLinkHolder | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
2.01 | |||
| armorLinks | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| expandMagicVariable | |
47.37% |
9 / 19 |
|
0.00% |
0 / 1 |
6.33 | |||
| initializeVariables | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| preprocessToDom | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| replaceVariables | |
55.56% |
10 / 18 |
|
0.00% |
0 / 1 |
11.30 | |||
| setUseParsoidFragments | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| useParsoidFragments | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| limitationWarn | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
| braceSubstitution | |
85.65% |
185 / 216 |
|
0.00% |
0 / 1 |
107.86 | |||
| callParserFunction | |
95.24% |
40 / 42 |
|
0.00% |
0 / 1 |
16 | |||
| getTemplateDom | |
95.45% |
21 / 22 |
|
0.00% |
0 / 1 |
8 | |||
| fetchCurrentRevisionRecordOfTitle | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
4 | |||
| isCurrentRevisionOfTitleCached | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| defaultFetchRevisionRecord | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
| statelessFetchRevisionRecord | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| fetchTemplateAndTitle | |
88.24% |
15 / 17 |
|
0.00% |
0 / 1 |
6.06 | |||
| defaultFetchTemplate | |
94.94% |
75 / 79 |
|
0.00% |
0 / 1 |
24.07 | |||
| statelessFetchTemplate | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
| fetchFileAndTitle | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
5 | |||
| fetchFileNoRegister | |
71.43% |
5 / 7 |
|
0.00% |
0 / 1 |
3.21 | |||
| interwikiTransclude | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
110 | |||
| argSubstitution | |
86.36% |
19 / 22 |
|
0.00% |
0 / 1 |
12.37 | |||
| tagNeedsNowikiStrippedInTagPF | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| extensionSubstitution | |
72.55% |
37 / 51 |
|
0.00% |
0 / 1 |
37.93 | |||
| incrementIncludeSize | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
| incrementExpensiveFunctionCount | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| handleDoubleUnderscore | |
97.06% |
33 / 34 |
|
0.00% |
0 / 1 |
17 | |||
| addTrackingCategory | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| msg | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| cleanUpTocLine | |
100.00% |
28 / 28 |
|
100.00% |
1 / 1 |
16 | |||
| finalizeHeadings | |
99.31% |
143 / 144 |
|
0.00% |
0 / 1 |
43 | |||
| localizeTOC | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
6 | |||
| preSaveTransform | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
| pstPass2 | |
100.00% |
31 / 31 |
|
100.00% |
1 / 1 |
5 | |||
| getUserSig | |
76.92% |
30 / 39 |
|
0.00% |
0 / 1 |
17.77 | |||
| validateSig | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
| cleanSig | |
100.00% |
21 / 21 |
|
100.00% |
1 / 1 |
4 | |||
| cleanSigInSig | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| replaceTableOfContentsMarker | |
94.12% |
16 / 17 |
|
0.00% |
0 / 1 |
4.00 | |||
| startExternalParse | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| startParse | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| transformMsg | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
2.01 | |||
| setHook | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
| clearTagHooks | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| setFunctionHook | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
6 | |||
| getFunctionHooks | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| replaceLinkHoldersPrivate | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| replaceLinkHoldersText | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| renderImageGallery | |
95.00% |
95 / 100 |
|
0.00% |
0 / 1 |
25 | |||
| getImageParams | |
80.77% |
21 / 26 |
|
0.00% |
0 / 1 |
8.46 | |||
| makeImageHtml | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| makeImage | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| makeImageInternal | |
98.98% |
97 / 98 |
|
0.00% |
0 / 1 |
36 | |||
| parseLinkParameter | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
6 | |||
| modifyImageHtml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| stripAltText | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
2 | |||
| getTags | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getFunctionSynonyms | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getUrlProtocols | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| extractSections | |
94.12% |
48 / 51 |
|
0.00% |
0 / 1 |
21.09 | |||
| getSection | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| replaceSection | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getFlatSectionInfo | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
12 | |||
| getRevisionId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getRevisionRecordObject | |
72.22% |
13 / 18 |
|
0.00% |
0 / 1 |
9.37 | |||
| getRevisionTimestamp | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
4 | |||
| getRevisionUser | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
6 | |||
| getRevisionSize | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
| getSectionNameFromStrippedText | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| makeAnchor | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| makeLegacyAnchor | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
| guessSectionNameFromWikiText | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| guessLegacySectionNameFromWikiText | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| guessSectionNameFromStrippedText | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| normalizeSectionName | |
60.00% |
3 / 5 |
|
0.00% |
0 / 1 |
2.26 | |||
| stripSectionName | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
| markerSkipCallback | |
87.50% |
14 / 16 |
|
0.00% |
0 / 1 |
4.03 | |||
| killMarkers | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| parseWidthParam | |
94.44% |
17 / 18 |
|
0.00% |
0 / 1 |
9.01 | |||
| lock | |
60.00% |
12 / 20 |
|
0.00% |
0 / 1 |
6.60 | |||
| isLocked | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| stripOuterParagraph | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
| splitDisplayTitle | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
| splitPageTitle | |
100.00% |
21 / 21 |
|
100.00% |
1 / 1 |
4 | |||
| formatPageTitle | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
3 | |||
| unformatPageTitle | |
90.48% |
19 / 21 |
|
0.00% |
0 / 1 |
4.01 | |||
| extractBody | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
20 | |||
| setOutputFlag | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * PHP parser that converts wiki markup to HTML. |
| 4 | * |
| 5 | * @license GPL-2.0-or-later |
| 6 | * @file |
| 7 | * @ingroup Parser |
| 8 | */ |
| 9 | |
| 10 | namespace MediaWiki\Parser; |
| 11 | |
| 12 | use BadMethodCallException; |
| 13 | use DateTime; |
| 14 | use DateTimeZone; |
| 15 | use Exception; |
| 16 | use InvalidArgumentException; |
| 17 | use LogicException; |
| 18 | use MediaWiki\Category\TrackingCategories; |
| 19 | use MediaWiki\Config\ServiceOptions; |
| 20 | use MediaWiki\Content\TextContent; |
| 21 | use MediaWiki\Context\RequestContext; |
| 22 | use MediaWiki\Debug\DeprecationHelper; |
| 23 | use MediaWiki\FileRepo\File\File; |
| 24 | use MediaWiki\FileRepo\RepoGroup; |
| 25 | use MediaWiki\Gallery\Exception\ImageGalleryClassNotFoundException; |
| 26 | use MediaWiki\Gallery\ImageGalleryBase; |
| 27 | use MediaWiki\HookContainer\HookContainer; |
| 28 | use MediaWiki\HookContainer\HookRunner; |
| 29 | use MediaWiki\Html\Html; |
| 30 | use MediaWiki\Html\HtmlHelper; |
| 31 | use MediaWiki\Http\HttpRequestFactory; |
| 32 | use MediaWiki\Language\ILanguageConverter; |
| 33 | use MediaWiki\Language\Language; |
| 34 | use MediaWiki\Language\LanguageCode; |
| 35 | use MediaWiki\Language\LanguageConverterFactory; |
| 36 | use MediaWiki\Language\LanguageFactory; |
| 37 | use MediaWiki\Language\LanguageNameUtils; |
| 38 | use MediaWiki\Language\MessageLocalizer; |
| 39 | use MediaWiki\Language\RawMessage; |
| 40 | use MediaWiki\Linker\Linker; |
| 41 | use MediaWiki\Linker\LinkRenderer; |
| 42 | use MediaWiki\Linker\LinkRendererFactory; |
| 43 | use MediaWiki\MainConfigNames; |
| 44 | use MediaWiki\Media\MediaHandler; |
| 45 | use MediaWiki\MediaWikiServices; |
| 46 | use MediaWiki\Message\Message; |
| 47 | use MediaWiki\Page\CacheKeyHelper; |
| 48 | use MediaWiki\Page\File\BadFileLookup; |
| 49 | use MediaWiki\Page\LinkAlwaysKnownLookup; |
| 50 | use MediaWiki\Page\LinkCache; |
| 51 | use MediaWiki\Page\PageIdentity; |
| 52 | use MediaWiki\Page\PageReference; |
| 53 | use MediaWiki\Preferences\SignatureValidatorFactory; |
| 54 | use MediaWiki\Profiler\SectionProfiler; |
| 55 | use MediaWiki\Request\FauxRequest; |
| 56 | use MediaWiki\Revision\RevisionAccessException; |
| 57 | use MediaWiki\Revision\RevisionLookup; |
| 58 | use MediaWiki\Revision\RevisionRecord; |
| 59 | use MediaWiki\Revision\SlotRecord; |
| 60 | use MediaWiki\ShadowPage\ShadowPageLoader; |
| 61 | use MediaWiki\SpecialPage\SpecialPage; |
| 62 | use MediaWiki\SpecialPage\SpecialPageFactory; |
| 63 | use MediaWiki\Tidy\TidyDriverBase; |
| 64 | use MediaWiki\Title\MalformedTitleException; |
| 65 | use MediaWiki\Title\NamespaceInfo; |
| 66 | use MediaWiki\Title\Title; |
| 67 | use MediaWiki\Title\TitleFormatter; |
| 68 | use MediaWiki\Title\TitleValue; |
| 69 | use MediaWiki\User\Options\UserOptionsLookup; |
| 70 | use MediaWiki\User\User; |
| 71 | use MediaWiki\User\UserFactory; |
| 72 | use MediaWiki\User\UserIdentity; |
| 73 | use MediaWiki\User\UserNameUtils; |
| 74 | use MediaWiki\Utils\MWTimestamp; |
| 75 | use MediaWiki\Utils\UrlUtils; |
| 76 | use MediaWiki\Xml\Xml; |
| 77 | use Psr\Log\LoggerInterface; |
| 78 | use RuntimeException; |
| 79 | use UnexpectedValueException; |
| 80 | use Wikimedia\Bcp47Code\Bcp47CodeValue; |
| 81 | use Wikimedia\HtmlArmor\HtmlArmor; |
| 82 | use Wikimedia\IPUtils; |
| 83 | use Wikimedia\ObjectCache\MapCacheLRU; |
| 84 | use Wikimedia\ObjectCache\WANObjectCache; |
| 85 | use Wikimedia\Parsoid\Core\LinkTarget; |
| 86 | use Wikimedia\Parsoid\Core\SectionMetadata; |
| 87 | use Wikimedia\Parsoid\Core\TOCData; |
| 88 | use Wikimedia\Parsoid\DOM\Comment; |
| 89 | use Wikimedia\Parsoid\DOM\DocumentFragment; |
| 90 | use Wikimedia\Parsoid\DOM\Element; |
| 91 | use Wikimedia\Parsoid\DOM\Node; |
| 92 | use Wikimedia\Parsoid\Utils\DOMCompat; |
| 93 | use Wikimedia\Parsoid\Utils\DOMUtils; |
| 94 | use Wikimedia\RemexHtml\Serializer\SerializerNode; |
| 95 | use Wikimedia\ScopedCallback; |
| 96 | use Wikimedia\StringUtils\StringUtils; |
| 97 | |
| 98 | /** |
| 99 | * @defgroup Parser Parser |
| 100 | */ |
| 101 | |
| 102 | /** |
| 103 | * PHP Parser - Processes wiki markup (which uses a more user-friendly |
| 104 | * syntax, such as "[[link]]" for making links), and provides a one-way |
| 105 | * transformation of that wiki markup it into (X)HTML output / markup |
| 106 | * (which in turn the browser understands, and can display). |
| 107 | * |
| 108 | * There are seven main entry points into the Parser class: |
| 109 | * |
| 110 | * - Parser::parse() |
| 111 | * produces HTML output |
| 112 | * - Parser::preSaveTransform() |
| 113 | * produces altered wiki markup |
| 114 | * - Parser::preprocess() |
| 115 | * removes HTML comments and expands templates |
| 116 | * - Parser::cleanSig() and Parser::cleanSigInSig() |
| 117 | * cleans a signature before saving it to preferences |
| 118 | * - Parser::getSection() |
| 119 | * return the content of a section from an article for section editing |
| 120 | * - Parser::replaceSection() |
| 121 | * replaces a section by number inside an article |
| 122 | * - Parser::getPreloadText() |
| 123 | * removes <noinclude> sections and <includeonly> tags |
| 124 | * |
| 125 | * @warning $wgTitle or $wgRequest or $wgLang. Keep them away! |
| 126 | * |
| 127 | * @par Settings: |
| 128 | * $wgNamespacesWithSubpages |
| 129 | * |
| 130 | * @par Settings only within ParserOptions: |
| 131 | * $wgAllowExternalImages |
| 132 | * $wgAllowSpecialInclusion |
| 133 | * $wgInterwikiMagic |
| 134 | * $wgMaxArticleSize |
| 135 | * |
| 136 | * @ingroup Parser |
| 137 | */ |
| 138 | #[\AllowDynamicProperties] |
| 139 | class Parser implements MessageLocalizer { |
| 140 | use DeprecationHelper; |
| 141 | |
| 142 | # Flags for Parser::setFunctionHook |
| 143 | public const SFH_NO_HASH = 1; |
| 144 | public const SFH_OBJECT_ARGS = 2; |
| 145 | |
| 146 | # Constants needed for external link processing |
| 147 | /** |
| 148 | * Everything except bracket, space, or control characters. |
| 149 | * \p{Zs} is unicode 'separator, space' category. It covers the space 0x20 |
| 150 | * as well as U+3000 is IDEOGRAPHIC SPACE for T21052. |
| 151 | * \x{FFFD} is the Unicode replacement character, which the HTML5 spec |
| 152 | * uses to replace invalid HTML characters. |
| 153 | */ |
| 154 | public const EXT_LINK_URL_CLASS = '[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}]'; |
| 155 | /** |
| 156 | * Simplified expression to match an IPv4 or IPv6 address, or |
| 157 | * at least one character of a host name (embeds Parser::EXT_LINK_URL_CLASS) |
| 158 | */ |
| 159 | // phpcs:ignore Generic.Files.LineLength |
| 160 | private const EXT_LINK_ADDR = '(?:[0-9.]+|\\[(?i:[0-9a-f:.]+)\\]|[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}])'; |
| 161 | /** RegExp to make image URLs (embeds IPv6 part of Parser::EXT_LINK_ADDR) */ |
| 162 | // phpcs:ignore Generic.Files.LineLength |
| 163 | private const EXT_IMAGE_REGEX = '/^(http:\/\/|https:\/\/)((?:\\[(?i:[0-9a-f:.]+)\\])?[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}]+) |
| 164 | \\/([A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]+)\\.((?i)avif|gif|jpg|jpeg|png|svg|webp)$/Sxu'; |
| 165 | |
| 166 | /** Regular expression for a non-newline space */ |
| 167 | private const SPACE_NOT_NL = '(?:\t| |&\#0*160;|&\#[Xx]0*[Aa]0;|\p{Zs})'; |
| 168 | |
| 169 | /** |
| 170 | * @var int Preprocess wikitext in transclusion mode |
| 171 | * @deprecated Since 1.36 |
| 172 | */ |
| 173 | public const PTD_FOR_INCLUSION = Preprocessor::DOM_FOR_INCLUSION; |
| 174 | |
| 175 | # Allowed values for $this->mOutputType |
| 176 | /** Output type: like Parser::parse() */ |
| 177 | public const OT_HTML = 1; |
| 178 | /** Output type: like Parser::preSaveTransform() */ |
| 179 | public const OT_WIKI = 2; |
| 180 | /** Output type: like Parser::preprocess() */ |
| 181 | public const OT_PREPROCESS = 3; |
| 182 | /** |
| 183 | * Output type: like Parser::extractSections() - portions of the |
| 184 | * original are returned unchanged. |
| 185 | */ |
| 186 | public const OT_PLAIN = 4; |
| 187 | |
| 188 | /** |
| 189 | * @var string Prefix and suffix for temporary replacement strings |
| 190 | * for the multipass parser. |
| 191 | * |
| 192 | * \x7f should never appear in input as it's disallowed in XML. |
| 193 | * Using it at the front also gives us a little extra robustness |
| 194 | * since it shouldn't match when butted up against identifier-like |
| 195 | * string constructs. |
| 196 | * |
| 197 | * Must not consist of all title characters, or else it will change |
| 198 | * the behavior of <nowiki> in a link. |
| 199 | * |
| 200 | * Must have a character that needs escaping in attributes, otherwise |
| 201 | * someone could put a strip marker in an attribute, to get around |
| 202 | * escaping quote marks, and break out of the attribute. Thus we add |
| 203 | * `'". |
| 204 | */ |
| 205 | public const MARKER_SUFFIX = "-QINU`\"'\x7f"; |
| 206 | public const MARKER_PREFIX = "\x7f'\"`UNIQ-"; |
| 207 | private const HEADLINE_MARKER_REGEX = '/^' . self::MARKER_PREFIX . '-h-(\d+)-' . self::MARKER_SUFFIX . '/'; |
| 208 | |
| 209 | /** |
| 210 | * Internal marker used by parser to track where the table of |
| 211 | * contents should be. Various magic words can change the position |
| 212 | * during the parse. The table of contents is generated during |
| 213 | * the parse, however skins have the final decision on whether the |
| 214 | * table of contents is injected. This placeholder element |
| 215 | * identifies where in the page the table of contents should be |
| 216 | * injected, if at all. |
| 217 | * @var string |
| 218 | * @see Keep this in sync with BlockLevelPass::execute() and |
| 219 | * RemexCompatMunger::isTableOfContentsMarker() |
| 220 | * @internal Skins should *not* directly reference TOC_PLACEHOLDER |
| 221 | * but instead use Parser::replaceTableOfContentsMarker(). |
| 222 | */ |
| 223 | public const TOC_PLACEHOLDER = '<meta property="mw:PageProp/toc" />'; |
| 224 | |
| 225 | # Persistent: |
| 226 | /** @var array<string,callable> */ |
| 227 | private array $mTagHooks = []; |
| 228 | /** @var array<string,array{0:callable,1:int}> */ |
| 229 | private array $mFunctionHooks = []; |
| 230 | /** @var array{0:array<string,string>,1:array<string,string>} */ |
| 231 | private array $mFunctionSynonyms = [ 0 => [], 1 => [] ]; |
| 232 | /** @var string[] */ |
| 233 | private array $mStripList = []; |
| 234 | /** @var array<string,string> */ |
| 235 | private array $mVarCache = []; |
| 236 | /** @var array<string,array<string,string[]>> */ |
| 237 | private array $mImageParams = []; |
| 238 | /** @var array<string,MagicWordArray> */ |
| 239 | private array $mImageParamsMagicArray = []; |
| 240 | /** @deprecated since 1.35 */ |
| 241 | public $mMarkerIndex = 0; |
| 242 | |
| 243 | // Initialised by initializeVariables() |
| 244 | /** @var MagicWordArray */ |
| 245 | private MagicWordArray $mVariables; |
| 246 | private MagicWordArray $mSubstWords; |
| 247 | |
| 248 | // Initialised in constructor |
| 249 | /** @var string */ |
| 250 | private string $mExtLinkBracketedRegex; |
| 251 | private HookRunner $hookRunner; |
| 252 | private Preprocessor $mPreprocessor; |
| 253 | |
| 254 | // Cleared with clearState(): |
| 255 | /** @var ParserOutput */ |
| 256 | private ParserOutput $mOutput; |
| 257 | private int $mAutonumber = 0; |
| 258 | private StripState $mStripState; |
| 259 | private LinkHolderArray $mLinkHolders; |
| 260 | private int $mLinkID = 0; |
| 261 | private array $mIncludeSizes; |
| 262 | /** |
| 263 | * @internal |
| 264 | * @var int |
| 265 | */ |
| 266 | public $mPPNodeCount; |
| 267 | /** |
| 268 | * @internal |
| 269 | * @var int |
| 270 | */ |
| 271 | public $mHighestExpansionDepth; |
| 272 | private array $mTplRedirCache; |
| 273 | /** @internal */ |
| 274 | public array $mHeadings; |
| 275 | /** @var array<string,string> */ |
| 276 | private array $mDoubleUnderscores; |
| 277 | /** |
| 278 | * Number of expensive parser function calls |
| 279 | * @deprecated since 1.35 |
| 280 | */ |
| 281 | public $mExpensiveFunctionCount; |
| 282 | private bool $mShowToc; |
| 283 | private bool $mForceTocPosition; |
| 284 | private array $mTplDomCache; |
| 285 | private ?UserIdentity $mUser; |
| 286 | |
| 287 | # Temporary |
| 288 | # These are variables reset at least once per parse regardless of $clearState |
| 289 | |
| 290 | /** |
| 291 | * @var ParserOptions|null |
| 292 | * @deprecated since 1.35, use Parser::getOptions() |
| 293 | */ |
| 294 | private $mOptions; |
| 295 | |
| 296 | # Deprecated "dynamic" properties |
| 297 | # These used to be dynamic properties added to the parser, but these |
| 298 | # have been deprecated since 1.42. |
| 299 | /** @deprecated since 1.42: T203531 */ |
| 300 | public $mExtVariables; |
| 301 | /** @deprecated since 1.42: T203532 */ |
| 302 | public $mExtArrays; |
| 303 | /** @deprecated since 1.42: T359887 */ |
| 304 | public $mExtHashTables; |
| 305 | /** @deprecated since 1.42: T203563 */ |
| 306 | public $mExtLoopsCounter; |
| 307 | |
| 308 | /** |
| 309 | * Title context, used for self-link rendering and similar things |
| 310 | * |
| 311 | * @deprecated since 1.35, use Parser::getPage() |
| 312 | */ |
| 313 | private Title $mTitle; |
| 314 | /** Output type, one of the OT_xxx constants */ |
| 315 | private int $mOutputType; |
| 316 | /** |
| 317 | * When false (default), extension tags are put in the general strip state |
| 318 | * for OT_PREPROCESS. |
| 319 | * When true, extension tags are skipped during OT_PREPROCESS (parsoid |
| 320 | * fragment v1) or put into the `exttag` strip state (parsoid fragment |
| 321 | * v2+) |
| 322 | */ |
| 323 | private bool $useParsoidFragments = false; |
| 324 | /** |
| 325 | * Shortcut alias, see Parser::setOutputType() |
| 326 | * @deprecated since 1.35 |
| 327 | */ |
| 328 | private array $ot; |
| 329 | /** ID to display in {{REVISIONID}} tags */ |
| 330 | private ?int $mRevisionId = null; |
| 331 | /** The timestamp of the specified revision ID */ |
| 332 | private ?string $mRevisionTimestamp = null; |
| 333 | /** User to display in {{REVISIONUSER}} tag */ |
| 334 | private ?string $mRevisionUser = null; |
| 335 | /** Size to display in {{REVISIONSIZE}} variable */ |
| 336 | private ?int $mRevisionSize = null; |
| 337 | /** @var int|false For {{PAGESIZE}} on current page */ |
| 338 | private $mInputSize = false; |
| 339 | |
| 340 | private ?RevisionRecord $mRevisionRecordObject = null; |
| 341 | |
| 342 | /** |
| 343 | * A cache of the current revisions of titles. Keys are $title->getPrefixedDbKey() |
| 344 | * |
| 345 | * @since 1.24 |
| 346 | */ |
| 347 | private ?MapCacheLRU $currentRevisionCache = null; |
| 348 | |
| 349 | /** |
| 350 | * @var bool|string Recursive call protection. |
| 351 | * @internal |
| 352 | */ |
| 353 | private $mInParse = false; |
| 354 | |
| 355 | private SectionProfiler $mProfiler; |
| 356 | private ?LinkRenderer $mLinkRenderer = null; |
| 357 | |
| 358 | /** |
| 359 | * @internal For use by ServiceWiring |
| 360 | */ |
| 361 | public const CONSTRUCTOR_OPTIONS = [ |
| 362 | // See documentation for the corresponding config options |
| 363 | // Many of these are only used in (eg) CoreMagicVariables |
| 364 | MainConfigNames::AllowDisplayTitle, |
| 365 | MainConfigNames::AllowSlowParserFunctions, |
| 366 | MainConfigNames::ArticlePath, |
| 367 | MainConfigNames::EnableScaryTranscluding, |
| 368 | MainConfigNames::ExtraInterlanguageLinkPrefixes, |
| 369 | MainConfigNames::FragmentMode, |
| 370 | MainConfigNames::Localtimezone, |
| 371 | MainConfigNames::MaxArticleSize, |
| 372 | MainConfigNames::MaxSigChars, |
| 373 | MainConfigNames::MaxTocLevel, |
| 374 | MainConfigNames::MiserMode, |
| 375 | MainConfigNames::RawHtml, |
| 376 | MainConfigNames::ScriptPath, |
| 377 | MainConfigNames::Server, |
| 378 | MainConfigNames::ServerName, |
| 379 | MainConfigNames::ShowHostnames, |
| 380 | MainConfigNames::SignatureValidation, |
| 381 | MainConfigNames::Sitename, |
| 382 | MainConfigNames::StylePath, |
| 383 | MainConfigNames::TranscludeCacheExpiry, |
| 384 | MainConfigNames::PreprocessorCacheThreshold, |
| 385 | MainConfigNames::EnableParserLimitReporting, |
| 386 | MainConfigNames::ParserEnableUserLanguage, |
| 387 | ]; |
| 388 | |
| 389 | /** |
| 390 | * Constructing parsers directly is not allowed! Use a ParserFactory. |
| 391 | * @internal |
| 392 | */ |
| 393 | public function __construct( |
| 394 | // This is called $svcOptions instead of $options like elsewhere to avoid confusion with |
| 395 | // $mOptions, which is public and widely used, and also with the local variable $options used |
| 396 | // for ParserOptions throughout this file. |
| 397 | private ServiceOptions $svcOptions, |
| 398 | private ParserCoreTagHooks $parserCoreTagHooks, |
| 399 | private MagicWordFactory $magicWordFactory, |
| 400 | private Language $contLang, |
| 401 | private UrlUtils $urlUtils, |
| 402 | private SpecialPageFactory $specialPageFactory, |
| 403 | private LinkRendererFactory $linkRendererFactory, |
| 404 | private NamespaceInfo $nsInfo, |
| 405 | private LoggerInterface $logger, |
| 406 | private BadFileLookup $badFileLookup, |
| 407 | private RepoGroup $repoGroup, |
| 408 | private LanguageFactory $languageFactory, |
| 409 | private LanguageConverterFactory $languageConverterFactory, |
| 410 | private LanguageNameUtils $languageNameUtils, |
| 411 | private HookContainer $hookContainer, |
| 412 | private TidyDriverBase $tidy, |
| 413 | private WANObjectCache $wanCache, |
| 414 | private UserOptionsLookup $userOptionsLookup, |
| 415 | private UserFactory $userFactory, |
| 416 | private TitleFormatter $titleFormatter, |
| 417 | private HttpRequestFactory $httpRequestFactory, |
| 418 | private TrackingCategories $trackingCategories, |
| 419 | private SignatureValidatorFactory $signatureValidatorFactory, |
| 420 | private UserNameUtils $userNameUtils, |
| 421 | private LinkAlwaysKnownLookup $linkAlwaysKnownLookup, |
| 422 | ) { |
| 423 | $this->deprecateDynamicPropertiesAccess( '1.42', __CLASS__ ); |
| 424 | $this->deprecatePublicProperty( 'ot', '1.35', __CLASS__ ); |
| 425 | $this->deprecatePublicProperty( 'mTitle', '1.35', __CLASS__ ); |
| 426 | $this->deprecatePublicProperty( 'mOptions', '1.35', __CLASS__ ); |
| 427 | |
| 428 | if ( ParserFactory::$inParserFactory === 0 ) { |
| 429 | // Direct construction of Parser was deprecated in 1.34 and |
| 430 | // removed in 1.36; use a ParserFactory instead. |
| 431 | throw new BadMethodCallException( 'Direct construction of Parser not allowed' ); |
| 432 | } |
| 433 | $svcOptions->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); |
| 434 | |
| 435 | $this->mExtLinkBracketedRegex = '/\[(((?i)' . $this->urlUtils->validProtocols() . ')' . |
| 436 | self::EXT_LINK_ADDR . |
| 437 | self::EXT_LINK_URL_CLASS . '*)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F\\x{FFFD}]*)\]/Su'; |
| 438 | |