Merge "Improve clarity of diff-multi message"
[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 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
577 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
578 $ret['license'] = SpecialPage::getTitleFor( 'Version', "License/{$ext['name']}" )->getLinkURL();
579 }
580 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
581 $ret['credits'] = SpecialPage::getTitleFor( 'Version', "Credits/{$ext['name']}" )->getLinkURL();
582 }
583 }
584 $data[] = $ret;
585 }
586 }
587
588 $this->getResult()->setIndexedTagName( $data, 'ext' );
589
590 return $this->getResult()->addValue( 'query', $property, $data );
591 }
592
593 protected function appendRightsInfo( $property ) {
594 global $wgRightsPage, $wgRightsUrl, $wgRightsText;
595 $title = Title::newFromText( $wgRightsPage );
596 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $wgRightsUrl;
597 $text = $wgRightsText;
598 if ( !$text && $title ) {
599 $text = $title->getPrefixedText();
600 }
601
602 $data = array(
603 'url' => $url ? $url : '',
604 'text' => $text ? $text : ''
605 );
606
607 return $this->getResult()->addValue( 'query', $property, $data );
608 }
609
610 public function appendLanguages( $property ) {
611 $params = $this->extractRequestParams();
612 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
613 $langNames = Language::fetchLanguageNames( $langCode );
614
615 $data = array();
616
617 foreach ( $langNames as $code => $name ) {
618 $lang = array( 'code' => $code );
619 ApiResult::setContent( $lang, $name );
620 $data[] = $lang;
621 }
622 $this->getResult()->setIndexedTagName( $data, 'lang' );
623
624 return $this->getResult()->addValue( 'query', $property, $data );
625 }
626
627 public function appendSkins( $property ) {
628 $data = array();
629 $usable = Skin::getUsableSkins();
630 $default = Skin::normalizeKey( 'default' );
631 foreach ( Skin::getSkinNames() as $name => $displayName ) {
632 $skin = array( 'code' => $name );
633 ApiResult::setContent( $skin, $displayName );
634 if ( !isset( $usable[$name] ) ) {
635 $skin['unusable'] = '';
636 }
637 if ( $name === $default ) {
638 $skin['default'] = '';
639 }
640 $data[] = $skin;
641 }
642 $this->getResult()->setIndexedTagName( $data, 'skin' );
643
644 return $this->getResult()->addValue( 'query', $property, $data );
645 }
646
647 public function appendExtensionTags( $property ) {
648 global $wgParser;
649 $wgParser->firstCallInit();
650 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
651 $this->getResult()->setIndexedTagName( $tags, 't' );
652
653 return $this->getResult()->addValue( 'query', $property, $tags );
654 }
655
656 public function appendFunctionHooks( $property ) {
657 global $wgParser;
658 $wgParser->firstCallInit();
659 $hooks = $wgParser->getFunctionHooks();
660 $this->getResult()->setIndexedTagName( $hooks, 'h' );
661
662 return $this->getResult()->addValue( 'query', $property, $hooks );
663 }
664
665 public function appendVariables( $property ) {
666 $variables = MagicWord::getVariableIDs();
667 $this->getResult()->setIndexedTagName( $variables, 'v' );
668
669 return $this->getResult()->addValue( 'query', $property, $variables );
670 }
671
672 public function appendProtocols( $property ) {
673 global $wgUrlProtocols;
674 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
675 $protocols = array_values( $wgUrlProtocols );
676 $this->getResult()->setIndexedTagName( $protocols, 'p' );
677
678 return $this->getResult()->addValue( 'query', $property, $protocols );
679 }
680
681 public function appendDefaultOptions( $property ) {
682 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
683 }
684
685 private function formatParserTags( $item ) {
686 return "<{$item}>";
687 }
688
689 public function appendSubscribedHooks( $property ) {
690 global $wgHooks;
691 $myWgHooks = $wgHooks;
692 ksort( $myWgHooks );
693
694 $data = array();
695 foreach ( $myWgHooks as $hook => $hooks ) {
696 $arr = array(
697 'name' => $hook,
698 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $hooks ),
699 );
700
701 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
702 $data[] = $arr;
703 }
704
705 $this->getResult()->setIndexedTagName( $data, 'hook' );
706
707 return $this->getResult()->addValue( 'query', $property, $data );
708 }
709
710 public function getCacheMode( $params ) {
711 return 'public';
712 }
713
714 public function getAllowedParams() {
715 return array(
716 'prop' => array(
717 ApiBase::PARAM_DFLT => 'general',
718 ApiBase::PARAM_ISMULTI => true,
719 ApiBase::PARAM_TYPE => array(
720 'general',
721 'namespaces',
722 'namespacealiases',
723 'specialpagealiases',
724 'magicwords',
725 'interwikimap',
726 'dbrepllag',
727 'statistics',
728 'usergroups',
729 'extensions',
730 'fileextensions',
731 'rightsinfo',
732 'languages',
733 'skins',
734 'extensiontags',
735 'functionhooks',
736 'showhooks',
737 'variables',
738 'protocols',
739 'defaultoptions',
740 )
741 ),
742 'filteriw' => array(
743 ApiBase::PARAM_TYPE => array(
744 'local',
745 '!local',
746 )
747 ),
748 'showalldb' => false,
749 'numberingroup' => false,
750 'inlanguagecode' => null,
751 );
752 }
753
754 public function getParamDescription() {
755 $p = $this->getModulePrefix();
756
757 return array(
758 'prop' => array(
759 'Which sysinfo properties to get:',
760 ' general - Overall system information',
761 ' namespaces - List of registered namespaces and their canonical names',
762 ' namespacealiases - List of registered namespace aliases',
763 ' specialpagealiases - List of special page aliases',
764 ' magicwords - List of magic words and their aliases',
765 ' statistics - Returns site statistics',
766 ' interwikimap - Returns interwiki map ' .
767 "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
768 ' dbrepllag - Returns database server with the highest replication lag',
769 ' usergroups - Returns user groups and the associated permissions',
770 ' extensions - Returns extensions installed on the wiki',
771 ' fileextensions - Returns list of file extensions allowed to be uploaded',
772 ' rightsinfo - Returns wiki rights (license) information if available',
773 ' languages - Returns a list of languages MediaWiki supports' .
774 "(optionally localised by using {$p}inlanguagecode)",
775 ' skins - Returns a list of all enabled skins',
776 ' extensiontags - Returns a list of parser extension tags',
777 ' functionhooks - Returns a list of parser function hooks',
778 ' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
779 ' variables - Returns a list of variable IDs',
780 ' protocols - Returns a list of protocols that are allowed in external links.',
781 ' defaultoptions - Returns the default values for user preferences.',
782 ),
783 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
784 'showalldb' => 'List all database servers, not just the one lagging the most',
785 'numberingroup' => 'Lists the number of users in user groups',
786 'inlanguagecode' => 'Language code for localised language names ' .
787 '(best effort, use CLDR extension)',
788 );
789 }
790
791 public function getDescription() {
792 return 'Return general information about the site';
793 }
794
795 public function getPossibleErrors() {
796 return array_merge( parent::getPossibleErrors(), array( array(
797 'code' => 'includeAllDenied',
798 'info' => 'Cannot view all servers info unless $wgShowHostnames is true'
799 ), ) );
800 }
801
802 public function getExamples() {
803 return array(
804 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
805 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
806 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb=',
807 );
808 }
809
810 public function getHelpUrls() {
811 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';
812 }
813 }