Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.37% covered (warning)
86.37%
2141 / 2479
56.16% covered (warning)
56.16%
82 / 146
CRAP
0.00% covered (danger)
0.00%
0 / 1
Parser
86.40% covered (warning)
86.40%
2141 / 2478
56.16% covered (warning)
56.16%
82 / 146
2374.73
0.00% covered (danger)
0.00%
0 / 1
 __construct
98.08% covered (success)
98.08%
51 / 52
0.00% covered (danger)
0.00%
0 / 1
2
 __destruct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 __clone
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 firstCallInit
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 clearState
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
1
 resetOutput
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 parse
92.16% covered (success)
92.16%
47 / 51
0.00% covered (danger)
0.00%
0 / 1
10.05
 makeLimitReport
100.00% covered (success)
100.00%
46 / 46
100.00% covered (success)
100.00%
1 / 1
5
 recursiveTagParse
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 recursiveTagParseFully
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 parseExtensionTagAsTopLevelDoc
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 preprocess
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
2.01
 recursivePreprocess
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getPreloadText
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 setUser
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTitle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPage
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 getPage
33.33% covered (danger)
33.33%
2 / 6
0.00% covered (danger)
0.00%
0 / 1
5.67
 getOutputType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setOutputType
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 OutputType
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getOutput
50.00% covered (danger)
50.00%
2 / 4
0.00% covered (danger)
0.00%
0 / 1
2.50
 getOptions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setOptions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 Options
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 nextLinkID
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setLinkID
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFunctionLang
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getTargetLanguage
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 getUserIdentity
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPreprocessor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkRenderer
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getMagicWordFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentLanguage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBadFileLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 extractTagsAndParams
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
56
 getStripList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStripState
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 insertStripItem
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 handleTables
99.14% covered (success)
99.14%
115 / 116
0.00% covered (danger)
0.00%
0 / 1
33
 internalParse
93.75% covered (success)
93.75%
30 / 32
0.00% covered (danger)
0.00%
0 / 1
4.00
 getTargetLanguageConverter
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getContentLanguageConverter
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getHookContainer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHookRunner
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 internalParseHalfParsed
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
6
 handleMagicLinks
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
1
 magicLinkCallback
96.30% covered (success)
96.30%
52 / 54
0.00% covered (danger)
0.00%
0 / 1
16
 makeFreeExternalLink
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
9
 handleHeadings
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 handleAllQuotes
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 doQuotes
98.28% covered (success)
98.28%
114 / 116
0.00% covered (danger)
0.00%
0 / 1
46
 handleExternalLinks
97.22% covered (success)
97.22%
35 / 36
0.00% covered (danger)
0.00%
0 / 1
7
 getExternalLinkRel
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 getExternalLinkAttribs
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 normalizeLinkUrl
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
11
 normalizeUrlComponent
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 maybeMakeExternalImage
44.83% covered (danger)
44.83%
13 / 29
0.00% covered (danger)
0.00%
0 / 1
65.54
 handleInternalLinks
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 handleInternalLinks2
96.77% covered (success)
96.77%
150 / 155
0.00% covered (danger)
0.00%
0 / 1
49
 makeKnownLinkHolder
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 armorLinks
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 doBlockLevels
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 expandMagicVariable
76.47% covered (warning)
76.47%
13 / 17
0.00% covered (danger)
0.00%
0 / 1
4.21
 initializeVariables
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 preprocessToDom
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 replaceVariables
56.25% covered (warning)
56.25%
9 / 16
0.00% covered (danger)
0.00%
0 / 1
9.01
 limitationWarn
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 braceSubstitution
84.73% covered (warning)
84.73%
172 / 203
0.00% covered (danger)
0.00%
0 / 1
98.11
 callParserFunction
