16 self::$mTimeChars = 0;
29 $wgHooks[
'ParserClearState'][] = __CLASS__ .
'::clearState';
38 if ( !isset( self::$mExprParser ) ) {
53 return '<strong class="error">' . htmlspecialchars(
$e->getMessage() ) .
'</strong>';
64 public static function ifexpr(
$parser, $expr =
'', $then =
'', $else =
'' ) {
67 if ( is_numeric(
$ret ) ) {
76 return '<strong class="error">' . htmlspecialchars(
$e->getMessage() ) .
'</strong>';
87 $expr = isset(
$args[0] ) ? trim( $frame->expand(
$args[0] ) ) :
'';
91 if ( is_object( $result ) ) {
92 $result = trim( $frame->expand( $result ) );
104 $test = isset(
$args[0] ) ? trim( $frame->expand(
$args[0] ) ) :
'';
105 if ( $test !==
'' ) {
106 return isset(
$args[1] ) ? trim( $frame->expand(
$args[1] ) ) :
'';
108 return isset(
$args[2] ) ? trim( $frame->expand(
$args[2] ) ) :
'';
124 if ( $left == $right ) {
125 return isset(
$args[2] ) ? trim( $frame->expand(
$args[2] ) ) :
'';
127 return isset(
$args[3] ) ? trim( $frame->expand(
$args[3] ) ) :
'';
138 public static function iferror(
$parser, $test =
'', $then =
'', $else =
false ) {
140 '/<(?:strong|span|p|div)\s(?:[^\s>]*\s+)*?class="(?:[^"\s>]*\s+)*?error(?:\s[^">]*)?"/',
144 } elseif ( $else ===
false ) {
158 $test = isset(
$args[0] ) ? trim( $frame->expand(
$args[0] ) ) :
'';
162 if ( $result ===
false ) {
165 return trim( $frame->expand( $result ) );
176 if ( count(
$args ) === 0 ) {
180 $found = $defaultFound =
false;
182 $lastItemHadNoEquals =
false;
184 if ( class_exists( MagicWordFactory::class ) ) {
185 $mwDefault =
$parser->getMagicWordFactory()->get(
'default' );
189 foreach (
$args as $arg ) {
190 $bits = $arg->splitArg();
191 $nameNode = $bits[
'name'];
192 $index = $bits[
'index'];
193 $valueNode = $bits[
'value'];
195 if ( $index ===
'' ) {
197 $lastItemHadNoEquals =
false;
199 # Multiple input match
200 return trim( $frame->expand( $valueNode ) );
204 if ( $test == $primary ) {
205 # Found a match, return now
206 return trim( $frame->expand( $valueNode ) );
207 } elseif ( $defaultFound || $mwDefault->matchStartToEnd( $test ) ) {
208 $default = $valueNode;
209 $defaultFound =
false;
210 } #
else wrong
case,
continue
213 # Multiple input, single output
214 # If the value matches, set a flag and continue
215 $lastItemHadNoEquals =
true;
219 if ( $decodedTest == $primary ) {
221 } elseif ( $mwDefault->matchStartToEnd( $decodedTest ) ) {
222 $defaultFound =
true;
227 # Check if the last item had no = sign, thus specifying the default case
228 if ( $lastItemHadNoEquals ) {
230 } elseif ( !is_null( $default ) ) {
231 return trim( $frame->expand( $default ) );
251 $from = trim( $from );
252 if ( $from ===
'' ) {
253 $from =
$parser->getTitle()->getPrefixedText();
256 $to = rtrim( $to,
' /' );
259 if ( $to ===
'' || $to ===
'.' ) {
264 if ( substr( $to, 0, 1 ) !==
'/' &&
265 substr( $to, 0, 2 ) !==
'./' &&
266 substr( $to, 0, 3 ) !==
'../' &&
272 $fullPath =
'/' . $from .
'/' . $to .
'/';
275 $fullPath = preg_replace(
'!/(\./)+!',
'/', $fullPath );
278 $fullPath = preg_replace(
'!/{2,}!',
'/', $fullPath );
281 $fullPath = trim( $fullPath,
'/' );
282 $exploded = explode(
'/', $fullPath );
285 foreach ( $exploded as $current ) {
286 if ( $current ===
'..' ) {
287 if ( !count( $newExploded ) ) {
289 $msg =
wfMessage(
'pfunc_rel2abs_invalid_depth', $fullPath )
290 ->inContentLanguage()->escaped();
291 return '<strong class="error">' . $msg .
'</strong>';
294 array_pop( $newExploded );
297 $newExploded[] = $current;
302 return implode(
'/', $newExploded );
315 $parser, $frame, $titletext =
'', $then =
'', $else =
''
318 $title = Title::newFromText( $titletext );
319 $wgContLang->findVariantLink( $titletext, $title,
true );
321 if ( $title->getNamespace() ===
NS_MEDIA ) {
325 if ( !
$parser->incrementExpensiveFunctionCount() ) {
333 $file->getName(), $file->getTimestamp(), $file->getSha1() );
334 return $file->exists() ? $then : $else;
335 } elseif ( $title->isSpecialPage() ) {
340 return MediaWikiServices::getInstance()->getSpecialPageFactory()
341 ->exists( $title->getDBkey() ) ? $then : $else;
342 } elseif ( $title->isExternal() ) {
349 $pdbk = $title->getPrefixedDBkey();
350 $lc = LinkCache::singleton();
351 $id = $lc->getGoodLinkID( $pdbk );
353 $parser->mOutput->addLink( $title, $id );
355 } elseif ( $lc->isBadLink( $pdbk ) ) {
356 $parser->mOutput->addLink( $title, 0 );
359 if ( !
$parser->incrementExpensiveFunctionCount() ) {
362 $id = $title->getArticleID();
363 $parser->mOutput->addLink( $title, $id );
366 if ( $title->exists() ) {
381 $title = isset(
$args[0] ) ? trim( $frame->expand(
$args[0] ) ) :
'';
386 if ( $result ===
null ) {
389 return trim( $frame->expand( $result ) );
403 $parser, $frame =
null, $format =
'', $date =
'', $language =
'', $local =
false
407 if ( $date ===
'' ) {
408 $cacheKey =
$parser->getOptions()->getTimestamp();
410 $date = $timestamp->getTimestamp( TS_ISO_8601 );
416 if ( isset( self::$mTimeCache[$format][$cacheKey][$language][$local] ) ) {
417 $cachedVal = self::$mTimeCache[$format][$cacheKey][$language][$local];
419 && $cachedVal[1] !==
null && $frame && is_callable( [ $frame,
'setTTL' ] )
421 $frame->setTTL( $cachedVal[1] );
423 return $cachedVal[0];
426 # compute the timestamp string $ts
427 # PHP >= 5.2 can handle dates before 1970 or after 2038 using the DateTime object
429 $invalidTime =
false;
431 # the DateTime constructor must be used because it throws exceptions
432 # when errors occur, whereas date_create appears to just output a warning
433 # that can't really be detected from within the code
436 # Default input timezone is UTC.
437 $utc =
new DateTimeZone(
'UTC' );
439 # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
440 if ( preg_match(
'/^[0-9]{4}$/', $date ) ) {
441 $date =
'00:00 ' . $date;
445 # UTC is a default input timezone.
446 $dateObject =
new DateTime( $date, $utc );
448 # Set output timezone.
453 $tz =
new DateTimeZone( date_default_timezone_get() );
458 $dateObject->setTimezone( $tz );
460 $ts = $dateObject->format(
'YmdHis' );
462 }
catch ( Exception $ex ) {
467 # format the timestamp and return the result
468 if ( $invalidTime ) {
469 $result =
'<strong class="error">' .
470 wfMessage(
'pfunc_time_error' )->inContentLanguage()->escaped() .
473 self::$mTimeChars += strlen( $format );
474 if ( self::$mTimeChars > self::$mMaxTimeChars ) {
475 return '<strong class="error">' .
476 wfMessage(
'pfunc_time_too_long' )->inContentLanguage()->escaped() .
480 return '<strong class="error">' .
481 wfMessage(
'pfunc_time_too_small' )->inContentLanguage()->escaped() .
483 } elseif ( $ts < 100000000000000 ) {
484 if ( $language !==
'' && Language::isValidBuiltInCode( $language ) ) {
486 $langObject = Language::factory( $language );
489 $langObject =
$parser->getFunctionLang();
493 $result = $langObject->sprintfDate( $format, $ts, $tz, $ttl );
495 return '<strong class="error">' .
496 wfMessage(
'pfunc_time_too_big' )->inContentLanguage()->escaped() .
501 self::$mTimeCache[$format][$cacheKey][$language][$local] = [
$result, $ttl ];
502 if ( $useTTL && $ttl !==
null && $frame && is_callable( [ $frame,
'setTTL' ] ) ) {
503 $frame->setTTL( $ttl );
517 $parser, $format =
'', $date =
'', $language =
'', $local =
false
529 $format = isset(
$args[0] ) ? trim( $frame->expand(
$args[0] ) ) :
'';
530 $date = isset(
$args[1] ) ? trim( $frame->expand(
$args[1] ) ) :
'';
531 $language = isset(
$args[2] ) ? trim( $frame->expand(
$args[2] ) ) :
'';
532 $local = isset(
$args[3] ) && trim( $frame->expand(
$args[3] ) );
554 $format = isset(
$args[0] ) ? trim( $frame->expand(
$args[0] ) ) :
'';
555 $date = isset(
$args[1] ) ? trim( $frame->expand(
$args[1] ) ) :
'';
556 $language = isset(
$args[2] ) ? trim( $frame->expand(
$args[2] ) ) :
'';
571 $parts = (int)$parts;
572 $offset = (int)$offset;
573 $ntitle = Title::newFromText( $title );
574 if ( $ntitle instanceof
Title ) {
575 $bits = explode(
'/', $ntitle->getPrefixedText(), 25 );
576 if ( count( $bits ) <= 0 ) {
577 return $ntitle->getPrefixedText();
582 if ( $parts === 0 ) {
583 return implode(
'/', array_slice( $bits, $offset ) );
585 return implode(
'/', array_slice( $bits, $offset, $parts ) );
599 global $wgPFStringLengthLimit;
600 return ( mb_strlen( $text ) < $wgPFStringLengthLimit );
608 global $wgPFStringLengthLimit;
609 $msg =
wfMessage(
'pfunc_string_too_long' )->numParams( $wgPFStringLengthLimit );
610 return '<strong class="error">' . $msg->inContentLanguage()->escaped() .
'</strong>';
622 $inStr =
$parser->killMarkers( (
string)$inStr );
623 return mb_strlen( $inStr );
639 public static function runPos(
$parser, $inStr =
'', $inNeedle =
'', $inOffset = 0 ) {
640 $inStr =
$parser->killMarkers( (
string)$inStr );
641 $inNeedle =
$parser->killMarkers( (
string)$inNeedle );
643 if ( !self::checkLength( $inStr ) ||
644 !self::checkLength( $inNeedle ) ) {
648 if ( $inNeedle ===
'' ) {
652 $pos = mb_strpos( $inStr, $inNeedle, min( (
int)$inOffset, mb_strlen( $inStr ) ) );
653 if ( $pos ===
false ) {
673 $inStr =
$parser->killMarkers( (
string)$inStr );
674 $inNeedle =
$parser->killMarkers( (
string)$inNeedle );
676 if ( !self::checkLength( $inStr ) ||
677 !self::checkLength( $inNeedle ) ) {
681 if ( $inNeedle ===
'' ) {
685 $pos = mb_strrpos( $inStr, $inNeedle );
686 if ( $pos ===
false ) {
711 public static function runSub(
$parser, $inStr =
'', $inStart = 0, $inLength = 0 ) {
712 $inStr =
$parser->killMarkers( (
string)$inStr );
714 if ( !self::checkLength( $inStr ) ) {
718 if ( (
int)$inLength === 0 ) {
719 $result = mb_substr( $inStr, (
int)$inStart );
721 $result = mb_substr( $inStr, (
int)$inStart, (
int)$inLength );
739 $inStr =
$parser->killMarkers( (
string)$inStr );
740 $inSubStr =
$parser->killMarkers( (
string)$inSubStr );
742 if ( !self::checkLength( $inStr ) ||
743 !self::checkLength( $inSubStr ) ) {
747 if ( $inSubStr ===
'' ) {
751 $result = mb_substr_count( $inStr, $inSubStr );
772 $inReplaceFrom =
'', $inReplaceTo =
'', $inLimit = -1 ) {
773 global $wgPFStringLengthLimit;
775 $inStr =
$parser->killMarkers( (
string)$inStr );
776 $inReplaceFrom =
$parser->killMarkers( (
string)$inReplaceFrom );
777 $inReplaceTo =
$parser->killMarkers( (
string)$inReplaceTo );
779 if ( !self::checkLength( $inStr ) ||
780 !self::checkLength( $inReplaceFrom ) ||
781 !self::checkLength( $inReplaceTo ) ) {
785 if ( $inReplaceFrom ===
'' ) {
786 $inReplaceFrom =
' ';
790 $diff = mb_strlen( $inReplaceTo ) - mb_strlen( $inReplaceFrom );
792 $limit = ( ( $wgPFStringLengthLimit - mb_strlen( $inStr ) ) / $diff ) + 1;
797 $inLimit = (int)$inLimit;
798 if ( $inLimit >= 0 ) {
799 if ( $limit > $inLimit || $limit == -1 ) {
805 $inReplaceFrom = preg_quote( $inReplaceFrom,
'/' );
808 $result = preg_replace(
'/' . $inReplaceFrom .
'/u',
809 $inReplaceTo, $inStr, $limit );
811 if ( !self::checkLength( $result ) ) {
835 $parser, $inStr =
'', $inDiv =
'', $inPos = 0, $inLim =
null
837 $inStr =
$parser->killMarkers( (
string)$inStr );
838 $inDiv =
$parser->killMarkers( (
string)$inDiv );
840 if ( $inDiv ===
'' ) {
844 if ( !self::checkLength( $inStr ) ||
845 !self::checkLength( $inDiv ) ) {
849 $inDiv = preg_quote( $inDiv,
'/' );
851 $matches = preg_split(
'/' . $inDiv .
'/u', $inStr, $inLim );
853 if ( $inPos >= 0 && isset(
$matches[$inPos] ) ) {
873 $inStr =
$parser->killMarkers( (
string)$inStr );
874 if ( !self::checkLength( $inStr ) ) {
878 return urldecode( $inStr );
894 $expanded = $frame->expand( $obj );
895 $trimExpanded = trim( $expanded );
896 return trim( Sanitizer::decodeCharReferences( $expanded ) );
$wgLocaltimezone
Fake out the timezone that the server thinks it's in.
wfFindFile( $title, $options=[])
Find a file.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
static ifeqObj( $parser, $frame, $args)
static runUrlDecode( $parser, $inStr='')
{{#urldecode:string}}
static runRPos( $parser, $inStr='', $inNeedle='')
{{#rpos: string | needle}}
static checkLength( $text)
Verifies parameter is less than max string length.
static ifexistCommon( $parser, $frame, $titletext='', $then='', $else='')
static iferrorObj( $parser, $frame, $args)
static expr( $parser, $expr='')
static titleparts( $parser, $title='', $parts=0, $offset=0)
Obtain a specified number of slash-separated parts of a title, e.g.
static ifObj( $parser, $frame, $args)
static runReplace( $parser, $inStr='', $inReplaceFrom='', $inReplaceTo='', $inLimit=-1)
{{replace:string | from | to | limit }}
static switchObj( $parser, $frame, $args)
static runPos( $parser, $inStr='', $inNeedle='', $inOffset=0)
{{#pos: string | needle | offset}}
static tooLongError()
Generates error message.
static runSub( $parser, $inStr='', $inStart=0, $inLength=0)
{{#sub: string | start | length }}
static localTime( $parser, $format='', $date='', $language='')
static rel2abs( $parser, $to='', $from='')
Returns the absolute path to a subpage, relative to the current article title.
static time( $parser, $format='', $date='', $language='', $local=false)
static runLen( $parser, $inStr='')
{{#len:string}}
static runExplode( $parser, $inStr='', $inDiv='', $inPos=0, $inLim=null)
{{#explode:string | delimiter | position | limit}}
static registerClearHook()
Register ParserClearState hook.
static decodeTrimExpand( $obj, $frame, &$trimExpanded=null)
Take a PPNode (-ish thing), expand it, remove entities, and trim.
static timeObj( $parser, $frame, $args)
static runCount( $parser, $inStr='', $inSubStr='')
{{#count: string | substr }}
static ifexpr( $parser, $expr='', $then='', $else='')
static localTimeObj( $parser, $frame, $args)
static iferror( $parser, $test='', $then='', $else=false)
static clearState( $parser)
static ifexistObj( $parser, $frame, $args)
static ifexprObj( $parser, $frame, $args)
static timeCommon( $parser, $frame=null, $format='', $date='', $language='', $local=false)
Library for creating and parsing MW-style timestamps.
static get( $id)
Factory: creates an object representing an ID.
static escapeRegexReplacement( $string)
Escape a string to make it suitable for inclusion in a preg_replace() replacement parameter.
static unstub(&$obj)
Unstubs an object, if it is a stub object.
Represents a title within MediaWiki.
namespace being checked & $result
see documentation in includes Linker php for Linker::makeImageLink or false for current used if you return false $parser
namespace and then decline to actually register it file or subcat img or subcat $title
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "<div ...>$1</div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
$wgHooks['ArticleShow'][]
returning false will NOT prevent logging $e