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