Set Redis::OPT_READ_TIMEOUT by default
[mediawiki.git] / includes / api / ApiQuerySiteinfo.php
blobb0e9bd227ee71c16d889e00aa58faa31d9ee8887
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( $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, $wgDisableLangConversion, $wgDisableTitleConversion;
125 $data = array();
126 $mainPage = Title::newMainPage();
127 $data['mainpage'] = $mainPage->getPrefixedText();
128 $data['base'] = wfExpandUrl( $mainPage->getFullURL(), PROTO_CURRENT );
129 $data['sitename'] = $GLOBALS['wgSitename'];
131 // wgLogo can either be a relative or an absolute path
132 // make sure we always return an absolute path
133 $data['logo'] = wfExpandUrl( $GLOBALS['wgLogo'], PROTO_RELATIVE );
135 $data['generator'] = "MediaWiki {$GLOBALS['wgVersion']}";
136 $data['phpversion'] = phpversion();
137 $data['phpsapi'] = PHP_SAPI;
138 $data['dbtype'] = $GLOBALS['wgDBtype'];
139 $data['dbversion'] = $this->getDB()->getServerVersion();
141 $allowFrom = array( '' );
142 $allowException = true;
143 if ( !$GLOBALS['wgAllowExternalImages'] ) {
144 if ( $GLOBALS['wgEnableImageWhitelist'] ) {
145 $data['imagewhitelistenabled'] = '';
147 $allowFrom = $GLOBALS['wgAllowExternalImagesFrom'];
148 $allowException = !empty( $allowFrom );
150 if ( $allowException ) {
151 $data['externalimages'] = (array)$allowFrom;
152 $this->getResult()->setIndexedTagName( $data['externalimages'], 'prefix' );
155 if ( !$wgDisableLangConversion ) {
156 $data['langconversion'] = '';
159 if ( !$wgDisableTitleConversion ) {
160 $data['titleconversion'] = '';
163 if ( $wgContLang->linkPrefixExtension() ) {
164 $linkPrefixCharset = $wgContLang->linkPrefixCharset();
165 $data['linkprefixcharset'] = $linkPrefixCharset;
166 // For backwards compatability
167 $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
168 } else {
169 $data['linkprefixcharset'] = '';
170 $data['linkprefix'] = '';
173 $linktrail = $wgContLang->linkTrail();
174 if ( $linktrail ) {
175 $data['linktrail'] = $linktrail;
176 } else {
177 $data['linktrail'] = '';
180 $git = SpecialVersion::getGitHeadSha1( $GLOBALS['IP'] );
181 if ( $git ) {
182 $data['git-hash'] = $git;
183 } else {
184 $svn = SpecialVersion::getSvnRevision( $GLOBALS['IP'] );
185 if ( $svn ) {
186 $data['rev'] = $svn;
190 // 'case-insensitive' option is reserved for future
191 $data['case'] = $GLOBALS['wgCapitalLinks'] ? 'first-letter' : 'case-sensitive';
193 $data['lang'] = $GLOBALS['wgLanguageCode'];
195 $fallbacks = array();
196 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
197 $fallbacks[] = array( 'code' => $code );
199 $data['fallback'] = $fallbacks;
200 $this->getResult()->setIndexedTagName( $data['fallback'], 'lang' );
202 if ( $wgContLang->hasVariants() ) {
203 $variants = array();
204 foreach ( $wgContLang->getVariants() as $code ) {
205 $variants[] = array(
206 'code' => $code,
207 'name' => $wgContLang->getVariantname( $code ),
210 $data['variants'] = $variants;
211 $this->getResult()->setIndexedTagName( $data['variants'], 'lang' );
214 if ( $wgContLang->isRTL() ) {
215 $data['rtl'] = '';
217 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
219 if ( wfReadOnly() ) {
220 $data['readonly'] = '';
221 $data['readonlyreason'] = wfReadOnlyReason();
223 if ( $GLOBALS['wgEnableWriteAPI'] ) {
224 $data['writeapi'] = '';
227 $tz = $GLOBALS['wgLocaltimezone'];
228 $offset = $GLOBALS['wgLocalTZoffset'];
229 if ( is_null( $tz ) ) {
230 $tz = 'UTC';
231 $offset = 0;
232 } elseif ( is_null( $offset ) ) {
233 $offset = 0;
235 $data['timezone'] = $tz;
236 $data['timeoffset'] = intval( $offset );
237 $data['articlepath'] = $GLOBALS['wgArticlePath'];
238 $data['scriptpath'] = $GLOBALS['wgScriptPath'];
239 $data['script'] = $GLOBALS['wgScript'];
240 $data['variantarticlepath'] = $GLOBALS['wgVariantArticlePath'];
241 $data['server'] = $GLOBALS['wgServer'];
242 $data['wikiid'] = wfWikiID();
243 $data['time'] = wfTimestamp( TS_ISO_8601, time() );
245 if ( $GLOBALS['wgMiserMode'] ) {
246 $data['misermode'] = '';
249 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
251 $data['thumblimits'] = $GLOBALS['wgThumbLimits'];
252 $this->getResult()->setIndexedTagName( $data['thumblimits'], 'limit' );
253 $data['imagelimits'] = array();
254 $this->getResult()->setIndexedTagName( $data['imagelimits'], 'limit' );
255 foreach ( $GLOBALS['wgImageLimits'] as $k => $limit ) {
256 $data['imagelimits'][$k] = array( 'width' => $limit[0], 'height' => $limit[1] );
259 if ( !empty( $GLOBALS['wgFavicon'] ) ) {
260 // wgFavicon can either be a relative or an absolute path
261 // make sure we always return an absolute path
262 $data['favicon'] = wfExpandUrl( $GLOBALS['wgFavicon'], PROTO_RELATIVE );
265 wfRunHooks( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
267 return $this->getResult()->addValue( 'query', $property, $data );
270 protected function appendNamespaces( $property ) {
271 global $wgContLang;
272 $data = array();
273 foreach ( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
274 $data[$ns] = array(
275 'id' => intval( $ns ),
276 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
278 ApiResult::setContent( $data[$ns], $title );
279 $canonical = MWNamespace::getCanonicalName( $ns );
281 if ( MWNamespace::hasSubpages( $ns ) ) {
282 $data[$ns]['subpages'] = '';
285 if ( $canonical ) {
286 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
289 if ( MWNamespace::isContent( $ns ) ) {
290 $data[$ns]['content'] = '';
293 if ( MWNamespace::isNonincludable( $ns ) ) {
294 $data[$ns]['nonincludable'] = '';
297 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
298 if ( $contentmodel ) {
299 $data[$ns]['defaultcontentmodel'] = $contentmodel;
303 $this->getResult()->setIndexedTagName( $data, 'ns' );
305 return $this->getResult()->addValue( 'query', $property, $data );
308 protected function appendNamespaceAliases( $property ) {
309 global $wgNamespaceAliases, $wgContLang;
310 $aliases = array_merge( $wgNamespaceAliases, $wgContLang->getNamespaceAliases() );
311 $namespaces = $wgContLang->getNamespaces();
312 $data = array();
313 foreach ( $aliases as $title => $ns ) {
314 if ( $namespaces[$ns] == $title ) {
315 // Don't list duplicates
316 continue;
318 $item = array(
319 'id' => intval( $ns )
321 ApiResult::setContent( $item, strtr( $title, '_', ' ' ) );
322 $data[] = $item;
325 sort( $data );
327 $this->getResult()->setIndexedTagName( $data, 'ns' );
329 return $this->getResult()->addValue( 'query', $property, $data );
332 protected function appendSpecialPageAliases( $property ) {
333 global $wgContLang;
334 $data = array();
335 $aliases = $wgContLang->getSpecialPageAliases();
336 foreach ( SpecialPageFactory::getList() as $specialpage => $stuff ) {
337 if ( isset( $aliases[$specialpage] ) ) {
338 $arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
339 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
340 $data[] = $arr;
343 $this->getResult()->setIndexedTagName( $data, 'specialpage' );
345 return $this->getResult()->addValue( 'query', $property, $data );
348 protected function appendMagicWords( $property ) {
349 global $wgContLang;
350 $data = array();
351 foreach ( $wgContLang->getMagicWords() as $magicword => $aliases ) {
352 $caseSensitive = array_shift( $aliases );
353 $arr = array( 'name' => $magicword, 'aliases' => $aliases );
354 if ( $caseSensitive ) {
355 $arr['case-sensitive'] = '';
357 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
358 $data[] = $arr;
360 $this->getResult()->setIndexedTagName( $data, 'magicword' );
362 return $this->getResult()->addValue( 'query', $property, $data );
365 protected function appendInterwikiMap( $property, $filter ) {
366 $local = null;
367 if ( $filter === 'local' ) {
368 $local = 1;
369 } elseif ( $filter === '!local' ) {
370 $local = 0;
371 } elseif ( $filter ) {
372 ApiBase::dieDebug( __METHOD__, "Unknown filter=$filter" );
375 $params = $this->extractRequestParams();
376 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
377 $langNames = Language::fetchLanguageNames( $langCode );
379 $getPrefixes = Interwiki::getAllPrefixes( $local );
380 $data = array();
382 foreach ( $getPrefixes as $row ) {
383 $prefix = $row['iw_prefix'];
384 $val = array();
385 $val['prefix'] = $prefix;
386 if ( $row['iw_local'] == '1' ) {
387 $val['local'] = '';
389 if ( $row['iw_trans'] == '1' ) {
390 $val['trans'] = '';
392 if ( isset( $langNames[$prefix] ) ) {
393 $val['language'] = $langNames[$prefix];
395 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
396 if ( isset( $row['iw_wikiid'] ) ) {
397 $val['wikiid'] = $row['iw_wikiid'];
399 if ( isset( $row['iw_api'] ) ) {
400 $val['api'] = $row['iw_api'];
403 $data[] = $val;
406 $this->getResult()->setIndexedTagName( $data, 'iw' );
408 return $this->getResult()->addValue( 'query', $property, $data );
411 protected function appendDbReplLagInfo( $property, $includeAll ) {
412 global $wgShowHostnames;
413 $data = array();
414 $lb = wfGetLB();
415 if ( $includeAll ) {
416 if ( !$wgShowHostnames ) {
417 $this->dieUsage(
418 'Cannot view all servers info unless $wgShowHostnames is true',
419 'includeAllDenied'
423 $lags = $lb->getLagTimes();
424 foreach ( $lags as $i => $lag ) {
425 $data[] = array(
426 'host' => $lb->getServerName( $i ),
427 'lag' => $lag
430 } else {
431 list( , $lag, $index ) = $lb->getMaxLag();
432 $data[] = array(
433 'host' => $wgShowHostnames
434 ? $lb->getServerName( $index )
435 : '',
436 'lag' => intval( $lag )
440 $result = $this->getResult();
441 $result->setIndexedTagName( $data, 'db' );
443 return $this->getResult()->addValue( 'query', $property, $data );
446 protected function appendStatistics( $property ) {
447 global $wgDisableCounters;
448 $data = array();
449 $data['pages'] = intval( SiteStats::pages() );
450 $data['articles'] = intval( SiteStats::articles() );
451 if ( !$wgDisableCounters ) {
452 $data['views'] = intval( SiteStats::views() );
454 $data['edits'] = intval( SiteStats::edits() );
455 $data['images'] = intval( SiteStats::images() );
456 $data['users'] = intval( SiteStats::users() );
457 $data['activeusers'] = intval( SiteStats::activeUsers() );
458 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
459 $data['jobs'] = intval( SiteStats::jobs() );
461 wfRunHooks( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
463 return $this->getResult()->addValue( 'query', $property, $data );
466 protected function appendUserGroups( $property, $numberInGroup ) {
467 global $wgGroupPermissions, $wgAddGroups, $wgRemoveGroups;
468 global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
470 $data = array();
471 $result = $this->getResult();
472 foreach ( $wgGroupPermissions as $group => $permissions ) {
473 $arr = array(
474 'name' => $group,
475 'rights' => array_keys( $permissions, true ),
478 if ( $numberInGroup ) {
479 global $wgAutopromote;
481 if ( $group == 'user' ) {
482 $arr['number'] = SiteStats::users();
483 // '*' and autopromote groups have no size
484 } elseif ( $group !== '*' && !isset( $wgAutopromote[$group] ) ) {
485 $arr['number'] = SiteStats::numberInGroup( $group );
489 $groupArr = array(
490 'add' => $wgAddGroups,
491 'remove' => $wgRemoveGroups,
492 'add-self' => $wgGroupsAddToSelf,
493 'remove-self' => $wgGroupsRemoveFromSelf
496 foreach ( $groupArr as $type => $rights ) {
497 if ( isset( $rights[$group] ) ) {
498 $arr[$type] = $rights[$group];
499 $result->setIndexedTagName( $arr[$type], 'group' );
503 $result->setIndexedTagName( $arr['rights'], 'permission' );
504 $data[] = $arr;
507 $result->setIndexedTagName( $data, 'group' );
509 return $result->addValue( 'query', $property, $data );
512 protected function appendFileExtensions( $property ) {
513 global $wgFileExtensions;
515 $data = array();
516 foreach ( array_unique( $wgFileExtensions ) as $ext ) {
517 $data[] = array( 'ext' => $ext );
519 $this->getResult()->setIndexedTagName( $data, 'fe' );
521 return $this->getResult()->addValue( 'query', $property, $data );
524 protected function appendExtensions( $property ) {
525 global $wgExtensionCredits;
526 $data = array();
527 foreach ( $wgExtensionCredits as $type => $extensions ) {
528 foreach ( $extensions as $ext ) {
529 $ret = array();
530 $ret['type'] = $type;
531 if ( isset( $ext['name'] ) ) {
532 $ret['name'] = $ext['name'];
534 if ( isset( $ext['description'] ) ) {
535 $ret['description'] = $ext['description'];
537 if ( isset( $ext['descriptionmsg'] ) ) {
538 // Can be a string or array( key, param1, param2, ... )
539 if ( is_array( $ext['descriptionmsg'] ) ) {
540 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
541 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
542 $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
543 } else {
544 $ret['descriptionmsg'] = $ext['descriptionmsg'];
547 if ( isset( $ext['author'] ) ) {
548 $ret['author'] = is_array( $ext['author'] ) ?
549 implode( ', ', $ext['author'] ) : $ext['author'];
551 if ( isset( $ext['url'] ) ) {
552 $ret['url'] = $ext['url'];
554 if ( isset( $ext['version'] ) ) {
555 $ret['version'] = $ext['version'];
556 } elseif ( isset( $ext['svn-revision'] ) &&
557 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
558 $ext['svn-revision'], $m )
560 $ret['version'] = 'r' . $m[1];
562 if ( isset( $ext['path'] ) ) {
563 $extensionPath = dirname( $ext['path'] );
564 $gitInfo = new GitInfo( $extensionPath );
565 $vcsVersion = $gitInfo->getHeadSHA1();
566 if ( $vcsVersion !== false ) {
567 $ret['vcs-system'] = 'git';
568 $ret['vcs-version'] = $vcsVersion;
569 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
570 $vcsDate = $gitInfo->getHeadCommitDate();
571 if ( $vcsDate !== false ) {
572 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
574 } else {
575 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
576 if ( $svnInfo !== false ) {
577 $ret['vcs-system'] = 'svn';
578 $ret['vcs-version'] = $svnInfo['checkout-rev'];
579 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
583 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
584 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
585 $ret['license'] = SpecialPage::getTitleFor(
586 'Version',
587 "License/{$ext['name']}"
588 )->getLinkURL();
591 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
592 $ret['credits'] = SpecialPage::getTitleFor(
593 'Version',
594 "Credits/{$ext['name']}"
595 )->getLinkURL();
598 $data[] = $ret;
602 $this->getResult()->setIndexedTagName( $data, 'ext' );
604 return $this->getResult()->addValue( 'query', $property, $data );
607 protected function appendRightsInfo( $property ) {
608 global $wgRightsPage, $wgRightsUrl, $wgRightsText;
609 $title = Title::newFromText( $wgRightsPage );
610 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $wgRightsUrl;
611 $text = $wgRightsText;
612 if ( !$text && $title ) {
613 $text = $title->getPrefixedText();
616 $data = array(
617 'url' => $url ? $url : '',
618 'text' => $text ? $text : ''
621 return $this->getResult()->addValue( 'query', $property, $data );
624 protected function appendRestrictions( $property ) {
625 global $wgRestrictionTypes, $wgRestrictionLevels,
626 $wgCascadingRestrictionLevels, $wgSemiprotectedRestrictionLevels;
628 $data = array(
629 'types' => $wgRestrictionTypes,
630 'levels' => $wgRestrictionLevels,
631 'cascadinglevels' => $wgCascadingRestrictionLevels,
632 'semiprotectedlevels' => $wgSemiprotectedRestrictionLevels,
635 $this->getResult()->setIndexedTagName( $data['types'], 'type' );
636 $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
637 $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
638 $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
640 return $this->getResult()->addValue( 'query', $property, $data );
643 public function appendLanguages( $property ) {
644 $params = $this->extractRequestParams();
645 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
646 $langNames = Language::fetchLanguageNames( $langCode );
648 $data = array();
650 foreach ( $langNames as $code => $name ) {
651 $lang = array( 'code' => $code );
652 ApiResult::setContent( $lang, $name );
653 $data[] = $lang;
655 $this->getResult()->setIndexedTagName( $data, 'lang' );
657 return $this->getResult()->addValue( 'query', $property, $data );
660 public function appendSkins( $property ) {
661 $data = array();
662 $allowed = Skin::getAllowedSkins();
663 $default = Skin::normalizeKey( 'default' );
664 foreach ( Skin::getSkinNames() as $name => $displayName ) {
665 $skin = array( 'code' => $name );
666 ApiResult::setContent( $skin, $displayName );
667 if ( !isset( $allowed[$name] ) ) {
668 $skin['unusable'] = '';
670 if ( $name === $default ) {
671 $skin['default'] = '';
673 $data[] = $skin;
675 $this->getResult()->setIndexedTagName( $data, 'skin' );
677 return $this->getResult()->addValue( 'query', $property, $data );
680 public function appendExtensionTags( $property ) {
681 global $wgParser;
682 $wgParser->firstCallInit();
683 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
684 $this->getResult()->setIndexedTagName( $tags, 't' );
686 return $this->getResult()->addValue( 'query', $property, $tags );
689 public function appendFunctionHooks( $property ) {
690 global $wgParser;
691 $wgParser->firstCallInit();
692 $hooks = $wgParser->getFunctionHooks();
693 $this->getResult()->setIndexedTagName( $hooks, 'h' );
695 return $this->getResult()->addValue( 'query', $property, $hooks );
698 public function appendVariables( $property ) {
699 $variables = MagicWord::getVariableIDs();
700 $this->getResult()->setIndexedTagName( $variables, 'v' );
702 return $this->getResult()->addValue( 'query', $property, $variables );
705 public function appendProtocols( $property ) {
706 global $wgUrlProtocols;
707 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
708 $protocols = array_values( $wgUrlProtocols );
709 $this->getResult()->setIndexedTagName( $protocols, 'p' );
711 return $this->getResult()->addValue( 'query', $property, $protocols );
714 public function appendDefaultOptions( $property ) {
715 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
718 private function formatParserTags( $item ) {
719 return "<{$item}>";
722 public function appendSubscribedHooks( $property ) {
723 global $wgHooks;
724 $myWgHooks = $wgHooks;
725 ksort( $myWgHooks );
727 $data = array();
728 foreach ( $myWgHooks as $hook => $hooks ) {
729 $arr = array(
730 'name' => $hook,
731 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $hooks ),
734 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
735 $data[] = $arr;
738 $this->getResult()->setIndexedTagName( $data, 'hook' );
740 return $this->getResult()->addValue( 'query', $property, $data );
743 public function getCacheMode( $params ) {
744 return 'public';
747 public function getAllowedParams() {
748 return array(
749 'prop' => array(
750 ApiBase::PARAM_DFLT => 'general',
751 ApiBase::PARAM_ISMULTI => true,
752 ApiBase::PARAM_TYPE => array(
753 'general',
754 'namespaces',
755 'namespacealiases',
756 'specialpagealiases',
757 'magicwords',
758 'interwikimap',
759 'dbrepllag',
760 'statistics',
761 'usergroups',
762 'extensions',
763 'fileextensions',
764 'rightsinfo',
765 'restrictions',
766 'languages',
767 'skins',
768 'extensiontags',
769 'functionhooks',
770 'showhooks',
771 'variables',
772 'protocols',
773 'defaultoptions',
776 'filteriw' => array(
777 ApiBase::PARAM_TYPE => array(
778 'local',
779 '!local',
782 'showalldb' => false,
783 'numberingroup' => false,
784 'inlanguagecode' => null,
788 public function getParamDescription() {
789 $p = $this->getModulePrefix();
791 return array(
792 'prop' => array(
793 'Which sysinfo properties to get:',
794 ' general - Overall system information',
795 ' namespaces - List of registered namespaces and their canonical names',
796 ' namespacealiases - List of registered namespace aliases',
797 ' specialpagealiases - List of special page aliases',
798 ' magicwords - List of magic words and their aliases',
799 ' statistics - Returns site statistics',
800 ' interwikimap - Returns interwiki map ' .
801 "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
802 ' dbrepllag - Returns database server with the highest replication lag',
803 ' usergroups - Returns user groups and the associated permissions',
804 ' extensions - Returns extensions installed on the wiki',
805 ' fileextensions - Returns list of file extensions allowed to be uploaded',
806 ' rightsinfo - Returns wiki rights (license) information if available',
807 ' restrictions - Returns information on available restriction (protection) types',
808 ' languages - Returns a list of languages MediaWiki supports' .
809 "(optionally localised by using {$p}inlanguagecode)",
810 ' skins - Returns a list of all enabled skins',
811 ' extensiontags - Returns a list of parser extension tags',
812 ' functionhooks - Returns a list of parser function hooks',
813 ' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
814 ' variables - Returns a list of variable IDs',
815 ' protocols - Returns a list of protocols that are allowed in external links.',
816 ' defaultoptions - Returns the default values for user preferences.',
818 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
819 'showalldb' => 'List all database servers, not just the one lagging the most',
820 'numberingroup' => 'Lists the number of users in user groups',
821 'inlanguagecode' => 'Language code for localised language names ' .
822 '(best effort, use CLDR extension)',
826 public function getDescription() {
827 return 'Return general information about the site.';
830 public function getPossibleErrors() {
831 return array_merge( parent::getPossibleErrors(), array( array(
832 'code' => 'includeAllDenied',
833 'info' => 'Cannot view all servers info unless $wgShowHostnames is true'
834 ), ) );
837 public function getExamples() {
838 return array(
839 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
840 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
841 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb=',
845 public function getHelpUrls() {
846 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';