Merge "Clarify docs for wgCookieExpiration"
[lhc/web/wiklou.git] / includes / api / ApiQuerySiteinfo.php
1 <?php
2 /**
3 *
4 *
5 * Created on Sep 25, 2006
6 *
7 * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
8 *
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.
13 *
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.
18 *
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
23 *
24 * @file
25 */
26
27 /**
28 * A query action to return meta information about the wiki site.
29 *
30 * @ingroup API
31 */
32 class ApiQuerySiteinfo extends ApiQueryBase {
33
34 public function __construct( $query, $moduleName ) {
35 parent::__construct( $query, $moduleName, 'si' );
36 }
37
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" );
110 }
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;
117 }
118 $done[] = $p;
119 }
120 }
121
122 protected function appendGeneralInfo( $property ) {
123 global $wgContLang, $wgDisableLangConversion, $wgDisableTitleConversion;
124
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'];
130
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 );
134
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();
140
141 $allowFrom = array( '' );
142 $allowException = true;
143 if ( !$GLOBALS['wgAllowExternalImages'] ) {
144 if ( $GLOBALS['wgEnableImageWhitelist'] ) {
145 $data['imagewhitelistenabled'] = '';
146 }
147 $allowFrom = $GLOBALS['wgAllowExternalImagesFrom'];
148 $allowException = !empty( $allowFrom );
149 }
150 if ( $allowException ) {
151 $data['externalimages'] = (array)$allowFrom;
152 $this->getResult()->setIndexedTagName( $data['externalimages'], 'prefix' );
153 }
154
155 if ( !$wgDisableLangConversion ) {
156 $data['langconversion'] = '';
157 }
158
159 if ( !$wgDisableTitleConversion ) {
160 $data['titleconversion'] = '';
161 }
162
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'] = '';
171 }
172
173 $linktrail = $wgContLang->linkTrail();
174 if ( $linktrail ) {
175 $data['linktrail'] = $linktrail;
176 } else {
177 $data['linktrail'] = '';
178 }
179
180 $git = SpecialVersion::getGitHeadSha1( $GLOBALS['IP'] );
181 if ( $git ) {
182 $data['git-hash'] = $git;
183 $data['git-branch'] =
184 SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
185 } else {
186 $svn = SpecialVersion::getSvnRevision( $GLOBALS['IP'] );
187 if ( $svn ) {
188 $data['rev'] = $svn;
189 }
190 }
191
192 // 'case-insensitive' option is reserved for future
193 $data['case'] = $GLOBALS['wgCapitalLinks'] ? 'first-letter' : 'case-sensitive';
194
195 $data['lang'] = $GLOBALS['wgLanguageCode'];
196
197 $fallbacks = array();
198 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
199 $fallbacks[] = array( 'code' => $code );
200 }
201 $data['fallback'] = $fallbacks;
202 $this->getResult()->setIndexedTagName( $data['fallback'], 'lang' );
203
204 if ( $wgContLang->hasVariants() ) {
205 $variants = array();
206 foreach ( $wgContLang->getVariants() as $code ) {
207 $variants[] = array(
208 'code' => $code,
209 'name' => $wgContLang->getVariantname( $code ),
210 );
211 }
212 $data['variants'] = $variants;
213 $this->getResult()->setIndexedTagName( $data['variants'], 'lang' );
214 }
215
216 if ( $wgContLang->isRTL() ) {
217 $data['rtl'] = '';
218 }
219 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
220
221 if ( wfReadOnly() ) {
222 $data['readonly'] = '';
223 $data['readonlyreason'] = wfReadOnlyReason();
224 }
225 if ( $GLOBALS['wgEnableWriteAPI'] ) {
226 $data['writeapi'] = '';
227 }
228
229 $tz = $GLOBALS['wgLocaltimezone'];
230 $offset = $GLOBALS['wgLocalTZoffset'];
231 if ( is_null( $tz ) ) {
232 $tz = 'UTC';
233 $offset = 0;
234 } elseif ( is_null( $offset ) ) {
235 $offset = 0;
236 }
237 $data['timezone'] = $tz;
238 $data['timeoffset'] = intval( $offset );
239 $data['articlepath'] = $GLOBALS['wgArticlePath'];
240 $data['scriptpath'] = $GLOBALS['wgScriptPath'];
241 $data['script'] = $GLOBALS['wgScript'];
242 $data['variantarticlepath'] = $GLOBALS['wgVariantArticlePath'];
243 $data['server'] = $GLOBALS['wgServer'];
244 $data['wikiid'] = wfWikiID();
245 $data['time'] = wfTimestamp( TS_ISO_8601, time() );
246
247 if ( $GLOBALS['wgMiserMode'] ) {
248 $data['misermode'] = '';
249 }
250
251 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
252
253 $data['thumblimits'] = $GLOBALS['wgThumbLimits'];
254 $this->getResult()->setIndexedTagName( $data['thumblimits'], 'limit' );
255 $data['imagelimits'] = array();
256 $this->getResult()->setIndexedTagName( $data['imagelimits'], 'limit' );
257 foreach ( $GLOBALS['wgImageLimits'] as $k => $limit ) {
258 $data['imagelimits'][$k] = array( 'width' => $limit[0], 'height' => $limit[1] );
259 }
260
261 if ( !empty( $GLOBALS['wgFavicon'] ) ) {
262 // wgFavicon can either be a relative or an absolute path
263 // make sure we always return an absolute path
264 $data['favicon'] = wfExpandUrl( $GLOBALS['wgFavicon'], PROTO_RELATIVE );
265 }
266
267 wfRunHooks( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
268
269 return $this->getResult()->addValue( 'query', $property, $data );
270 }
271
272 protected function appendNamespaces( $property ) {
273 global $wgContLang;
274 $data = array();
275 foreach ( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
276 $data[$ns] = array(
277 'id' => intval( $ns ),
278 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
279 );
280 ApiResult::setContent( $data[$ns], $title );
281 $canonical = MWNamespace::getCanonicalName( $ns );
282
283 if ( MWNamespace::hasSubpages( $ns ) ) {
284 $data[$ns]['subpages'] = '';
285 }
286
287 if ( $canonical ) {
288 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
289 }
290
291 if ( MWNamespace::isContent( $ns ) ) {
292 $data[$ns]['content'] = '';
293 }
294
295 if ( MWNamespace::isNonincludable( $ns ) ) {
296 $data[$ns]['nonincludable'] = '';
297 }
298
299 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
300 if ( $contentmodel ) {
301 $data[$ns]['defaultcontentmodel'] = $contentmodel;
302 }
303 }
304
305 $this->getResult()->setIndexedTagName( $data, 'ns' );
306
307 return $this->getResult()->addValue( 'query', $property, $data );
308 }
309
310 protected function appendNamespaceAliases( $property ) {
311 global $wgNamespaceAliases, $wgContLang;
312 $aliases = array_merge( $wgNamespaceAliases, $wgContLang->getNamespaceAliases() );
313 $namespaces = $wgContLang->getNamespaces();
314 $data = array();
315 foreach ( $aliases as $title => $ns ) {
316 if ( $namespaces[$ns] == $title ) {
317 // Don't list duplicates
318 continue;
319 }
320 $item = array(
321 'id' => intval( $ns )
322 );
323 ApiResult::setContent( $item, strtr( $title, '_', ' ' ) );
324 $data[] = $item;
325 }
326
327 sort( $data );
328
329 $this->getResult()->setIndexedTagName( $data, 'ns' );
330
331 return $this->getResult()->addValue( 'query', $property, $data );
332 }
333
334 protected function appendSpecialPageAliases( $property ) {
335 global $wgContLang;
336 $data = array();
337 $aliases = $wgContLang->getSpecialPageAliases();
338 foreach ( SpecialPageFactory::getList() as $specialpage => $stuff ) {
339 if ( isset( $aliases[$specialpage] ) ) {
340 $arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
341 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
342 $data[] = $arr;
343 }
344 }
345 $this->getResult()->setIndexedTagName( $data, 'specialpage' );
346
347 return $this->getResult()->addValue( 'query', $property, $data );
348 }
349
350 protected function appendMagicWords( $property ) {
351 global $wgContLang;
352 $data = array();
353 foreach ( $wgContLang->getMagicWords() as $magicword => $aliases ) {
354 $caseSensitive = array_shift( $aliases );
355 $arr = array( 'name' => $magicword, 'aliases' => $aliases );
356 if ( $caseSensitive ) {
357 $arr['case-sensitive'] = '';
358 }
359 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
360 $data[] = $arr;
361 }
362 $this->getResult()->setIndexedTagName( $data, 'magicword' );
363
364 return $this->getResult()->addValue( 'query', $property, $data );
365 }
366
367 protected function appendInterwikiMap( $property, $filter ) {
368 $local = null;
369 if ( $filter === 'local' ) {
370 $local = 1;
371 } elseif ( $filter === '!local' ) {
372 $local = 0;
373 } elseif ( $filter ) {
374 ApiBase::dieDebug( __METHOD__, "Unknown filter=$filter" );
375 }
376
377 $params = $this->extractRequestParams();
378 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
379 $langNames = Language::fetchLanguageNames( $langCode );
380
381 $getPrefixes = Interwiki::getAllPrefixes( $local );
382 $data = array();
383
384 foreach ( $getPrefixes as $row ) {
385 $prefix = $row['iw_prefix'];
386 $val = array();
387 $val['prefix'] = $prefix;
388 if ( $row['iw_local'] == '1' ) {
389 $val['local'] = '';
390 }
391 if ( $row['iw_trans'] == '1' ) {
392 $val['trans'] = '';
393 }
394 if ( isset( $langNames[$prefix] ) ) {
395 $val['language'] = $langNames[$prefix];
396 }
397 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
398 if ( isset( $row['iw_wikiid'] ) ) {
399 $val['wikiid'] = $row['iw_wikiid'];
400 }
401 if ( isset( $row['iw_api'] ) ) {
402 $val['api'] = $row['iw_api'];
403 }
404
405 $data[] = $val;
406 }
407
408 $this->getResult()->setIndexedTagName( $data, 'iw' );
409
410 return $this->getResult()->addValue( 'query', $property, $data );
411 }
412
413 protected function appendDbReplLagInfo( $property, $includeAll ) {
414 global $wgShowHostnames;
415 $data = array();
416 $lb = wfGetLB();
417 if ( $includeAll ) {
418 if ( !$wgShowHostnames ) {
419 $this->dieUsage(
420 'Cannot view all servers info unless $wgShowHostnames is true',
421 'includeAllDenied'
422 );
423 }
424
425 $lags = $lb->getLagTimes();
426 foreach ( $lags as $i => $lag ) {
427 $data[] = array(
428 'host' => $lb->getServerName( $i ),
429 'lag' => $lag
430 );
431 }
432 } else {
433 list( , $lag, $index ) = $lb->getMaxLag();
434 $data[] = array(
435 'host' => $wgShowHostnames
436 ? $lb->getServerName( $index )
437 : '',
438 'lag' => intval( $lag )
439 );
440 }
441
442 $result = $this->getResult();
443 $result->setIndexedTagName( $data, 'db' );
444
445 return $this->getResult()->addValue( 'query', $property, $data );
446 }
447
448 protected function appendStatistics( $property ) {
449 global $wgDisableCounters;
450 $data = array();
451 $data['pages'] = intval( SiteStats::pages() );
452 $data['articles'] = intval( SiteStats::articles() );
453 if ( !$wgDisableCounters ) {
454 $data['views'] = intval( SiteStats::views() );
455 }
456 $data['edits'] = intval( SiteStats::edits() );
457 $data['images'] = intval( SiteStats::images() );
458 $data['users'] = intval( SiteStats::users() );
459 $data['activeusers'] = intval( SiteStats::activeUsers() );
460 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
461 $data['jobs'] = intval( SiteStats::jobs() );
462
463 wfRunHooks( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
464
465 return $this->getResult()->addValue( 'query', $property, $data );
466 }
467
468 protected function appendUserGroups( $property, $numberInGroup ) {
469 global $wgGroupPermissions, $wgAddGroups, $wgRemoveGroups;
470 global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
471
472 $data = array();
473 $result = $this->getResult();
474 foreach ( $wgGroupPermissions as $group => $permissions ) {
475 $arr = array(
476 'name' => $group,
477 'rights' => array_keys( $permissions, true ),
478 );
479
480 if ( $numberInGroup ) {
481 global $wgAutopromote;
482
483 if ( $group == 'user' ) {
484 $arr['number'] = SiteStats::users();
485 // '*' and autopromote groups have no size
486 } elseif ( $group !== '*' && !isset( $wgAutopromote[$group] ) ) {
487 $arr['number'] = SiteStats::numberInGroup( $group );
488 }
489 }
490
491 $groupArr = array(
492 'add' => $wgAddGroups,
493 'remove' => $wgRemoveGroups,
494 'add-self' => $wgGroupsAddToSelf,
495 'remove-self' => $wgGroupsRemoveFromSelf
496 );
497
498 foreach ( $groupArr as $type => $rights ) {
499 if ( isset( $rights[$group] ) ) {
500 $arr[$type] = $rights[$group];
501 $result->setIndexedTagName( $arr[$type], 'group' );
502 }
503 }
504
505 $result->setIndexedTagName( $arr['rights'], 'permission' );
506 $data[] = $arr;
507 }
508
509 $result->setIndexedTagName( $data, 'group' );
510
511 return $result->addValue( 'query', $property, $data );
512 }
513
514 protected function appendFileExtensions( $property ) {
515 global $wgFileExtensions;
516
517 $data = array();
518 foreach ( array_unique( $wgFileExtensions ) as $ext ) {
519 $data[] = array( 'ext' => $ext );
520 }
521 $this->getResult()->setIndexedTagName( $data, 'fe' );
522
523 return $this->getResult()->addValue( 'query', $property, $data );
524 }
525
526 protected function appendExtensions( $property ) {
527 global $wgExtensionCredits;
528 $data = array();
529 foreach ( $wgExtensionCredits as $type => $extensions ) {
530 foreach ( $extensions as $ext ) {
531 $ret = array();
532 $ret['type'] = $type;
533 if ( isset( $ext['name'] ) ) {
534 $ret['name'] = $ext['name'];
535 }
536 if ( isset( $ext['description'] ) ) {
537 $ret['description'] = $ext['description'];
538 }
539 if ( isset( $ext['descriptionmsg'] ) ) {
540 // Can be a string or array( key, param1, param2, ... )
541 if ( is_array( $ext['descriptionmsg'] ) ) {
542 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
543 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
544 $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
545 } else {
546 $ret['descriptionmsg'] = $ext['descriptionmsg'];
547 }
548 }
549 if ( isset( $ext['author'] ) ) {
550 $ret['author'] = is_array( $ext['author'] ) ?
551 implode( ', ', $ext['author'] ) : $ext['author'];
552 }
553 if ( isset( $ext['url'] ) ) {
554 $ret['url'] = $ext['url'];
555 }
556 if ( isset( $ext['version'] ) ) {
557 $ret['version'] = $ext['version'];
558 } elseif ( isset( $ext['svn-revision'] ) &&
559 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
560 $ext['svn-revision'], $m )
561 ) {
562 $ret['version'] = 'r' . $m[1];
563 }
564 if ( isset( $ext['path'] ) ) {
565 $extensionPath = dirname( $ext['path'] );
566 $gitInfo = new GitInfo( $extensionPath );
567 $vcsVersion = $gitInfo->getHeadSHA1();
568 if ( $vcsVersion !== false ) {
569 $ret['vcs-system'] = 'git';
570 $ret['vcs-version'] = $vcsVersion;
571 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
572 $vcsDate = $gitInfo->getHeadCommitDate();
573 if ( $vcsDate !== false ) {
574 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
575 }
576 } else {
577 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
578 if ( $svnInfo !== false ) {
579 $ret['vcs-system'] = 'svn';
580 $ret['vcs-version'] = $svnInfo['checkout-rev'];
581 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
582 }
583 }
584
585 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
586 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
587 $ret['license'] = SpecialPage::getTitleFor(
588 'Version',
589 "License/{$ext['name']}"
590 )->getLinkURL();
591 }
592
593 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
594 $ret['credits'] = SpecialPage::getTitleFor(
595 'Version',
596 "Credits/{$ext['name']}"
597 )->getLinkURL();
598 }
599 }
600 $data[] = $ret;
601 }
602 }
603
604 $this->getResult()->setIndexedTagName( $data, 'ext' );
605
606 return $this->getResult()->addValue( 'query', $property, $data );
607 }
608
609 protected function appendRightsInfo( $property ) {
610 global $wgRightsPage, $wgRightsUrl, $wgRightsText;
611 $title = Title::newFromText( $wgRightsPage );
612 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $wgRightsUrl;
613 $text = $wgRightsText;
614 if ( !$text && $title ) {
615 $text = $title->getPrefixedText();
616 }
617
618 $data = array(
619 'url' => $url ? $url : '',
620 'text' => $text ? $text : ''
621 );
622
623 return $this->getResult()->addValue( 'query', $property, $data );
624 }
625
626 protected function appendRestrictions( $property ) {
627 global $wgRestrictionTypes, $wgRestrictionLevels,
628 $wgCascadingRestrictionLevels, $wgSemiprotectedRestrictionLevels;
629
630 $data = array(
631 'types' => $wgRestrictionTypes,
632 'levels' => $wgRestrictionLevels,
633 'cascadinglevels' => $wgCascadingRestrictionLevels,
634 'semiprotectedlevels' => $wgSemiprotectedRestrictionLevels,
635 );
636
637 $this->getResult()->setIndexedTagName( $data['types'], 'type' );
638 $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
639 $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
640 $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
641
642 return $this->getResult()->addValue( 'query', $property, $data );
643 }
644
645 public function appendLanguages( $property ) {
646 $params = $this->extractRequestParams();
647 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
648 $langNames = Language::fetchLanguageNames( $langCode );
649
650 $data = array();
651
652 foreach ( $langNames as $code => $name ) {
653 $lang = array( 'code' => $code );
654 ApiResult::setContent( $lang, $name );
655 $data[] = $lang;
656 }
657 $this->getResult()->setIndexedTagName( $data, 'lang' );
658
659 return $this->getResult()->addValue( 'query', $property, $data );
660 }
661
662 public function appendSkins( $property ) {
663 $data = array();
664 $allowed = Skin::getAllowedSkins();
665 $default = Skin::normalizeKey( 'default' );
666 foreach ( Skin::getSkinNames() as $name => $displayName ) {
667 $skin = array( 'code' => $name );
668 ApiResult::setContent( $skin, $displayName );
669 if ( !isset( $allowed[$name] ) ) {
670 $skin['unusable'] = '';
671 }
672 if ( $name === $default ) {
673 $skin['default'] = '';
674 }
675 $data[] = $skin;
676 }
677 $this->getResult()->setIndexedTagName( $data, 'skin' );
678
679 return $this->getResult()->addValue( 'query', $property, $data );
680 }
681
682 public function appendExtensionTags( $property ) {
683 global $wgParser;
684 $wgParser->firstCallInit();
685 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
686 $this->getResult()->setIndexedTagName( $tags, 't' );
687
688 return $this->getResult()->addValue( 'query', $property, $tags );
689 }
690
691 public function appendFunctionHooks( $property ) {
692 global $wgParser;
693 $wgParser->firstCallInit();
694 $hooks = $wgParser->getFunctionHooks();
695 $this->getResult()->setIndexedTagName( $hooks, 'h' );
696
697 return $this->getResult()->addValue( 'query', $property, $hooks );
698 }
699
700 public function appendVariables( $property ) {
701 $variables = MagicWord::getVariableIDs();
702 $this->getResult()->setIndexedTagName( $variables, 'v' );
703
704 return $this->getResult()->addValue( 'query', $property, $variables );
705 }
706
707 public function appendProtocols( $property ) {
708 global $wgUrlProtocols;
709 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
710 $protocols = array_values( $wgUrlProtocols );
711 $this->getResult()->setIndexedTagName( $protocols, 'p' );
712
713 return $this->getResult()->addValue( 'query', $property, $protocols );
714 }
715
716 public function appendDefaultOptions( $property ) {
717 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
718 }
719
720 private function formatParserTags( $item ) {
721 return "<{$item}>";
722 }
723
724 public function appendSubscribedHooks( $property ) {
725 global $wgHooks;
726 $myWgHooks = $wgHooks;
727 ksort( $myWgHooks );
728
729 $data = array();
730 foreach ( $myWgHooks as $hook => $hooks ) {
731 $arr = array(
732 'name' => $hook,
733 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $hooks ),
734 );
735
736 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
737 $data[] = $arr;
738 }
739
740 $this->getResult()->setIndexedTagName( $data, 'hook' );
741
742 return $this->getResult()->addValue( 'query', $property, $data );
743 }
744
745 public function getCacheMode( $params ) {
746 return 'public';
747 }
748
749 public function getAllowedParams() {
750 return array(
751 'prop' => array(
752 ApiBase::PARAM_DFLT => 'general',
753 ApiBase::PARAM_ISMULTI => true,
754 ApiBase::PARAM_TYPE => array(
755 'general',
756 'namespaces',
757 'namespacealiases',
758 'specialpagealiases',
759 'magicwords',
760 'interwikimap',
761 'dbrepllag',
762 'statistics',
763 'usergroups',
764 'extensions',
765 'fileextensions',
766 'rightsinfo',
767 'restrictions',
768 'languages',
769 'skins',
770 'extensiontags',
771 'functionhooks',
772 'showhooks',
773 'variables',
774 'protocols',
775 'defaultoptions',
776 )
777 ),
778 'filteriw' => array(
779 ApiBase::PARAM_TYPE => array(
780 'local',
781 '!local',
782 )
783 ),
784 'showalldb' => false,
785 'numberingroup' => false,
786 'inlanguagecode' => null,
787 );
788 }
789
790 public function getParamDescription() {
791 $p = $this->getModulePrefix();
792
793 return array(
794 'prop' => array(
795 'Which sysinfo properties to get:',
796 ' general - Overall system information',
797 ' namespaces - List of registered namespaces and their canonical names',
798 ' namespacealiases - List of registered namespace aliases',
799 ' specialpagealiases - List of special page aliases',
800 ' magicwords - List of magic words and their aliases',
801 ' statistics - Returns site statistics',
802 ' interwikimap - Returns interwiki map ' .
803 "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
804 ' dbrepllag - Returns database server with the highest replication lag',
805 ' usergroups - Returns user groups and the associated permissions',
806 ' extensions - Returns extensions installed on the wiki',
807 ' fileextensions - Returns list of file extensions allowed to be uploaded',
808 ' rightsinfo - Returns wiki rights (license) information if available',
809 ' restrictions - Returns information on available restriction (protection) types',
810 ' languages - Returns a list of languages MediaWiki supports' .
811 "(optionally localised by using {$p}inlanguagecode)",
812 ' skins - Returns a list of all enabled skins',
813 ' extensiontags - Returns a list of parser extension tags',
814 ' functionhooks - Returns a list of parser function hooks',
815 ' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
816 ' variables - Returns a list of variable IDs',
817 ' protocols - Returns a list of protocols that are allowed in external links.',
818 ' defaultoptions - Returns the default values for user preferences.',
819 ),
820 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
821 'showalldb' => 'List all database servers, not just the one lagging the most',
822 'numberingroup' => 'Lists the number of users in user groups',
823 'inlanguagecode' => 'Language code for localised language names ' .
824 '(best effort, use CLDR extension)',
825 );
826 }
827
828 public function getDescription() {
829 return 'Return general information about the site.';
830 }
831
832 public function getPossibleErrors() {
833 return array_merge( parent::getPossibleErrors(), array( array(
834 'code' => 'includeAllDenied',
835 'info' => 'Cannot view all servers info unless $wgShowHostnames is true'
836 ), ) );
837 }
838
839 public function getExamples() {
840 return array(
841 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
842 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
843 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb=',
844 );
845 }
846
847 public function getHelpUrls() {
848 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';
849 }
850 }