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