95.45% covered (success)
95.45%
42 / 44
0.00% covered (danger)
0.00%
0 / 1
17
 getTemplateDom
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
5
 fetchCurrentRevisionRecordOfTitle
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
4
 isCurrentRevisionOfTitleCached
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 statelessFetchRevisionRecord
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 fetchTemplateAndTitle
88.24% covered (warning)
88.24%
15 / 17
0.00% covered (danger)
0.00%
0 / 1
6.06
 statelessFetchTemplate
96.59% covered (success)
96.59%
85 / 88
0.00% covered (danger)
0.00%
0 / 1
25
 fetchFileAndTitle
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 fetchFileNoRegister
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
3.21
 interwikiTransclude
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 1
110
 argSubstitution
86.36% covered (warning)
86.36%
19 / 22
0.00% covered (danger)
0.00%
0 / 1
12.37
 tagNeedsNowikiStrippedInTagPF
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 extensionSubstitution
75.56% covered (warning)
75.56%
34 / 45
0.00% covered (danger)
0.00%
0 / 1
27.44
 incrementIncludeSize
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 incrementExpensiveFunctionCount
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 handleDoubleUnderscore
76.00% covered (warning)
76.00%
19 / 25
0.00% covered (danger)
0.00%
0 / 1
13.99
 addTrackingCategory
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 msg
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 cleanUpTocLine
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
15
 finalizeHeadings
100.00% covered (success)
100.00%
145 / 145
100.00% covered (success)
100.00%
1 / 1
39
 localizeTOC
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
6
 preSaveTransform
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
3
 pstPass2
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
1 / 1
5
 getUserSig
42.86% covered (danger)
42.86%
15 / 35
0.00% covered (danger)
0.00%
0 / 1
38.87
 validateSig
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 cleanSig
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
4
 cleanSigInSig
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 replaceTableOfContentsMarker
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
2.01
 startExternalParse
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 startParse
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 transformMsg
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 setHook
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 clearTagHooks
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setFunctionHook
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
 getFunctionHooks
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 replaceLinkHolders
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 replaceLinkHoldersPrivate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 replaceLinkHoldersText
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 renderImageGallery
95.24% covered (success)
95.24%
100 / 105
0.00% covered (danger)
0.00%
0 / 1
27
 getImageParams
82.14% covered (warning)
82.14%
23 / 28
0.00% covered (danger)
0.00%
0 / 1
8.36
 makeImage
