MediaWiki master
CoreMagicVariables.php
Go to the documentation of this file.
1<?php
28use Psr\Log\LoggerInterface;
29use Wikimedia\Timestamp\ConvertibleTimestamp;
30
38 private const CACHE_TTL_BY_ID = [
39 'currenttime' => 3600,
40 'localtime' => 3600,
41 'numberofarticles' => 3600,
42 'numberoffiles' => 3600,
43 'numberofedits' => 3600,
44 'numberofusers' => 3600,
45 'numberofactiveusers' => 3600,
46 'numberofpages' => 3600,
47 'currentversion' => 86400,
48 'currenttimestamp' => 3600,
49 'localtimestamp' => 3600,
50 'pagesinnamespace' => 3600,
51 'numberofadmins' => 3600,
52 'numberingroup' => 3600,
53 ];
54
56 private const DEADLINE_DATE_SPEC_BY_UNIT = [
57 'Y' => 'first day of January next year midnight',
58 'M' => 'first day of next month midnight',
59 'D' => 'next day midnight',
60 // Note that this relative datetime specifier does not zero out
61 // minutes/seconds, but we will do so manually in
62 // ::applyUnitTimestampDeadline() when given the unit 'H'
63 'H' => 'next hour'
64 ];
66 private const DEADLINE_TTL_CLOCK_FUDGE = 1;
68 private const DEADLINE_TTL_STAGGER_MAX = 15;
70 private const MIN_DEADLINE_TTL = 15;
71
84 public static function expand(
85 // Fundamental options
86 Parser $parser,
87 string $id,
88 // Context passed over from the parser
89 ConvertibleTimestamp $ts,
90 ServiceOptions $svcOptions,
91 LoggerInterface $logger
92 ): ?string {
93 $pageLang = $parser->getTargetLanguage();
94
95 $cacheTTL = self::CACHE_TTL_BY_ID[$id] ?? -1;
96 if ( $cacheTTL > -1 ) {
97 $parser->getOutput()->updateCacheExpiry( $cacheTTL );
98 }
99
100 switch ( $id ) {
101 case '!':
102 return '|';
103 case '=':
104 return '=';
105 case 'currentmonth':
106 self::applyUnitTimestampDeadline( $parser, $ts, 'M' );
107
108 return $pageLang->formatNumNoSeparators( $ts->format( 'm' ) );
109 case 'currentmonth1':
110 self::applyUnitTimestampDeadline( $parser, $ts, 'M' );
111
112 return $pageLang->formatNumNoSeparators( $ts->format( 'n' ) );
113 case 'currentmonthname':
114 self::applyUnitTimestampDeadline( $parser, $ts, 'M' );
115
116 return $pageLang->getMonthName( (int)$ts->format( 'n' ) );
117 case 'currentmonthnamegen':
118 self::applyUnitTimestampDeadline( $parser, $ts, 'M' );
119
120 return $pageLang->getMonthNameGen( (int)$ts->format( 'n' ) );
121 case 'currentmonthabbrev':
122 self::applyUnitTimestampDeadline( $parser, $ts, 'M' );
123
124 return $pageLang->getMonthAbbreviation( (int)$ts->format( 'n' ) );
125 case 'currentday':
126 self::applyUnitTimestampDeadline( $parser, $ts, 'D' );
127
128 return $pageLang->formatNumNoSeparators( $ts->format( 'j' ) );
129 case 'currentday2':
130 self::applyUnitTimestampDeadline( $parser, $ts, 'D' );
131
132 return $pageLang->formatNumNoSeparators( $ts->format( 'd' ) );
133 case 'localmonth':
134 $localTs = self::makeTsLocal( $svcOptions, $ts );
135 self::applyUnitTimestampDeadline( $parser, $localTs, 'M' );
136
137 return $pageLang->formatNumNoSeparators( $localTs->format( 'm' ) );
138 case 'localmonth1':
139 $localTs = self::makeTsLocal( $svcOptions, $ts );
140 self::applyUnitTimestampDeadline( $parser, $localTs, 'M' );
141
142 return $pageLang->formatNumNoSeparators( $localTs->format( 'n' ) );
143 case 'localmonthname':
144 $localTs = self::makeTsLocal( $svcOptions, $ts );
145 self::applyUnitTimestampDeadline( $parser, $localTs, 'M' );
146
147 return $pageLang->getMonthName( (int)$localTs->format( 'n' ) );
148 case 'localmonthnamegen':
149 $localTs = self::makeTsLocal( $svcOptions, $ts );
150 self::applyUnitTimestampDeadline( $parser, $localTs, 'M' );
151
152 return $pageLang->getMonthNameGen( (int)$localTs->format( 'n' ) );
153 case 'localmonthabbrev':
154 $localTs = self::makeTsLocal( $svcOptions, $ts );
155 self::applyUnitTimestampDeadline( $parser, $localTs, 'M' );
156
157 return $pageLang->getMonthAbbreviation( (int)$localTs->format( 'n' ) );
158 case 'localday':
159 $localTs = self::makeTsLocal( $svcOptions, $ts );
160 self::applyUnitTimestampDeadline( $parser, $localTs, 'D' );
161
162 return $pageLang->formatNumNoSeparators( $localTs->format( 'j' ) );
163 case 'localday2':
164 $localTs = self::makeTsLocal( $svcOptions, $ts );
165 self::applyUnitTimestampDeadline( $parser, $localTs, 'D' );
166
167 return $pageLang->formatNumNoSeparators( $localTs->format( 'd' ) );
168 case 'pagename':
169 case 'pagenamee':
170 case 'fullpagename':
171 case 'fullpagenamee':
172 case 'subpagename':
173 case 'subpagenamee':
174 case 'rootpagename':
175 case 'rootpagenamee':
176 case 'basepagename':
177 case 'basepagenamee':
178 case 'talkpagename':
179 case 'talkpagenamee':
180 case 'subjectpagename':
181 case 'subjectpagenamee':
182 case 'pageid':
183 case 'revisionid':
184 case 'revisionuser':
185 case 'revisionday':
186 case 'revisionday2':
187 case 'revisionmonth':
188 case 'revisionmonth1':
189 case 'revisionyear':
190 case 'revisiontimestamp':
191 case 'namespace':
192 case 'namespacee':
193 case 'namespacenumber':
194 case 'talkspace':
195 case 'talkspacee':
196 case 'subjectspace':
197 case 'subjectspacee':
198 case 'cascadingsources':
199 # First argument of the corresponding parser function
200 # (second argument of the PHP implementation) is
201 # "title".
202
203 # Note that for many of these {{FOO}} is subtly different
204 # from {{FOO:{{PAGENAME}}}}, so we can't pass $title here
205 # we have to explicitly use the "no arguments" form of the
206 # parser function by passing `null` to indicate a missing
207 # argument (which then defaults to the current page title).
208 return CoreParserFunctions::$id( $parser, null );
209 case 'revisionsize':
210 return (string)$parser->getRevisionSize();
211 case 'currentdayname':
212 self::applyUnitTimestampDeadline( $parser, $ts, 'D' );
213
214 return $pageLang->getWeekdayName( (int)$ts->format( 'w' ) + 1 );
215 case 'currentyear':
216 self::applyUnitTimestampDeadline( $parser, $ts, 'Y' );
217
218 return $pageLang->formatNumNoSeparators( $ts->format( 'Y' ) );
219 case 'currenttime':
220 return $pageLang->time( $ts->getTimestamp( TS_MW ), false, false );
221 case 'currenthour':
222 self::applyUnitTimestampDeadline( $parser, $ts, 'H' );
223
224 return $pageLang->formatNumNoSeparators( $ts->format( 'H' ) );
225 case 'currentweek':
226 self::applyUnitTimestampDeadline( $parser, $ts, 'D' );
227 // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
228 // int to remove the padding
229 return $pageLang->formatNum( (int)$ts->format( 'W' ) );
230 case 'currentdow':
231 self::applyUnitTimestampDeadline( $parser, $ts, 'D' );
232
233 return $pageLang->formatNum( $ts->format( 'w' ) );
234 case 'localdayname':
235 $localTs = self::makeTsLocal( $svcOptions, $ts );
236 self::applyUnitTimestampDeadline( $parser, $localTs, 'D' );
237
238 return $pageLang->getWeekdayName( (int)$localTs->format( 'w' ) + 1 );
239 case 'localyear':
240 $localTs = self::makeTsLocal( $svcOptions, $ts );
241 self::applyUnitTimestampDeadline( $parser, $localTs, 'Y' );
242
243 return $pageLang->formatNumNoSeparators( $localTs->format( 'Y' ) );
244 case 'localtime':
245 $localTs = self::makeTsLocal( $svcOptions, $ts );
246
247 return $pageLang->time(
248 $localTs->format( 'YmdHis' ),
249 false,
250 false
251 );
252 case 'localhour':
253 $localTs = self::makeTsLocal( $svcOptions, $ts );
254 self::applyUnitTimestampDeadline( $parser, $localTs, 'H' );
255
256 return $pageLang->formatNumNoSeparators( $localTs->format( 'H' ) );
257 case 'localweek':
258 $localTs = self::makeTsLocal( $svcOptions, $ts );
259 self::applyUnitTimestampDeadline( $parser, $localTs, 'D' );
260 // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
261 // int to remove the padding
262 return $pageLang->formatNum( (int)$localTs->format( 'W' ) );
263 case 'localdow':
264 $localTs = self::makeTsLocal( $svcOptions, $ts );
265 self::applyUnitTimestampDeadline( $parser, $localTs, 'D' );
266
267 return $pageLang->formatNum( $localTs->format( 'w' ) );
268 case 'numberofarticles':
269 case 'numberoffiles':
270 case 'numberofusers':
271 case 'numberofactiveusers':
272 case 'numberofpages':
273 case 'numberofadmins':
274 case 'numberofedits':
275 # second argument is 'raw'; magic variables are "not raw"
276 return CoreParserFunctions::$id( $parser, null );
277 case 'currenttimestamp':
278 return $ts->getTimestamp( TS_MW );
279 case 'localtimestamp':
280 $localTs = self::makeTsLocal( $svcOptions, $ts );
281
282 return $localTs->format( 'YmdHis' );
283 case 'currentversion':
284 return SpecialVersion::getVersion();
285 case 'articlepath':
286 return (string)$svcOptions->get( MainConfigNames::ArticlePath );
287 case 'sitename':
288 return (string)$svcOptions->get( MainConfigNames::Sitename );
289 case 'server':
290 return (string)$svcOptions->get( MainConfigNames::Server );
291 case 'servername':
292 return (string)$svcOptions->get( MainConfigNames::ServerName );
293 case 'scriptpath':
294 return (string)$svcOptions->get( MainConfigNames::ScriptPath );
295 case 'stylepath':
296 return (string)$svcOptions->get( MainConfigNames::StylePath );
297 case 'directionmark':
298 return $pageLang->getDirMark();
299 case 'contentlanguage':
300 return $parser->getContentLanguage()->getCode();
301 case 'pagelanguage':
302 return $pageLang->getCode();
303 case 'userlanguage':
304 if ( $svcOptions->get( MainConfigNames::ParserEnableUserLanguage ) ) {
305 return $parser->getOptions()->getUserLang();
306 } else {
307 return $pageLang->getCode();
308 }
309 case 'bcp47':
310 case 'dir':
311 case 'language':
312 # magic variables are the same as empty/default first argument
313 return CoreParserFunctions::$id( $parser );
314 default:
315 // This is not one of the core magic variables
316 return null;
317 }
318 }
319
327 private static function makeTsLocal( $svcOptions, $ts ) {
328 $localtimezone = $svcOptions->get( MainConfigNames::Localtimezone );
329 $ts->setTimezone( $localtimezone );
330 return $ts;
331 }
332
340 private static function applyUnitTimestampDeadline(
341 Parser $parser,
342 ConvertibleTimestamp $ts,
343 string $unit
344 ) {
345 $tsUnix = (int)$ts->getTimestamp( TS_UNIX );
346
347 $date = new DateTime( "@$tsUnix" );
348 $date->setTimezone( $ts->getTimezone() );
349 $date->modify( self::DEADLINE_DATE_SPEC_BY_UNIT[$unit] );
350 if ( $unit === 'H' ) {
351 // Zero out the minutes/seconds
352 $date->setTime( intval( $date->format( 'H' ), 10 ), 0, 0 );
353 } else {
354 $date->setTime( 0, 0, 0 );
355 }
356 $deadlineUnix = (int)$date->format( 'U' );
357
358 $ttl = max( $deadlineUnix - $tsUnix, self::MIN_DEADLINE_TTL );
359 $ttl += self::DEADLINE_TTL_CLOCK_FUDGE;
360 $ttl += ( $tsUnix % self::DEADLINE_TTL_STAGGER_MAX );
361
362 $parser->getOutput()->updateCacheExpiry( $ttl );
363 }
364}
Expansions of core magic variables, used by the parser.
static expand(Parser $parser, string $id, ConvertibleTimestamp $ts, ServiceOptions $svcOptions, LoggerInterface $logger)
Expand the magic variable given by $index.
A class for passing options to services.
A class containing constants representing the names of configuration variables.
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:155
getContentLanguage()
Get the content language that this Parser is using.
Definition Parser.php:1250
getRevisionSize()
Get the size of the revision.
Definition Parser.php:6158
Version information about MediaWiki (core, extensions, libs), PHP, and the database.
Library for creating and parsing MW-style timestamps.