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