Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4153565
MockSiteConfig.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
MockSiteConfig.php
View Options
<?php
declare
(
strict_types
=
1
);
namespace
Wikimedia\Parsoid\Mocks
;
use
Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface
;
use
Monolog\Formatter\LineFormatter
;
use
Monolog\Handler\ErrorLogHandler
;
use
Monolog\Logger
;
use
Wikimedia\Bcp47Code\Bcp47Code
;
use
Wikimedia\Bcp47Code\Bcp47CodeValue
;
use
Wikimedia\Parsoid\Config\SiteConfig
;
use
Wikimedia\Parsoid\Config\StubMetadataCollector
;
use
Wikimedia\Parsoid\Core\ContentMetadataCollector
;
use
Wikimedia\Parsoid\Core\LinkTarget
;
use
Wikimedia\Parsoid\DOM\Document
;
use
Wikimedia\Parsoid\Utils\Title
;
use
Wikimedia\Parsoid\Utils\Utils
;
class
MockSiteConfig
extends
SiteConfig
{
/** @var ?int Unix timestamp */
private
$fakeTimestamp
=
946782245
;
// 2000-01-02T03:04:05Z
/** @var int */
private
$timezoneOffset
=
0
;
// UTC
/** @var bool */
private
$interwikiMagic
=
true
;
/** @var array */
private
$linterOverrides
=
[];
private
const
NAMESPACE_MAP
=
[
'media'
=>
-
2
,
'special'
=>
-
1
,
''
=>
0
,
'talk'
=>
1
,
'user'
=>
2
,
'user_talk'
=>
3
,
// Last one will be used by namespaceName
'project'
=>
4
,
'wp'
=>
4
,
'wikipedia'
=>
4
,
'project_talk'
=>
5
,
'wt'
=>
5
,
'wikipedia_talk'
=>
5
,
'file'
=>
6
,
'file_talk'
=>
7
,
'template'
=>
10
,
'template_talk'
=>
11
,
'help'
=>
12
,
'category'
=>
14
,
'category_talk'
=>
15
,
];
/** @var array<int,bool> */
protected
$namespacesWithSubpages
=
[];
/** @var array */
protected
$interwikiMap
=
[];
/** @var int */
private
$maxDepth
=
40
;
/** @var string|null */
private
$linkPrefixRegex
=
null
;
/** @var string|bool */
private
$externalLinkTarget
;
public
function
__construct
(
array
$opts
)
{
parent
::
__construct
();
if
(
isset
(
$opts
[
'linting'
]
)
)
{
$this
->
linterEnabled
=
$opts
[
'linting'
];
}
if
(
isset
(
$opts
[
'maxDepth'
]
)
)
{
$this
->
maxDepth
=
$opts
[
'maxDepth'
];
}
if
(
isset
(
$opts
[
'linterOverrides'
]
)
)
{
$this
->
linterOverrides
=
$opts
[
'linterOverrides'
];
}
$this
->
linkPrefixRegex
=
$opts
[
'linkPrefixRegex'
]
??
null
;
$this
->
linkTrailRegex
=
$opts
[
'linkTrailRegex'
]
??
'/^([a-z]+)/sD'
;
// enwiki default
$this
->
externalLinkTarget
=
$opts
[
'externallinktarget'
]
??
false
;
// Use Monolog's PHP console handler
$logger
=
new
Logger
(
"Parsoid CLI"
);
$handler
=
new
ErrorLogHandler
();
$handler
->
setFormatter
(
new
LineFormatter
(
'%message%'
)
);
$logger
->
pushHandler
(
$handler
);
$this
->
setLogger
(
$logger
);
}
public
function
getLinterSiteConfig
():
array
{
return
$this
->
linterOverrides
+
parent
::
getLinterSiteConfig
();
}
public
function
allowedExternalImagePrefixes
():
array
{
return
[];
}
public
function
baseURI
():
string
{
return
'//my.wiki.example/wikix/'
;
}
/**
* @inheritDoc
*/
public
function
exportMetadataToHeadBcp47
(
Document
$document
,
ContentMetadataCollector
$metadata
,
string
$defaultTitle
,
Bcp47Code
$lang
):
void
{
'@phan-var StubMetadataCollector $metadata'
;
// @var StubMetadataCollector $metadata
$moduleLoadURI
=
$this
->
server
()
.
$this
->
scriptpath
()
.
'/load.php'
;
// Look for a displaytitle.
$displayTitle
=
$metadata
->
getPageProperty
(
'displaytitle'
)
??
// Use the default title, properly escaped
Utils
::
escapeHtml
(
$defaultTitle
);
$this
->
exportMetadataHelper
(
$document
,
$moduleLoadURI
,
$metadata
->
getModules
(),
$metadata
->
getModuleStyles
(),
$metadata
->
getJsConfigVars
(),
$displayTitle
,
$lang
);
}
public
function
redirectRegexp
():
string
{
return
'/(?i:#REDIRECT)/'
;
}
public
function
categoryRegexp
():
string
{
return
'/Category/'
;
}
public
function
bswRegexp
():
string
{
return
'/'
.
'NOGLOBAL|DISAMBIG|NOCOLLABORATIONHUBTOC|nocollaborationhubtoc|NOTOC|notoc|'
.
'NOGALLERY|nogallery|FORCETOC|forcetoc|TOC|toc|NOEDITSECTION|noeditsection|'
.
'NOTITLECONVERT|notitleconvert|NOTC|notc|NOCONTENTCONVERT|nocontentconvert|'
.
'NOCC|nocc|NEWSECTIONLINK|NONEWSECTIONLINK|HIDDENCAT|INDEX|NOINDEX|STATICREDIRECT'
.
'/'
;
}
/** @inheritDoc */
public
function
canonicalNamespaceId
(
string
$name
):
?
int
{
return
self
::
NAMESPACE_MAP
[
$name
]
??
null
;
}
/** @inheritDoc */
public
function
namespaceId
(
string
$name
):
?
int
{
$name
=
Utils
::
normalizeNamespaceName
(
$name
);
return
self
::
NAMESPACE_MAP
[
$name
]
??
null
;
}
/** @inheritDoc */
public
function
namespaceName
(
int
$ns
):
?
string
{
static
$map
=
null
;
if
(
$map
===
null
)
{
$map
=
array_flip
(
self
::
NAMESPACE_MAP
);
}
if
(
!
isset
(
$map
[
$ns
]
)
)
{
return
null
;
}
return
ucwords
(
strtr
(
$map
[
$ns
],
'_'
,
' '
)
);
}
/** @inheritDoc */
public
function
namespaceHasSubpages
(
int
$ns
):
bool
{
return
!
empty
(
$this
->
namespacesWithSubpages
[
$ns
]
);
}
/** @inheritDoc */
public
function
namespaceCase
(
int
$ns
):
string
{
return
'first-letter'
;
}
/** @inheritDoc */
public
function
specialPageLocalName
(
string
$alias
):
?
string
{
return
null
;
}
public
function
setInterwikiMagic
(
bool
$val
):
void
{
$this
->
interwikiMagic
=
$val
;
}
public
function
interwikiMagic
():
bool
{
return
$this
->
interwikiMagic
;
}
public
function
interwikiMap
():
array
{
return
$this
->
interwikiMap
;
}
public
function
iwp
():
string
{
return
'mywiki'
;
}
public
function
legalTitleChars
():
string
{
return
' %!"$&
\'
()*,
\-
.
\/
0-9:;=?@A-Z
\\\\
^_`a-z~
\x
80-
\x
FF+'
;
}
public
function
linkPrefixRegex
():
?
string
{
return
$this
->
linkPrefixRegex
;
}
protected
function
linkTrail
():
string
{
// @phan-suppress-previous-line PhanPluginNeverReturnMethod
throw
new
\BadMethodCallException
(
'Should not be used. linkTrailRegex() is overridden here.'
);
}
public
function
linkTrailRegex
():
?
string
{
return
$this
->
linkTrailRegex
;
}
public
function
langBcp47
():
Bcp47Code
{
return
new
Bcp47CodeValue
(
'en'
);
}
public
function
mainPageLinkTarget
():
LinkTarget
{
return
Title
::
newFromText
(
'Main Page'
,
$this
);
}
/** @inheritDoc */
public
function
getMWConfigValue
(
string
$key
)
{
switch
(
$key
)
{
case
'CiteResponsiveReferences'
:
return
true
;
case
'CiteResponsiveReferencesThreshold'
:
return
10
;
default
:
return
null
;
}
}
public
function
rtl
():
bool
{
return
false
;
}
/** @inheritDoc */
public
function
langConverterEnabledBcp47
(
Bcp47Code
$lang
):
bool
{
return
$lang
->
toBcp47Code
()
===
'sr'
;
}
public
function
script
():
string
{
return
'/wx/index.php'
;
}
public
function
scriptpath
():
string
{
return
'/wx'
;
}
public
function
server
():
string
{
return
'//my.wiki.example'
;
}
public
function
timezoneOffset
():
int
{
return
$this
->
timezoneOffset
;
}
/** @inheritDoc */
public
function
variantsFor
(
Bcp47Code
$lang
):
?
array
{
switch
(
$lang
->
toBcp47Code
()
)
{
case
'sr'
:
return
[
'base'
=>
new
Bcp47CodeValue
(
'sr'
),
'fallbacks'
=>
[
new
Bcp47CodeValue
(
'sr-Cyrl'
)
]
];
case
'sr-Cyrl'
:
return
[
'base'
=>
new
Bcp47CodeValue
(
'sr'
),
'fallbacks'
=>
[
new
Bcp47CodeValue
(
'sr'
)
]
];
case
'sr-Latn'
:
return
[
'base'
=>
new
Bcp47CodeValue
(
'sr'
),
'fallbacks'
=>
[
new
Bcp47CodeValue
(
'sr'
)
]
];
default
:
return
null
;
}
}
public
function
widthOption
():
int
{
return
220
;
}
/** @inheritDoc */
protected
function
getVariableIDs
():
array
{
return
[];
// None for now
}
/** @inheritDoc */
protected
function
haveComputedFunctionSynonyms
():
bool
{
return
false
;
}
/** @inheritDoc */
protected
function
updateFunctionSynonym
(
string
$func
,
string
$magicword
,
bool
$caseSensitive
):
void
{
/* Nothing for now. Look at src/Config/Api/SiteConfig when mocking is needed. */
}
/** @inheritDoc */
protected
function
getMagicWords
():
array
{
return
[
'toc'
=>
[
0
,
'__TOC__'
],
'img_thumbnail'
=>
[
1
,
'thumb'
],
'img_framed'
=>
[
1
,
'frame'
,
'framed'
],
'img_frameless'
=>
[
1
,
'frameless'
],
'img_manualthumb'
=>
[
1
,
'thumbnail=$1'
,
'thumb=$1'
],
'img_none'
=>
[
1
,
'none'
],
'img_left'
=>
[
1
,
'left'
],
'img_right'
=>
[
1
,
'right'
],
// T345026: 'sub' should follow 'img_sub' to match dewikivoyage
'img_sub'
=>
[
1
,
'sub'
],
'sub'
=>
[
0
,
'sub'
],
'notoc'
=>
[
0
,
'__NOTOC__'
],
'timedmedia_loop'
=>
[
0
,
'loop'
],
'timedmedia_muted'
=>
[
0
,
'muted'
],
];
}
/** @inheritDoc */
public
function
getMagicWordMatcher
(
string
$id
):
string
{
if
(
$id
===
'toc'
)
{
return
'/^TOC$/'
;
}
else
{
return
'/(?!)/'
;
}
}
/** @inheritDoc */
public
function
getParameterizedAliasMatcher
(
array
$words
):
callable
{
$paramMWs
=
[
'img_lossy'
=>
"/^(?:(?i:lossy
\=
(.*?)))$/uS"
,
'timedmedia_thumbtime'
=>
"/^(?:(?i:thumbtime
\=
(.*?)))$/uS"
,
'timedmedia_starttime'
=>
"/^(?:(?i:start
\=
(.*?)))$/uS"
,
'timedmedia_endtime'
=>
"/^(?:(?i:end
\=
(.*?)))$/uS"
,
'timedmedia_disablecontrols'
=>
"/^(?:(?i:disablecontrols
\=
(.*?)))$/uS"
,
'img_manualthumb'
=>
"/^(?:(?:thumbnail
\=
(.*?)|thumb
\=
(.*?)))$/uS"
,
'img_width'
=>
"/^(?:(?:(.*?)px))$/uS"
,
'img_lang'
=>
"/^(?:(?:lang
\=
(.*?)))$/uS"
,
'img_page'
=>
"/^(?:(?:page
\=
(.*?)|page (.*?)))$/uS"
,
'img_upright'
=>
"/^(?:(?:upright
\=
(.*?)|upright (.*?)))$/uS"
,
'img_link'
=>
"/^(?:(?:link
\=
(.*?)))$/uS"
,
'img_alt'
=>
"/^(?:(?:alt
\=
(.*?)))$/uS"
,
'img_class'
=>
"/^(?:(?:class
\=
(.*?)))$/uS"
];
$regexes
=
array_intersect_key
(
$paramMWs
,
array_flip
(
$words
)
);
return
static
function
(
$text
)
use
(
$regexes
)
{
/**
* $name is the canonical magic word name
* $re has patterns for matching aliases
*/
foreach
(
$regexes
as
$name
=>
$re
)
{
if
(
preg_match
(
$re
,
$text
,
$m
)
)
{
unset
(
$m
[
0
]
);
// Ex. regexp here is, /^(?:(?:|vinculo\=(.*?)|enlace\=(.*?)|link\=(.*?)))$/uS
// Check all the capture groups for a value, if not, it's safe to return an
// empty string since we did get a match.
foreach
(
$m
as
$v
)
{
if
(
$v
!==
''
)
{
return
[
'k'
=>
$name
,
'v'
=>
$v
];
}
}
return
[
'k'
=>
$name
,
'v'
=>
''
];
}
}
return
null
;
};
}
/** @inheritDoc */
protected
function
getNonNativeExtensionTags
():
array
{
return
[
'indicator'
=>
true
,
'timeline'
=>
true
,
'hiero'
=>
true
,
'charinsert'
=>
true
,
'inputbox'
=>
true
,
'source'
=>
true
,
'syntaxhighlight'
=>
true
,
'section'
=>
true
,
'score'
=>
true
,
'templatedata'
=>
true
,
'math'
=>
true
,
'ce'
=>
true
,
'chem'
=>
true
,
'graph'
=>
true
,
'maplink'
=>
true
,
'categorytree'
=>
true
,
'templatestyles'
=>
true
];
}
/** @inheritDoc */
public
function
getMaxTemplateDepth
():
int
{
return
$this
->
maxDepth
;
}
/** @inheritDoc */
protected
function
getSpecialPageAliases
(
string
$specialPage
):
array
{
if
(
$specialPage
===
'Booksources'
)
{
return
[
'Booksources'
,
'BookSources'
];
// Mock value
}
else
{
throw
new
\BadMethodCallException
(
'Not implemented'
);
}
}
/** @inheritDoc */
protected
function
getSpecialNSAliases
():
array
{
return
[
"Special"
,
"special"
];
// Mock value
}
/** @inheritDoc */
protected
function
getProtocols
():
array
{
return
[
"http:"
,
"https:"
,
"irc:"
,
"ircs:"
,
"news:"
,
"ftp:"
,
"mailto:"
,
"gopher:"
,
"//"
];
}
public
function
fakeTimestamp
():
?
int
{
return
$this
->
fakeTimestamp
;
}
/**
* Set the fake timestamp for testing
* @param ?int $ts Unix timestamp
*/
public
function
setFakeTimestamp
(
?
int
$ts
):
void
{
$this
->
fakeTimestamp
=
$ts
;
}
/**
* Set the timezone offset for testing
* @param int $offset Offset from UTC
*/
public
function
setTimezoneOffset
(
int
$offset
):
void
{
$this
->
timezoneOffset
=
$offset
;
}
public
function
scrubBidiChars
():
bool
{
return
true
;
}
/** @inheritDoc */
public
function
getNoFollowConfig
():
array
{
return
[
'nofollow'
=>
true
,
'nsexceptions'
=>
[
1
],
'domainexceptions'
=>
[
'www.example.com'
]
];
}
/** @inheritDoc */
public
function
getExternalLinkTarget
()
{
return
$this
->
externalLinkTarget
;
}
/** @var ?MockMetrics */
private
$metrics
;
/** @inheritDoc */
public
function
metrics
():
?
StatsdDataFactoryInterface
{
if
(
$this
->
metrics
===
null
)
{
$this
->
metrics
=
new
MockMetrics
();
}
return
$this
->
metrics
;
}
/**
* Increment a counter metric
* @param string $name
* @param array $labels
* @param float $amount
* @return void
*/
public
function
incrementCounter
(
string
$name
,
array
$labels
,
float
$amount
=
1
):
void
{
// We don't use the labels for now, using MockMetrics instead
$this
->
metrics
->
increment
(
$name
);
}
/**
* Record a timing metric
* @param string $name
* @param float $value
* @param array $labels
* @return void
*/
public
function
observeTiming
(
string
$name
,
float
$value
,
array
$labels
):
void
{
// We don't use the labels for now, using MockMetrics instead
$this
->
metrics
->
timing
(
$name
,
$value
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Aug 19 2026, 20:46 (7 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ba/f4/4da601dee6c200a4539a0c9e28bc
Default Alt Text
MockSiteConfig.php (12 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment