MediaWiki  master
CoreMagicVariables.php
Go to the documentation of this file.
1 <?php
25 use Psr\Log\LoggerInterface;
26 
34  private const MAX_TTS = 900;
35 
49  public static function expand(
50  // Fundamental options
51  Parser $parser,
52  string $id,
53  // Context passed over from the parser
54  int $ts,
55  NamespaceInfo $nsInfo,
56  ServiceOptions $svcOptions,
57  LoggerInterface $logger
58  ): ?string {
59  $pageLang = $parser->getFunctionLang();
60  $title = $parser->getTitle();
61 
62  switch ( $id ) {
63  case '!':
64  return '|';
65  case 'currentmonth':
66  return $pageLang->formatNumNoSeparators( MWTimestamp::getInstance( $ts )->format( 'm' ) );
67  case 'currentmonth1':
68  return $pageLang->formatNumNoSeparators( MWTimestamp::getInstance( $ts )->format( 'n' ) );
69  case 'currentmonthname':
70  return $pageLang->getMonthName( MWTimestamp::getInstance( $ts )->format( 'n' ) );
71  case 'currentmonthnamegen':
72  return $pageLang->getMonthNameGen( MWTimestamp::getInstance( $ts )->format( 'n' ) );
73  case 'currentmonthabbrev':
74  return $pageLang->getMonthAbbreviation( MWTimestamp::getInstance( $ts )->format( 'n' ) );
75  case 'currentday':
76  return $pageLang->formatNumNoSeparators( MWTimestamp::getInstance( $ts )->format( 'j' ) );
77  case 'currentday2':
78  return $pageLang->formatNumNoSeparators( MWTimestamp::getInstance( $ts )->format( 'd' ) );
79  case 'localmonth':
80  return $pageLang->formatNumNoSeparators( MWTimestamp::getLocalInstance( $ts )->format( 'm' ) );
81  case 'localmonth1':
82  return $pageLang->formatNumNoSeparators( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) );
83  case 'localmonthname':
84  return $pageLang->getMonthName( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) );
85  case 'localmonthnamegen':
86  return $pageLang->getMonthNameGen( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) );
87  case 'localmonthabbrev':
88  return $pageLang->getMonthAbbreviation( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) );
89  case 'localday':
90  return $pageLang->formatNumNoSeparators( MWTimestamp::getLocalInstance( $ts )->format( 'j' ) );
91  case 'localday2':
92  return $pageLang->formatNumNoSeparators( MWTimestamp::getLocalInstance( $ts )->format( 'd' ) );
93  case 'pagename':
94  return wfEscapeWikiText( $title->getText() );
95  case 'pagenamee':
96  return wfEscapeWikiText( $title->getPartialURL() );
97  case 'fullpagename':
98  return wfEscapeWikiText( $title->getPrefixedText() );
99  case 'fullpagenamee':
100  return wfEscapeWikiText( $title->getPrefixedURL() );
101  case 'subpagename':
102  return wfEscapeWikiText( $title->getSubpageText() );
103  case 'subpagenamee':
104  return wfEscapeWikiText( $title->getSubpageUrlForm() );
105  case 'rootpagename':
106  return wfEscapeWikiText( $title->getRootText() );
107  case 'rootpagenamee':
108  return wfEscapeWikiText( wfUrlencode( str_replace(
109  ' ',
110  '_',
111  $title->getRootText()
112  ) ) );
113  case 'basepagename':
114  return wfEscapeWikiText( $title->getBaseText() );
115  case 'basepagenamee':
116  return wfEscapeWikiText( wfUrlencode( str_replace(
117  ' ',
118  '_',
119  $title->getBaseText()
120  ) ) );
121  case 'talkpagename':
122  if ( $title->canHaveTalkPage() ) {
123  $talkPage = $title->getTalkPage();
124  return wfEscapeWikiText( $talkPage->getPrefixedText() );
125  }
126  return '';
127  case 'talkpagenamee':
128  if ( $title->canHaveTalkPage() ) {
129  $talkPage = $title->getTalkPage();
130  return wfEscapeWikiText( $talkPage->getPrefixedURL() );
131  }
132  return '';
133  case 'subjectpagename':
134  $subjPage = $title->getSubjectPage();
135  return wfEscapeWikiText( $subjPage->getPrefixedText() );
136  case 'subjectpagenamee':
137  $subjPage = $title->getSubjectPage();
138  return wfEscapeWikiText( $subjPage->getPrefixedURL() );
139  case 'pageid': // requested in T25427
140  // Inform the edit saving system that getting the canonical output
141  // after page insertion requires a parse that used that exact page ID
142  self::setOutputFlag( $parser, $logger, ParserOutputFlags::VARY_PAGE_ID, '{{PAGEID}} used' );
143  $value = $title->getArticleID();
144  if ( !$value ) {
145  $value = $parser->getOptions()->getSpeculativePageId();
146  if ( $value ) {
147  $parser->getOutput()->setSpeculativePageIdUsed( $value );
148  }
149  }
150  return (string)$value;
151  case 'revisionid':
152  $namespace = $title->getNamespace();
153  if (
154  $svcOptions->get( 'MiserMode' ) &&
155  !$parser->getOptions()->getInterfaceMessage() &&
156  // @TODO: disallow this variable on all namespaces
157  $nsInfo->isSubject( $namespace )
158  ) {
159  // Use a stub result instead of the actual revision ID in order to avoid
160  // double parses on page save but still allow preview detection (T137900)
161  if ( $parser->getRevisionId() || $parser->getOptions()->getSpeculativeRevId() ) {
162  return '-';
163  } else {
165  $parser,
166  $logger,
167  ParserOutputFlags::VARY_REVISION_EXISTS,
168  '{{REVISIONID}} used'
169  );
170  return '';
171  }
172  } else {
173  // Inform the edit saving system that getting the canonical output after
174  // revision insertion requires a parse that used that exact revision ID
175  self::setOutputFlag( $parser, $logger, ParserOutputFlags::VARY_REVISION_ID, '{{REVISIONID}} used' );
176  $value = $parser->getRevisionId();
177  if ( $value === 0 ) {
178  $rev = $parser->getRevisionRecordObject();
179  $value = $rev ? $rev->getId() : $value;
180  }
181  if ( !$value ) {
182  $value = $parser->getOptions()->getSpeculativeRevId();
183  if ( $value ) {
184  $parser->getOutput()->setSpeculativeRevIdUsed( $value );
185  }
186  }
187  return (string)$value;
188  }
189  case 'revisionday':
190  return strval( (int)self::getRevisionTimestampSubstring(
191  $parser, $logger, 6, 2, self::MAX_TTS, $id
192  ) );
193  case 'revisionday2':
195  $parser, $logger, 6, 2, self::MAX_TTS, $id
196  );
197  case 'revisionmonth':
199  $parser, $logger, 4, 2, self::MAX_TTS, $id
200  );
201  case 'revisionmonth1':
202  return strval( (int)self::getRevisionTimestampSubstring(
203  $parser, $logger, 4, 2, self::MAX_TTS, $id
204  ) );
205  case 'revisionyear':
207  $parser, $logger, 0, 4, self::MAX_TTS, $id
208  );
209  case 'revisiontimestamp':
211  $parser, $logger, 0, 14, self::MAX_TTS, $id
212  );
213  case 'revisionuser':
214  // Inform the edit saving system that getting the canonical output after
215  // revision insertion requires a parse that used the actual user ID
216  self::setOutputFlag( $parser, $logger, ParserOutputFlags::VARY_USER, '{{REVISIONUSER}} used' );
217  // Note that getRevisionUser() can return null; we need to
218  // be sure to cast this to (an empty) string, since 'null'
219  // means "magic variable not handled here".
220  return (string)$parser->getRevisionUser();
221  case 'revisionsize':
222  return (string)$parser->getRevisionSize();
223  case 'namespace':
224  return str_replace( '_', ' ',
225  $parser->getContentLanguage()->getNsText( $title->getNamespace() ) );
226  case 'namespacee':
227  return wfUrlencode( $parser->getContentLanguage()->getNsText( $title->getNamespace() ) );
228  case 'namespacenumber':
229  return $title->getNamespace();
230  case 'talkspace':
231  return $title->canHaveTalkPage()
232  ? str_replace( '_', ' ', $title->getTalkNsText() )
233  : '';
234  case 'talkspacee':
235  return $title->canHaveTalkPage()
236  ? wfUrlencode( $title->getTalkNsText() )
237  : '';
238  case 'subjectspace':
239  return str_replace( '_', ' ', $title->getSubjectNsText() );
240  case 'subjectspacee':
241  return ( wfUrlencode( $title->getSubjectNsText() ) );
242  case 'currentdayname':
243  return $pageLang->getWeekdayName( (int)MWTimestamp::getInstance( $ts )->format( 'w' ) + 1 );
244  case 'currentyear':
245  return $pageLang->formatNumNoSeparators( MWTimestamp::getInstance( $ts )->format( 'Y' ) );
246  case 'currenttime':
247  return $pageLang->time( wfTimestamp( TS_MW, $ts ), false, false );
248  case 'currenthour':
249  return $pageLang->formatNumNoSeparators( MWTimestamp::getInstance( $ts )->format( 'H' ) );
250  case 'currentweek':
251  // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
252  // int to remove the padding
253  return $pageLang->formatNum( (int)MWTimestamp::getInstance( $ts )->format( 'W' ) );
254  case 'currentdow':
255  return $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'w' ) );
256  case 'localdayname':
257  return $pageLang->getWeekdayName(
258  (int)MWTimestamp::getLocalInstance( $ts )->format( 'w' ) + 1
259  );
260  case 'localyear':
261  return $pageLang->formatNumNoSeparators( MWTimestamp::getLocalInstance( $ts )->format( 'Y' ) );
262  case 'localtime':
263  return $pageLang->time(
264  MWTimestamp::getLocalInstance( $ts )->format( 'YmdHis' ),
265  false,
266  false
267  );
268  case 'localhour':
269  return $pageLang->formatNumNoSeparators( MWTimestamp::getLocalInstance( $ts )->format( 'H' ) );
270  case 'localweek':
271  // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
272  // int to remove the padding
273  return $pageLang->formatNum( (int)MWTimestamp::getLocalInstance( $ts )->format( 'W' ) );
274  case 'localdow':
275  return $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'w' ) );
276  case 'numberofarticles':
277  return $pageLang->formatNum( SiteStats::articles() );
278  case 'numberoffiles':
279  return $pageLang->formatNum( SiteStats::images() );
280  case 'numberofusers':
281  return $pageLang->formatNum( SiteStats::users() );
282  case 'numberofactiveusers':
283  return $pageLang->formatNum( SiteStats::activeUsers() );
284  case 'numberofpages':
285  return $pageLang->formatNum( SiteStats::pages() );
286  case 'numberofadmins':
287  return $pageLang->formatNum( SiteStats::numberingroup( 'sysop' ) );
288  case 'numberofedits':
289  return $pageLang->formatNum( SiteStats::edits() );
290  case 'currenttimestamp':
291  return wfTimestamp( TS_MW, $ts );
292  case 'localtimestamp':
293  return MWTimestamp::getLocalInstance( $ts )->format( 'YmdHis' );
294  case 'currentversion':
296  case 'articlepath':
297  return (string)$svcOptions->get( 'ArticlePath' );
298  case 'sitename':
299  return (string)$svcOptions->get( 'Sitename' );
300  case 'server':
301  return (string)$svcOptions->get( 'Server' );
302  case 'servername':
303  return (string)$svcOptions->get( 'ServerName' );
304  case 'scriptpath':
305  return (string)$svcOptions->get( 'ScriptPath' );
306  case 'stylepath':
307  return (string)$svcOptions->get( 'StylePath' );
308  case 'directionmark':
309  return $pageLang->getDirMark();
310  case 'contentlanguage':
311  return $parser->getContentLanguage()->getCode();
312  case 'pagelanguage':
313  return $pageLang->getCode();
314  case 'cascadingsources':
315  return CoreParserFunctions::cascadingsources( $parser );
316  default:
317  // This is not one of the core magic variables
318  return null;
319  }
320  }
321 
331  private static function getRevisionTimestampSubstring(
332  Parser $parser,
333  LoggerInterface $logger,
334  int $start,
335  int $len,
336  int $mtts,
337  string $variable
338  ): string {
339  // Get the timezone-adjusted timestamp to be used for this revision
340  $resNow = substr( $parser->getRevisionTimestamp(), $start, $len );
341  // Possibly set vary-revision if there is not yet an associated revision
342  if ( !$parser->getRevisionRecordObject() ) {
343  // Get the timezone-adjusted timestamp $mtts seconds in the future.
344  // This future is relative to the current time and not that of the
345  // parser options. The rendered timestamp can be compared to that
346  // of the timestamp specified by the parser options.
347  $resThen = substr(
348  $parser->getContentLanguage()->userAdjust( wfTimestamp( TS_MW, time() + $mtts ), '' ),
349  $start,
350  $len
351  );
352 
353  if ( $resNow !== $resThen ) {
354  // Inform the edit saving system that getting the canonical output after
355  // revision insertion requires a parse that used an actual revision timestamp
356  self::setOutputFlag( $parser, $logger, ParserOutputFlags::VARY_REVISION_TIMESTAMP, "$variable used" );
357  }
358  }
359 
360  return $resNow;
361  }
362 
371  private static function setOutputFlag(
372  Parser $parser,
373  LoggerInterface $logger,
374  string $flag,
375  string $reason
376  ): void {
377  $parser->getOutput()->setOutputFlag( $flag );
378  $name = $parser->getTitle()->getPrefixedText();
379  // This code was moved from Parser::setOutputFlag and used __METHOD__
380  // originally; we've hard-coded that output here so that our refactor
381  // doesn't change the messages in the logs.
382  $logger->debug( "Parser::setOutputFlag: set $flag flag on '$name'; $reason" );
383  }
384 }
SiteStats\articles
static articles()
Definition: SiteStats.php:103
SiteStats\users
static users()
Definition: SiteStats.php:121
SiteStats\activeUsers
static activeUsers()
Definition: SiteStats.php:130
Parser\getRevisionSize
getRevisionSize()
Get the size of the revision.
Definition: Parser.php:5993
Parser\ParserOutputFlags
Definition: ParserOutputFlags.php:41
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1649
SiteStats\pages
static pages()
Definition: SiteStats.php:112
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:292
SiteStats\numberingroup
static numberingroup( $group)
Find the number of users in a given user group.
Definition: SiteStats.php:150
NamespaceInfo\isSubject
isSubject( $index)
Is the given namespace is a subject (non-talk) namespace?
Definition: NamespaceInfo.php:180
Parser\getOptions
getOptions()
Definition: Parser.php:1089
SiteStats\images
static images()
Definition: SiteStats.php:139
Parser\getFunctionLang
getFunctionLang()
Get a language object for use in parser functions such as {{FORMATNUM:}}.
Definition: Parser.php:1135
Parser\getTitle
getTitle()
Definition: Parser.php:1000
Parser\getRevisionRecordObject
getRevisionRecordObject()
Get the revision record object for $this->mRevisionId.
Definition: Parser.php:5888
MediaWiki\Config\ServiceOptions
A class for passing options to services.
Definition: ServiceOptions.php:27
CoreMagicVariables\setOutputFlag
static setOutputFlag(Parser $parser, LoggerInterface $logger, string $flag, string $reason)
Helper method borrowed from Parser.php: sets the flag on the output but also does some debug logging.
Definition: CoreMagicVariables.php:371
MWTimestamp\getInstance
static getInstance( $ts=false)
Get a timestamp instance in GMT.
Definition: MWTimestamp.php:45
$title
$title
Definition: testCompression.php:38
Parser\getContentLanguage
getContentLanguage()
Get the content language that this Parser is using.
Definition: Parser.php:1211
Parser\getRevisionUser
getRevisionUser()
Get the name of the user that edited the last revision.
Definition: Parser.php:5969
CoreMagicVariables
Expansions of core magic variables, used by the parser.
Definition: CoreMagicVariables.php:32
SpecialVersion\getVersion
static getVersion( $flags='', $lang=null)
Return a string of the MediaWiki version with Git revision if available.
Definition: SpecialVersion.php:322
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1440
Parser
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition: Parser.php:91
CoreParserFunctions\cascadingsources
static cascadingsources( $parser, $title='')
Returns the sources of any cascading protection acting on a specified page.
Definition: CoreParserFunctions.php:1456
Parser\getOutput
getOutput()
Definition: Parser.php:1081
CoreMagicVariables\getRevisionTimestampSubstring
static getRevisionTimestampSubstring(Parser $parser, LoggerInterface $logger, int $start, int $len, int $mtts, string $variable)
Definition: CoreMagicVariables.php:331
MediaWiki\Config\ServiceOptions\get
get( $key)
Definition: ServiceOptions.php:93
CoreMagicVariables\expand
static expand(Parser $parser, string $id, int $ts, NamespaceInfo $nsInfo, ServiceOptions $svcOptions, LoggerInterface $logger)
Expand the magic variable given by $index.
Definition: CoreMagicVariables.php:49
NamespaceInfo
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Definition: NamespaceInfo.php:35
Parser\getRevisionTimestamp
getRevisionTimestamp()
Get the timestamp associated with the current revision, adjusted for the default server-local timesta...
Definition: Parser.php:5943
MWTimestamp\getLocalInstance
static getLocalInstance( $ts=false)
Get a timestamp instance in the server local timezone ($wgLocaltimezone)
Definition: MWTimestamp.php:173
SiteStats\edits
static edits()
Definition: SiteStats.php:94
Parser\getRevisionId
getRevisionId()
Get the ID of the revision we are parsing.
Definition: Parser.php:5878