Merge "Move profile In/OUT call out of MWPHPUnitCommand"
[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 } else {
184 $svn = SpecialVersion::getSvnRevision( $GLOBALS['IP'] );
185 if ( $svn ) {
186 $data['rev'] = $svn;
187 }
188 }
189
190 // 'case-insensitive' option is reserved for future
191 $data['case'] = $GLOBALS['wgCapitalLinks'] ? 'first-letter' : 'case-sensitive';
192
193 $data['lang'] = $GLOBALS['wgLanguageCode'];
194
195 $fallbacks = array();
196 foreach ( $wgContLang->getFallbackLanguages() as $code ) {
197 $fallbacks[] = array( 'code' => $code );
198 }
199 $data['fallback'] = $fallbacks;
200 $this->getResult()->setIndexedTagName( $data['fallback'], 'lang' );
201
202 if ( $wgContLang->hasVariants() ) {
203 $variants = array();
204 foreach ( $wgContLang->getVariants() as $code ) {
205 $variants[] = array(
206 'code' => $code,
207 'name' => $wgContLang->getVariantname( $code ),
208 );
209 }
210 $data['variants'] = $variants;
211 $this->getResult()->setIndexedTagName( $data['variants'], 'lang' );
212 }
213
214 if ( $wgContLang->isRTL() ) {
215 $data['rtl'] = '';
216 }
217 $data['fallback8bitEncoding'] = $wgContLang->fallback8bitEncoding();
218
219 if ( wfReadOnly() ) {
220 $data['readonly'] = '';
221 $data['readonlyreason'] = wfReadOnlyReason();
222 }
223 if ( $GLOBALS['wgEnableWriteAPI'] ) {
224 $data['writeapi'] = '';
225 }
226
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;
234 }
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() );
244
245 if ( $GLOBALS['wgMiserMode'] ) {
246 $data['misermode'] = '';
247 }
248
249 $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
250
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] );
257 }
258
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 );
263 }
264
265 wfRunHooks( 'APIQuerySiteInfoGeneralInfo', array( $this, &$data ) );
266
267 return $this->getResult()->addValue( 'query', $property, $data );
268 }
269
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',
277 );
278 ApiResult::setContent( $data[$ns], $title );
279 $canonical = MWNamespace::getCanonicalName( $ns );
280
281 if ( MWNamespace::hasSubpages( $ns ) ) {
282 $data[$ns]['subpages'] = '';
283 }
284
285 if ( $canonical ) {
286 $data[$ns]['canonical'] = strtr( $canonical, '_', ' ' );
287 }
288
289 if ( MWNamespace::isContent( $ns ) ) {
290 $data[$ns]['content'] = '';
291 }
292
293 if ( MWNamespace::isNonincludable( $ns ) ) {
294 $data[$ns]['nonincludable'] = '';
295 }
296
297 $contentmodel = MWNamespace::getNamespaceContentModel( $ns );
298 if ( $contentmodel ) {
299 $data[$ns]['defaultcontentmodel'] = $contentmodel;
300 }
301 }
302
303 $this->getResult()->setIndexedTagName( $data, 'ns' );
304
305 return $this->getResult()->addValue( 'query', $property, $data );
306 }
307
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;
317 }
318 $item = array(
319 'id' => intval( $ns )
320 );
321 ApiResult::setContent( $item, strtr( $title, '_', ' ' ) );
322 $data[] = $item;
323 }
324
325 sort( $data );
326
327 $this->getResult()->setIndexedTagName( $data, 'ns' );
328
329 return $this->getResult()->addValue( 'query', $property, $data );
330 }
331
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;
341 }
342 }
343 $this->getResult()->setIndexedTagName( $data, 'specialpage' );
344
345 return $this->getResult()->addValue( 'query', $property, $data );
346 }
347
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'] = '';
356 }
357 $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
358 $data[] = $arr;
359 }
360 $this->getResult()->setIndexedTagName( $data, 'magicword' );
361
362 return $this->getResult()->addValue( 'query', $property, $data );
363 }
364
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" );
373 }
374
375 $params = $this->extractRequestParams();
376 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
377 $langNames = Language::fetchLanguageNames( $langCode );
378
379 $getPrefixes = Interwiki::getAllPrefixes( $local );
380 $data = array();
381
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'] = '';
388 }
389 if ( $row['iw_trans'] == '1' ) {
390 $val['trans'] = '';
391 }
392 if ( isset( $langNames[$prefix] ) ) {
393 $val['language'] = $langNames[$prefix];
394 }
395 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
396 if ( isset( $row['iw_wikiid'] ) ) {
397 $val['wikiid'] = $row['iw_wikiid'];
398 }
399 if ( isset( $row['iw_api'] ) ) {
400 $val['api'] = $row['iw_api'];
401 }
402
403 $data[] = $val;
404 }
405
406 $this->getResult()->setIndexedTagName( $data, 'iw' );
407
408 return $this->getResult()->addValue( 'query', $property, $data );
409 }
410
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'
420 );
421 }
422
423 $lags = $lb->getLagTimes();
424 foreach ( $lags as $i => $lag ) {
425 $data[] = array(
426 'host' => $lb->getServerName( $i ),
427 'lag' => $lag
428 );
429 }
430 } else {
431 list( , $lag, $index ) = $lb->getMaxLag();
432 $data[] = array(
433 'host' => $wgShowHostnames
434 ? $lb->getServerName( $index )
435 : '',
436 'lag' => intval( $lag )
437 );
438 }
439
440 $result = $this->getResult();
441 $result->setIndexedTagName( $data, 'db' );
442
443 return $this->getResult()->addValue( 'query', $property, $data );
444 }
445
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() );
453 }
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() );
460
461 wfRunHooks( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
462
463 return $this->getResult()->addValue( 'query', $property, $data );
464 }
465
466 protected function appendUserGroups( $property, $numberInGroup ) {
467 global $wgGroupPermissions, $wgAddGroups, $wgRemoveGroups;
468 global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
469
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 ),
476 );
477
478 if ( $numberInGroup ) {
479 global $wgAutopromote;
480
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 );
486 }
487 }
488
489 $groupArr = array(
490 'add' => $wgAddGroups,
491 'remove' => $wgRemoveGroups,
492 'add-self' => $wgGroupsAddToSelf,
493 'remove-self' => $wgGroupsRemoveFromSelf
494 );
495
496 foreach ( $groupArr as $type => $rights ) {
497 if ( isset( $rights[$group] ) ) {
498 $arr[$type] = $rights[$group];
499 $result->setIndexedTagName( $arr[$type], 'group' );
500 }
501 }
502
503 $result->setIndexedTagName( $arr['rights'], 'permission' );
504 $data[] = $arr;
505 }
506
507 $result->setIndexedTagName( $data, 'group' );
508
509 return $result->addValue( 'query', $property, $data );
510 }
511
512 protected function appendFileExtensions( $property ) {
513 global $wgFileExtensions;
514
515 $data = array();
516 foreach ( array_unique( $wgFileExtensions ) as $ext ) {
517 $data[] = array( 'ext' => $ext );
518 }
519 $this->getResult()->setIndexedTagName( $data, 'fe' );
520
521 return $this->getResult()->addValue( 'query', $property, $data );
522 }
523
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'];
533 }
534 if ( isset( $ext['description'] ) ) {
535 $ret['description'] = $ext['description'];
536 }
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'];
545 }
546 }
547 if ( isset( $ext['author'] ) ) {
548 $ret['author'] = is_array( $ext['author'] ) ?
549 implode( ', ', $ext['author'] ) : $ext['author'];
550 }
551 if ( isset( $ext['url'] ) ) {
552 $ret['url'] = $ext['url'];
553 }
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 )
559 ) {
560 $ret['version'] = 'r' . $m[1];
561 }
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 );
573 }
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'] : '';
580 }
581 }
582
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();
589 }
590
591 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
592 $ret['credits'] = SpecialPage::getTitleFor(
593 'Version',
594 "Credits/{$ext['name']}"
595 )->getLinkURL();
596 }
597 }
598 $data[] = $ret;
599 }
600 }
601
602 $this->getResult()->setIndexedTagName( $data, 'ext' );
603
604 return $this->getResult()->addValue( 'query', $property, $data );
605 }
606
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();
614 }
615
616 $data = array(
617 'url' => $url ? $url : '',
618 'text' => $text ? $text : ''
619 );
620
621 return $this->getResult()->addValue( 'query', $property, $data );
622 }
623
624 protected function appendRestrictions( $property ) {
625 global $wgRestrictionTypes, $wgRestrictionLevels,
626 $wgCascadingRestrictionLevels, $wgSemiprotectedRestrictionLevels;
627
628 $data = array(
629 'types' => $wgRestrictionTypes,
630 'levels' => $wgRestrictionLevels,
631 'cascadinglevels' => $wgCascadingRestrictionLevels,
632 'semiprotectedlevels' => $wgSemiprotectedRestrictionLevels,
633 );
634
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' );
639
640 return $this->getResult()->addValue( 'query', $property, $data );
641 }
642
643 public function appendLanguages( $property ) {
644 $params = $this->extractRequestParams();
645 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
646 $langNames = Language::fetchLanguageNames( $langCode );
647
648 $data = array();
649
650 foreach ( $langNames as $code => $name ) {
651 $lang = array( 'code' => $code );
652 ApiResult::setContent( $lang, $name );
653 $data[] = $lang;
654 }
655 $this->getResult()->setIndexedTagName( $data, 'lang' );
656
657 return $this->getResult()->addValue( 'query', $property, $data );
658 }
659
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'] = '';
669 }
670 if ( $name === $default ) {
671 $skin['default'] = '';
672 }
673 $data[] = $skin;
674 }
675 $this->getResult()->setIndexedTagName( $data, 'skin' );
676
677 return $this->getResult()->addValue( 'query', $property, $data );
678 }
679
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' );
685
686 return $this->getResult()->addValue( 'query', $property, $tags );
687 }
688
689 public function appendFunctionHooks( $property ) {
690 global $wgParser;
691 $wgParser->firstCallInit();
692 $hooks = $wgParser->getFunctionHooks();
693 $this->getResult()->setIndexedTagName( $hooks, 'h' );
694
695 return $this->getResult()->addValue( 'query', $property, $hooks );
696 }
697
698 public function appendVariables( $property ) {
699 $variables = MagicWord::getVariableIDs();
700 $this->getResult()->setIndexedTagName( $variables, 'v' );
701
702 return $this->getResult()->addValue( 'query', $property, $variables );
703 }
704
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' );
710
711 return $this->getResult()->addValue( 'query', $property, $protocols );
712 }
713
714 public function appendDefaultOptions( $property ) {
715 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
716 }
717
718 private function formatParserTags( $item ) {
719 return "<{$item}>";
720 }
721
722 public function appendSubscribedHooks( $property ) {
723 global $wgHooks;
724 $myWgHooks = $wgHooks;
725 ksort( $myWgHooks );
726
727 $data = array();
728 foreach ( $myWgHooks as $hook => $hooks ) {
729 $arr = array(
730 'name' => $hook,
731 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $hooks ),
732 );
733
734 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
735 $data[] = $arr;
736 }
737
738 $this->getResult()->setIndexedTagName( $data, 'hook' );
739
740 return $this->getResult()->addValue( 'query', $property, $data );
741 }
742
743 public function getCacheMode( $params ) {
744 return 'public';
745 }
746
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',
774 )
775 ),
776 'filteriw' => array(
777 ApiBase::PARAM_TYPE => array(
778 'local',
779 '!local',
780 )
781 ),
782 'showalldb' => false,
783 'numberingroup' => false,
784 'inlanguagecode' => null,
785 );
786 }
787
788 public function getParamDescription() {
789 $p = $this->getModulePrefix();
790
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.',
817 ),
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)',
823 );
824 }
825
826 public function getDescription() {
827 return 'Return general information about the site.';
828 }
829
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 ), ) );
835 }
836
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=',
842 );
843 }
844
845 public function getHelpUrls() {
846 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';
847 }
848 }