Merge "SpecialChangeEmail: Remove cancel button"
[mediawiki.git] / includes / api / ApiQuerySiteinfo.php
blob311438fd0ee5f6dec29b934597ecd0193eb61de2
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 = array();
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 'extensions':
73 $fit = $this->appendExtensions( $p );
74 break;
75 case 'fileextensions':
76 $fit = $this->appendFileExtensions( $p );
77 break;
78 case 'rightsinfo':
79 $fit = $this->appendRightsInfo( $p );
80 break;
81 case 'restrictions':
82 $fit = $this->appendRestrictions( $p );
83 break;
84 case 'languages':
85 $fit = $this->appendLanguages( $p );
86 break;
87 case 'skins':
88 $fit = $this->appendSkins( $p );
89 break;
90 case 'extensiontags':
91 $fit = $this->appendExtensionTags( $p );
92 break;
93 case 'functionhooks':
94 $fit = $this->appendFunctionHooks( $p );
95 break;
96 case 'showhooks':
97 $fit = $this->appendSubscribedHooks( $p );
98 break;
99 case 'variables':
100 $fit = $this->appendVariables( $p );
101 break;
102 case 'protocols':
103 $fit = $this->appendProtocols( $p );
104 break;
105 case 'defaultoptions':
106 $fit = $this->appendDefaultOptions( $p );
107 break;
108 default:
109 ApiBase::dieDebug( __METHOD__, "Unknown prop=$p" );
111 if ( !$fit ) {
112 // Abuse siprop as a query-continue parameter
113 // and set it to all unprocessed props
114 $this->setContinueEnumParameter( 'prop', implode( '|',
115 array_diff( $params['prop'], $done ) ) );
116 break;
118 $done[] = $p;
122 protected function appendGeneralInfo( $property ) {
123 global $wgContLang;
125 $config = $this->getConfig();
127 $data = array();
128 $mainPage = Title::newMainPage();
129 $data['mainpage'] = $mainPage->getPrefixedText();
130 $data['base'] = wfExpandUrl( $mainPage->getFullURL(), PROTO_CURRENT );
131 $data['sitename'] = $config->get( 'Sitename' );
133 // wgLogo can either be a relative or an absolute path
134 // make sure we always return an absolute path
135 $data['logo'] = wfExpandUrl( $config->get( 'Logo' ), PROTO_RELATIVE );
137 $data['generator'] = "MediaWiki {$config->get( 'Version' )}";
139 $data['phpversion'] = PHP_VERSION;
140 $data['phpsapi'] = PHP_SAPI;
141 if ( defined( 'HHVM_VERSION' ) ) {
142 $data['hhvmversion'] = HHVM_VERSION;
144 $data['dbtype'] = $config->get( 'DBtype' );
145 $data['dbversion'] = $this->getDB()->getServerVersion();
147 $allowFrom = array( '' );
148 $allowException = true;
149 if ( !$config->get( 'AllowExternalImages' ) ) {
150 if ( $config->get( 'EnableImageWhitelist' ) ) {
151 $data['imagewhitelistenabled'] = '';
153 $allowFrom = $config->get( 'AllowExternalImagesFrom' );
154 $allowException = !empty( $allowFrom );
156 if ( $allowException ) {
157 $data['externalimages'] = (array)$allowFrom;
158 $this->getResult()->setIndexedTagName( $data['externalimages'], 'prefix' );
161 if ( !$config->get( 'DisableLangConversion' ) ) {
162 $data['langconversion'] = '';
165 if ( !$config->get( 'DisableTitleConversion' ) ) {
166 $data['titleconversion'] = '';
169 if ( $wgContLang->linkPrefixExtension() ) {
170 $linkPrefixCharset = $wgContLang->linkPrefixCharset();
171 $data['linkprefixcharset'] = $linkPrefixCharset;
172 // For backwards compatibility
173 $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
174 } else {
175 $data['linkprefixcharset'] = '';
176 $data['linkprefix'] = '';
179 $linktrail = $wgContLang->linkTrail();
180 if ( $linktrail ) {
181 $data['linktrail'] = $linktrail;
182 } else {
183 $data['linktrail'] = '';
186 global $IP;
187 $git = SpecialVersion::getGitHeadSha1( $IP );
188 if ( $git ) {
189 $data['git-hash'] = $git;
190 $data['git-branch'] =
191 SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
192 } else {
193 $svn = SpecialVersion::getSvnRevision( $IP );
194 if ( $svn ) {
195 $data['rev'] = $svn;
199 // 'case-insensitive' option is reserved for future
200 $data['case'] = $config->get( 'CapitalLinks' ) ? 'first-letter' : 'case-sensitive';
201 $data['lang'] = $config->get( 'LanguageCode' );
203 $fallbacks = array();
204 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
205 $fallbacks[] = array( 'code' => $code );
207 $data['fallback'] = $fallbacks;
208 $this->getResult()->setIndexedTagName( $data['fallback'], 'lang' );
210 if ( $wgContLang->hasVariants() ) {
211 $variants = array();
212 foreach ( $wgContLang->getVariants() as $code ) {
213 $variants[] = array(
214 'code' => $code,
215 'name' => $wgContLang->getVariantname( $code ),
218 $data['variants'] = $variants;
219 $this->getResult()->setIndexedTagName( $data['variants'], 'lang' );
222 if ( $wgContLang->isRTL() ) {
223 $data['rtl'] = '';
225 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
227 if ( wfReadOnly() ) {
228 $data['readonly'] = '';
229 $data['readonlyreason'] = wfReadOnlyReason();
231 if ( $config->get( 'EnableWriteAPI' ) ) {
232 $data['writeapi'] = '';
235 $tz = $config->get( 'Localtimezone' );
236 $offset = $config->get( 'LocalTZoffset' );
237 if ( is_null( $tz ) ) {
238 $tz = 'UTC';
239 $offset = 0;
240 } elseif ( is_null( $offset ) ) {
241 $offset = 0;
243 $data['timezone'] = $tz;
244 $data['timeoffset'] = intval( $offset );
245 $data['articlepath'] = $config->get( 'ArticlePath' );
246 $data['scriptpath'] = $config->get( 'ScriptPath' );
247 $data['script'] = $config->get( 'Script' );
248 $data['variantarticlepath'] = $config->get( 'VariantArticlePath' );
249 $data['server'] = $config->get( 'Server' );
250 $data['servername'] = $config->get( 'ServerName' );
251 $data['wikiid'] = wfWikiID();
252 $data['time'] = wfTimestamp( TS_ISO_8601, time() );
254 if ( $config->get( 'MiserMode' ) ) {
255 $data['misermode'] = '';
258 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
260 $data['thumblimits'] = $config->get( 'ThumbLimits' );
261 $this->getResult()->setIndexedTagName( $data['thumblimits'], 'limit' );
262 $data['imagelimits'] = array();
263 $this->getResult()->setIndexedTagName( $data['imagelimits'], 'limit' );
264 foreach ( $config->get( 'ImageLimits' ) as $k => $limit ) {
265 $data['imagelimits'][$k] = array( 'width' => $limit[0], 'height' => $limit[1] );
268 $favicon = $config->get( 'Favicon' );
269 if ( !empty( $favicon ) ) {
270 // wgFavicon can either be a relative or an absolute path
271 // make sure we always return an absolute path
272 $data['favicon'] = wfExpandUrl( $favicon, PROTO_RELATIVE );
275 wfRunHooks( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
277 return $this->getResult()->addValue( 'query', $property, $data );
280 protected function appendNamespaces( $property ) {
281 global $wgContLang;
282 $data = array();
283 foreach ( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
284 $data[$ns] = array(
285 'id' => intval( $ns ),
286 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
288 ApiResult::setContent( $data[$ns], $title );
289 $canonical = MWNamespace::getCanonicalName( $ns );
291 if ( MWNamespace::hasSubpages( $ns ) ) {
292 $data[$ns]['subpages'] = '';
295 if ( $canonical ) {
296 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
299 if ( MWNamespace::isContent( $ns ) ) {
300 $data[$ns]['content'] = '';
303 if ( MWNamespace::isNonincludable( $ns ) ) {
304 $data[$ns]['nonincludable'] = '';
307 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
308 if ( $contentmodel ) {
309 $data[$ns]['defaultcontentmodel'] = $contentmodel;
313 $this->getResult()->setIndexedTagName( $data, 'ns' );
315 return $this->getResult()->addValue( 'query', $property, $data );
318 protected function appendNamespaceAliases( $property ) {
319 global $wgContLang;
320 $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ),
321 $wgContLang->getNamespaceAliases() );
322 $namespaces = $wgContLang->getNamespaces();
323 $data = array();
324 foreach ( $aliases as $title => $ns ) {
325 if ( $namespaces[$ns] == $title ) {
326 // Don't list duplicates
327 continue;
329 $item = array(
330 'id' => intval( $ns )
332 ApiResult::setContent( $item, strtr( $title, '_', ' ' ) );
333 $data[] = $item;
336 sort( $data );
338 $this->getResult()->setIndexedTagName( $data, 'ns' );
340 return $this->getResult()->addValue( 'query', $property, $data );
343 protected function appendSpecialPageAliases( $property ) {
344 global $wgContLang;
345 $data = array();
346 $aliases = $wgContLang->getSpecialPageAliases();
347 foreach ( SpecialPageFactory::getNames() as $specialpage ) {
348 if ( isset( $aliases[$specialpage] ) ) {
349 $arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
350 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
351 $data[] = $arr;
354 $this->getResult()->setIndexedTagName( $data, 'specialpage' );
356 return $this->getResult()->addValue( 'query', $property, $data );
359 protected function appendMagicWords( $property ) {
360 global $wgContLang;
361 $data = array();
362 foreach ( $wgContLang->getMagicWords() as $magicword => $aliases ) {
363 $caseSensitive = array_shift( $aliases );
364 $arr = array( 'name' => $magicword, 'aliases' => $aliases );
365 if ( $caseSensitive ) {
366 $arr['case-sensitive'] = '';
368 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
369 $data[] = $arr;
371 $this->getResult()->setIndexedTagName( $data, 'magicword' );
373 return $this->getResult()->addValue( 'query', $property, $data );
376 protected function appendInterwikiMap( $property, $filter ) {
377 $local = null;
378 if ( $filter === 'local' ) {
379 $local = 1;
380 } elseif ( $filter === '!local' ) {
381 $local = 0;
382 } elseif ( $filter ) {
383 ApiBase::dieDebug( __METHOD__, "Unknown filter=$filter" );
386 $params = $this->extractRequestParams();
387 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
388 $langNames = Language::fetchLanguageNames( $langCode );
390 $getPrefixes = Interwiki::getAllPrefixes( $local );
391 $extraLangPrefixes = $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' );
392 $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
393 $data = array();
395 foreach ( $getPrefixes as $row ) {
396 $prefix = $row['iw_prefix'];
397 $val = array();
398 $val['prefix'] = $prefix;
399 if ( isset( $row['iw_local'] ) && $row['iw_local'] == '1' ) {
400 $val['local'] = '';
402 if ( isset( $row['iw_trans'] ) && $row['iw_trans'] == '1' ) {
403 $val['trans'] = '';
406 if ( isset( $langNames[$prefix] ) ) {
407 $val['language'] = $langNames[$prefix];
409 if ( in_array( $prefix, $localInterwikis ) ) {
410 $val['localinterwiki'] = '';
412 if ( in_array( $prefix, $extraLangPrefixes ) ) {
413 $val['extralanglink'] = '';
415 $linktext = wfMessage( "interlanguage-link-$prefix" );
416 if ( !$linktext->isDisabled() ) {
417 $val['linktext'] = $linktext->text();
420 $sitename = wfMessage( "interlanguage-link-sitename-$prefix" );
421 if ( !$sitename->isDisabled() ) {
422 $val['sitename'] = $sitename->text();
426 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
427 if ( substr( $row['iw_url'], 0, 2 ) == '//' ) {
428 $val['protorel'] = '';
430 if ( isset( $row['iw_wikiid'] ) ) {
431 $val['wikiid'] = $row['iw_wikiid'];
433 if ( isset( $row['iw_api'] ) ) {
434 $val['api'] = $row['iw_api'];
437 $data[] = $val;
440 $this->getResult()->setIndexedTagName( $data, 'iw' );
442 return $this->getResult()->addValue( 'query', $property, $data );
445 protected function appendDbReplLagInfo( $property, $includeAll ) {
446 $data = array();
447 $lb = wfGetLB();
448 $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
449 if ( $includeAll ) {
450 if ( !$showHostnames ) {
451 $this->dieUsage(
452 'Cannot view all servers info unless $wgShowHostnames is true',
453 'includeAllDenied'
457 $lags = $lb->getLagTimes();
458 foreach ( $lags as $i => $lag ) {
459 $data[] = array(
460 'host' => $lb->getServerName( $i ),
461 'lag' => $lag
464 } else {
465 list( , $lag, $index ) = $lb->getMaxLag();
466 $data[] = array(
467 'host' => $showHostnames
468 ? $lb->getServerName( $index )
469 : '',
470 'lag' => intval( $lag )
474 $result = $this->getResult();
475 $result->setIndexedTagName( $data, 'db' );
477 return $this->getResult()->addValue( 'query', $property, $data );
480 protected function appendStatistics( $property ) {
481 $data = array();
482 $data['pages'] = intval( SiteStats::pages() );
483 $data['articles'] = intval( SiteStats::articles() );
484 if ( !$this->getConfig()->get( 'DisableCounters' ) ) {
485 $data['views'] = intval( SiteStats::views() );
487 $data['edits'] = intval( SiteStats::edits() );
488 $data['images'] = intval( SiteStats::images() );
489 $data['users'] = intval( SiteStats::users() );
490 $data['activeusers'] = intval( SiteStats::activeUsers() );
491 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
492 $data['jobs'] = intval( SiteStats::jobs() );
494 wfRunHooks( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
496 return $this->getResult()->addValue( 'query', $property, $data );
499 protected function appendUserGroups( $property, $numberInGroup ) {
500 $config = $this->getConfig();
502 $data = array();
503 $result = $this->getResult();
504 $allGroups = User::getAllGroups();
505 foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
506 $arr = array(
507 'name' => $group,
508 'rights' => array_keys( $permissions, true ),
511 if ( $numberInGroup ) {
512 $autopromote = $config->get( 'Autopromote' );
514 if ( $group == 'user' ) {
515 $arr['number'] = SiteStats::users();
516 // '*' and autopromote groups have no size
517 } elseif ( $group !== '*' && !isset( $autopromote[$group] ) ) {
518 $arr['number'] = SiteStats::numberInGroup( $group );
522 $groupArr = array(
523 'add' => $config->get( 'AddGroups' ),
524 'remove' => $config->get( 'RemoveGroups' ),
525 'add-self' => $config->get( 'GroupsAddToSelf' ),
526 'remove-self' => $config->get( 'GroupsRemoveFromSelf' )
529 foreach ( $groupArr as $type => $rights ) {
530 if ( isset( $rights[$group] ) ) {
531 $groups = array_intersect( $rights[$group], $allGroups );
532 if ( $groups ) {
533 $arr[$type] = $groups;
534 $result->setIndexedTagName( $arr[$type], 'group' );
539 $result->setIndexedTagName( $arr['rights'], 'permission' );
540 $data[] = $arr;
543 $result->setIndexedTagName( $data, 'group' );
545 return $result->addValue( 'query', $property, $data );
548 protected function appendFileExtensions( $property ) {
549 $data = array();
550 foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
551 $data[] = array( 'ext' => $ext );
553 $this->getResult()->setIndexedTagName( $data, 'fe' );
555 return $this->getResult()->addValue( 'query', $property, $data );
558 protected function appendExtensions( $property ) {
559 $data = array();
560 foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $type => $extensions ) {
561 foreach ( $extensions as $ext ) {
562 $ret = array();
563 $ret['type'] = $type;
564 if ( isset( $ext['name'] ) ) {
565 $ret['name'] = $ext['name'];
567 if ( isset( $ext['namemsg'] ) ) {
568 $ret['namemsg'] = $ext['namemsg'];
570 if ( isset( $ext['description'] ) ) {
571 $ret['description'] = $ext['description'];
573 if ( isset( $ext['descriptionmsg'] ) ) {
574 // Can be a string or array( key, param1, param2, ... )
575 if ( is_array( $ext['descriptionmsg'] ) ) {
576 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
577 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
578 $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
579 } else {
580 $ret['descriptionmsg'] = $ext['descriptionmsg'];
583 if ( isset( $ext['author'] ) ) {
584 $ret['author'] = is_array( $ext['author'] ) ?
585 implode( ', ', $ext['author'] ) : $ext['author'];
587 if ( isset( $ext['url'] ) ) {
588 $ret['url'] = $ext['url'];
590 if ( isset( $ext['version'] ) ) {
591 $ret['version'] = $ext['version'];
592 } elseif ( isset( $ext['svn-revision'] ) &&
593 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
594 $ext['svn-revision'], $m )
596 $ret['version'] = 'r' . $m[1];
598 if ( isset( $ext['path'] ) ) {
599 $extensionPath = dirname( $ext['path'] );
600 $gitInfo = new GitInfo( $extensionPath );
601 $vcsVersion = $gitInfo->getHeadSHA1();
602 if ( $vcsVersion !== false ) {
603 $ret['vcs-system'] = 'git';
604 $ret['vcs-version'] = $vcsVersion;
605 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
606 $vcsDate = $gitInfo->getHeadCommitDate();
607 if ( $vcsDate !== false ) {
608 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
610 } else {
611 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
612 if ( $svnInfo !== false ) {
613 $ret['vcs-system'] = 'svn';
614 $ret['vcs-version'] = $svnInfo['checkout-rev'];
615 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
619 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
620 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
621 $ret['license'] = SpecialPage::getTitleFor(
622 'Version',
623 "License/{$ext['name']}"
624 )->getLinkURL();
627 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
628 $ret['credits'] = SpecialPage::getTitleFor(
629 'Version',
630 "Credits/{$ext['name']}"
631 )->getLinkURL();
634 $data[] = $ret;
638 $this->getResult()->setIndexedTagName( $data, 'ext' );
640 return $this->getResult()->addValue( 'query', $property, $data );
643 protected function appendRightsInfo( $property ) {
644 $config = $this->getConfig();
645 $title = Title::newFromText( $config->get( 'RightsPage' ) );
646 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $config->get( 'RightsUrl' );
647 $text = $config->get( 'RightsText' );
648 if ( !$text && $title ) {
649 $text = $title->getPrefixedText();
652 $data = array(
653 'url' => $url ? $url : '',
654 'text' => $text ? $text : ''
657 return $this->getResult()->addValue( 'query', $property, $data );
660 protected function appendRestrictions( $property ) {
661 $config = $this->getConfig();
662 $data = array(
663 'types' => $config->get( 'RestrictionTypes' ),
664 'levels' => $config->get( 'RestrictionLevels' ),
665 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
666 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
669 $this->getResult()->setIndexedTagName( $data['types'], 'type' );
670 $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
671 $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
672 $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
674 return $this->getResult()->addValue( 'query', $property, $data );
677 public function appendLanguages( $property ) {
678 $params = $this->extractRequestParams();
679 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
680 $langNames = Language::fetchLanguageNames( $langCode );
682 $data = array();
684 foreach ( $langNames as $code => $name ) {
685 $lang = array( 'code' => $code );
686 ApiResult::setContent( $lang, $name );
687 $data[] = $lang;
689 $this->getResult()->setIndexedTagName( $data, 'lang' );
691 return $this->getResult()->addValue( 'query', $property, $data );
694 public function appendSkins( $property ) {
695 $data = array();
696 $allowed = Skin::getAllowedSkins();
697 $default = Skin::normalizeKey( 'default' );
698 foreach ( Skin::getSkinNames() as $name => $displayName ) {
699 $msg = $this->msg( "skinname-{$name}" );
700 $code = $this->getParameter( 'inlanguagecode' );
701 if ( $code && Language::isValidCode( $code ) ) {
702 $msg->inLanguage( $code );
703 } else {
704 $msg->inContentLanguage();
706 if ( $msg->exists() ) {
707 $displayName = $msg->text();
709 $skin = array( 'code' => $name );
710 ApiResult::setContent( $skin, $displayName );
711 if ( !isset( $allowed[$name] ) ) {
712 $skin['unusable'] = '';
714 if ( $name === $default ) {
715 $skin['default'] = '';
717 $data[] = $skin;
719 $this->getResult()->setIndexedTagName( $data, 'skin' );
721 return $this->getResult()->addValue( 'query', $property, $data );
724 public function appendExtensionTags( $property ) {
725 global $wgParser;
726 $wgParser->firstCallInit();
727 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
728 $this->getResult()->setIndexedTagName( $tags, 't' );
730 return $this->getResult()->addValue( 'query', $property, $tags );
733 public function appendFunctionHooks( $property ) {
734 global $wgParser;
735 $wgParser->firstCallInit();
736 $hooks = $wgParser->getFunctionHooks();
737 $this->getResult()->setIndexedTagName( $hooks, 'h' );
739 return $this->getResult()->addValue( 'query', $property, $hooks );
742 public function appendVariables( $property ) {
743 $variables = MagicWord::getVariableIDs();
744 $this->getResult()->setIndexedTagName( $variables, 'v' );
746 return $this->getResult()->addValue( 'query', $property, $variables );
749 public function appendProtocols( $property ) {
750 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
751 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
752 $this->getResult()->setIndexedTagName( $protocols, 'p' );
754 return $this->getResult()->addValue( 'query', $property, $protocols );
757 public function appendDefaultOptions( $property ) {
758 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
761 private function formatParserTags( $item ) {
762 return "<{$item}>";
765 public function appendSubscribedHooks( $property ) {
766 $hooks = $this->getConfig()->get( 'Hooks' );
767 $myWgHooks = $hooks;
768 ksort( $myWgHooks );
770 $data = array();
771 foreach ( $myWgHooks as $name => $subscribers ) {
772 $arr = array(
773 'name' => $name,
774 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $subscribers ),
777 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
778 $data[] = $arr;
781 $this->getResult()->setIndexedTagName( $data, 'hook' );
783 return $this->getResult()->addValue( 'query', $property, $data );
786 public function getCacheMode( $params ) {
787 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
788 if (
789 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
790 !is_null( $params['prop'] ) &&
791 in_array( 'interwikimap', $params['prop'] )
793 return 'anon-public-user-private';
796 return 'public';
799 public function getAllowedParams() {
800 return array(
801 'prop' => array(
802 ApiBase::PARAM_DFLT => 'general',
803 ApiBase::PARAM_ISMULTI => true,
804 ApiBase::PARAM_TYPE => array(
805 'general',
806 'namespaces',
807 'namespacealiases',
808 'specialpagealiases',
809 'magicwords',
810 'interwikimap',
811 'dbrepllag',
812 'statistics',
813 'usergroups',
814 'extensions',
815 'fileextensions',
816 'rightsinfo',
817 'restrictions',
818 'languages',
819 'skins',
820 'extensiontags',
821 'functionhooks',
822 'showhooks',
823 'variables',
824 'protocols',
825 'defaultoptions',
828 'filteriw' => array(
829 ApiBase::PARAM_TYPE => array(
830 'local',
831 '!local',
834 'showalldb' => false,
835 'numberingroup' => false,
836 'inlanguagecode' => null,
840 public function getParamDescription() {
841 $p = $this->getModulePrefix();
843 return array(
844 'prop' => array(
845 'Which sysinfo properties to get:',
846 ' general - Overall system information',
847 ' namespaces - List of registered namespaces and their canonical names',
848 ' namespacealiases - List of registered namespace aliases',
849 ' specialpagealiases - List of special page aliases',
850 ' magicwords - List of magic words and their aliases',
851 ' statistics - Returns site statistics',
852 ' interwikimap - Returns interwiki map ' .
853 "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
854 ' dbrepllag - Returns database server with the highest replication lag',
855 ' usergroups - Returns user groups and the associated permissions',
856 ' extensions - Returns extensions installed on the wiki',
857 ' fileextensions - Returns list of file extensions allowed to be uploaded',
858 ' rightsinfo - Returns wiki rights (license) information if available',
859 ' restrictions - Returns information on available restriction (protection) types',
860 ' languages - Returns a list of languages MediaWiki supports ' .
861 "(optionally localised by using {$p}inlanguagecode)",
862 ' skins - Returns a list of all enabled skins ' .
863 "(optionally localised by using {$p}inlanguagecode, otherwise in content language)",
864 ' extensiontags - Returns a list of parser extension tags',
865 ' functionhooks - Returns a list of parser function hooks',
866 ' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
867 ' variables - Returns a list of variable IDs',
868 ' protocols - Returns a list of protocols that are allowed in external links.',
869 ' defaultoptions - Returns the default values for user preferences.',
871 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
872 'showalldb' => 'List all database servers, not just the one lagging the most',
873 'numberingroup' => 'Lists the number of users in user groups',
874 'inlanguagecode' => 'Language code for localised language names ' .
875 '(best effort, use CLDR extension) and skin names',
879 public function getDescription() {
880 return 'Return general information about the site.';
883 public function getExamples() {
884 return array(
885 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
886 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
887 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb=',
891 public function getHelpUrls() {
892 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';