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