MediaWiki master
CoreMagicVariables.php
Go to the documentation of this file.
1<?php
10namespace MediaWiki\Parser;
11
17use Psr\Log\LoggerInterface;
18use Wikimedia\Timestamp\ConvertibleTimestamp;
19use Wikimedia\Timestamp\TimestampFormat as TS;
20
28 private const CACHE_TTL_BY_ID = [
29 'currenttime' => 3600,
30 'localtime' => 3600,
31 'numberofarticles' => 3600,
32 'numberoffiles' => 3600,
33 'numberofedits' => 3600,
34 'numberofusers' => 3600,
35 'numberofactiveusers' => 3600,
36 'numberofpages' => 3600,
37 'currentversion' => 86400,
38 'currenttimestamp' => 3600,
39 'localtimestamp' => 3600,
40 'pagesinnamespace' => 3600,
41 'numberofadmins' => 3600,
42 'numberingroup' => 3600,
43 ];
44
46 private const DEADLINE_TTL_CLOCK_FUDGE = 1;
47
49 private const DEADLINE_TTL_STAGGER_MAX = 15;
50
52 private const MIN_DEADLINE_TTL = 30 * 60;
53
68 public static function expand(
69 // Fundamental options
70 Parser $parser,
71 string $id,
72 // Context passed over from the parser
73 ConvertibleTimestamp $ts,
74 ServiceOptions $svcOptions,
75 LoggerInterface $logger,
76 $frame = false
77 ): ?string {
78 $pageLang = $parser->getTargetLanguage();
79
80 $title = $frame ? $frame->getTitle() : $parser->getTitle();
81 $source = $title->getPrefixedDBkey() . " ($id)";
82
83 $cacheTTL = self::CACHE_TTL_BY_ID[$id] ?? -1;
84 if ( $cacheTTL > -1 ) {
85 $parser->getOutput()->updateCacheExpiry( $cacheTTL, $source );
86 }
87
88 switch ( $id ) {
89 case '!':
90 return '|';
91 case '=':
92 return '=';
93 case 'currentmonth':
94 self::applyUnitTimestampDeadline( $parser, $ts, 'M', $source );
95
96 return $pageLang->formatNumNoSeparators( $ts->format( 'm' ) );
97 case 'currentmonth1':
98 self::applyUnitTimestampDeadline( $parser, $ts, 'M', $source );
99
100 return $pageLang->formatNumNoSeparators( $ts->format( 'n' ) );
101 case 'currentmonthname':
102 self::applyUnitTimestampDeadline( $parser, $ts, 'M', $source );
103
104 return $pageLang->getMonthName( (int)$ts->format( 'n' ) );
105 case 'currentmonthnamegen':
106 self::applyUnitTimestampDeadline( $parser, $ts, 'M', $source );
107
108 return $pageLang->getMonthNameGen( (int)$ts->format( 'n' ) );
109 case 'currentmonthabbrev':
110 self::applyUnitTimestampDeadline( $parser, $ts, 'M', $source );
111
112 return $pageLang->getMonthAbbreviation( (int)$ts->format( 'n' ) );
113 case 'currentday':
114 self::applyUnitTimestampDeadline( $parser, $ts, 'D', $source );
115
116 return $pageLang->formatNumNoSeparators( $ts->format( 'j' ) );
117 case 'currentday2':
118 self::applyUnitTimestampDeadline( $parser, $ts, 'D', $source );
119
120 return $pageLang->formatNumNoSeparators( $ts->format( 'd' ) );
121 case 'localmonth':
122 $localTs = self::makeTsLocal( $svcOptions, $ts );
123 self::applyUnitTimestampDeadline( $parser, $localTs, 'M', $source );
124
125 return $pageLang->formatNumNoSeparators( $localTs->format( 'm' ) );
126 case 'localmonth1':
127 $localTs = self::makeTsLocal( $svcOptions, $ts );
128 self::applyUnitTimestampDeadline( $parser, $localTs, 'M', $source );
129
130 return $pageLang->formatNumNoSeparators( $localTs->format( 'n' ) );
131 case 'localmonthname':
132 $localTs = self::makeTsLocal( $svcOptions, $ts );
133 self::applyUnitTimestampDeadline( $parser, $localTs, 'M', $source );
134
135 return $pageLang->getMonthName( (int)$localTs->format( 'n' ) );
136 case 'localmonthnamegen':
137 $localTs = self::makeTsLocal( $svcOptions, $ts );
138 self::applyUnitTimestampDeadline( $parser, $localTs, 'M', $source );
139
140 return $pageLang->getMonthNameGen( (int)$localTs->format( 'n' ) );
141 case 'localmonthabbrev':
142 $localTs = self::makeTsLocal( $svcOptions, $ts );
143 self::applyUnitTimestampDeadline( $parser, $localTs, 'M', $source );
144
145 return $pageLang->getMonthAbbreviation( (int)$localTs->format( 'n' ) );
146 case 'localday':
147 $localTs = self::makeTsLocal( $svcOptions, $ts );
148 self::applyUnitTimestampDeadline( $parser, $localTs, 'D', $source );
149
150 return $pageLang->formatNumNoSeparators( $localTs->format( 'j' ) );
151 case 'localday2':
152 $localTs = self::makeTsLocal( $svcOptions, $ts );
153 self::applyUnitTimestampDeadline( $parser, $localTs, 'D', $source );
154
155 return $pageLang->formatNumNoSeparators( $localTs->format( 'd' ) );
156 case 'pagename':
157 case 'pagenamee':
158 case 'fullpagename':
159 case 'fullpagenamee':
160 case 'subpagename':
161 case 'subpagenamee':
162 case 'rootpagename':
163 case 'rootpagenamee':
164 case 'basepagename':
165 case 'basepagenamee':
166 case 'talkpagename':
167 case 'talkpagenamee':
168 case 'subjectpagename':
169 case 'subjectpagenamee':
170 case 'pageid':
171 case 'revisionid':
172 case 'revisionuser':
173 case 'revisionday':
174 case 'revisionday2':
175 case 'revisionmonth':
176 case 'revisionmonth1':
177 case 'revisionyear':
178 case 'revisiontimestamp':
179 case 'namespace':
180 case 'namespacee':
181 case 'namespacenumber':
182 case 'talkspace':
183 case 'talkspacee':
184 case 'subjectspace':
185 case 'subjectspacee':
186 case 'cascadingsources':
187 # First argument of the corresponding parser function
188 # (second argument of the PHP implementation) is
189 # "title".
190
191 # Note that for many of these {{FOO}} is subtly different
192 # from {{FOO:{{PAGENAME}}}}, so we can't pass $title here
193 # we have to explicitly use the "no arguments" form of the
194 # parser function by passing `null` to indicate a missing
195 # argument (which then defaults to the current page title).
196 return CoreParserFunctions::$id( $parser, null );
197 case 'revisionsize':
198 return (string)$parser->getRevisionSize();
199 case 'currentdayname':
200 self::applyUnitTimestampDeadline( $parser, $ts, 'D', $source );
201
202 return $pageLang->getWeekdayName( (int)$ts->format( 'w' ) + 1 );
203 case 'currentyear':
204 self::applyUnitTimestampDeadline( $parser, $ts, 'Y', $source );
205
206 return $pageLang->formatNumNoSeparators( $ts->format( 'Y' ) );
207 case 'currenttime':
208 return $pageLang->time( $ts->getTimestamp( TS::MW ), false, false );
209 case 'currenthour':
210 self::applyUnitTimestampDeadline( $parser, $ts, 'H', $source );
211
212 return $pageLang->formatNumNoSeparators( $ts->format( 'H' ) );
213 case 'currentweek':
214 self::applyUnitTimestampDeadline( $parser, $ts, 'D', $source );
215 // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
216 // int to remove the padding
217 return $pageLang->formatNum( (int)$ts->format( 'W' ) );
218 case 'currentdow':
219 self::applyUnitTimestampDeadline( $parser, $ts, 'D', $source );
220
221 return $pageLang->formatNum( $ts->format( 'w' ) );
222 case 'localdayname':
223 $localTs = self::makeTsLocal( $svcOptions, $ts );
224 self::applyUnitTimestampDeadline( $parser, $localTs, 'D', $source );
225
226 return $pageLang->getWeekdayName( (int)$localTs->format( 'w' ) + 1 );
227 case 'localyear':
228 $localTs = self::makeTsLocal( $svcOptions, $ts );
229 self::applyUnitTimestampDeadline( $parser, $localTs, 'Y', $source );
230
231 return $pageLang->formatNumNoSeparators( $localTs->format( 'Y' ) );
232 case 'localtime':
233 $localTs = self::makeTsLocal( $svcOptions, $ts );
234
235 return $pageLang->time(
236 $localTs->format( 'YmdHis' ),
237 false,
238 false
239 );
240 case 'localhour':
241 $localTs = self::makeTsLocal( $svcOptions, $ts );
242 self::applyUnitTimestampDeadline( $parser, $localTs, 'H', $source );
243
244 return $pageLang->formatNumNoSeparators( $localTs->format( 'H' ) );
245 case 'localweek':
246 $localTs = self::makeTsLocal( $svcOptions, $ts );
247 self::applyUnitTimestampDeadline( $parser, $localTs, 'D', $source );
248 // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
249 // int to remove the padding
250 return $pageLang->formatNum( (int)$localTs->format( 'W' ) );
251 case 'localdow':
252 $localTs = self::makeTsLocal( $svcOptions, $ts );
253 self::applyUnitTimestampDeadline( $parser, $localTs, 'D', $source );
254
255 return $pageLang->formatNum( $localTs->format( 'w' ) );
256 case 'numberofarticles':
257 case 'numberoffiles':
258 case 'numberofusers':
259 case 'numberofactiveusers':
260 case 'numberofpages':
261 case 'numberofadmins':
262 case 'numberofedits':
263 # second argument is 'raw'; magic variables are "not raw"
264 return CoreParserFunctions::$id( $parser, null );
265 case 'currenttimestamp':
266 return $ts->getTimestamp( TS::MW );
267 case 'localtimestamp':
268 $localTs = self::makeTsLocal( $svcOptions, $ts );
269
270 return $localTs->format( 'YmdHis' );
271 case 'currentversion':
272 return SpecialVersion::getVersion();
273 case 'articlepath':
274 return (string)$svcOptions->get( MainConfigNames::ArticlePath );
275 case 'sitename':
276 return (string)$svcOptions->get( MainConfigNames::Sitename );
277 case 'server':
278 return (string)$svcOptions->get( MainConfigNames::Server );
279 case 'servername':
280 return (string)$svcOptions->get( MainConfigNames::ServerName );
281 case 'scriptpath':
282 return (string)$svcOptions->get( MainConfigNames::ScriptPath );
283 case 'stylepath':
284 return (string)$svcOptions->get( MainConfigNames::StylePath );
285 case 'directionmark':
286 return $pageLang->getDirMark();
287 case 'contentlanguage':
288 return $parser->getContentLanguage()->getCode();
289 case 'pagelanguage':
290 return $pageLang->getCode();
291 case 'userlanguage':
292 if ( $parser->getOptions()->isMessage()
294 ) {
295 return $parser->getOptions()->getUserLang();
296 } else {
297 return $pageLang->getCode();
298 }
299 case 'bcp47':
300 case 'contentmodel':
301 case 'dir':
302 case 'language':
303 # magic variables are the same as empty/default first argument
304 return CoreParserFunctions::$id( $parser );
305 default:
306 // This is not one of the core magic variables
307 return null;
308 }
309 }
310
318 private static function makeTsLocal( $svcOptions, $ts ) {
319 $localtimezone = $svcOptions->get( MainConfigNames::Localtimezone );
320 $ts->setTimezone( $localtimezone );
321 return $ts;
322 }
323
333 public static function applyUnitTimestampDeadline(
334 Parser $parser,
335 ?ConvertibleTimestamp $ts,
336 string $unit,
337 ?string $source = null
338 ): void {
339 $date = $ts?->timestamp ?? $parser->getParseTime();
340 $ttl = Language::computeUnitTimestampDeadline( $date, $unit );
341 self::applyCacheExpiry( $parser, $ttl, $date->getTimestamp(), $source );
342 }
343
353 public static function applyCacheExpiry(
354 Parser $parser,
355 int $ttl,
356 ?int $stagger = null,
357 ?string $source = null
358 ): void {
359 $stagger ??= abs( $ttl ) ?: time();
360 $ttl = max( $ttl, self::MIN_DEADLINE_TTL );
361 $ttl += self::DEADLINE_TTL_CLOCK_FUDGE;
362 $ttl += ( $stagger % self::DEADLINE_TTL_STAGGER_MAX );
363 $parser->getOutput()->updateCacheExpiry( $ttl, $source );
364 }
365}
366
368class_alias( CoreMagicVariables::class, 'CoreMagicVariables' );
A class for passing options to services.
Base class for language-specific code.
Definition Language.php:65
A class containing constants representing the names of configuration variables.
const ServerName
Name constant for the ServerName setting, for use with Config::get()
const ParserEnableUserLanguage
Name constant for the ParserEnableUserLanguage setting, for use with Config::get()
const StylePath
Name constant for the StylePath setting, for use with Config::get()
const Localtimezone
Name constant for the Localtimezone setting, for use with Config::get()
const Server
Name constant for the Server setting, for use with Config::get()
const Sitename
Name constant for the Sitename setting, for use with Config::get()
const ArticlePath
Name constant for the ArticlePath setting, for use with Config::get()
const ScriptPath
Name constant for the ScriptPath setting, for use with Config::get()
Expansions of core magic variables, used by the parser.
static applyUnitTimestampDeadline(Parser $parser, ?ConvertibleTimestamp $ts, string $unit, ?string $source=null)
Adjust the cache expiry to account for a dynamic timestamp displayed in output.
static expand(Parser $parser, string $id, ConvertibleTimestamp $ts, ServiceOptions $svcOptions, LoggerInterface $logger, $frame=false)
Expand the magic variable given by $index.
static applyCacheExpiry(Parser $parser, int $ttl, ?int $stagger=null, ?string $source=null)
Apply the given $ttl to the cache expiry of the parser output, adjusting slightly to ensure a minimum...
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:139
getContentLanguage()
Get the content language that this Parser is using.
Definition Parser.php:1144
getRevisionSize()
Get the size of the revision.
Definition Parser.php:6204
Version information about MediaWiki (core, extensions, libs), PHP, and the database.
Library for creating and parsing MW-style timestamps.
$source