100.00% covered (success)
100.00%
101 / 101
100.00% covered (success)
100.00%
1 / 1
39
 parseLinkParameter
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
6
 modifyImageHtml
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 stripAltText
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 attributeStripCallback
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getTags
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFunctionSynonyms
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUrlProtocols
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 extractSections
85.96% covered (warning)
85.96%
49 / 57
0.00% covered (danger)
0.00%
0 / 1
22.22
 getSection
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 replaceSection
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFlatSectionInfo
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
12
 getRevisionId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionRecordObject
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
7
 getRevisionTimestamp
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 getRevisionUser
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
 getRevisionSize
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 getDefaultSort
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSectionNameFromStrippedText
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 makeAnchor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeLegacyAnchor
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 guessSectionNameFromWikiText
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 guessLegacySectionNameFromWikiText
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 guessSectionNameFromStrippedText
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 normalizeSectionName
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
2.26
 stripSectionName
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 markerSkipCallback
87.50% covered (warning)
87.50%
14 / 16
0.00% covered (danger)
0.00%
0 / 1
4.03
 killMarkers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parseWidthParam
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
5.01
 lock
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 isLocked
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 stripOuterParagraph
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 formatPageTitle
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 extractBody
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 enableOOUI
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 setOutputFlag
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * PHP parser that converts wiki markup to HTML.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Parser
22 */
23
24namespace MediaWiki\Parser;
25
26use BadMethodCallException;
27use BlockLevelPass;
28use CoreMagicVariables;
29use CoreParserFunctions;
30use CoreTagHooks;
31use Exception;
32use File;
33use HtmlArmor;
34use ILanguageConverter;
35use ImageGalleryBase;
36use ImageGalleryClassNotFoundException;
37use InvalidArgumentException;
38use Language;
39use LanguageCode;
40use LinkHolderArray;
41use LogicException;
42use MapCacheLRU;
43use MediaHandler;
44use MediaWiki\Cache\CacheKeyHelper;
45use MediaWiki\Category\TrackingCategories;
46use MediaWiki\Config\ServiceOptions;
47use MediaWiki\Content\TextContent;
48use MediaWiki\Context\RequestContext;
49use MediaWiki\Debug\DeprecationHelper;
50use MediaWiki\HookContainer\HookContainer;
51use MediaWiki\HookContainer\HookRunner;
52use MediaWiki\Html\Html;
53use MediaWiki\Http\HttpRequestFactory;
54use MediaWiki\Language\RawMessage;
55use MediaWiki\Languages\LanguageConverterFactory;
56use MediaWiki\Languages\LanguageNameUtils;
57use MediaWiki\Linker\Linker;
58use MediaWiki\Linker\LinkRenderer;
59use MediaWiki\Linker\LinkRendererFactory;
60use MediaWiki\Linker\LinkTarget;
61use MediaWiki\MainConfigNames;
62use MediaWiki\MediaWikiServices;
63use MediaWiki\Message\Message;
64use MediaWiki\Output\OutputPage;
65use MediaWiki\Page\File\BadFileLookup;
66use MediaWiki\Page\PageIdentity;
67use MediaWiki\Page\PageReference;
68use MediaWiki\Preferences\SignatureValidatorFactory;
69use MediaWiki\Request\FauxRequest;
70use MediaWiki\Revision\RevisionAccessException;
71use MediaWiki\Revision\RevisionRecord;
72use MediaWiki\Revision\SlotRecord;
73use MediaWiki\SpecialPage\SpecialPage;
74use MediaWiki\SpecialPage\SpecialPageFactory;
75use MediaWiki\Tidy\TidyDriverBase;
76use MediaWiki\Title\MalformedTitleException;
77use MediaWiki\Title\MediaWikiTitleCodec;
78use MediaWiki\Title\NamespaceInfo;
79use MediaWiki\Title\Title;
80use MediaWiki\Title\TitleFormatter;
81use MediaWiki\User\Options\UserOptionsLookup;
82use MediaWiki\User\User;
83use MediaWiki\User\UserFactory;
84use MediaWiki\User\UserIdentity;
85use MediaWiki\User\UserNameUtils;
86use MediaWiki\Utils\MWTimestamp;
87use MediaWiki\Utils\UrlUtils;
88use MediaWiki\Xml\Xml;
89use ParserFactory;
90use ParserOptions;
91use PPFrame;
92use PPNode;
93use Preprocessor;
94use Preprocessor_Hash;
95use Psr\Log\LoggerInterface;
96use RuntimeException;
97use SectionProfiler;
98use StringUtils;
99use StripState;
100use UnexpectedValueException;
101use WANObjectCache;
102use Wikimedia\Bcp47Code\Bcp47CodeValue;
103use Wikimedia\IPUtils;
104use Wikimedia\Parsoid\Core\SectionMetadata;
105use Wikimedia\Parsoid\Core\TOCData;
106use Wikimedia\Parsoid\DOM\Comment;
107use Wikimedia\Parsoid\DOM\DocumentFragment;
108use Wikimedia\Parsoid\DOM\Element;
109use Wikimedia\Parsoid\DOM\Node;
110use Wikimedia\Parsoid\Utils\DOMCompat;
111use Wikimedia\Parsoid\Utils\DOMUtils;
112use Wikimedia\ScopedCallback;
113
114/**
115 * @defgroup Parser Parser
116 */
117
118/**
119 * PHP Parser - Processes wiki markup (which uses a more user-friendly
120 * syntax, such as "[[link]]" for making links), and provides a one-way
121 * transformation of that wiki markup it into (X)HTML output / markup
122 * (which in turn the browser understands, and can display).
123 *
124 * There are seven main entry points into the Parser class:
125 *
126 * - Parser::parse()
127 *     produces HTML output
128 * - Parser::preSaveTransform()
129 *     produces altered wiki markup
130 * - Parser::preprocess()
131 *     removes HTML comments and expands templates
132 * - Parser::cleanSig() and Parser::cleanSigInSig()
133 *     cleans a signature before saving it to preferences
134 * - Parser::getSection()
135 *     return the content of a section from an article for section editing
136 * - Parser::replaceSection()
137 *     replaces a section by number inside an article
138 * - Parser::getPreloadText()
139 *     removes <noinclude> sections and <includeonly> tags
140 *
141 * @warning $wgUser or $wgTitle or $wgRequest or $wgLang. Keep them away!
142 *
143 * @par Settings:
144 * $wgNamespacesWithSubpages
145 *
146 * @par Settings only within ParserOptions:
147 * $wgAllowExternalImages
148 * $wgAllowSpecialInclusion
149 * $wgInterwikiMagic
150 * $wgMaxArticleSize
151 *
152 * @ingroup Parser
153 */
154#[\AllowDynamicProperties]
155class Parser {
156    use DeprecationHelper;
157
158    # Flags for Parser::setFunctionHook
159    public const SFH_NO_HASH = 1;
160    public const SFH_OBJECT_ARGS = 2;
161
162    # Constants needed for external link processing
163    /**
164     * Everything except bracket, space, or control characters.
165     * \p{Zs} is unicode 'separator, space' category. It covers the space 0x20
166     * as well as U+3000 is IDEOGRAPHIC SPACE for T21052.
167     * \x{FFFD} is the Unicode replacement character, which the HTML5 spec
168     * uses to replace invalid HTML characters.
169     */
170    public const EXT_LINK_URL_CLASS = '[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}]';
171    /**
172     * Simplified expression to match an IPv4 or IPv6 address, or
173     * at least one character of a host name (embeds Parser::EXT_LINK_URL_CLASS)
174     */
175    // phpcs:ignore Generic.Files.LineLength
176    private const EXT_LINK_ADDR = '(?:[0-9.]+|\\[(?i:[0-9a-f:.]+)\\]|[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}])';
177    /** RegExp to make image URLs (embeds IPv6 part of Parser::EXT_LINK_ADDR) */
178    // phpcs:ignore Generic.Files.LineLength
179    private const EXT_IMAGE_REGEX = '/^(http:\/\/|https:\/\/)((?:\\[(?i:[0-9a-f:.]+)\\])?[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}]+)
180        \\/([A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]+)\\.((?i)avif|gif|jpg|jpeg|png|svg|webp)$/Sxu';
181
182    /** Regular expression for a non-newline space */
183    private const SPACE_NOT_NL = '(?:\t|&nbsp;|&\#0*160;|&\#[Xx]0*[Aa]0;|\p{Zs})';
184
185    /**
186     * @var int Preprocess wikitext in transclusion mode
187     * @deprecated Since 1.36
188     */
189    public const PTD_FOR_INCLUSION = Preprocessor::DOM_FOR_INCLUSION;
190
191    # Allowed values for $this->mOutputType
192    /** Output type: like Parser::parse() */
193    public const OT_HTML = 1;
194    /** Output type: like Parser::preSaveTransform() */
195    public const OT_WIKI = 2;
196    /** Output type: like Parser::preprocess() */
197    public const OT_PREPROCESS = 3;
198    /**
199     * Output type: like Parser::extractSections() - portions of the
200     * original are returned unchanged.
201     */
202    public const OT_PLAIN = 4;
203
204    /**
205     * @var string Prefix and suffix for temporary replacement strings
206     * for the multipass parser.
207     *
208     * \x7f should never appear in input as it's disallowed in XML.
209     * Using it at the front also gives us a little extra robustness
210     * since it shouldn't match when butted up against identifier-like
211     * string constructs.
212     *
213     * Must not consist of all title characters, or else it will change
214     * the behavior of <nowiki> in a link.
215     *
216     * Must have a character that needs escaping in attributes, otherwise
217     * someone could put a strip marker in an attribute, to get around
218     * escaping quote marks, and break out of the attribute. Thus we add
219     * `'".
220     */
221    public const MARKER_SUFFIX = "-QINU`\"'\x7f";
222    public const MARKER_PREFIX = "\x7f'\"`UNIQ-";
223
224    /**
225     * Internal marker used by parser to track where the table of
226     * contents should be. Various magic words can change the position
227     * during the parse.  The table of contents is generated during
228     * the parse, however skins have the final decision on whether the
229     * table of contents is injected.  This placeholder element
230     * identifies where in the page the table of contents should be
231     * injected, if at all.
232     * @var string
233     * @see Keep this in sync with BlockLevelPass::execute() and
234     *  RemexCompatMunger::isTableOfContentsMarker()
235     * @internal Skins should *not* directly reference TOC_PLACEHOLDER
236     * but instead use Parser::replaceTableOfContentsMarker().
237     */
238    public const TOC_PLACEHOLDER = '<meta property="mw:PageProp/toc" />';
239
240    /**
241     * Permissive regexp matching TOC_PLACEHOLDER.  This allows for some
242     * minor modifications to the placeholder to be made by extensions
243     * without breaking the TOC (T317857); note also that Parsoid's version
244     * of the placeholder might include additional attributes.
245     * @var string
246     */
247    private const TOC_PLACEHOLDER_REGEX = '/<meta\\b[^>]*\\bproperty\\s*=\\s*"mw:PageProp\\/toc"[^>]*>/';
248
249    # Persistent:
250    /** @var array<string,callable> */
251    private array $mTagHooks = [];
252    /** @var array<string,array{0:callable,1:int}> */
253    private array $mFunctionHooks = [];
254    /** @var array{0:array<string,string>,1:array<string,string>} */
255    private array $mFunctionSynonyms = [ 0 => [], 1 => [] ];
256    /** @var string[] */
257    private array $mStripList = [];
258    /** @var array<string,string> */
259    private array $mVarCache = [];
260    /** @var array<string,array<string,string[]>> */
261    private array $mImageParams = [];
262    /** @var array<string,MagicWordArray> */
263    private array $mImageParamsMagicArray = [];
264    /** @deprecated since 1.35 */
265    public $mMarkerIndex = 0;
266
267    // Initialised by initializeVariables()
268    /** @var MagicWordArray */
269    private MagicWordArray $mVariables;
270    private MagicWordArray $mSubstWords;
271
272    // Initialised in constructor
273    /** @var string */
274    private string $mExtLinkBracketedRegex;
275    private UrlUtils $urlUtils;
276    private Preprocessor $mPreprocessor;
277
278    // Cleared with clearState():
279    /** @var ParserOutput */
280    private ParserOutput $mOutput;
281    private int $mAutonumber = 0;
282    private StripState $mStripState;
283    private LinkHolderArray $mLinkHolders;
284    private int $mLinkID = 0;
285    private array $mIncludeSizes;
286    /** @internal */
287    public $mPPNodeCount;
288    /** @internal */
289    public $mHighestExpansionDepth;
290    private array $mTplRedirCache;
291    /** @internal */
292    public array $mHeadings;
293    /** @var array<string,false> */
294    private array $mDoubleUnderscores;
295    /**
296     * Number of expensive parser function calls
297     * @deprecated since 1.35
298     */
299    public $mExpensiveFunctionCount;
300    private bool $mShowToc;
301    private bool $mForceTocPosition;
302    private array $mTplDomCache;
303    private ?UserIdentity $mUser;
304
305    # Temporary
306    # These are variables reset at least once per parse regardless of $clearState
307
308    /**
309     * @var ParserOptions|null
310     * @deprecated since 1.35, use Parser::getOptions()
311     */
312    private $mOptions;
313
314    # Deprecated "dynamic" properties
315    # These used to be dynamic properties added to the parser, but these
316    # have been deprecated since 1.42.
317    /** @deprecated since 1.42: T343229 */
318    public $scribunto_engine;
319    /** @deprecated since 1.42: T343230 */
320    public $extCite;
321    /** @deprecated since 1.42: T343226 */
322    public $extTemplateStylesCache;
323    /** @deprecated since 1.42: T357838 */
324    public $static_tag_buf;
325    /** @deprecated since 1.42: T203531 */
326    public $mExtVariables;
327    /** @deprecated since 1.42: T203532 */
328    public $mExtArrays;
329    /** @deprecated since 1.42: T359887 */
330    public $mExtHashTables;
331    /** @deprecated since 1.42: T203563 */
332    public $mExtLoopsCounter;
333    /** @deprecated since 1.42: T362664 */
334    public $proofreadRenderingPages;
335    /** @deprecated since 1.42: T362693 */
336    public $mTemplatePath;
337
338    /**
339     * Title context, used for self-link rendering and similar things
340     *
341     * @deprecated since 1.35, use Parser::getPage()
342     */
343    private Title $mTitle;
344    /** Output type, one of the OT_xxx constants */
345    private int $mOutputType;
346    /**
347     * Shortcut alias, see Parser::setOutputType()
348     * @deprecated since 1.35
349     */
350    private array $ot;
351    /** ID to display in {{REVISIONID}} tags */
352    private ?int $mRevisionId = null;
353    /** The timestamp of the specified revision ID */
354    private ?string $mRevisionTimestamp = null;
355    /** User to display in {{REVISIONUSER}} tag */
356    private ?string $mRevisionUser = null;
357    /** Size to display in {{REVISIONSIZE}} variable */
358    private ?int $mRevisionSize = null;
359    /** @var int|false For {{PAGESIZE}} on current page */
360    private $mInputSize = false;
361
362    private ?RevisionRecord $mRevisionRecordObject = null;
363
364    /**
365     * Array with the language name of each language link (i.e. the
366     * interwiki prefix) in the key, value arbitrary. Used to avoid sending
367     * duplicate language links to the ParserOutput.
368     */
369    private array $mLangLinkLanguages;
370
371    /**
372     * A cache of the current revisions of titles. Keys are $title->getPrefixedDbKey()
373     *
374     * @since 1.24
375     */
376    private ?MapCacheLRU $currentRevisionCache = null;
377
378    /**
379     * @var bool|string Recursive call protection.
380     * @internal
381     */
382    private $mInParse = false;
383
384    private SectionProfiler $mProfiler;
385    private ?LinkRenderer $mLinkRenderer = null;
386
387    private MagicWordFactory $magicWordFactory;
388    private Language $contLang;
389    private LanguageConverterFactory $languageConverterFactory;
390    private LanguageNameUtils $languageNameUtils;
391    private ParserFactory $factory;
392    private SpecialPageFactory $specialPageFactory;
393    private TitleFormatter $titleFormatter;
394    /**
395     * This is called $svcOptions instead of $options like elsewhere to avoid confusion with
396     * $mOptions, which is public and widely used, and also with the local variable $options used
397     * for ParserOptions throughout this file.
398     */
399    private ServiceOptions $svcOptions;
400    private LinkRendererFactory $linkRendererFactory;
401    private NamespaceInfo $nsInfo;
402    private LoggerInterface $logger;
403    private BadFileLookup $badFileLookup;
404    private HookContainer $hookContainer;
405    private HookRunner $hookRunner;
406    private TidyDriverBase $tidy;
407    private WANObjectCache $wanCache;
408    private UserOptionsLookup $userOptionsLookup;
409    private UserFactory $userFactory;
410    private HttpRequestFactory $httpRequestFactory;
411    private TrackingCategories $trackingCategories;
412    private SignatureValidatorFactory $signatureValidatorFactory;
413    private UserNameUtils $userNameUtils;
414
415    /**
416     * @internal For use by ServiceWiring
417     */
418    public const CONSTRUCTOR_OPTIONS = [
419        // See documentation for the corresponding config options
420        // Many of these are only used in (eg) CoreMagicVariables
421        MainConfigNames::AllowDisplayTitle,
422        MainConfigNames::AllowSlowParserFunctions,
423        MainConfigNames::ArticlePath,
424        MainConfigNames::EnableScaryTranscluding,
425        MainConfigNames::ExtraInterlanguageLinkPrefixes,
426        MainConfigNames::FragmentMode,
427        MainConfigNames::Localtimezone,
428        MainConfigNames::MaxSigChars,
429        MainConfigNames::MaxTocLevel,
430        MainConfigNames::MiserMode,
431        MainConfigNames::RawHtml,
432        MainConfigNames::ScriptPath,
433        MainConfigNames::Server,
434        MainConfigNames::ServerName,
435        MainConfigNames::ShowHostnames,
436        MainConfigNames::SignatureValidation,
437        MainConfigNames::Sitename,
438        MainConfigNames::StylePath,
439        MainConfigNames::TranscludeCacheExpiry,
440        MainConfigNames::PreprocessorCacheThreshold,
441        MainConfigNames::ParserEnableLegacyMediaDOM,
442        MainConfigNames::EnableParserLimitReporting,
443    ];
444
445    /**
446     * Constructing parsers directly is not allowed! Use a ParserFactory.
447     * @internal
448     *
449     * @param ServiceOptions $svcOptions
450     * @param MagicWordFactory $magicWordFactory
451     * @param Language $contLang Content language
452     * @param ParserFactory $factory
453     * @param UrlUtils $urlUtils
454     * @param SpecialPageFactory $spFactory
455     * @param LinkRendererFactory $linkRendererFactory
456     * @param NamespaceInfo $nsInfo
457     * @param LoggerInterface $logger
458     * @param BadFileLookup $badFileLookup
459     * @param LanguageConverterFactory $languageConverterFactory
460     * @param LanguageNameUtils $languageNameUtils
461     * @param HookContainer $hookContainer
462     * @param TidyDriverBase $tidy
463     * @param WANObjectCache $wanCache
464     * @param UserOptionsLookup $userOptionsLookup
465     * @param UserFactory $userFactory
466     * @param TitleFormatter $titleFormatter
467     * @param HttpRequestFactory $httpRequestFactory
468     * @param TrackingCategories $trackingCategories
469     * @param SignatureValidatorFactory $signatureValidatorFactory
470     * @param UserNameUtils $userNameUtils
471     */
472    public function __construct(
473        ServiceOptions $svcOptions,
474        MagicWordFactory $magicWordFactory,
475        Language $contLang,
476        ParserFactory $factory,
477        UrlUtils $urlUtils,
478        SpecialPageFactory $spFactory,
479        LinkRendererFactory $linkRendererFactory,
480        NamespaceInfo $nsInfo,
481        LoggerInterface $logger,
482        BadFileLookup $badFileLookup,
483        LanguageConverterFactory $languageConverterFactory,
484        LanguageNameUtils $languageNameUtils,
485        HookContainer $hookContainer,
486        TidyDriverBase $tidy,
487        WANObjectCache $wanCache,
488        UserOptionsLookup $userOptionsLookup,
489        UserFactory $userFactory,
490        TitleFormatter $titleFormatter,
491        HttpRequestFactory $httpRequestFactory,
492        TrackingCategories $trackingCategories,
493        SignatureValidatorFactory $signatureValidatorFactory,
494        UserNameUtils $userNameUtils
495    ) {
496        $this->deprecateDynamicPropertiesAccess( '1.42', __CLASS__ );