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