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