Expose $wgMaxArticleSize in siteinfo query api
[mediawiki.git] / includes / api / ApiQuerySiteinfo.php
blob90ad584ca75c10569f2da535c793d0d218a0aa9d
1 <?php
2 /**
5 * Created on Sep 25, 2006
7 * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * http://www.gnu.org/copyleft/gpl.html
24 * @file
27 /**
28 * A query action to return meta information about the wiki site.
30 * @ingroup API
32 class ApiQuerySiteinfo extends ApiQueryBase {
34 public function __construct( ApiQuery $query, $moduleName ) {
35 parent::__construct( $query, $moduleName, 'si' );
38 public function execute() {
39 $params = $this->extractRequestParams();
40 $done = [];
41 $fit = false;
42 foreach ( $params['prop'] as $p ) {
43 switch ( $p ) {
44 case 'general':
45 $fit = $this->appendGeneralInfo( $p );
46 break;
47 case 'namespaces':
48 $fit = $this->appendNamespaces( $p );
49 break;
50 case 'namespacealiases':
51 $fit = $this->appendNamespaceAliases( $p );
52 break;
53 case 'specialpagealiases':
54 $fit = $this->appendSpecialPageAliases( $p );
55 break;
56 case 'magicwords':
57 $fit = $this->appendMagicWords( $p );
58 break;
59 case 'interwikimap':
60 $filteriw = isset( $params['filteriw'] ) ? $params['filteriw'] : false;
61 $fit = $this->appendInterwikiMap( $p, $filteriw );
62 break;
63 case 'dbrepllag':
64 $fit = $this->appendDbReplLagInfo( $p, $params['showalldb'] );
65 break;
66 case 'statistics':
67 $fit = $this->appendStatistics( $p );
68 break;
69 case 'usergroups':
70 $fit = $this->appendUserGroups( $p, $params['numberingroup'] );
71 break;
72 case 'libraries':
73 $fit = $this->appendInstalledLibraries( $p );
74 break;
75 case 'extensions':
76 $fit = $this->appendExtensions( $p );
77 break;
78 case 'fileextensions':
79 $fit = $this->appendFileExtensions( $p );
80 break;
81 case 'rightsinfo':
82 $fit = $this->appendRightsInfo( $p );
83 break;
84 case 'restrictions':
85 $fit = $this->appendRestrictions( $p );
86 break;
87 case 'languages':
88 $fit = $this->appendLanguages( $p );
89 break;
90 case 'skins':
91 $fit = $this->appendSkins( $p );
92 break;
93 case 'extensiontags':
94 $fit = $this->appendExtensionTags( $p );
95 break;
96 case 'functionhooks':
97 $fit = $this->appendFunctionHooks( $p );
98 break;
99 case 'showhooks':
100 $fit = $this->appendSubscribedHooks( $p );
101 break;
102 case 'variables':
103 $fit = $this->appendVariables( $p );
104 break;
105 case 'protocols':
106 $fit = $this->appendProtocols( $p );
107 break;
108 case 'defaultoptions':
109 $fit = $this->appendDefaultOptions( $p );
110 break;
111 case 'uploaddialog':
112 $fit = $this->appendUploadDialog( $p );
113 break;
114 default:
115 ApiBase::dieDebug( __METHOD__, "Unknown prop=$p" );
117 if ( !$fit ) {
118 // Abuse siprop as a query-continue parameter
119 // and set it to all unprocessed props
120 $this->setContinueEnumParameter( 'prop', implode( '|',
121 array_diff( $params['prop'], $done ) ) );
122 break;
124 $done[] = $p;
128 protected function appendGeneralInfo( $property ) {
129 global $wgContLang;
131 $config = $this->getConfig();
133 $data = [];
134 $mainPage = Title::newMainPage();
135 $data['mainpage'] = $mainPage->getPrefixedText();
136 $data['base'] = wfExpandUrl( $mainPage->getFullURL(), PROTO_CURRENT );
137 $data['sitename'] = $config->get( 'Sitename' );
139 // wgLogo can either be a relative or an absolute path
140 // make sure we always return an absolute path
141 $data['logo'] = wfExpandUrl( $config->get( 'Logo' ), PROTO_RELATIVE );
143 $data['generator'] = "MediaWiki {$config->get( 'Version' )}";
145 $data['phpversion'] = PHP_VERSION;
146 $data['phpsapi'] = PHP_SAPI;
147 if ( defined( 'HHVM_VERSION' ) ) {
148 $data['hhvmversion'] = HHVM_VERSION;
150 $data['dbtype'] = $config->get( 'DBtype' );
151 $data['dbversion'] = $this->getDB()->getServerVersion();
153 $allowFrom = [ '' ];
154 $allowException = true;
155 if ( !$config->get( 'AllowExternalImages' ) ) {
156 $data['imagewhitelistenabled'] = (bool)$config->get( 'EnableImageWhitelist' );
157 $allowFrom = $config->get( 'AllowExternalImagesFrom' );
158 $allowException = !empty( $allowFrom );
160 if ( $allowException ) {
161 $data['externalimages'] = (array)$allowFrom;
162 ApiResult::setIndexedTagName( $data['externalimages'], 'prefix' );
165 $data['langconversion'] = !$config->get( 'DisableLangConversion' );
166 $data['titleconversion'] = !$config->get( 'DisableTitleConversion' );
168 if ( $wgContLang->linkPrefixExtension() ) {
169 $linkPrefixCharset = $wgContLang->linkPrefixCharset();
170 $data['linkprefixcharset'] = $linkPrefixCharset;
171 // For backwards compatibility
172 $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
173 } else {
174 $data['linkprefixcharset'] = '';
175 $data['linkprefix'] = '';
178 $linktrail = $wgContLang->linkTrail();
179 $data['linktrail'] = $linktrail ?: '';
181 $data['legaltitlechars'] = Title::legalChars();
182 $data['invalidusernamechars'] = $config->get( 'InvalidUsernameCharacters' );
184 global $IP;
185 $git = SpecialVersion::getGitHeadSha1( $IP );
186 if ( $git ) {
187 $data['git-hash'] = $git;
188 $data['git-branch'] =
189 SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
192 // 'case-insensitive' option is reserved for future
193 $data['case'] = $config->get( 'CapitalLinks' ) ? 'first-letter' : 'case-sensitive';
194 $data['lang'] = $config->get( 'LanguageCode' );
196 $fallbacks = [];
197 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
198 $fallbacks[] = [ 'code' => $code ];
200 $data['fallback'] = $fallbacks;
201 ApiResult::setIndexedTagName( $data['fallback'], 'lang' );
203 if ( $wgContLang->hasVariants() ) {
204 $variants = [];
205 foreach ( $wgContLang->getVariants() as $code ) {
206 $variants[] = [
207 'code' => $code,
208 'name' => $wgContLang->getVariantname( $code ),
211 $data['variants'] = $variants;
212 ApiResult::setIndexedTagName( $data['variants'], 'lang' );
215 $data['rtl'] = $wgContLang->isRTL();
216 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
218 $data['readonly'] = wfReadOnly();
219 if ( $data['readonly'] ) {
220 $data['readonlyreason'] = wfReadOnlyReason();
222 $data['writeapi'] = (bool)$config->get( 'EnableWriteAPI' );
224 $data['maxarticlesize'] = $config->get( 'MaxArticleSize' ) * 1024;
226 $tz = $config->get( 'Localtimezone' );
227 $offset = $config->get( 'LocalTZoffset' );
228 if ( is_null( $tz ) ) {
229 $tz = 'UTC';
230 $offset = 0;
231 } elseif ( is_null( $offset ) ) {
232 $offset = 0;
234 $data['timezone'] = $tz;
235 $data['timeoffset'] = intval( $offset );
236 $data['articlepath'] = $config->get( 'ArticlePath' );
237 $data['scriptpath'] = $config->get( 'ScriptPath' );
238 $data['script'] = $config->get( 'Script' );
239 $data['variantarticlepath'] = $config->get( 'VariantArticlePath' );
240 $data[ApiResult::META_BC_BOOLS][] = 'variantarticlepath';
241 $data['server'] = $config->get( 'Server' );
242 $data['servername'] = $config->get( 'ServerName' );
243 $data['wikiid'] = wfWikiID();
244 $data['time'] = wfTimestamp( TS_ISO_8601, time() );
246 $data['misermode'] = (bool)$config->get( 'MiserMode' );
248 $data['uploadsenabled'] = UploadBase::isEnabled();
249 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
250 $data['minuploadchunksize'] = (int)$config->get( 'MinUploadChunkSize' );
252 $data['thumblimits'] = $config->get( 'ThumbLimits' );
253 ApiResult::setArrayType( $data['thumblimits'], 'BCassoc' );
254 ApiResult::setIndexedTagName( $data['thumblimits'], 'limit' );
255 $data['imagelimits'] = [];
256 ApiResult::setArrayType( $data['imagelimits'], 'BCassoc' );
257 ApiResult::setIndexedTagName( $data['imagelimits'], 'limit' );
258 foreach ( $config->get( 'ImageLimits' ) as $k => $limit ) {
259 $data['imagelimits'][$k] = [ 'width' => $limit[0], 'height' => $limit[1] ];
262 $favicon = $config->get( 'Favicon' );
263 if ( !empty( $favicon ) ) {
264 // wgFavicon can either be a relative or an absolute path
265 // make sure we always return an absolute path
266 $data['favicon'] = wfExpandUrl( $favicon, PROTO_RELATIVE );
269 $data['centralidlookupprovider'] = $config->get( 'CentralIdLookupProvider' );
270 $providerIds = array_keys( $config->get( 'CentralIdLookupProviders' ) );
271 $data['allcentralidlookupproviders'] = $providerIds;
273 $data['interwikimagic'] = (bool)$config->get( 'InterwikiMagic' );
275 Hooks::run( 'APIQuerySiteInfoGeneralInfo', [ $this, &$data ] );
277 return $this->getResult()->addValue( 'query', $property, $data );
280 protected function appendNamespaces( $property ) {
281 global $wgContLang;
282 $data = [
283 ApiResult::META_TYPE => 'assoc',
285 foreach ( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
286 $data[$ns] = [
287 'id' => intval( $ns ),
288 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
290 ApiResult::setContentValue( $data[$ns], 'name', $title );
291 $canonical = MWNamespace::getCanonicalName( $ns );
293 $data[$ns]['subpages'] = MWNamespace::hasSubpages( $ns );
295 if ( $canonical ) {
296 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
299 $data[$ns]['content'] = MWNamespace::isContent( $ns );
300 $data[$ns]['nonincludable'] = MWNamespace::isNonincludable( $ns );
302 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
303 if ( $contentmodel ) {
304 $data[$ns]['defaultcontentmodel'] = $contentmodel;
308 ApiResult::setArrayType( $data, 'assoc' );
309 ApiResult::setIndexedTagName( $data, 'ns' );
311 return $this->getResult()->addValue( 'query', $property, $data );
314 protected function appendNamespaceAliases( $property ) {
315 global $wgContLang;
316 $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ),
317 $wgContLang->getNamespaceAliases() );
318 $namespaces = $wgContLang->getNamespaces();
319 $data = [];
320 foreach ( $aliases as $title => $ns ) {
321 if ( $namespaces[$ns] == $title ) {
322 // Don't list duplicates
323 continue;
325 $item = [
326 'id' => intval( $ns )
328 ApiResult::setContentValue( $item, 'alias', strtr( $title, '_', ' ' ) );
329 $data[] = $item;
332 sort( $data );
334 ApiResult::setIndexedTagName( $data, 'ns' );
336 return $this->getResult()->addValue( 'query', $property, $data );
339 protected function appendSpecialPageAliases( $property ) {
340 global $wgContLang;
341 $data = [];
342 $aliases = $wgContLang->getSpecialPageAliases();
343 foreach ( SpecialPageFactory::getNames() as $specialpage ) {
344 if ( isset( $aliases[$specialpage] ) ) {
345 $arr = [ 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] ];
346 ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
347 $data[] = $arr;
350 ApiResult::setIndexedTagName( $data, 'specialpage' );
352 return $this->getResult()->addValue( 'query', $property, $data );
355 protected function appendMagicWords( $property ) {
356 global $wgContLang;
357 $data = [];
358 foreach ( $wgContLang->getMagicWords() as $magicword => $aliases ) {
359 $caseSensitive = array_shift( $aliases );
360 $arr = [ 'name' => $magicword, 'aliases' => $aliases ];
361 $arr['case-sensitive'] = (bool)$caseSensitive;
362 ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
363 $data[] = $arr;
365 ApiResult::setIndexedTagName( $data, 'magicword' );
367 return $this->getResult()->addValue( 'query', $property, $data );
370 protected function appendInterwikiMap( $property, $filter ) {
371 $local = null;
372 if ( $filter === 'local' ) {
373 $local = 1;
374 } elseif ( $filter === '!local' ) {
375 $local = 0;
376 } elseif ( $filter ) {
377 ApiBase::dieDebug( __METHOD__, "Unknown filter=$filter" );
380 $params = $this->extractRequestParams();
381 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
382 $langNames = Language::fetchLanguageNames( $langCode );
384 $getPrefixes = Interwiki::getAllPrefixes( $local );
385 $extraLangPrefixes = $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' );
386 $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
387 $data = [];
389 foreach ( $getPrefixes as $row ) {
390 $prefix = $row['iw_prefix'];
391 $val = [];
392 $val['prefix'] = $prefix;
393 if ( isset( $row['iw_local'] ) && $row['iw_local'] == '1' ) {
394 $val['local'] = true;
396 if ( isset( $row['iw_trans'] ) && $row['iw_trans'] == '1' ) {
397 $val['trans'] = true;
400 if ( isset( $langNames[$prefix] ) ) {
401 $val['language'] = $langNames[$prefix];
403 if ( in_array( $prefix, $localInterwikis ) ) {
404 $val['localinterwiki'] = true;
406 if ( in_array( $prefix, $extraLangPrefixes ) ) {
407 $val['extralanglink'] = true;
409 $linktext = wfMessage( "interlanguage-link-$prefix" );
410 if ( !$linktext->isDisabled() ) {
411 $val['linktext'] = $linktext->text();
414 $sitename = wfMessage( "interlanguage-link-sitename-$prefix" );
415 if ( !$sitename->isDisabled() ) {
416 $val['sitename'] = $sitename->text();
420 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
421 $val['protorel'] = substr( $row['iw_url'], 0, 2 ) == '//';
422 if ( isset( $row['iw_wikiid'] ) && $row['iw_wikiid'] !== '' ) {
423 $val['wikiid'] = $row['iw_wikiid'];
425 if ( isset( $row['iw_api'] ) && $row['iw_api'] !== '' ) {
426 $val['api'] = $row['iw_api'];
429 $data[] = $val;
432 ApiResult::setIndexedTagName( $data, 'iw' );
434 return $this->getResult()->addValue( 'query', $property, $data );
437 protected function appendDbReplLagInfo( $property, $includeAll ) {
438 $data = [];
439 $lb = wfGetLB();
440 $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
441 if ( $includeAll ) {
442 if ( !$showHostnames ) {
443 $this->dieUsage(
444 'Cannot view all servers info unless $wgShowHostnames is true',
445 'includeAllDenied'
449 $lags = $lb->getLagTimes();
450 foreach ( $lags as $i => $lag ) {
451 $data[] = [
452 'host' => $lb->getServerName( $i ),
453 'lag' => $lag
456 } else {
457 list( , $lag, $index ) = $lb->getMaxLag();
458 $data[] = [
459 'host' => $showHostnames
460 ? $lb->getServerName( $index )
461 : '',
462 'lag' => intval( $lag )
466 ApiResult::setIndexedTagName( $data, 'db' );
468 return $this->getResult()->addValue( 'query', $property, $data );
471 protected function appendStatistics( $property ) {
472 $data = [];
473 $data['pages'] = intval( SiteStats::pages() );
474 $data['articles'] = intval( SiteStats::articles() );
475 $data['edits'] = intval( SiteStats::edits() );
476 $data['images'] = intval( SiteStats::images() );
477 $data['users'] = intval( SiteStats::users() );
478 $data['activeusers'] = intval( SiteStats::activeUsers() );
479 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
480 $data['jobs'] = intval( SiteStats::jobs() );
482 Hooks::run( 'APIQuerySiteInfoStatisticsInfo', [ &$data ] );
484 return $this->getResult()->addValue( 'query', $property, $data );
487 protected function appendUserGroups( $property, $numberInGroup ) {
488 $config = $this->getConfig();
490 $data = [];
491 $result = $this->getResult();
492 $allGroups = array_values( User::getAllGroups() );
493 foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
494 $arr = [
495 'name' => $group,
496 'rights' => array_keys( $permissions, true ),
499 if ( $numberInGroup ) {
500 $autopromote = $config->get( 'Autopromote' );
502 if ( $group == 'user' ) {
503 $arr['number'] = SiteStats::users();
504 // '*' and autopromote groups have no size
505 } elseif ( $group !== '*' && !isset( $autopromote[$group] ) ) {
506 $arr['number'] = SiteStats::numberingroup( $group );
510 $groupArr = [
511 'add' => $config->get( 'AddGroups' ),
512 'remove' => $config->get( 'RemoveGroups' ),
513 'add-self' => $config->get( 'GroupsAddToSelf' ),
514 'remove-self' => $config->get( 'GroupsRemoveFromSelf' )
517 foreach ( $groupArr as $type => $rights ) {
518 if ( isset( $rights[$group] ) ) {
519 if ( $rights[$group] === true ) {
520 $groups = $allGroups;
521 } else {
522 $groups = array_intersect( $rights[$group], $allGroups );
524 if ( $groups ) {
525 $arr[$type] = $groups;
526 ApiResult::setArrayType( $arr[$type], 'BCarray' );
527 ApiResult::setIndexedTagName( $arr[$type], 'group' );
532 ApiResult::setIndexedTagName( $arr['rights'], 'permission' );
533 $data[] = $arr;
536 ApiResult::setIndexedTagName( $data, 'group' );
538 return $result->addValue( 'query', $property, $data );
541 protected function appendFileExtensions( $property ) {
542 $data = [];
543 foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
544 $data[] = [ 'ext' => $ext ];
546 ApiResult::setIndexedTagName( $data, 'fe' );
548 return $this->getResult()->addValue( 'query', $property, $data );
551 protected function appendInstalledLibraries( $property ) {
552 global $IP;
553 $path = "$IP/vendor/composer/installed.json";
554 if ( !file_exists( $path ) ) {
555 return true;
558 $data = [];
559 $installed = new ComposerInstalled( $path );
560 foreach ( $installed->getInstalledDependencies() as $name => $info ) {
561 if ( strpos( $info['type'], 'mediawiki-' ) === 0 ) {
562 // Skip any extensions or skins since they'll be listed
563 // in their proper section
564 continue;
566 $data[] = [
567 'name' => $name,
568 'version' => $info['version'],
571 ApiResult::setIndexedTagName( $data, 'library' );
573 return $this->getResult()->addValue( 'query', $property, $data );
577 protected function appendExtensions( $property ) {
578 $data = [];
579 foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $type => $extensions ) {
580 foreach ( $extensions as $ext ) {
581 $ret = [];
582 $ret['type'] = $type;
583 if ( isset( $ext['name'] ) ) {
584 $ret['name'] = $ext['name'];
586 if ( isset( $ext['namemsg'] ) ) {
587 $ret['namemsg'] = $ext['namemsg'];
589 if ( isset( $ext['description'] ) ) {
590 $ret['description'] = $ext['description'];
592 if ( isset( $ext['descriptionmsg'] ) ) {
593 // Can be a string or array( key, param1, param2, ... )
594 if ( is_array( $ext['descriptionmsg'] ) ) {
595 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
596 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
597 ApiResult::setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
598 } else {
599 $ret['descriptionmsg'] = $ext['descriptionmsg'];
602 if ( isset( $ext['author'] ) ) {
603 $ret['author'] = is_array( $ext['author'] ) ?
604 implode( ', ', $ext['author'] ) : $ext['author'];
606 if ( isset( $ext['url'] ) ) {
607 $ret['url'] = $ext['url'];
609 if ( isset( $ext['version'] ) ) {
610 $ret['version'] = $ext['version'];
612 if ( isset( $ext['path'] ) ) {
613 $extensionPath = dirname( $ext['path'] );
614 $gitInfo = new GitInfo( $extensionPath );
615 $vcsVersion = $gitInfo->getHeadSHA1();
616 if ( $vcsVersion !== false ) {
617 $ret['vcs-system'] = 'git';
618 $ret['vcs-version'] = $vcsVersion;
619 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
620 $vcsDate = $gitInfo->getHeadCommitDate();
621 if ( $vcsDate !== false ) {
622 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
626 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
627 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
628 $ret['license'] = SpecialPage::getTitleFor(
629 'Version',
630 "License/{$ext['name']}"
631 )->getLinkURL();
634 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
635 $ret['credits'] = SpecialPage::getTitleFor(
636 'Version',
637 "Credits/{$ext['name']}"
638 )->getLinkURL();
641 $data[] = $ret;
645 ApiResult::setIndexedTagName( $data, 'ext' );
647 return $this->getResult()->addValue( 'query', $property, $data );
650 protected function appendRightsInfo( $property ) {
651 $config = $this->getConfig();
652 $rightsPage = $config->get( 'RightsPage' );
653 if ( is_string( $rightsPage ) ) {
654 $title = Title::newFromText( $rightsPage );
655 $url = wfExpandUrl( $title, PROTO_CURRENT );
656 } else {
657 $title = false;
658 $url = $config->get( 'RightsUrl' );
660 $text = $config->get( 'RightsText' );
661 if ( !$text && $title ) {
662 $text = $title->getPrefixedText();
665 $data = [
666 'url' => $url ?: '',
667 'text' => $text ?: ''
670 return $this->getResult()->addValue( 'query', $property, $data );
673 protected function appendRestrictions( $property ) {
674 $config = $this->getConfig();
675 $data = [
676 'types' => $config->get( 'RestrictionTypes' ),
677 'levels' => $config->get( 'RestrictionLevels' ),
678 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
679 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
682 ApiResult::setArrayType( $data['types'], 'BCarray' );
683 ApiResult::setArrayType( $data['levels'], 'BCarray' );
684 ApiResult::setArrayType( $data['cascadinglevels'], 'BCarray' );
685 ApiResult::setArrayType( $data['semiprotectedlevels'], 'BCarray' );
687 ApiResult::setIndexedTagName( $data['types'], 'type' );
688 ApiResult::setIndexedTagName( $data['levels'], 'level' );
689 ApiResult::setIndexedTagName( $data['cascadinglevels'], 'level' );
690 ApiResult::setIndexedTagName( $data['semiprotectedlevels'], 'level' );
692 return $this->getResult()->addValue( 'query', $property, $data );
695 public function appendLanguages( $property ) {
696 $params = $this->extractRequestParams();
697 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
698 $langNames = Language::fetchLanguageNames( $langCode );
700 $data = [];
702 foreach ( $langNames as $code => $name ) {
703 $lang = [ 'code' => $code ];
704 ApiResult::setContentValue( $lang, 'name', $name );
705 $data[] = $lang;
707 ApiResult::setIndexedTagName( $data, 'lang' );
709 return $this->getResult()->addValue( 'query', $property, $data );
712 public function appendSkins( $property ) {
713 $data = [];
714 $allowed = Skin::getAllowedSkins();
715 $default = Skin::normalizeKey( 'default' );
716 foreach ( Skin::getSkinNames() as $name => $displayName ) {
717 $msg = $this->msg( "skinname-{$name}" );
718 $code = $this->getParameter( 'inlanguagecode' );
719 if ( $code && Language::isValidCode( $code ) ) {
720 $msg->inLanguage( $code );
721 } else {
722 $msg->inContentLanguage();
724 if ( $msg->exists() ) {
725 $displayName = $msg->text();
727 $skin = [ 'code' => $name ];
728 ApiResult::setContentValue( $skin, 'name', $displayName );
729 if ( !isset( $allowed[$name] ) ) {
730 $skin['unusable'] = true;
732 if ( $name === $default ) {
733 $skin['default'] = true;
735 $data[] = $skin;
737 ApiResult::setIndexedTagName( $data, 'skin' );
739 return $this->getResult()->addValue( 'query', $property, $data );
742 public function appendExtensionTags( $property ) {
743 global $wgParser;
744 $wgParser->firstCallInit();
745 $tags = array_map( [ $this, 'formatParserTags' ], $wgParser->getTags() );
746 ApiResult::setArrayType( $tags, 'BCarray' );
747 ApiResult::setIndexedTagName( $tags, 't' );
749 return $this->getResult()->addValue( 'query', $property, $tags );
752 public function appendFunctionHooks( $property ) {
753 global $wgParser;
754 $wgParser->firstCallInit();
755 $hooks = $wgParser->getFunctionHooks();
756 ApiResult::setArrayType( $hooks, 'BCarray' );
757 ApiResult::setIndexedTagName( $hooks, 'h' );
759 return $this->getResult()->addValue( 'query', $property, $hooks );
762 public function appendVariables( $property ) {
763 $variables = MagicWord::getVariableIDs();
764 ApiResult::setArrayType( $variables, 'BCarray' );
765 ApiResult::setIndexedTagName( $variables, 'v' );
767 return $this->getResult()->addValue( 'query', $property, $variables );
770 public function appendProtocols( $property ) {
771 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
772 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
773 ApiResult::setArrayType( $protocols, 'BCarray' );
774 ApiResult::setIndexedTagName( $protocols, 'p' );
776 return $this->getResult()->addValue( 'query', $property, $protocols );
779 public function appendDefaultOptions( $property ) {
780 $options = User::getDefaultOptions();
781 $options[ApiResult::META_BC_BOOLS] = array_keys( $options );
782 return $this->getResult()->addValue( 'query', $property, $options );
785 public function appendUploadDialog( $property ) {
786 $config = $this->getConfig()->get( 'UploadDialog' );
787 return $this->getResult()->addValue( 'query', $property, $config );
790 private function formatParserTags( $item ) {
791 return "<{$item}>";
794 public function appendSubscribedHooks( $property ) {
795 $hooks = $this->getConfig()->get( 'Hooks' );
796 $myWgHooks = $hooks;
797 ksort( $myWgHooks );
799 $data = [];
800 foreach ( $myWgHooks as $name => $subscribers ) {
801 $arr = [
802 'name' => $name,
803 'subscribers' => array_map( [ 'SpecialVersion', 'arrayToString' ], $subscribers ),
806 ApiResult::setArrayType( $arr['subscribers'], 'array' );
807 ApiResult::setIndexedTagName( $arr['subscribers'], 's' );
808 $data[] = $arr;
811 ApiResult::setIndexedTagName( $data, 'hook' );
813 return $this->getResult()->addValue( 'query', $property, $data );
816 public function getCacheMode( $params ) {
817 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
818 if (
819 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
820 !is_null( $params['prop'] ) &&
821 in_array( 'interwikimap', $params['prop'] )
823 return 'anon-public-user-private';
826 return 'public';
829 public function getAllowedParams() {
830 return [
831 'prop' => [
832 ApiBase::PARAM_DFLT => 'general',
833 ApiBase::PARAM_ISMULTI => true,
834 ApiBase::PARAM_TYPE => [
835 'general',
836 'namespaces',
837 'namespacealiases',
838 'specialpagealiases',
839 'magicwords',
840 'interwikimap',
841 'dbrepllag',
842 'statistics',
843 'usergroups',
844 'libraries',
845 'extensions',
846 'fileextensions',
847 'rightsinfo',
848 'restrictions',
849 'languages',
850 'skins',
851 'extensiontags',
852 'functionhooks',
853 'showhooks',
854 'variables',
855 'protocols',
856 'defaultoptions',
857 'uploaddialog',
859 ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
861 'filteriw' => [
862 ApiBase::PARAM_TYPE => [
863 'local',
864 '!local',
867 'showalldb' => false,
868 'numberingroup' => false,
869 'inlanguagecode' => null,
873 protected function getExamplesMessages() {
874 return [
875 'action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics'
876 => 'apihelp-query+siteinfo-example-simple',
877 'action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local'
878 => 'apihelp-query+siteinfo-example-interwiki',
879 'action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb='
880 => 'apihelp-query+siteinfo-example-replag',
884 public function getHelpUrls() {
885 return 'https://www.mediawiki.org/wiki/API:Siteinfo';