wfMsgForContentNoTrans() was removed
[mediawiki.git] / includes / api / ApiQuerySiteinfo.php
blobca9ceca59eea094b0b059ad1f18abfada86e9b5f
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 '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 default:
112 ApiBase::dieDebug( __METHOD__, "Unknown prop=$p" );
114 if ( !$fit ) {
115 // Abuse siprop as a query-continue parameter
116 // and set it to all unprocessed props
117 $this->setContinueEnumParameter( 'prop', implode( '|',
118 array_diff( $params['prop'], $done ) ) );
119 break;
121 $done[] = $p;
125 protected function appendGeneralInfo( $property ) {
126 global $wgContLang;
128 $config = $this->getConfig();
130 $data = array();
131 $mainPage = Title::newMainPage();
132 $data['mainpage'] = $mainPage->getPrefixedText();
133 $data['base'] = wfExpandUrl( $mainPage->getFullURL(), PROTO_CURRENT );
134 $data['sitename'] = $config->get( 'Sitename' );
136 // wgLogo can either be a relative or an absolute path
137 // make sure we always return an absolute path
138 $data['logo'] = wfExpandUrl( $config->get( 'Logo' ), PROTO_RELATIVE );
140 $data['generator'] = "MediaWiki {$config->get( 'Version' )}";
142 $data['phpversion'] = PHP_VERSION;
143 $data['phpsapi'] = PHP_SAPI;
144 if ( defined( 'HHVM_VERSION' ) ) {
145 $data['hhvmversion'] = HHVM_VERSION;
147 $data['dbtype'] = $config->get( 'DBtype' );
148 $data['dbversion'] = $this->getDB()->getServerVersion();
150 $allowFrom = array( '' );
151 $allowException = true;
152 if ( !$config->get( 'AllowExternalImages' ) ) {
153 $data['imagewhitelistenabled'] = (bool)$config->get( 'EnableImageWhitelist' );
154 $allowFrom = $config->get( 'AllowExternalImagesFrom' );
155 $allowException = !empty( $allowFrom );
157 if ( $allowException ) {
158 $data['externalimages'] = (array)$allowFrom;
159 ApiResult::setIndexedTagName( $data['externalimages'], 'prefix' );
162 $data['langconversion'] = !$config->get( 'DisableLangConversion' );
163 $data['titleconversion'] = !$config->get( 'DisableTitleConversion' );
165 if ( $wgContLang->linkPrefixExtension() ) {
166 $linkPrefixCharset = $wgContLang->linkPrefixCharset();
167 $data['linkprefixcharset'] = $linkPrefixCharset;
168 // For backwards compatibility
169 $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
170 } else {
171 $data['linkprefixcharset'] = '';
172 $data['linkprefix'] = '';
175 $linktrail = $wgContLang->linkTrail();
176 $data['linktrail'] = $linktrail ?: '';
178 $data['legaltitlechars'] = Title::legalChars();
179 $data['invalidusernamechars'] = $config->get( 'InvalidUsernameCharacters' );
181 global $IP;
182 $git = SpecialVersion::getGitHeadSha1( $IP );
183 if ( $git ) {
184 $data['git-hash'] = $git;
185 $data['git-branch'] =
186 SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
187 } else {
188 $svn = SpecialVersion::getSvnRevision( $IP );
189 if ( $svn ) {
190 $data['rev'] = $svn;
194 // 'case-insensitive' option is reserved for future
195 $data['case'] = $config->get( 'CapitalLinks' ) ? 'first-letter' : 'case-sensitive';
196 $data['lang'] = $config->get( 'LanguageCode' );
198 $fallbacks = array();
199 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
200 $fallbacks[] = array( 'code' => $code );
202 $data['fallback'] = $fallbacks;
203 ApiResult::setIndexedTagName( $data['fallback'], 'lang' );
205 if ( $wgContLang->hasVariants() ) {
206 $variants = array();
207 foreach ( $wgContLang->getVariants() as $code ) {
208 $variants[] = array(
209 'code' => $code,
210 'name' => $wgContLang->getVariantname( $code ),
213 $data['variants'] = $variants;
214 ApiResult::setIndexedTagName( $data['variants'], 'lang' );
217 $data['rtl'] = $wgContLang->isRTL();
218 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
220 $data['readonly'] = wfReadOnly();
221 if ( $data['readonly'] ) {
222 $data['readonlyreason'] = wfReadOnlyReason();
224 $data['writeapi'] = (bool)$config->get( 'EnableWriteAPI' );
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)$this->getConfig()->get( 'MinUploadChunkSize' );
252 $data['thumblimits'] = $config->get( 'ThumbLimits' );
253 ApiResult::setArrayType( $data['thumblimits'], 'BCassoc' );
254 ApiResult::setIndexedTagName( $data['thumblimits'], 'limit' );
255 $data['imagelimits'] = array();
256 ApiResult::setArrayType( $data['imagelimits'], 'BCassoc' );
257 ApiResult::setIndexedTagName( $data['imagelimits'], 'limit' );
258 foreach ( $config->get( 'ImageLimits' ) as $k => $limit ) {
259 $data['imagelimits'][$k] = array( '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'] = $this->getConfig()->get( 'CentralIdLookupProvider' );
270 $providerIds = array_keys( $this->getConfig()->get( 'CentralIdLookupProviders' ) );
271 $data['allcentralidlookupproviders'] = $providerIds;
273 Hooks::run( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
275 return $this->getResult()->addValue( 'query', $property, $data );
278 protected function appendNamespaces( $property ) {
279 global $wgContLang;
280 $data = array(
281 ApiResult::META_TYPE => 'assoc',
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::setContentValue( $data[$ns], 'name', $title );
289 $canonical = MWNamespace::getCanonicalName( $ns );
291 $data[$ns]['subpages'] = MWNamespace::hasSubpages( $ns );
293 if ( $canonical ) {
294 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
297 $data[$ns]['content'] = MWNamespace::isContent( $ns );
298 $data[$ns]['nonincludable'] = MWNamespace::isNonincludable( $ns );
300 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
301 if ( $contentmodel ) {
302 $data[$ns]['defaultcontentmodel'] = $contentmodel;
306 ApiResult::setArrayType( $data, 'assoc' );
307 ApiResult::setIndexedTagName( $data, 'ns' );
309 return $this->getResult()->addValue( 'query', $property, $data );
312 protected function appendNamespaceAliases( $property ) {
313 global $wgContLang;
314 $aliases = array_merge( $this->getConfig()->get( 'NamespaceAliases' ),
315 $wgContLang->getNamespaceAliases() );
316 $namespaces = $wgContLang->getNamespaces();
317 $data = array();
318 foreach ( $aliases as $title => $ns ) {
319 if ( $namespaces[$ns] == $title ) {
320 // Don't list duplicates
321 continue;
323 $item = array(
324 'id' => intval( $ns )
326 ApiResult::setContentValue( $item, 'alias', strtr( $title, '_', ' ' ) );
327 $data[] = $item;
330 sort( $data );
332 ApiResult::setIndexedTagName( $data, 'ns' );
334 return $this->getResult()->addValue( 'query', $property, $data );
337 protected function appendSpecialPageAliases( $property ) {
338 global $wgContLang;
339 $data = array();
340 $aliases = $wgContLang->getSpecialPageAliases();
341 foreach ( SpecialPageFactory::getNames() as $specialpage ) {
342 if ( isset( $aliases[$specialpage] ) ) {
343 $arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
344 ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
345 $data[] = $arr;
348 ApiResult::setIndexedTagName( $data, 'specialpage' );
350 return $this->getResult()->addValue( 'query', $property, $data );
353 protected function appendMagicWords( $property ) {
354 global $wgContLang;
355 $data = array();
356 foreach ( $wgContLang->getMagicWords() as $magicword => $aliases ) {
357 $caseSensitive = array_shift( $aliases );
358 $arr = array( 'name' => $magicword, 'aliases' => $aliases );
359 $arr['case-sensitive'] = (bool)$caseSensitive;
360 ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
361 $data[] = $arr;
363 ApiResult::setIndexedTagName( $data, 'magicword' );
365 return $this->getResult()->addValue( 'query', $property, $data );
368 protected function appendInterwikiMap( $property, $filter ) {
369 $local = null;
370 if ( $filter === 'local' ) {
371 $local = 1;
372 } elseif ( $filter === '!local' ) {
373 $local = 0;
374 } elseif ( $filter ) {
375 ApiBase::dieDebug( __METHOD__, "Unknown filter=$filter" );
378 $params = $this->extractRequestParams();
379 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
380 $langNames = Language::fetchLanguageNames( $langCode );
382 $getPrefixes = Interwiki::getAllPrefixes( $local );
383 $extraLangPrefixes = $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' );
384 $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
385 $data = array();
387 foreach ( $getPrefixes as $row ) {
388 $prefix = $row['iw_prefix'];
389 $val = array();
390 $val['prefix'] = $prefix;
391 if ( isset( $row['iw_local'] ) && $row['iw_local'] == '1' ) {
392 $val['local'] = true;
394 if ( isset( $row['iw_trans'] ) && $row['iw_trans'] == '1' ) {
395 $val['trans'] = true;
398 if ( isset( $langNames[$prefix] ) ) {
399 $val['language'] = $langNames[$prefix];
401 if ( in_array( $prefix, $localInterwikis ) ) {
402 $val['localinterwiki'] = true;
404 if ( in_array( $prefix, $extraLangPrefixes ) ) {
405 $val['extralanglink'] = true;
407 $linktext = wfMessage( "interlanguage-link-$prefix" );
408 if ( !$linktext->isDisabled() ) {
409 $val['linktext'] = $linktext->text();
412 $sitename = wfMessage( "interlanguage-link-sitename-$prefix" );
413 if ( !$sitename->isDisabled() ) {
414 $val['sitename'] = $sitename->text();
418 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
419 $val['protorel'] = substr( $row['iw_url'], 0, 2 ) == '//';
420 if ( isset( $row['iw_wikiid'] ) && $row['iw_wikiid'] !== '' ) {
421 $val['wikiid'] = $row['iw_wikiid'];
423 if ( isset( $row['iw_api'] ) && $row['iw_api'] !== '' ) {
424 $val['api'] = $row['iw_api'];
427 $data[] = $val;
430 ApiResult::setIndexedTagName( $data, 'iw' );
432 return $this->getResult()->addValue( 'query', $property, $data );
435 protected function appendDbReplLagInfo( $property, $includeAll ) {
436 $data = array();
437 $lb = wfGetLB();
438 $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
439 if ( $includeAll ) {
440 if ( !$showHostnames ) {
441 $this->dieUsage(
442 'Cannot view all servers info unless $wgShowHostnames is true',
443 'includeAllDenied'
447 $lags = $lb->getLagTimes();
448 foreach ( $lags as $i => $lag ) {
449 $data[] = array(
450 'host' => $lb->getServerName( $i ),
451 'lag' => $lag
454 } else {
455 list( , $lag, $index ) = $lb->getMaxLag();
456 $data[] = array(
457 'host' => $showHostnames
458 ? $lb->getServerName( $index )
459 : '',
460 'lag' => intval( $lag )
464 ApiResult::setIndexedTagName( $data, 'db' );
466 return $this->getResult()->addValue( 'query', $property, $data );
469 protected function appendStatistics( $property ) {
470 $data = array();
471 $data['pages'] = intval( SiteStats::pages() );
472 $data['articles'] = intval( SiteStats::articles() );
473 $data['edits'] = intval( SiteStats::edits() );
474 $data['images'] = intval( SiteStats::images() );
475 $data['users'] = intval( SiteStats::users() );
476 $data['activeusers'] = intval( SiteStats::activeUsers() );
477 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
478 $data['jobs'] = intval( SiteStats::jobs() );
480 Hooks::run( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
482 return $this->getResult()->addValue( 'query', $property, $data );
485 protected function appendUserGroups( $property, $numberInGroup ) {
486 $config = $this->getConfig();
488 $data = array();
489 $result = $this->getResult();
490 $allGroups = User::getAllGroups();
491 foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
492 $arr = array(
493 'name' => $group,
494 'rights' => array_keys( $permissions, true ),
497 if ( $numberInGroup ) {
498 $autopromote = $config->get( 'Autopromote' );
500 if ( $group == 'user' ) {
501 $arr['number'] = SiteStats::users();
502 // '*' and autopromote groups have no size
503 } elseif ( $group !== '*' && !isset( $autopromote[$group] ) ) {
504 $arr['number'] = SiteStats::numberingroup( $group );
508 $groupArr = array(
509 'add' => $config->get( 'AddGroups' ),
510 'remove' => $config->get( 'RemoveGroups' ),
511 'add-self' => $config->get( 'GroupsAddToSelf' ),
512 'remove-self' => $config->get( 'GroupsRemoveFromSelf' )
515 foreach ( $groupArr as $type => $rights ) {
516 if ( isset( $rights[$group] ) ) {
517 $groups = array_intersect( $rights[$group], $allGroups );
518 if ( $groups ) {
519 $arr[$type] = $groups;
520 ApiResult::setArrayType( $arr[$type], 'BCarray' );
521 ApiResult::setIndexedTagName( $arr[$type], 'group' );
526 ApiResult::setIndexedTagName( $arr['rights'], 'permission' );
527 $data[] = $arr;
530 ApiResult::setIndexedTagName( $data, 'group' );
532 return $result->addValue( 'query', $property, $data );
535 protected function appendFileExtensions( $property ) {
536 $data = array();
537 foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
538 $data[] = array( 'ext' => $ext );
540 ApiResult::setIndexedTagName( $data, 'fe' );
542 return $this->getResult()->addValue( 'query', $property, $data );
545 protected function appendInstalledLibraries( $property ) {
546 global $IP;
547 $path = "$IP/vendor/composer/installed.json";
548 if ( !file_exists( $path ) ) {
549 return true;
552 $data = array();
553 $installed = new ComposerInstalled( $path );
554 foreach ( $installed->getInstalledDependencies() as $name => $info ) {
555 if ( strpos( $info['type'], 'mediawiki-' ) === 0 ) {
556 // Skip any extensions or skins since they'll be listed
557 // in their proper section
558 continue;
560 $data[] = array(
561 'name' => $name,
562 'version' => $info['version'],
565 ApiResult::setIndexedTagName( $data, 'library' );
567 return $this->getResult()->addValue( 'query', $property, $data );
571 protected function appendExtensions( $property ) {
572 $data = array();
573 foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $type => $extensions ) {
574 foreach ( $extensions as $ext ) {
575 $ret = array();
576 $ret['type'] = $type;
577 if ( isset( $ext['name'] ) ) {
578 $ret['name'] = $ext['name'];
580 if ( isset( $ext['namemsg'] ) ) {
581 $ret['namemsg'] = $ext['namemsg'];
583 if ( isset( $ext['description'] ) ) {
584 $ret['description'] = $ext['description'];
586 if ( isset( $ext['descriptionmsg'] ) ) {
587 // Can be a string or array( key, param1, param2, ... )
588 if ( is_array( $ext['descriptionmsg'] ) ) {
589 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
590 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
591 ApiResult::setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
592 } else {
593 $ret['descriptionmsg'] = $ext['descriptionmsg'];
596 if ( isset( $ext['author'] ) ) {
597 $ret['author'] = is_array( $ext['author'] ) ?
598 implode( ', ', $ext['author'] ) : $ext['author'];
600 if ( isset( $ext['url'] ) ) {
601 $ret['url'] = $ext['url'];
603 if ( isset( $ext['version'] ) ) {
604 $ret['version'] = $ext['version'];
605 } elseif ( isset( $ext['svn-revision'] ) &&
606 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
607 $ext['svn-revision'], $m )
609 $ret['version'] = 'r' . $m[1];
611 if ( isset( $ext['path'] ) ) {
612 $extensionPath = dirname( $ext['path'] );
613 $gitInfo = new GitInfo( $extensionPath );
614 $vcsVersion = $gitInfo->getHeadSHA1();
615 if ( $vcsVersion !== false ) {
616 $ret['vcs-system'] = 'git';
617 $ret['vcs-version'] = $vcsVersion;
618 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
619 $vcsDate = $gitInfo->getHeadCommitDate();
620 if ( $vcsDate !== false ) {
621 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
623 } else {
624 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
625 if ( $svnInfo !== false ) {
626 $ret['vcs-system'] = 'svn';
627 $ret['vcs-version'] = $svnInfo['checkout-rev'];
628 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
632 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
633 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
634 $ret['license'] = SpecialPage::getTitleFor(
635 'Version',
636 "License/{$ext['name']}"
637 )->getLinkURL();
640 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
641 $ret['credits'] = SpecialPage::getTitleFor(
642 'Version',
643 "Credits/{$ext['name']}"
644 )->getLinkURL();
647 $data[] = $ret;
651 ApiResult::setIndexedTagName( $data, 'ext' );
653 return $this->getResult()->addValue( 'query', $property, $data );
656 protected function appendRightsInfo( $property ) {
657 $config = $this->getConfig();
658 $rightsPage = $config->get( 'RightsPage' );
659 if ( is_string( $rightsPage ) ) {
660 $title = Title::newFromText( $rightsPage );
661 $url = wfExpandUrl( $title, PROTO_CURRENT );
662 } else {
663 $title = false;
664 $url = $config->get( 'RightsUrl' );
666 $text = $config->get( 'RightsText' );
667 if ( !$text && $title ) {
668 $text = $title->getPrefixedText();
671 $data = array(
672 'url' => $url ? $url : '',
673 'text' => $text ? $text : ''
676 return $this->getResult()->addValue( 'query', $property, $data );
679 protected function appendRestrictions( $property ) {
680 $config = $this->getConfig();
681 $data = array(
682 'types' => $config->get( 'RestrictionTypes' ),
683 'levels' => $config->get( 'RestrictionLevels' ),
684 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
685 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
688 ApiResult::setArrayType( $data['types'], 'BCarray' );
689 ApiResult::setArrayType( $data['levels'], 'BCarray' );
690 ApiResult::setArrayType( $data['cascadinglevels'], 'BCarray' );
691 ApiResult::setArrayType( $data['semiprotectedlevels'], 'BCarray' );
693 ApiResult::setIndexedTagName( $data['types'], 'type' );
694 ApiResult::setIndexedTagName( $data['levels'], 'level' );
695 ApiResult::setIndexedTagName( $data['cascadinglevels'], 'level' );
696 ApiResult::setIndexedTagName( $data['semiprotectedlevels'], 'level' );
698 return $this->getResult()->addValue( 'query', $property, $data );
701 public function appendLanguages( $property ) {
702 $params = $this->extractRequestParams();
703 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
704 $langNames = Language::fetchLanguageNames( $langCode );
706 $data = array();
708 foreach ( $langNames as $code => $name ) {
709 $lang = array( 'code' => $code );
710 ApiResult::setContentValue( $lang, 'name', $name );
711 $data[] = $lang;
713 ApiResult::setIndexedTagName( $data, 'lang' );
715 return $this->getResult()->addValue( 'query', $property, $data );
718 public function appendSkins( $property ) {
719 $data = array();
720 $allowed = Skin::getAllowedSkins();
721 $default = Skin::normalizeKey( 'default' );
722 foreach ( Skin::getSkinNames() as $name => $displayName ) {
723 $msg = $this->msg( "skinname-{$name}" );
724 $code = $this->getParameter( 'inlanguagecode' );
725 if ( $code && Language::isValidCode( $code ) ) {
726 $msg->inLanguage( $code );
727 } else {
728 $msg->inContentLanguage();
730 if ( $msg->exists() ) {
731 $displayName = $msg->text();
733 $skin = array( 'code' => $name );
734 ApiResult::setContentValue( $skin, 'name', $displayName );
735 if ( !isset( $allowed[$name] ) ) {
736 $skin['unusable'] = true;
738 if ( $name === $default ) {
739 $skin['default'] = true;
741 $data[] = $skin;
743 ApiResult::setIndexedTagName( $data, 'skin' );
745 return $this->getResult()->addValue( 'query', $property, $data );
748 public function appendExtensionTags( $property ) {
749 global $wgParser;
750 $wgParser->firstCallInit();
751 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
752 ApiResult::setArrayType( $tags, 'BCarray' );
753 ApiResult::setIndexedTagName( $tags, 't' );
755 return $this->getResult()->addValue( 'query', $property, $tags );
758 public function appendFunctionHooks( $property ) {
759 global $wgParser;
760 $wgParser->firstCallInit();
761 $hooks = $wgParser->getFunctionHooks();
762 ApiResult::setArrayType( $hooks, 'BCarray' );
763 ApiResult::setIndexedTagName( $hooks, 'h' );
765 return $this->getResult()->addValue( 'query', $property, $hooks );
768 public function appendVariables( $property ) {
769 $variables = MagicWord::getVariableIDs();
770 ApiResult::setArrayType( $variables, 'BCarray' );
771 ApiResult::setIndexedTagName( $variables, 'v' );
773 return $this->getResult()->addValue( 'query', $property, $variables );
776 public function appendProtocols( $property ) {
777 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
778 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
779 ApiResult::setArrayType( $protocols, 'BCarray' );
780 ApiResult::setIndexedTagName( $protocols, 'p' );
782 return $this->getResult()->addValue( 'query', $property, $protocols );
785 public function appendDefaultOptions( $property ) {
786 $options = User::getDefaultOptions();
787 $options[ApiResult::META_BC_BOOLS] = array_keys( $options );
788 return $this->getResult()->addValue( 'query', $property, $options );
791 private function formatParserTags( $item ) {
792 return "<{$item}>";
795 public function appendSubscribedHooks( $property ) {
796 $hooks = $this->getConfig()->get( 'Hooks' );
797 $myWgHooks = $hooks;
798 ksort( $myWgHooks );
800 $data = array();
801 foreach ( $myWgHooks as $name => $subscribers ) {
802 $arr = array(
803 'name' => $name,
804 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $subscribers ),
807 ApiResult::setArrayType( $arr['subscribers'], 'array' );
808 ApiResult::setIndexedTagName( $arr['subscribers'], 's' );
809 $data[] = $arr;
812 ApiResult::setIndexedTagName( $data, 'hook' );
814 return $this->getResult()->addValue( 'query', $property, $data );
817 public function getCacheMode( $params ) {
818 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
819 if (
820 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
821 !is_null( $params['prop'] ) &&
822 in_array( 'interwikimap', $params['prop'] )
824 return 'anon-public-user-private';
827 return 'public';
830 public function getAllowedParams() {
831 return array(
832 'prop' => array(
833 ApiBase::PARAM_DFLT => 'general',
834 ApiBase::PARAM_ISMULTI => true,
835 ApiBase::PARAM_TYPE => array(
836 'general',
837 'namespaces',
838 'namespacealiases',
839 'specialpagealiases',
840 'magicwords',
841 'interwikimap',
842 'dbrepllag',
843 'statistics',
844 'usergroups',
845 'libraries',
846 'extensions',
847 'fileextensions',
848 'rightsinfo',
849 'restrictions',
850 'languages',
851 'skins',
852 'extensiontags',
853 'functionhooks',
854 'showhooks',
855 'variables',
856 'protocols',
857 'defaultoptions',
859 ApiBase::PARAM_HELP_MSG_PER_VALUE => array(),
861 'filteriw' => array(
862 ApiBase::PARAM_TYPE => array(
863 'local',
864 '!local',
867 'showalldb' => false,
868 'numberingroup' => false,
869 'inlanguagecode' => null,
873 protected function getExamplesMessages() {
874 return array(
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';