Implement extension registration from an extension.json file
[mediawiki.git] / includes / api / ApiQuerySiteinfo.php
blobf373021e0ad40a3509a29508f0fee964a98456ef
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 $data['legaltitlechars'] = Title::legalChars();
188 global $IP;
189 $git = SpecialVersion::getGitHeadSha1( $IP );
190 if ( $git ) {
191 $data['git-hash'] = $git;
192 $data['git-branch'] =
193 SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
194 } else {
195 $svn = SpecialVersion::getSvnRevision( $IP );
196 if ( $svn ) {
197 $data['rev'] = $svn;
201 // 'case-insensitive' option is reserved for future
202 $data['case'] = $config->get( 'CapitalLinks' ) ? 'first-letter' : 'case-sensitive';
203 $data['lang'] = $config->get( 'LanguageCode' );
205 $fallbacks = array();
206 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
207 $fallbacks[] = array( 'code' => $code );
209 $data['fallback'] = $fallbacks;
210 $this->getResult()->setIndexedTagName( $data['fallback'], 'lang' );
212 if ( $wgContLang->hasVariants() ) {
213 $variants = array();
214 foreach ( $wgContLang->getVariants() as $code ) {
215 $variants[] = array(
216 'code' => $code,
217 'name' => $wgContLang->getVariantname( $code ),
220 $data['variants'] = $variants;
221 $this->getResult()->setIndexedTagName( $data['variants'], 'lang' );
224 if ( $wgContLang->isRTL() ) {
225 $data['rtl'] = '';
227 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
229 if ( wfReadOnly() ) {
230 $data['readonly'] = '';
231 $data['readonlyreason'] = wfReadOnlyReason();
233 if ( $config->get( 'EnableWriteAPI' ) ) {
234 $data['writeapi'] = '';
237 $tz = $config->get( 'Localtimezone' );
238 $offset = $config->get( 'LocalTZoffset' );
239 if ( is_null( $tz ) ) {
240 $tz = 'UTC';
241 $offset = 0;
242 } elseif ( is_null( $offset ) ) {
243 $offset = 0;
245 $data['timezone'] = $tz;
246 $data['timeoffset'] = intval( $offset );
247 $data['articlepath'] = $config->get( 'ArticlePath' );
248 $data['scriptpath'] = $config->get( 'ScriptPath' );
249 $data['script'] = $config->get( 'Script' );
250 $data['variantarticlepath'] = $config->get( 'VariantArticlePath' );
251 $data['server'] = $config->get( 'Server' );
252 $data['servername'] = $config->get( 'ServerName' );
253 $data['wikiid'] = wfWikiID();
254 $data['time'] = wfTimestamp( TS_ISO_8601, time() );
256 if ( $config->get( 'MiserMode' ) ) {
257 $data['misermode'] = '';
260 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
262 $data['thumblimits'] = $config->get( 'ThumbLimits' );
263 $this->getResult()->setIndexedTagName( $data['thumblimits'], 'limit' );
264 $data['imagelimits'] = array();
265 $this->getResult()->setIndexedTagName( $data['imagelimits'], 'limit' );
266 foreach ( $config->get( 'ImageLimits' ) as $k => $limit ) {
267 $data['imagelimits'][$k] = array( 'width' => $limit[0], 'height' => $limit[1] );
270 $favicon = $config->get( 'Favicon' );
271 if ( !empty( $favicon ) ) {
272 // wgFavicon can either be a relative or an absolute path
273 // make sure we always return an absolute path
274 $data['favicon'] = wfExpandUrl( $favicon, PROTO_RELATIVE );
277 Hooks::run( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
279 return $this->getResult()->addValue( 'query', $property, $data );
282 protected function appendNamespaces( $property ) {
283 global $wgContLang;
284 $data = array();
285 foreach ( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
286 $data[$ns] = array(
287 'id' => intval( $ns ),
288 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
290 ApiResult::setContent( $data[$ns], $title );
291 $canonical = MWNamespace::getCanonicalName( $ns );
293 if ( MWNamespace::hasSubpages( $ns ) ) {
294 $data[$ns]['subpages'] = '';
297 if ( $canonical ) {
298 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
301 if ( MWNamespace::isContent( $ns ) ) {
302 $data[$ns]['content'] = '';
305 if ( MWNamespace::isNonincludable( $ns ) ) {
306 $data[$ns]['nonincludable'] = '';
309 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
310 if ( $contentmodel ) {
311 $data[$ns]['defaultcontentmodel'] = $contentmodel;
315 $this->getResult()->setIndexedTagName( $data, 'ns' );
317 return $this->getResult()->addValue( 'query', $property, $data );
320 protected function appendNamespaceAliases( $property ) {
321 global $wgContLang;
322 $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ),
323 $wgContLang->getNamespaceAliases() );
324 $namespaces = $wgContLang->getNamespaces();
325 $data = array();
326 foreach ( $aliases as $title => $ns ) {
327 if ( $namespaces[$ns] == $title ) {
328 // Don't list duplicates
329 continue;
331 $item = array(
332 'id' => intval( $ns )
334 ApiResult::setContent( $item, strtr( $title, '_', ' ' ) );
335 $data[] = $item;
338 sort( $data );
340 $this->getResult()->setIndexedTagName( $data, 'ns' );
342 return $this->getResult()->addValue( 'query', $property, $data );
345 protected function appendSpecialPageAliases( $property ) {
346 global $wgContLang;
347 $data = array();
348 $aliases = $wgContLang->getSpecialPageAliases();
349 foreach ( SpecialPageFactory::getNames() as $specialpage ) {
350 if ( isset( $aliases[$specialpage] ) ) {
351 $arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
352 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
353 $data[] = $arr;
356 $this->getResult()->setIndexedTagName( $data, 'specialpage' );
358 return $this->getResult()->addValue( 'query', $property, $data );
361 protected function appendMagicWords( $property ) {
362 global $wgContLang;
363 $data = array();
364 foreach ( $wgContLang->getMagicWords() as $magicword => $aliases ) {
365 $caseSensitive = array_shift( $aliases );
366 $arr = array( 'name' => $magicword, 'aliases' => $aliases );
367 if ( $caseSensitive ) {
368 $arr['case-sensitive'] = '';
370 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
371 $data[] = $arr;
373 $this->getResult()->setIndexedTagName( $data, 'magicword' );
375 return $this->getResult()->addValue( 'query', $property, $data );
378 protected function appendInterwikiMap( $property, $filter ) {
379 $local = null;
380 if ( $filter === 'local' ) {
381 $local = 1;
382 } elseif ( $filter === '!local' ) {
383 $local = 0;
384 } elseif ( $filter ) {
385 ApiBase::dieDebug( __METHOD__, "Unknown filter=$filter" );
388 $params = $this->extractRequestParams();
389 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
390 $langNames = Language::fetchLanguageNames( $langCode );
392 $getPrefixes = Interwiki::getAllPrefixes( $local );
393 $extraLangPrefixes = $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' );
394 $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
395 $data = array();
397 foreach ( $getPrefixes as $row ) {
398 $prefix = $row['iw_prefix'];
399 $val = array();
400 $val['prefix'] = $prefix;
401 if ( isset( $row['iw_local'] ) && $row['iw_local'] == '1' ) {
402 $val['local'] = '';
404 if ( isset( $row['iw_trans'] ) && $row['iw_trans'] == '1' ) {
405 $val['trans'] = '';
408 if ( isset( $langNames[$prefix] ) ) {
409 $val['language'] = $langNames[$prefix];
411 if ( in_array( $prefix, $localInterwikis ) ) {
412 $val['localinterwiki'] = '';
414 if ( in_array( $prefix, $extraLangPrefixes ) ) {
415 $val['extralanglink'] = '';
417 $linktext = wfMessage( "interlanguage-link-$prefix" );
418 if ( !$linktext->isDisabled() ) {
419 $val['linktext'] = $linktext->text();
422 $sitename = wfMessage( "interlanguage-link-sitename-$prefix" );
423 if ( !$sitename->isDisabled() ) {
424 $val['sitename'] = $sitename->text();
428 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
429 if ( substr( $row['iw_url'], 0, 2 ) == '//' ) {
430 $val['protorel'] = '';
432 if ( isset( $row['iw_wikiid'] ) ) {
433 $val['wikiid'] = $row['iw_wikiid'];
435 if ( isset( $row['iw_api'] ) ) {
436 $val['api'] = $row['iw_api'];
439 $data[] = $val;
442 $this->getResult()->setIndexedTagName( $data, 'iw' );
444 return $this->getResult()->addValue( 'query', $property, $data );
447 protected function appendDbReplLagInfo( $property, $includeAll ) {
448 $data = array();
449 $lb = wfGetLB();
450 $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
451 if ( $includeAll ) {
452 if ( !$showHostnames ) {
453 $this->dieUsage(
454 'Cannot view all servers info unless $wgShowHostnames is true',
455 'includeAllDenied'
459 $lags = $lb->getLagTimes();
460 foreach ( $lags as $i => $lag ) {
461 $data[] = array(
462 'host' => $lb->getServerName( $i ),
463 'lag' => $lag
466 } else {
467 list( , $lag, $index ) = $lb->getMaxLag();
468 $data[] = array(
469 'host' => $showHostnames
470 ? $lb->getServerName( $index )
471 : '',
472 'lag' => intval( $lag )
476 $result = $this->getResult();
477 $result->setIndexedTagName( $data, 'db' );
479 return $this->getResult()->addValue( 'query', $property, $data );
482 protected function appendStatistics( $property ) {
483 $data = array();
484 $data['pages'] = intval( SiteStats::pages() );
485 $data['articles'] = intval( SiteStats::articles() );
486 $data['edits'] = intval( SiteStats::edits() );
487 $data['images'] = intval( SiteStats::images() );
488 $data['users'] = intval( SiteStats::users() );
489 $data['activeusers'] = intval( SiteStats::activeUsers() );
490 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
491 $data['jobs'] = intval( SiteStats::jobs() );
493 Hooks::run( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
495 return $this->getResult()->addValue( 'query', $property, $data );
498 protected function appendUserGroups( $property, $numberInGroup ) {
499 $config = $this->getConfig();
501 $data = array();
502 $result = $this->getResult();
503 $allGroups = User::getAllGroups();
504 foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
505 $arr = array(
506 'name' => $group,
507 'rights' => array_keys( $permissions, true ),
510 if ( $numberInGroup ) {
511 $autopromote = $config->get( 'Autopromote' );
513 if ( $group == 'user' ) {
514 $arr['number'] = SiteStats::users();
515 // '*' and autopromote groups have no size
516 } elseif ( $group !== '*' && !isset( $autopromote[$group] ) ) {
517 $arr['number'] = SiteStats::numberInGroup( $group );
521 $groupArr = array(
522 'add' => $config->get( 'AddGroups' ),
523 'remove' => $config->get( 'RemoveGroups' ),
524 'add-self' => $config->get( 'GroupsAddToSelf' ),
525 'remove-self' => $config->get( 'GroupsRemoveFromSelf' )
528 foreach ( $groupArr as $type => $rights ) {
529 if ( isset( $rights[$group] ) ) {
530 $groups = array_intersect( $rights[$group], $allGroups );
531 if ( $groups ) {
532 $arr[$type] = $groups;
533 $result->setIndexedTagName( $arr[$type], 'group' );
538 $result->setIndexedTagName( $arr['rights'], 'permission' );
539 $data[] = $arr;
542 $result->setIndexedTagName( $data, 'group' );
544 return $result->addValue( 'query', $property, $data );
547 protected function appendFileExtensions( $property ) {
548 $data = array();
549 foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
550 $data[] = array( 'ext' => $ext );
552 $this->getResult()->setIndexedTagName( $data, 'fe' );
554 return $this->getResult()->addValue( 'query', $property, $data );
557 protected function appendExtensions( $property ) {
558 $data = array();
559 foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $type => $extensions ) {
560 foreach ( $extensions as $ext ) {
561 $ret = array();
562 $ret['type'] = $type;
563 if ( isset( $ext['name'] ) ) {
564 $ret['name'] = $ext['name'];
566 if ( isset( $ext['namemsg'] ) ) {
567 $ret['namemsg'] = $ext['namemsg'];
569 if ( isset( $ext['description'] ) ) {
570 $ret['description'] = $ext['description'];
572 if ( isset( $ext['descriptionmsg'] ) ) {
573 // Can be a string or array( key, param1, param2, ... )
574 if ( is_array( $ext['descriptionmsg'] ) ) {
575 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
576 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
577 $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
578 } else {
579 $ret['descriptionmsg'] = $ext['descriptionmsg'];
582 if ( isset( $ext['author'] ) ) {
583 $ret['author'] = is_array( $ext['author'] ) ?
584 implode( ', ', $ext['author'] ) : $ext['author'];
586 if ( isset( $ext['url'] ) ) {
587 $ret['url'] = $ext['url'];
589 if ( isset( $ext['version'] ) ) {
590 $ret['version'] = $ext['version'];
591 } elseif ( isset( $ext['svn-revision'] ) &&
592 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
593 $ext['svn-revision'], $m )
595 $ret['version'] = 'r' . $m[1];
597 if ( isset( $ext['path'] ) ) {
598 $extensionPath = dirname( $ext['path'] );
599 $gitInfo = new GitInfo( $extensionPath );
600 $vcsVersion = $gitInfo->getHeadSHA1();
601 if ( $vcsVersion !== false ) {
602 $ret['vcs-system'] = 'git';
603 $ret['vcs-version'] = $vcsVersion;
604 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
605 $vcsDate = $gitInfo->getHeadCommitDate();
606 if ( $vcsDate !== false ) {
607 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
609 } else {
610 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
611 if ( $svnInfo !== false ) {
612 $ret['vcs-system'] = 'svn';
613 $ret['vcs-version'] = $svnInfo['checkout-rev'];
614 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
618 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
619 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
620 $ret['license'] = SpecialPage::getTitleFor(
621 'Version',
622 "License/{$ext['name']}"
623 )->getLinkURL();
626 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
627 $ret['credits'] = SpecialPage::getTitleFor(
628 'Version',
629 "Credits/{$ext['name']}"
630 )->getLinkURL();
633 $data[] = $ret;
637 $this->getResult()->setIndexedTagName( $data, 'ext' );
639 return $this->getResult()->addValue( 'query', $property, $data );
642 protected function appendRightsInfo( $property ) {
643 $config = $this->getConfig();
644 $title = Title::newFromText( $config->get( 'RightsPage' ) );
645 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $config->get( 'RightsUrl' );
646 $text = $config->get( 'RightsText' );
647 if ( !$text && $title ) {
648 $text = $title->getPrefixedText();
651 $data = array(
652 'url' => $url ? $url : '',
653 'text' => $text ? $text : ''
656 return $this->getResult()->addValue( 'query', $property, $data );
659 protected function appendRestrictions( $property ) {
660 $config = $this->getConfig();
661 $data = array(
662 'types' => $config->get( 'RestrictionTypes' ),
663 'levels' => $config->get( 'RestrictionLevels' ),
664 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
665 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
668 $this->getResult()->setIndexedTagName( $data['types'], 'type' );
669 $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
670 $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
671 $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
673 return $this->getResult()->addValue( 'query', $property, $data );
676 public function appendLanguages( $property ) {
677 $params = $this->extractRequestParams();
678 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
679 $langNames = Language::fetchLanguageNames( $langCode );
681 $data = array();
683 foreach ( $langNames as $code => $name ) {
684 $lang = array( 'code' => $code );
685 ApiResult::setContent( $lang, $name );
686 $data[] = $lang;
688 $this->getResult()->setIndexedTagName( $data, 'lang' );
690 return $this->getResult()->addValue( 'query', $property, $data );
693 public function appendSkins( $property ) {
694 $data = array();
695 $allowed = Skin::getAllowedSkins();
696 $default = Skin::normalizeKey( 'default' );
697 foreach ( Skin::getSkinNames() as $name => $displayName ) {
698 $msg = $this->msg( "skinname-{$name}" );
699 $code = $this->getParameter( 'inlanguagecode' );
700 if ( $code && Language::isValidCode( $code ) ) {
701 $msg->inLanguage( $code );
702 } else {
703 $msg->inContentLanguage();
705 if ( $msg->exists() ) {
706 $displayName = $msg->text();
708 $skin = array( 'code' => $name );
709 ApiResult::setContent( $skin, $displayName );
710 if ( !isset( $allowed[$name] ) ) {
711 $skin['unusable'] = '';
713 if ( $name === $default ) {
714 $skin['default'] = '';
716 $data[] = $skin;
718 $this->getResult()->setIndexedTagName( $data, 'skin' );
720 return $this->getResult()->addValue( 'query', $property, $data );
723 public function appendExtensionTags( $property ) {
724 global $wgParser;
725 $wgParser->firstCallInit();
726 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
727 $this->getResult()->setIndexedTagName( $tags, 't' );
729 return $this->getResult()->addValue( 'query', $property, $tags );
732 public function appendFunctionHooks( $property ) {
733 global $wgParser;
734 $wgParser->firstCallInit();
735 $hooks = $wgParser->getFunctionHooks();
736 $this->getResult()->setIndexedTagName( $hooks, 'h' );
738 return $this->getResult()->addValue( 'query', $property, $hooks );
741 public function appendVariables( $property ) {
742 $variables = MagicWord::getVariableIDs();
743 $this->getResult()->setIndexedTagName( $variables, 'v' );
745 return $this->getResult()->addValue( 'query', $property, $variables );
748 public function appendProtocols( $property ) {
749 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
750 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
751 $this->getResult()->setIndexedTagName( $protocols, 'p' );
753 return $this->getResult()->addValue( 'query', $property, $protocols );
756 public function appendDefaultOptions( $property ) {
757 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
760 private function formatParserTags( $item ) {
761 return "<{$item}>";
764 public function appendSubscribedHooks( $property ) {
765 $hooks = $this->getConfig()->get( 'Hooks' );
766 $myWgHooks = $hooks;
767 ksort( $myWgHooks );
769 $data = array();
770 foreach ( $myWgHooks as $name => $subscribers ) {
771 $arr = array(
772 'name' => $name,
773 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $subscribers ),
776 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
777 $data[] = $arr;
780 $this->getResult()->setIndexedTagName( $data, 'hook' );
782 return $this->getResult()->addValue( 'query', $property, $data );
785 public function getCacheMode( $params ) {
786 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
787 if (
788 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
789 !is_null( $params['prop'] ) &&
790 in_array( 'interwikimap', $params['prop'] )
792 return 'anon-public-user-private';
795 return 'public';
798 public function getAllowedParams() {
799 return array(
800 'prop' => array(
801 ApiBase::PARAM_DFLT => 'general',
802 ApiBase::PARAM_ISMULTI => true,
803 ApiBase::PARAM_TYPE => array(
804 'general',
805 'namespaces',
806 'namespacealiases',
807 'specialpagealiases',
808 'magicwords',
809 'interwikimap',
810 'dbrepllag',
811 'statistics',
812 'usergroups',
813 'extensions',
814 'fileextensions',
815 'rightsinfo',
816 'restrictions',
817 'languages',
818 'skins',
819 'extensiontags',
820 'functionhooks',
821 'showhooks',
822 'variables',
823 'protocols',
824 'defaultoptions',
827 'filteriw' => array(
828 ApiBase::PARAM_TYPE => array(
829 'local',
830 '!local',
833 'showalldb' => false,
834 'numberingroup' => false,
835 'inlanguagecode' => null,
839 protected function getExamplesMessages() {
840 return array(
841 'action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics'
842 => 'apihelp-query+siteinfo-example-simple',
843 'action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local'
844 => 'apihelp-query+siteinfo-example-interwiki',
845 'action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb='
846 => 'apihelp-query+siteinfo-example-replag',
850 public function getHelpUrls() {
851 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';