MediaWiki REL1_34
ApiQuerySiteinfo.php
Go to the documentation of this file.
1<?php
23
30
31 public function __construct( ApiQuery $query, $moduleName ) {
32 parent::__construct( $query, $moduleName, 'si' );
33 }
34
35 public function execute() {
36 $params = $this->extractRequestParams();
37 $done = [];
38 $fit = false;
39 foreach ( $params['prop'] as $p ) {
40 switch ( $p ) {
41 case 'general':
42 $fit = $this->appendGeneralInfo( $p );
43 break;
44 case 'namespaces':
45 $fit = $this->appendNamespaces( $p );
46 break;
47 case 'namespacealiases':
48 $fit = $this->appendNamespaceAliases( $p );
49 break;
50 case 'specialpagealiases':
51 $fit = $this->appendSpecialPageAliases( $p );
52 break;
53 case 'magicwords':
54 $fit = $this->appendMagicWords( $p );
55 break;
56 case 'interwikimap':
57 $fit = $this->appendInterwikiMap( $p, $params['filteriw'] );
58 break;
59 case 'dbrepllag':
60 $fit = $this->appendDbReplLagInfo( $p, $params['showalldb'] );
61 break;
62 case 'statistics':
63 $fit = $this->appendStatistics( $p );
64 break;
65 case 'usergroups':
66 $fit = $this->appendUserGroups( $p, $params['numberingroup'] );
67 break;
68 case 'libraries':
69 $fit = $this->appendInstalledLibraries( $p );
70 break;
71 case 'extensions':
72 $fit = $this->appendExtensions( $p );
73 break;
74 case 'fileextensions':
75 $fit = $this->appendFileExtensions( $p );
76 break;
77 case 'rightsinfo':
78 $fit = $this->appendRightsInfo( $p );
79 break;
80 case 'restrictions':
81 $fit = $this->appendRestrictions( $p );
82 break;
83 case 'languages':
84 $fit = $this->appendLanguages( $p );
85 break;
86 case 'languagevariants':
87 $fit = $this->appendLanguageVariants( $p );
88 break;
89 case 'skins':
90 $fit = $this->appendSkins( $p );
91 break;
92 case 'extensiontags':
93 $fit = $this->appendExtensionTags( $p );
94 break;
95 case 'functionhooks':
96 $fit = $this->appendFunctionHooks( $p );
97 break;
98 case 'showhooks':
99 $fit = $this->appendSubscribedHooks( $p );
100 break;
101 case 'variables':
102 $fit = $this->appendVariables( $p );
103 break;
104 case 'protocols':
105 $fit = $this->appendProtocols( $p );
106 break;
107 case 'defaultoptions':
108 $fit = $this->appendDefaultOptions( $p );
109 break;
110 case 'uploaddialog':
111 $fit = $this->appendUploadDialog( $p );
112 break;
113 default:
114 ApiBase::dieDebug( __METHOD__, "Unknown prop=$p" ); // @codeCoverageIgnore
115 }
116 if ( !$fit ) {
117 // Abuse siprop as a query-continue parameter
118 // and set it to all unprocessed props
119 $this->setContinueEnumParameter( 'prop', implode( '|',
120 array_diff( $params['prop'], $done ) ) );
121 break;
122 }
123 $done[] = $p;
124 }
125 }
126
127 protected function appendGeneralInfo( $property ) {
128 $config = $this->getConfig();
129
130 $data = [];
131 $mainPage = Title::newMainPage();
132 $data['mainpage'] = $mainPage->getPrefixedText();
133 $data['base'] = wfExpandUrl( $mainPage->getFullURL(), PROTO_CURRENT );
134 $data['sitename'] = $config->get( 'Sitename' );
135
136 // wgLogo can either be a relative or an absolute path
137 // make sure we always return an absolute path
138 $data['logo'] = wfExpandUrl( $config->get( 'Logo' ), PROTO_RELATIVE );
139
140 $data['generator'] = "MediaWiki {$config->get( 'Version' )}";
141
142 $data['phpversion'] = PHP_VERSION;
143 $data['phpsapi'] = PHP_SAPI;
144 if ( defined( 'HHVM_VERSION' ) ) {
145 $data['hhvmversion'] = HHVM_VERSION; // @codeCoverageIgnore
146 }
147 $data['dbtype'] = $config->get( 'DBtype' );
148 $data['dbversion'] = $this->getDB()->getServerVersion();
149
150 $allowFrom = [ '' ];
151 $allowException = true;
152 if ( !$config->get( 'AllowExternalImages' ) ) {
153 $data['imagewhitelistenabled'] = (bool)$config->get( 'EnableImageWhitelist' );
154 $allowFrom = $config->get( 'AllowExternalImagesFrom' );
155 $allowException = !empty( $allowFrom );
156 }
157 if ( $allowException ) {
158 $data['externalimages'] = (array)$allowFrom;
159 ApiResult::setIndexedTagName( $data['externalimages'], 'prefix' );
160 }
161
162 $data['langconversion'] = !$config->get( 'DisableLangConversion' );
163 $data['titleconversion'] = !$config->get( 'DisableTitleConversion' );
164
165 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
166 if ( $contLang->linkPrefixExtension() ) {
167 $linkPrefixCharset = $contLang->linkPrefixCharset();
168 $data['linkprefixcharset'] = $linkPrefixCharset;
169 // For backwards compatibility
170 $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
171 } else {
172 $data['linkprefixcharset'] = '';
173 $data['linkprefix'] = '';
174 }
175
176 $linktrail = $contLang->linkTrail();
177 $data['linktrail'] = $linktrail ?: '';
178
179 $data['legaltitlechars'] = Title::legalChars();
180 $data['invalidusernamechars'] = $config->get( 'InvalidUsernameCharacters' );
181
182 $data['allunicodefixes'] = (bool)$config->get( 'AllUnicodeFixes' );
183 $data['fixarabicunicode'] = (bool)$config->get( 'FixArabicUnicode' );
184 $data['fixmalayalamunicode'] = (bool)$config->get( 'FixMalayalamUnicode' );
185
186 global $IP;
188 if ( $git ) {
189 $data['git-hash'] = $git;
190 $data['git-branch'] =
192 }
193
194 // 'case-insensitive' option is reserved for future
195 $data['case'] = $config->get( 'CapitalLinks' ) ? 'first-letter' : 'case-sensitive';
196 $data['lang'] = $config->get( 'LanguageCode' );
197
198 $fallbacks = [];
199 foreach ( $contLang->getFallbackLanguages() as $code ) {
200 $fallbacks[] = [ 'code' => $code ];
201 }
202 $data['fallback'] = $fallbacks;
203 ApiResult::setIndexedTagName( $data['fallback'], 'lang' );
204
205 if ( $contLang->hasVariants() ) {
206 $variants = [];
207 foreach ( $contLang->getVariants() as $code ) {
208 $variants[] = [
209 'code' => $code,
210 'name' => $contLang->getVariantname( $code ),
211 ];
212 }
213 $data['variants'] = $variants;
214 ApiResult::setIndexedTagName( $data['variants'], 'lang' );
215 }
216
217 $data['rtl'] = $contLang->isRTL();
218 $data['fallback8bitEncoding'] = $contLang->fallback8bitEncoding();
219
220 $data['readonly'] = wfReadOnly();
221 if ( $data['readonly'] ) {
222 $data['readonlyreason'] = wfReadOnlyReason();
223 }
224 $data['writeapi'] = true; // Deprecated since MW 1.32
225
226 $data['maxarticlesize'] = $config->get( 'MaxArticleSize' ) * 1024;
227
228 $tz = $config->get( 'Localtimezone' );
229 $offset = $config->get( 'LocalTZoffset' );
230 $data['timezone'] = $tz;
231 $data['timeoffset'] = (int)$offset;
232 $data['articlepath'] = $config->get( 'ArticlePath' );
233 $data['scriptpath'] = $config->get( 'ScriptPath' );
234 $data['script'] = $config->get( 'Script' );
235 $data['variantarticlepath'] = $config->get( 'VariantArticlePath' );
236 $data[ApiResult::META_BC_BOOLS][] = 'variantarticlepath';
237 $data['server'] = $config->get( 'Server' );
238 $data['servername'] = $config->get( 'ServerName' );
239 $data['wikiid'] = WikiMap::getWikiIdFromDbDomain( WikiMap::getCurrentWikiDbDomain() );
240 $data['time'] = wfTimestamp( TS_ISO_8601, time() );
241
242 $data['misermode'] = (bool)$config->get( 'MiserMode' );
243
244 $data['uploadsenabled'] = UploadBase::isEnabled();
245 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
246 $data['minuploadchunksize'] = (int)$config->get( 'MinUploadChunkSize' );
247
248 $data['galleryoptions'] = $config->get( 'GalleryOptions' );
249
250 $data['thumblimits'] = $config->get( 'ThumbLimits' );
251 ApiResult::setArrayType( $data['thumblimits'], 'BCassoc' );
252 ApiResult::setIndexedTagName( $data['thumblimits'], 'limit' );
253 $data['imagelimits'] = [];
254 ApiResult::setArrayType( $data['imagelimits'], 'BCassoc' );
255 ApiResult::setIndexedTagName( $data['imagelimits'], 'limit' );
256 foreach ( $config->get( 'ImageLimits' ) as $k => $limit ) {
257 $data['imagelimits'][$k] = [ 'width' => $limit[0], 'height' => $limit[1] ];
258 }
259
260 $favicon = $config->get( 'Favicon' );
261 if ( !empty( $favicon ) ) {
262 // wgFavicon can either be a relative or an absolute path
263 // make sure we always return an absolute path
264 $data['favicon'] = wfExpandUrl( $favicon, PROTO_RELATIVE );
265 }
266
267 $data['centralidlookupprovider'] = $config->get( 'CentralIdLookupProvider' );
268 $providerIds = array_keys( $config->get( 'CentralIdLookupProviders' ) );
269 $data['allcentralidlookupproviders'] = $providerIds;
270
271 $data['interwikimagic'] = (bool)$config->get( 'InterwikiMagic' );
272 $data['magiclinks'] = $config->get( 'EnableMagicLinks' );
273
274 $data['categorycollation'] = $config->get( 'CategoryCollation' );
275
276 Hooks::run( 'APIQuerySiteInfoGeneralInfo', [ $this, &$data ] );
277
278 return $this->getResult()->addValue( 'query', $property, $data );
279 }
280
281 protected function appendNamespaces( $property ) {
282 $nsProtection = $this->getConfig()->get( 'NamespaceProtection' );
283
284 $data = [
285 ApiResult::META_TYPE => 'assoc',
286 ];
287 $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
288 foreach (
289 MediaWikiServices::getInstance()->getContentLanguage()->getFormattedNamespaces()
290 as $ns => $title
291 ) {
292 $data[$ns] = [
293 'id' => (int)$ns,
294 'case' => $nsInfo->isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
295 ];
296 ApiResult::setContentValue( $data[$ns], 'name', $title );
297 $canonical = $nsInfo->getCanonicalName( $ns );
298
299 $data[$ns]['subpages'] = $nsInfo->hasSubpages( $ns );
300
301 if ( $canonical ) {
302 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
303 }
304
305 $data[$ns]['content'] = $nsInfo->isContent( $ns );
306 $data[$ns]['nonincludable'] = $nsInfo->isNonincludable( $ns );
307
308 if ( isset( $nsProtection[$ns] ) ) {
309 if ( is_array( $nsProtection[$ns] ) ) {
310 $specificNs = implode( "|", array_filter( $nsProtection[$ns] ) );
311 } elseif ( $nsProtection[$ns] !== '' ) {
312 $specificNs = $nsProtection[$ns];
313 }
314 if ( isset( $specificNs ) && $specificNs !== '' ) {
315 $data[$ns]['namespaceprotection'] = $specificNs;
316 }
317 }
318
319 $contentmodel = $nsInfo->getNamespaceContentModel( $ns );
320 if ( $contentmodel ) {
321 $data[$ns]['defaultcontentmodel'] = $contentmodel;
322 }
323 }
324
325 ApiResult::setArrayType( $data, 'assoc' );
326 ApiResult::setIndexedTagName( $data, 'ns' );
327
328 return $this->getResult()->addValue( 'query', $property, $data );
329 }
330
331 protected function appendNamespaceAliases( $property ) {
332 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
333 $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ),
334 $contLang->getNamespaceAliases() );
335 $namespaces = $contLang->getNamespaces();
336 $data = [];
337 foreach ( $aliases as $title => $ns ) {
338 if ( $namespaces[$ns] == $title ) {
339 // Don't list duplicates
340 continue;
341 }
342 $item = [
343 'id' => (int)$ns
344 ];
345 ApiResult::setContentValue( $item, 'alias', strtr( $title, '_', ' ' ) );
346 $data[] = $item;
347 }
348
349 sort( $data );
350
351 ApiResult::setIndexedTagName( $data, 'ns' );
352
353 return $this->getResult()->addValue( 'query', $property, $data );
354 }
355
356 protected function appendSpecialPageAliases( $property ) {
357 $data = [];
358 $services = MediaWikiServices::getInstance();
359 $aliases = $services->getContentLanguage()->getSpecialPageAliases();
360 foreach ( $services->getSpecialPageFactory()->getNames() as $specialpage ) {
361 if ( isset( $aliases[$specialpage] ) ) {
362 $arr = [ 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] ];
363 ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
364 $data[] = $arr;
365 }
366 }
367 ApiResult::setIndexedTagName( $data, 'specialpage' );
368
369 return $this->getResult()->addValue( 'query', $property, $data );
370 }
371
372 protected function appendMagicWords( $property ) {
373 $data = [];
374 foreach (
375 MediaWikiServices::getInstance()->getContentLanguage()->getMagicWords()
376 as $magicword => $aliases
377 ) {
378 $caseSensitive = array_shift( $aliases );
379 $arr = [ 'name' => $magicword, 'aliases' => $aliases ];
380 $arr['case-sensitive'] = (bool)$caseSensitive;
381 ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
382 $data[] = $arr;
383 }
384 ApiResult::setIndexedTagName( $data, 'magicword' );
385
386 return $this->getResult()->addValue( 'query', $property, $data );
387 }
388
389 protected function appendInterwikiMap( $property, $filter ) {
390 if ( $filter === 'local' ) {
391 $local = 1;
392 } elseif ( $filter === '!local' ) {
393 $local = 0;
394 } else {
395 // $filter === null
396 $local = null;
397 }
398
399 $params = $this->extractRequestParams();
400 $langCode = $params['inlanguagecode'] ?? '';
401 $langNames = Language::fetchLanguageNames( $langCode );
402
403 $getPrefixes = MediaWikiServices::getInstance()->getInterwikiLookup()->getAllPrefixes( $local );
404 $extraLangPrefixes = $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' );
405 $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
406 $data = [];
407
408 foreach ( $getPrefixes as $row ) {
409 $prefix = $row['iw_prefix'];
410 $val = [];
411 $val['prefix'] = $prefix;
412 if ( isset( $row['iw_local'] ) && $row['iw_local'] == '1' ) {
413 $val['local'] = true;
414 }
415 if ( isset( $row['iw_trans'] ) && $row['iw_trans'] == '1' ) {
416 $val['trans'] = true;
417 }
418
419 if ( isset( $langNames[$prefix] ) ) {
420 $val['language'] = $langNames[$prefix];
421 }
422 if ( in_array( $prefix, $localInterwikis ) ) {
423 $val['localinterwiki'] = true;
424 }
425 if ( in_array( $prefix, $extraLangPrefixes ) ) {
426 $val['extralanglink'] = true;
427
428 $linktext = wfMessage( "interlanguage-link-$prefix" );
429 if ( !$linktext->isDisabled() ) {
430 $val['linktext'] = $linktext->text();
431 }
432
433 $sitename = wfMessage( "interlanguage-link-sitename-$prefix" );
434 if ( !$sitename->isDisabled() ) {
435 $val['sitename'] = $sitename->text();
436 }
437 }
438
439 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
440 $val['protorel'] = substr( $row['iw_url'], 0, 2 ) == '//';
441 if ( isset( $row['iw_wikiid'] ) && $row['iw_wikiid'] !== '' ) {
442 $val['wikiid'] = $row['iw_wikiid'];
443 }
444 if ( isset( $row['iw_api'] ) && $row['iw_api'] !== '' ) {
445 $val['api'] = $row['iw_api'];
446 }
447
448 $data[] = $val;
449 }
450
451 ApiResult::setIndexedTagName( $data, 'iw' );
452
453 return $this->getResult()->addValue( 'query', $property, $data );
454 }
455
456 protected function appendDbReplLagInfo( $property, $includeAll ) {
457 $data = [];
458 $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
459 $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
460 if ( $includeAll ) {
461 if ( !$showHostnames ) {
462 $this->dieWithError( 'apierror-siteinfo-includealldenied', 'includeAllDenied' );
463 }
464
465 $lags = $lb->getLagTimes();
466 foreach ( $lags as $i => $lag ) {
467 $data[] = [
468 'host' => $lb->getServerName( $i ),
469 'lag' => $lag
470 ];
471 }
472 } else {
473 list( , $lag, $index ) = $lb->getMaxLag();
474 $data[] = [
475 'host' => $showHostnames
476 ? $lb->getServerName( $index )
477 : '',
478 'lag' => $lag
479 ];
480 }
481
482 ApiResult::setIndexedTagName( $data, 'db' );
483
484 return $this->getResult()->addValue( 'query', $property, $data );
485 }
486
487 protected function appendStatistics( $property ) {
488 $data = [];
489 $data['pages'] = (int)SiteStats::pages();
490 $data['articles'] = (int)SiteStats::articles();
491 $data['edits'] = (int)SiteStats::edits();
492 $data['images'] = (int)SiteStats::images();
493 $data['users'] = (int)SiteStats::users();
494 $data['activeusers'] = (int)SiteStats::activeUsers();
495 $data['admins'] = (int)SiteStats::numberingroup( 'sysop' );
496 $data['jobs'] = (int)SiteStats::jobs();
497
498 Hooks::run( 'APIQuerySiteInfoStatisticsInfo', [ &$data ] );
499
500 return $this->getResult()->addValue( 'query', $property, $data );
501 }
502
503 protected function appendUserGroups( $property, $numberInGroup ) {
504 $config = $this->getConfig();
505
506 $data = [];
507 $result = $this->getResult();
508 $allGroups = array_values( User::getAllGroups() );
509 foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
510 $arr = [
511 'name' => $group,
512 'rights' => array_keys( $permissions, true ),
513 ];
514
515 if ( $numberInGroup ) {
516 $autopromote = $config->get( 'Autopromote' );
517
518 if ( $group == 'user' ) {
519 $arr['number'] = SiteStats::users();
520 // '*' and autopromote groups have no size
521 } elseif ( $group !== '*' && !isset( $autopromote[$group] ) ) {
522 $arr['number'] = SiteStats::numberingroup( $group );
523 }
524 }
525
526 $groupArr = [
527 'add' => $config->get( 'AddGroups' ),
528 'remove' => $config->get( 'RemoveGroups' ),
529 'add-self' => $config->get( 'GroupsAddToSelf' ),
530 'remove-self' => $config->get( 'GroupsRemoveFromSelf' )
531 ];
532
533 foreach ( $groupArr as $type => $rights ) {
534 if ( isset( $rights[$group] ) ) {
535 if ( $rights[$group] === true ) {
536 $groups = $allGroups;
537 } else {
538 $groups = array_intersect( $rights[$group], $allGroups );
539 }
540 if ( $groups ) {
541 $arr[$type] = $groups;
542 ApiResult::setArrayType( $arr[$type], 'BCarray' );
543 ApiResult::setIndexedTagName( $arr[$type], 'group' );
544 }
545 }
546 }
547
548 ApiResult::setIndexedTagName( $arr['rights'], 'permission' );
549 $data[] = $arr;
550 }
551
552 ApiResult::setIndexedTagName( $data, 'group' );
553
554 return $result->addValue( 'query', $property, $data );
555 }
556
557 protected function appendFileExtensions( $property ) {
558 $data = [];
559 foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
560 $data[] = [ 'ext' => $ext ];
561 }
562 ApiResult::setIndexedTagName( $data, 'fe' );
563
564 return $this->getResult()->addValue( 'query', $property, $data );
565 }
566
567 protected function appendInstalledLibraries( $property ) {
568 global $IP;
569 $path = "$IP/vendor/composer/installed.json";
570 if ( !file_exists( $path ) ) {
571 return true;
572 }
573
574 $data = [];
575 $installed = new ComposerInstalled( $path );
576 foreach ( $installed->getInstalledDependencies() as $name => $info ) {
577 if ( strpos( $info['type'], 'mediawiki-' ) === 0 ) {
578 // Skip any extensions or skins since they'll be listed
579 // in their proper section
580 continue;
581 }
582 $data[] = [
583 'name' => $name,
584 'version' => $info['version'],
585 ];
586 }
587 ApiResult::setIndexedTagName( $data, 'library' );
588
589 return $this->getResult()->addValue( 'query', $property, $data );
590 }
591
592 protected function appendExtensions( $property ) {
593 $data = [];
594 foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $type => $extensions ) {
595 foreach ( $extensions as $ext ) {
596 $ret = [];
597 $ret['type'] = $type;
598 if ( isset( $ext['name'] ) ) {
599 $ret['name'] = $ext['name'];
600 }
601 if ( isset( $ext['namemsg'] ) ) {
602 $ret['namemsg'] = $ext['namemsg'];
603 }
604 if ( isset( $ext['description'] ) ) {
605 $ret['description'] = $ext['description'];
606 }
607 if ( isset( $ext['descriptionmsg'] ) ) {
608 // Can be a string or [ key, param1, param2, ... ]
609 if ( is_array( $ext['descriptionmsg'] ) ) {
610 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
611 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
612 ApiResult::setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
613 } else {
614 $ret['descriptionmsg'] = $ext['descriptionmsg'];
615 }
616 }
617 if ( isset( $ext['author'] ) ) {
618 $ret['author'] = is_array( $ext['author'] ) ?
619 implode( ', ', $ext['author'] ) : $ext['author'];
620 }
621 if ( isset( $ext['url'] ) ) {
622 $ret['url'] = $ext['url'];
623 }
624 if ( isset( $ext['version'] ) ) {
625 $ret['version'] = $ext['version'];
626 }
627 if ( isset( $ext['path'] ) ) {
628 $extensionPath = dirname( $ext['path'] );
629 $gitInfo = new GitInfo( $extensionPath );
630 $vcsVersion = $gitInfo->getHeadSHA1();
631 if ( $vcsVersion !== false ) {
632 $ret['vcs-system'] = 'git';
633 $ret['vcs-version'] = $vcsVersion;
634 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
635 $vcsDate = $gitInfo->getHeadCommitDate();
636 if ( $vcsDate !== false ) {
637 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
638 }
639 }
640
641 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
642 $ret['license-name'] = $ext['license-name'] ?? '';
643 $ret['license'] = SpecialPage::getTitleFor(
644 'Version',
645 "License/{$ext['name']}"
646 )->getLinkURL();
647 }
648
649 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
650 $ret['credits'] = SpecialPage::getTitleFor(
651 'Version',
652 "Credits/{$ext['name']}"
653 )->getLinkURL();
654 }
655 }
656 $data[] = $ret;
657 }
658 }
659
660 ApiResult::setIndexedTagName( $data, 'ext' );
661
662 return $this->getResult()->addValue( 'query', $property, $data );
663 }
664
665 protected function appendRightsInfo( $property ) {
666 $config = $this->getConfig();
667 $rightsPage = $config->get( 'RightsPage' );
668 if ( is_string( $rightsPage ) ) {
669 $title = Title::newFromText( $rightsPage );
671 } else {
672 $title = false;
673 $url = $config->get( 'RightsUrl' );
674 }
675 $text = $config->get( 'RightsText' );
676 if ( $title && !strlen( $text ) ) {
677 $text = $title->getPrefixedText();
678 }
679
680 $data = [
681 'url' => (string)$url,
682 'text' => (string)$text,
683 ];
684
685 return $this->getResult()->addValue( 'query', $property, $data );
686 }
687
688 protected function appendRestrictions( $property ) {
689 $config = $this->getConfig();
690 $data = [
691 'types' => $config->get( 'RestrictionTypes' ),
692 'levels' => $config->get( 'RestrictionLevels' ),
693 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
694 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
695 ];
696
697 ApiResult::setArrayType( $data['types'], 'BCarray' );
698 ApiResult::setArrayType( $data['levels'], 'BCarray' );
699 ApiResult::setArrayType( $data['cascadinglevels'], 'BCarray' );
700 ApiResult::setArrayType( $data['semiprotectedlevels'], 'BCarray' );
701
702 ApiResult::setIndexedTagName( $data['types'], 'type' );
703 ApiResult::setIndexedTagName( $data['levels'], 'level' );
704 ApiResult::setIndexedTagName( $data['cascadinglevels'], 'level' );
705 ApiResult::setIndexedTagName( $data['semiprotectedlevels'], 'level' );
706
707 return $this->getResult()->addValue( 'query', $property, $data );
708 }
709
710 public function appendLanguages( $property ) {
711 $params = $this->extractRequestParams();
712 $langCode = $params['inlanguagecode'] ?? '';
713 $langNames = Language::fetchLanguageNames( $langCode );
714
715 $data = [];
716
717 foreach ( $langNames as $code => $name ) {
718 $lang = [
719 'code' => $code,
720 'bcp47' => LanguageCode::bcp47( $code ),
721 ];
722 ApiResult::setContentValue( $lang, 'name', $name );
723 $data[] = $lang;
724 }
725 ApiResult::setIndexedTagName( $data, 'lang' );
726
727 return $this->getResult()->addValue( 'query', $property, $data );
728 }
729
730 // Export information about which page languages will trigger
731 // language conversion. (T153341)
732 public function appendLanguageVariants( $property ) {
733 $langNames = LanguageConverter::$languagesWithVariants;
734 if ( $this->getConfig()->get( 'DisableLangConversion' ) ) {
735 // Ensure result is empty if language conversion is disabled.
736 $langNames = [];
737 }
738 sort( $langNames );
739
740 $data = [];
741 foreach ( $langNames as $langCode ) {
742 $lang = Language::factory( $langCode );
743 if ( $lang->getConverter() instanceof FakeConverter ) {
744 // Only languages which do not return instances of
745 // FakeConverter implement language conversion.
746 continue;
747 }
748 $data[$langCode] = [];
749 ApiResult::setIndexedTagName( $data[$langCode], 'variant' );
750 ApiResult::setArrayType( $data[$langCode], 'kvp', 'code' );
751
752 $variants = $lang->getVariants();
753 sort( $variants );
754 foreach ( $variants as $v ) {
755 $fallbacks = $lang->getConverter()->getVariantFallbacks( $v );
756 if ( !is_array( $fallbacks ) ) {
757 $fallbacks = [ $fallbacks ];
758 }
759 $data[$langCode][$v] = [
760 'fallbacks' => $fallbacks,
761 ];
763 $data[$langCode][$v]['fallbacks'], 'variant'
764 );
765 }
766 }
767 ApiResult::setIndexedTagName( $data, 'lang' );
768 ApiResult::setArrayType( $data, 'kvp', 'code' );
769
770 return $this->getResult()->addValue( 'query', $property, $data );
771 }
772
773 public function appendSkins( $property ) {
774 $data = [];
775 $allowed = Skin::getAllowedSkins();
776 $default = Skin::normalizeKey( 'default' );
777 foreach ( Skin::getSkinNames() as $name => $displayName ) {
778 $msg = $this->msg( "skinname-{$name}" );
779 $code = $this->getParameter( 'inlanguagecode' );
780 if ( $code && Language::isValidCode( $code ) ) {
781 $msg->inLanguage( $code );
782 } else {
783 $msg->inContentLanguage();
784 }
785 if ( $msg->exists() ) {
786 $displayName = $msg->text();
787 }
788 $skin = [ 'code' => $name ];
789 ApiResult::setContentValue( $skin, 'name', $displayName );
790 if ( !isset( $allowed[$name] ) ) {
791 $skin['unusable'] = true;
792 }
793 if ( $name === $default ) {
794 $skin['default'] = true;
795 }
796 $data[] = $skin;
797 }
798 ApiResult::setIndexedTagName( $data, 'skin' );
799
800 return $this->getResult()->addValue( 'query', $property, $data );
801 }
802
803 public function appendExtensionTags( $property ) {
804 $tags = array_map(
805 function ( $item ) {
806 return "<$item>";
807 },
808 MediaWikiServices::getInstance()->getParser()->getTags()
809 );
810 ApiResult::setArrayType( $tags, 'BCarray' );
811 ApiResult::setIndexedTagName( $tags, 't' );
812
813 return $this->getResult()->addValue( 'query', $property, $tags );
814 }
815
816 public function appendFunctionHooks( $property ) {
817 $hooks = MediaWikiServices::getInstance()->getParser()->getFunctionHooks();
818 ApiResult::setArrayType( $hooks, 'BCarray' );
819 ApiResult::setIndexedTagName( $hooks, 'h' );
820
821 return $this->getResult()->addValue( 'query', $property, $hooks );
822 }
823
824 public function appendVariables( $property ) {
825 $variables = MediaWikiServices::getInstance()->getMagicWordFactory()->getVariableIDs();
826 ApiResult::setArrayType( $variables, 'BCarray' );
827 ApiResult::setIndexedTagName( $variables, 'v' );
828
829 return $this->getResult()->addValue( 'query', $property, $variables );
830 }
831
832 public function appendProtocols( $property ) {
833 // Make a copy of the global so we don't try to set the _element key of it - T47130
834 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
835 ApiResult::setArrayType( $protocols, 'BCarray' );
836 ApiResult::setIndexedTagName( $protocols, 'p' );
837
838 return $this->getResult()->addValue( 'query', $property, $protocols );
839 }
840
841 public function appendDefaultOptions( $property ) {
844 return $this->getResult()->addValue( 'query', $property, $options );
845 }
846
847 public function appendUploadDialog( $property ) {
848 $config = $this->getConfig()->get( 'UploadDialog' );
849 return $this->getResult()->addValue( 'query', $property, $config );
850 }
851
852 public function appendSubscribedHooks( $property ) {
853 $hooks = $this->getConfig()->get( 'Hooks' );
854 $myWgHooks = $hooks;
855 ksort( $myWgHooks );
856
857 $data = [];
858 foreach ( $myWgHooks as $name => $subscribers ) {
859 $arr = [
860 'name' => $name,
861 'subscribers' => array_map( [ SpecialVersion::class, 'arrayToString' ], $subscribers ),
862 ];
863
864 ApiResult::setArrayType( $arr['subscribers'], 'array' );
865 ApiResult::setIndexedTagName( $arr['subscribers'], 's' );
866 $data[] = $arr;
867 }
868
869 ApiResult::setIndexedTagName( $data, 'hook' );
870
871 return $this->getResult()->addValue( 'query', $property, $data );
872 }
873
874 public function getCacheMode( $params ) {
875 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
876 if (
877 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
878 !is_null( $params['prop'] ) &&
879 in_array( 'interwikimap', $params['prop'] )
880 ) {
881 return 'anon-public-user-private';
882 }
883
884 return 'public';
885 }
886
887 public function getAllowedParams() {
888 return [
889 'prop' => [
890 ApiBase::PARAM_DFLT => 'general',
893 'general',
894 'namespaces',
895 'namespacealiases',
896 'specialpagealiases',
897 'magicwords',
898 'interwikimap',
899 'dbrepllag',
900 'statistics',
901 'usergroups',
902 'libraries',
903 'extensions',
904 'fileextensions',
905 'rightsinfo',
906 'restrictions',
907 'languages',
908 'languagevariants',
909 'skins',
910 'extensiontags',
911 'functionhooks',
912 'showhooks',
913 'variables',
914 'protocols',
915 'defaultoptions',
916 'uploaddialog',
917 ],
919 ],
920 'filteriw' => [
922 'local',
923 '!local',
924 ]
925 ],
926 'showalldb' => false,
927 'numberingroup' => false,
928 'inlanguagecode' => null,
929 ];
930 }
931
932 protected function getExamplesMessages() {
933 return [
934 'action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics'
935 => 'apihelp-query+siteinfo-example-simple',
936 'action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local'
937 => 'apihelp-query+siteinfo-example-interwiki',
938 'action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb='
939 => 'apihelp-query+siteinfo-example-replag',
940 ];
941 }
942
943 public function getHelpUrls() {
944 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Siteinfo';
945 }
946}
$GLOBALS['IP']
wfReadOnly()
Check whether the wiki is in read-only mode.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfReadOnlyReason()
Check if the site is in read-only mode and return the message if so.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
$linkPrefixCharset
$IP
Definition WebStart.php:41
getParameter( $paramName, $parseLimit=true)
Get a value for the given parameter.
Definition ApiBase.php:876
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition ApiBase.php:2014
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition ApiBase.php:2220
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
Definition ApiBase.php:94
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition ApiBase.php:55
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition ApiBase.php:164
getResult()
Get the result object.
Definition ApiBase.php:640
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:761
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition ApiBase.php:58
This is a base class for all Query modules.
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.
getDB()
Get the Query database connection (read-only)
A query action to return meta information about the wiki site.
appendLanguageVariants( $property)
appendLanguages( $property)
appendInterwikiMap( $property, $filter)
appendGeneralInfo( $property)
__construct(ApiQuery $query, $moduleName)
appendRightsInfo( $property)
getExamplesMessages()
Returns usage examples for this module.
appendInstalledLibraries( $property)
appendVariables( $property)
appendUserGroups( $property, $numberInGroup)
appendFileExtensions( $property)
appendNamespaces( $property)
appendDefaultOptions( $property)
appendMagicWords( $property)
getHelpUrls()
Return links to more detailed help pages about the module.
appendExtensions( $property)
getCacheMode( $params)
Get the cache mode for the data generated by this module.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
appendRestrictions( $property)
appendExtensionTags( $property)
appendUploadDialog( $property)
appendProtocols( $property)
appendStatistics( $property)
appendSpecialPageAliases( $property)
appendDbReplLagInfo( $property, $includeAll)
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
appendSubscribedHooks( $property)
appendFunctionHooks( $property)
appendNamespaceAliases( $property)
This is the main query class.
Definition ApiQuery.php:37
const META_TYPE
Key for the 'type' metadata item.
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
const META_BC_BOOLS
Key for the 'BC bools' metadata item.
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
static setContentValue(array &$arr, $name, $value, $flags=0)
Add an output value to the array by name and mark as META_CONTENT.
Reads an installed.json file and provides accessors to get what is installed.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
A fake language variant converter.
MediaWikiServices is the service locator for the application scope of MediaWiki.
static articles()
static jobs()
Total number of jobs in the job queue.
static images()
static edits()
Definition SiteStats.php:94
static users()
static pages()
static numberingroup( $group)
Find the number of users in a given user group.
static activeUsers()
static getGitHeadSha1( $dir)
static getExtLicenseFileName( $extDir)
Obtains the full path of an extensions copying or license file if one exists.
static getExtAuthorsFileName( $extDir)
Obtains the full path of an extensions authors or credits file if one exists.
static getGitCurrentBranch( $dir)
static isEnabled()
Returns true if uploads are enabled.
static getMaxUploadSize( $forType=null)
Get the MediaWiki maximum uploaded file size for given type of upload, based on $wgMaxUploadSize.
static getAllGroups()
Return the set of defined explicit groups.
Definition User.php:4914
static getDefaultOptions()
Combine the language default options with any site-specific options and add the default language vari...
Definition User.php:1692
const PROTO_CURRENT
Definition Defines.php:211
const PROTO_RELATIVE
Definition Defines.php:210
$filter
if(!is_readable( $file)) $ext
Definition router.php:48
if(!isset( $args[0])) $lang