Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.52% covered (warning)
86.52%
2182 / 2522
55.48% covered (warning)
55.48%
81 / 146
CRAP
0.00% covered (danger)
0.00%
0 / 1
Parser
86.55% covered (warning)
86.55%
2182 / 2521
55.48% covered (warning)
55.48%
81 / 146
2440.02
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 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 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%
32 / 32
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.73% covered (success)
96.73%
148 / 153
0.00% covered (danger)
0.00%
0 / 1
48
 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
62.50% covered (warning)
62.50%
15 / 24
0.00% covered (danger)
0.00%
0 / 1
11.38
 limitationWarn
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 braceSubstitution
85.78% covered (warning)
85.78%
187 / 218
0.00% covered (danger)
0.00%
0 / 1
107.27
 callParserFunction
95.56% covered (success)
95.56%
43 / 45
0.00% covered (danger)
0.00%
0 / 1
18
 getTemplateDom
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
7
 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
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
3.14
 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
69.81% covered (warning)
69.81%
37 / 53
0.00% covered (danger)
0.00%
0 / 1
42.20
 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
84.00% covered (warning)
84.00%
21 / 25
0.00% covered (danger)
0.00%
0 / 1
12.59
 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
99.32% covered (success)
99.32%
145 / 146
0.00% covered (danger)
0.00%
0 / 1
43
 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
41.18% covered (danger)
41.18%
14 / 34
0.00% covered (danger)
0.00%
0 / 1
35.63
 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
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
3.00
 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
95.24% covered (success)
95.24%
20 / 21
0.00% covered (danger)
0.00%
0 / 1
9
 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 Exception;
28use File;
29use HtmlArmor;
30use ImageGalleryBase;
31use ImageGalleryClassNotFoundException;
32use InvalidArgumentException;
33use LogicException;
34use MapCacheLRU;
35use MediaHandler;
36use MediaWiki\Cache\CacheKeyHelper;
37use MediaWiki\Category\TrackingCategories;
38use MediaWiki\Config\ServiceOptions;
39use MediaWiki\Content\TextContent;
40use MediaWiki\Context\RequestContext;
41use MediaWiki\Debug\DeprecationHelper;
42use MediaWiki\HookContainer\HookContainer;
43use MediaWiki\HookContainer\HookRunner;
44use MediaWiki\Html\Html;
45use MediaWiki\Html\HtmlHelper;
46use MediaWiki\Http\HttpRequestFactory;
47use MediaWiki\Language\ILanguageConverter;
48use MediaWiki\Language\Language;
49use MediaWiki\Language\LanguageCode;
50use MediaWiki\Language\RawMessage;
51use MediaWiki\Languages\LanguageConverterFactory;
52use MediaWiki\Languages\LanguageNameUtils;
53use MediaWiki\Linker\Linker;
54use MediaWiki\Linker\LinkRenderer;
55use MediaWiki\Linker\LinkRendererFactory;
56use MediaWiki\MainConfigNames;
57use MediaWiki\MediaWikiServices;
58use MediaWiki\Message\Message;
59use MediaWiki\Output\OutputPage;
60use MediaWiki\Page\File\BadFileLookup;
61use MediaWiki\Page\PageIdentity;
62use MediaWiki\Page\PageReference;
63use MediaWiki\Preferences\SignatureValidatorFactory;
64use MediaWiki\Request\FauxRequest;
65use MediaWiki\Revision\RevisionAccessException;
66use MediaWiki\Revision\RevisionRecord;
67use MediaWiki\Revision\SlotRecord;
68use MediaWiki\SpecialPage\SpecialPage;
69use MediaWiki\SpecialPage\SpecialPageFactory;
70use MediaWiki\Tidy\TidyDriverBase;
71use MediaWiki\Title\MalformedTitleException;
72use MediaWiki\Title\MediaWikiTitleCodec;
73use MediaWiki\Title\NamespaceInfo;
74use MediaWiki\Title\Title;
75use MediaWiki\Title\TitleFormatter;
76use MediaWiki\Title\TitleValue;
77use MediaWiki\User\Options\UserOptionsLookup;
78use MediaWiki\User\User;
79use MediaWiki\User\UserFactory;
80use MediaWiki\User\UserIdentity;
81use MediaWiki\User\UserNameUtils;
82use MediaWiki\Utils\MWTimestamp;
83use MediaWiki\Utils\UrlUtils;
84use MediaWiki\Xml\Xml;
85use Psr\Log\LoggerInterface;
86use RuntimeException;
87use SectionProfiler;
88use StringUtils;
89use UnexpectedValueException;
90use Wikimedia\Bcp47Code\Bcp47CodeValue;
91use Wikimedia\IPUtils;
92use Wikimedia\Message\MessageParam;
93use Wikimedia\Message\MessageSpecifier;
94use Wikimedia\ObjectCache\WANObjectCache;
95use Wikimedia\Parsoid\Core\LinkTarget;
96use Wikimedia\Parsoid\Core\SectionMetadata;
97use Wikimedia\Parsoid\Core\TOCData;
98use Wikimedia\Parsoid\DOM\Comment;
99use Wikimedia\Parsoid\DOM\DocumentFragment;
100use Wikimedia\Parsoid\DOM\Element;
101use Wikimedia\Parsoid\DOM\Node;
102use Wikimedia\Parsoid\Utils\DOMCompat;
103use Wikimedia\Parsoid\Utils\DOMUtils;
104use Wikimedia\RemexHtml\Serializer\SerializerNode;
105use Wikimedia\ScopedCallback;
106
107/**
108 * @defgroup Parser Parser
109 */
110
111/**
112 * PHP Parser - Processes wiki markup (which uses a more user-friendly
113 * syntax, such as "[[link]]" for making links), and provides a one-way
114 * transformation of that wiki markup it into (X)HTML output / markup
115 * (which in turn the browser understands, and can display).
116 *
117 * There are seven main entry points into the Parser class:
118 *
119 * - Parser::parse()
120 *     produces HTML output
121 * - Parser::preSaveTransform()
122 *     produces altered wiki markup
123 * - Parser::preprocess()
124 *     removes HTML comments and expands templates
125 * - Parser::cleanSig() and Parser::cleanSigInSig()
126 *     cleans a signature before saving it to preferences
127 * - Parser::getSection()
128 *     return the content of a section from an article for section editing
129 * - Parser::replaceSection()
130 *     replaces a section by number inside an article
131 * - Parser::getPreloadText()
132 *     removes <noinclude> sections and <includeonly> tags
133 *
134 * @warning $wgUser or $wgTitle or $wgRequest or $wgLang. Keep them away!
135 *
136 * @par Settings:
137 * $wgNamespacesWithSubpages
138 *
139 * @par Settings only within ParserOptions:
140 * $wgAllowExternalImages
141 * $wgAllowSpecialInclusion
142 * $wgInterwikiMagic
143 * $wgMaxArticleSize
144 *
145 * @ingroup Parser
146 */
147#[\AllowDynamicProperties]
148class Parser {
149    use DeprecationHelper;
150
151    # Flags for Parser::setFunctionHook
152    public const SFH_NO_HASH = 1;
153    public const SFH_OBJECT_ARGS = 2;
154
155    # Constants needed for external link processing
156    /**
157     * Everything except bracket, space, or control characters.
158     * \p{Zs} is unicode 'separator, space' category. It covers the space 0x20
159     * as well as U+3000 is IDEOGRAPHIC SPACE for T21052.
160     * \x{FFFD} is the Unicode replacement character, which the HTML5 spec
161     * uses to replace invalid HTML characters.
162     */
163    public const EXT_LINK_URL_CLASS = '[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}]';
164    /**
165     * Simplified expression to match an IPv4 or IPv6 address, or
166     * at least one character of a host name (embeds Parser::EXT_LINK_URL_CLASS)
167     */
168    // phpcs:ignore Generic.Files.LineLength
169    private const EXT_LINK_ADDR = '(?:[0-9.]+|\\[(?i:[0-9a-f:.]+)\\]|[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}])';
170    /** RegExp to make image URLs (embeds IPv6 part of Parser::EXT_LINK_ADDR) */
171    // phpcs:ignore Generic.Files.LineLength
172    private const EXT_IMAGE_REGEX = '/^(http:\/\/|https:\/\/)((?:\\[(?i:[0-9a-f:.]+)\\])?[^][<>"\\x00-\\x20\\x7F\p{Zs}\x{FFFD}]+)
173        \\/([A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]+)\\.((?i)avif|gif|jpg|jpeg|png|svg|webp)$/Sxu';
174
175    /** Regular expression for a non-newline space */
176    private const SPACE_NOT_NL = '(?:\t|&nbsp;|&\#0*160;|&\#[Xx]0*[Aa]0;|\p{Zs})';
177
178    /**
179     * @var int Preprocess wikitext in transclusion mode
180     * @deprecated Since 1.36
181     */
182    public const PTD_FOR_INCLUSION = Preprocessor::DOM_FOR_INCLUSION;
183
184    # Allowed values for $this->mOutputType
185    /** Output type: like Parser::parse() */
186    public const OT_HTML = 1;
187    /** Output type: like Parser::preSaveTransform() */
188    public const OT_WIKI = 2;
189    /** Output type: like Parser::preprocess() */
190    public const OT_PREPROCESS = 3;
191    /**
192     * Output type: like Parser::extractSections() - portions of the
193     * original are returned unchanged.
194     */
195    public const OT_PLAIN = 4;
196
197    /**
198     * @var string Prefix and suffix for temporary replacement strings
199     * for the multipass parser.
200     *
201     * \x7f should never appear in input as it's disallowed in XML.
202     * Using it at the front also gives us a little extra robustness
203     * since it shouldn't match when butted up against identifier-like
204     * string constructs.
205     *
206     * Must not consist of all title characters, or else it will change
207     * the behavior of <nowiki> in a link.
208     *
209     * Must have a character that needs escaping in attributes, otherwise
210     * someone could put a strip marker in an attribute, to get around
211     * escaping quote marks, and break out of the attribute. Thus we add
212     * `'".
213     */
214    public const MARKER_SUFFIX = "-QINU`\"'\x7f";
215    public const MARKER_PREFIX = "\x7f'\"`UNIQ-";
216
217    /**
218     * Internal marker used by parser to track where the table of
219     * contents should be. Various magic words can change the position
220     * during the parse.  The table of contents is generated during
221     * the parse, however skins have the final decision on whether the
222     * table of contents is injected.  This placeholder element
223     * identifies where in the page the table of contents should be
224     * injected, if at all.
225     * @var string
226     * @see Keep this in sync with BlockLevelPass::execute() and
227     *  RemexCompatMunger::isTableOfContentsMarker()
228     * @internal Skins should *not* directly reference TOC_PLACEHOLDER
229     * but instead use Parser::replaceTableOfContentsMarker().
230     */
231    public const TOC_PLACEHOLDER = '<meta property="mw:PageProp/toc" />';
232
233    # Persistent:
234    /** @var array<string,callable> */
235    private array $mTagHooks = [];
236    /** @var array<string,array{0:callable,1:int}> */
237    private array $mFunctionHooks = [];
238    /** @var array{0:array<string,string>,1:array<string,string>} */
239    private array $mFunctionSynonyms = [ 0 => [], 1 => [] ];
240    /** @var string[] */
241    private array $mStripList = [];
242    /** @var array<string,string> */
243    private array $mVarCache = [];
244    /** @var array<string,array<string,string[]>> */
245    private array $mImageParams = [];
246    /** @var array<string,MagicWordArray> */
247    private array $mImageParamsMagicArray = [];
248    /** @deprecated since 1.35 */
249    public $mMarkerIndex = 0;
250
251    // Initialised by initializeVariables()
252    /** @var MagicWordArray */
253    private MagicWordArray $mVariables;
254    private MagicWordArray $mSubstWords;
255
256    // Initialised in constructor
257    /** @var string */
258    private string $mExtLinkBracketedRegex;
259    private UrlUtils $urlUtils;
260    private Preprocessor $mPreprocessor;
261
262    // Cleared with clearState():
263    /** @var ParserOutput */
264    private ParserOutput $mOutput;
265    private int $mAutonumber = 0;
266    private StripState $mStripState;
267    private LinkHolderArray $mLinkHolders;
268    private int $mLinkID = 0;
269    private array $mIncludeSizes;
270    /**
271     * @internal
272     * @var int
273     */
274    public $mPPNodeCount;
275    /**
276     * @internal
277     * @var int
278     */
279    public $mHighestExpansionDepth;
280    private array $mTplRedirCache;
281    /** @internal */
282    public array $mHeadings;
283    /** @var array<string,false> */
284    private array $mDoubleUnderscores;
285    /**
286     * Number of expensive parser function calls
287     * @deprecated since 1.35
288     */
289    public $mExpensiveFunctionCount;
290    private bool $mShowToc;
291    private bool $mForceTocPosition;
292    private array $mTplDomCache;
293    private ?UserIdentity $mUser;
294
295    # Temporary
296    # These are variables reset at least once per parse regardless of $clearState
297
298    /**
299     * @var ParserOptions|null
300     * @deprecated since 1.35, use Parser::getOptions()
301     */
302    private $mOptions;
303
304    # Deprecated "dynamic" properties
305    # These used to be dynamic properties added to the parser, but these
306    # have been deprecated since 1.42.
307    /** @deprecated since 1.42: T343229 */
308    public $scribunto_engine;
309    /** @deprecated since 1.42: T343230 */
310    public $extCite;
311    /** @deprecated since 1.42: T343226 */
312    public $extTemplateStylesCache;
313    /** @deprecated since 1.42: T357838 */
314    public $static_tag_buf;
315    /** @deprecated since 1.42: T203531 */
316    public $mExtVariables;
317    /** @deprecated since 1.42: T203532 */
318    public $mExtArrays;
319    /** @deprecated since 1.42: T359887 */
320    public $mExtHashTables;
321    /** @deprecated since 1.42: T203563 */
322    public $mExtLoopsCounter;
323    /** @deprecated since 1.42: T362664 */
324    public $proofreadRenderingPages;
325    /** @deprecated since 1.42: T362693 */
326    public $mTemplatePath;
327
328    /**
329     * Title context, used for self-link rendering and similar things
330     *
331     * @deprecated since 1.35, use Parser::getPage()
332     */
333    private Title $mTitle;
334    /** Output type, one of the OT_xxx constants */
335    private int $mOutputType;
336    /** When false, suppress extension tag processing for OT_PREPROCESS */
337    private bool $mStripExtTags = true;
338    /**
339     * Shortcut alias, see Parser::setOutputType()
340     * @deprecated since 1.35
341     */
342    private array $ot;
343    /** ID to display in {{REVISIONID}} tags */
344    private ?int $mRevisionId = null;
345    /** The timestamp of the specified revision ID */
346    private ?string $mRevisionTimestamp = null;
347    /** User to display in {{REVISIONUSER}} tag */
348    private ?string $mRevisionUser = null;
349    /** Size to display in {{REVISIONSIZE}} variable */
350    private ?int $mRevisionSize = null;
351    /** @var int|false For {{PAGESIZE}} on current page */
352    private $mInputSize = false;
353
354    private ?RevisionRecord $mRevisionRecordObject = null;
355
356    /**
357     * A cache of the current revisions of titles. Keys are $title->getPrefixedDbKey()
358     *
359     * @since 1.24
360     */
361    private ?MapCacheLRU $currentRevisionCache = null;
362
363    /**
364     * @var bool|string Recursive call protection.
365     * @internal
366     */
367    private $mInParse = false;
368
369    private SectionProfiler $mProfiler;
370    private ?LinkRenderer $mLinkRenderer = null;
371
372    private MagicWordFactory $magicWordFactory;
373    private Language $contLang;
374    private LanguageConverterFactory $languageConverterFactory;
375    private LanguageNameUtils $languageNameUtils;
376    private ParserFactory $factory;
377    private SpecialPageFactory $specialPageFactory;
378    private TitleFormatter $titleFormatter;
379    /**
380     * This is called $svcOptions instead of $options like elsewhere to avoid confusion with
381     * $mOptions, which is public and widely used, and also with the local variable $options used
382     * for ParserOptions throughout this file.
383     */
384    private ServiceOptions $svcOptions;
385    private LinkRendererFactory $linkRendererFactory;
386    private NamespaceInfo $nsInfo;
387    private LoggerInterface $logger;
388    private BadFileLookup $badFileLookup;
389    private HookContainer $hookContainer;
390    private HookRunner $hookRunner;
391    private TidyDriverBase $tidy;
392    private WANObjectCache $wanCache;
393    private UserOptionsLookup $userOptionsLookup;
394    private UserFactory $userFactory;
395    private HttpRequestFactory $httpRequestFactory;
396    private TrackingCategories $trackingCategories;
397    private SignatureValidatorFactory $signatureValidatorFactory;
398    private UserNameUtils $userNameUtils;
399
400    /**
401     * @internal For use by ServiceWiring
402     */
403    public const CONSTRUCTOR_OPTIONS = [
404        // See documentation for the corresponding config options
405        // Many of these are only used in (eg) CoreMagicVariables
406        MainConfigNames::AllowDisplayTitle,
407        MainConfigNames::AllowSlowParserFunctions,
408        MainConfigNames::ArticlePath,
409        MainConfigNames::EnableScaryTranscluding,
410        MainConfigNames::ExtraInterlanguageLinkPrefixes,
411        MainConfigNames::FragmentMode,
412        MainConfigNames::Localtimezone,
413        MainConfigNames::MaxSigChars,
414        MainConfigNames::MaxTocLevel,
415        MainConfigNames::MiserMode,
416        MainConfigNames::RawHtml,
417        MainConfigNames::ScriptPath,
418        MainConfigNames::Server,
419        MainConfigNames::ServerName,
420        MainConfigNames::ShowHostnames,
421        MainConfigNames::SignatureValidation,
422        MainConfigNames::Sitename,
423        MainConfigNames::StylePath,
424        MainConfigNames::TranscludeCacheExpiry,
425        MainConfigNames::PreprocessorCacheThreshold,
426        MainConfigNames::ParserEnableLegacyMediaDOM,
427        MainConfigNames::EnableParserLimitReporting,
428        MainConfigNames::ParserEnableUserLanguage,
429        MainConfigNames::ParsoidFragmentSupport,
430    ];
431
432    /**
433     * Constructing parsers directly is not allowed! Use a ParserFactory.
434     * @internal
435     *
436     * @param ServiceOptions $svcOptions
437     * @param MagicWordFactory $magicWordFactory
438     * @param Language $contLang Content language
439     * @param ParserFactory $factory
440     * @param UrlUtils $urlUtils
441     * @param SpecialPageFactory $spFactory
442     * @param LinkRendererFactory $linkRendererFactory
443     * @param NamespaceInfo $nsInfo
444     * @param LoggerInterface $logger
445     * @param BadFileLookup $badFileLookup
446     * @param LanguageConverterFactory $languageConverterFactory
447     * @param LanguageNameUtils $languageNameUtils
448     * @param HookContainer $hookContainer
449     * @param TidyDriverBase $tidy
450     * @param WANObjectCache $wanCache
451     * @param UserOptionsLookup $userOptionsLookup
452     * @param UserFactory $userFactory
453     * @param TitleFormatter $titleFormatter
454     * @param HttpRequestFactory $httpRequestFactory
455     * @param TrackingCategories $trackingCategories
456     * @param SignatureValidatorFactory $signatureValidatorFactory
457     * @param UserNameUtils $userNameUtils
458     */
459    public function __construct(
460        ServiceOptions $svcOptions,
461        MagicWordFactory $magicWordFactory,
462        Language $contLang,
463        ParserFactory $factory,
464        UrlUtils $urlUtils,
465        SpecialPageFactory $spFactory,
466        LinkRendererFactory $linkRendererFactory,
467        NamespaceInfo $nsInfo,
468        LoggerInterface $logger,
469        BadFileLookup $badFileLookup,
470        LanguageConverterFactory $languageConverterFactory,
471        LanguageNameUtils $languageNameUtils,
472        HookContainer $hookContainer,
473        TidyDriverBase $tidy,
474        WANObjectCache $wanCache,
475        UserOptionsLookup $userOptionsLookup,
476        UserFactory $userFactory,
477        TitleFormatter $titleFormatter,
478        HttpRequestFactory $httpRequestFactory,
479        TrackingCategories $trackingCategories,
480        SignatureValidatorFactory $signatureValidatorFactory,
481        UserNameUtils $userNameUtils
482    ) {
483        $this->deprecateDynamicPropertiesAccess( '1.42', __CLASS__ );