Merge "Revert "Breaking out disallowed CSS into a global variable""
[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'] = PHP_VERSION;
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 $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
389 $data = array();
390
391 foreach ( $getPrefixes as $row ) {
392 $prefix = $row['iw_prefix'];
393 $val = array();
394 $val['prefix'] = $prefix;
395 if ( $row['iw_local'] == '1' ) {
396 $val['local'] = '';
397 }
398 if ( $row['iw_trans'] == '1' ) {
399 $val['trans'] = '';
400 }
401
402 if ( isset( $langNames[$prefix] ) ) {
403 $val['language'] = $langNames[$prefix];
404 }
405 if ( in_array( $prefix, $localInterwikis ) ) {
406 $val['localinterwiki'] = '';
407 }
408 if ( in_array( $prefix, $extraLangPrefixes ) ) {
409 $val['extralanglink'] = '';
410
411 $linktext = wfMessage( "interlanguage-link-$prefix" );
412 if ( !$linktext->isDisabled() ) {
413 $val['linktext'] = $linktext->text();
414 }
415
416 $sitename = wfMessage( "interlanguage-link-sitename-$prefix" );
417 if ( !$sitename->isDisabled() ) {
418 $val['sitename'] = $sitename->text();
419 }
420 }
421
422 $val['url'] = wfExpandUrl( $row['iw_url'], PROTO_CURRENT );
423 if (substr( $row['iw_url'], 0, 2) == '//') {
424 $val['protorel'] = '';
425 }
426 if ( isset( $row['iw_wikiid'] ) ) {
427 $val['wikiid'] = $row['iw_wikiid'];
428 }
429 if ( isset( $row['iw_api'] ) ) {
430 $val['api'] = $row['iw_api'];
431 }
432
433 $data[] = $val;
434 }
435
436 $this->getResult()->setIndexedTagName( $data, 'iw' );
437
438 return $this->getResult()->addValue( 'query', $property, $data );
439 }
440
441 protected function appendDbReplLagInfo( $property, $includeAll ) {
442 $data = array();
443 $lb = wfGetLB();
444 $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
445 if ( $includeAll ) {
446 if ( !$showHostnames ) {
447 $this->dieUsage(
448 'Cannot view all servers info unless $wgShowHostnames is true',
449 'includeAllDenied'
450 );
451 }
452
453 $lags = $lb->getLagTimes();
454 foreach ( $lags as $i => $lag ) {
455 $data[] = array(
456 'host' => $lb->getServerName( $i ),
457 'lag' => $lag
458 );
459 }
460 } else {
461 list( , $lag, $index ) = $lb->getMaxLag();
462 $data[] = array(
463 'host' => $showHostnames
464 ? $lb->getServerName( $index )
465 : '',
466 'lag' => intval( $lag )
467 );
468 }
469
470 $result = $this->getResult();
471 $result->setIndexedTagName( $data, 'db' );
472
473 return $this->getResult()->addValue( 'query', $property, $data );
474 }
475
476 protected function appendStatistics( $property ) {
477 $data = array();
478 $data['pages'] = intval( SiteStats::pages() );
479 $data['articles'] = intval( SiteStats::articles() );
480 if ( !$this->getConfig()->get( 'DisableCounters' ) ) {
481 $data['views'] = intval( SiteStats::views() );
482 }
483 $data['edits'] = intval( SiteStats::edits() );
484 $data['images'] = intval( SiteStats::images() );
485 $data['users'] = intval( SiteStats::users() );
486 $data['activeusers'] = intval( SiteStats::activeUsers() );
487 $data['admins'] = intval( SiteStats::numberingroup( 'sysop' ) );
488 $data['jobs'] = intval( SiteStats::jobs() );
489
490 wfRunHooks( 'APIQuerySiteInfoStatisticsInfo', array( &$data ) );
491
492 return $this->getResult()->addValue( 'query', $property, $data );
493 }
494
495 protected function appendUserGroups( $property, $numberInGroup ) {
496 $config = $this->getConfig();
497
498 $data = array();
499 $result = $this->getResult();
500 foreach ( $config->get( 'GroupPermissions' ) as $group => $permissions ) {
501 $arr = array(
502 'name' => $group,
503 'rights' => array_keys( $permissions, true ),
504 );
505
506 if ( $numberInGroup ) {
507 $autopromote = $config->get( 'Autopromote' );
508
509 if ( $group == 'user' ) {
510 $arr['number'] = SiteStats::users();
511 // '*' and autopromote groups have no size
512 } elseif ( $group !== '*' && !isset( $autopromote[$group] ) ) {
513 $arr['number'] = SiteStats::numberInGroup( $group );
514 }
515 }
516
517 $groupArr = array(
518 'add' => $config->get( 'AddGroups' ),
519 'remove' => $config->get( 'RemoveGroups' ),
520 'add-self' => $config->get( 'GroupsAddToSelf' ),
521 'remove-self' => $config->get( 'GroupsRemoveFromSelf' )
522 );
523
524 foreach ( $groupArr as $type => $rights ) {
525 if ( isset( $rights[$group] ) ) {
526 $arr[$type] = $rights[$group];
527 $result->setIndexedTagName( $arr[$type], 'group' );
528 }
529 }
530
531 $result->setIndexedTagName( $arr['rights'], 'permission' );
532 $data[] = $arr;
533 }
534
535 $result->setIndexedTagName( $data, 'group' );
536
537 return $result->addValue( 'query', $property, $data );
538 }
539
540 protected function appendFileExtensions( $property ) {
541 $data = array();
542 foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
543 $data[] = array( 'ext' => $ext );
544 }
545 $this->getResult()->setIndexedTagName( $data, 'fe' );
546
547 return $this->getResult()->addValue( 'query', $property, $data );
548 }
549
550 protected function appendExtensions( $property ) {
551 $data = array();
552 foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $type => $extensions ) {
553 foreach ( $extensions as $ext ) {
554 $ret = array();
555 $ret['type'] = $type;
556 if ( isset( $ext['name'] ) ) {
557 $ret['name'] = $ext['name'];
558 }
559 if ( isset( $ext['namemsg'] ) ) {
560 $ret['namemsg'] = $ext['namemsg'];
561 }
562 if ( isset( $ext['description'] ) ) {
563 $ret['description'] = $ext['description'];
564 }
565 if ( isset( $ext['descriptionmsg'] ) ) {
566 // Can be a string or array( key, param1, param2, ... )
567 if ( is_array( $ext['descriptionmsg'] ) ) {
568 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
569 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
570 $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
571 } else {
572 $ret['descriptionmsg'] = $ext['descriptionmsg'];
573 }
574 }
575 if ( isset( $ext['author'] ) ) {
576 $ret['author'] = is_array( $ext['author'] ) ?
577 implode( ', ', $ext['author'] ) : $ext['author'];
578 }
579 if ( isset( $ext['url'] ) ) {
580 $ret['url'] = $ext['url'];
581 }
582 if ( isset( $ext['version'] ) ) {
583 $ret['version'] = $ext['version'];
584 } elseif ( isset( $ext['svn-revision'] ) &&
585 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
586 $ext['svn-revision'], $m )
587 ) {
588 $ret['version'] = 'r' . $m[1];
589 }
590 if ( isset( $ext['path'] ) ) {
591 $extensionPath = dirname( $ext['path'] );
592 $gitInfo = new GitInfo( $extensionPath );
593 $vcsVersion = $gitInfo->getHeadSHA1();
594 if ( $vcsVersion !== false ) {
595 $ret['vcs-system'] = 'git';
596 $ret['vcs-version'] = $vcsVersion;
597 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
598 $vcsDate = $gitInfo->getHeadCommitDate();
599 if ( $vcsDate !== false ) {
600 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
601 }
602 } else {
603 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
604 if ( $svnInfo !== false ) {
605 $ret['vcs-system'] = 'svn';
606 $ret['vcs-version'] = $svnInfo['checkout-rev'];
607 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
608 }
609 }
610
611 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
612 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
613 $ret['license'] = SpecialPage::getTitleFor(
614 'Version',
615 "License/{$ext['name']}"
616 )->getLinkURL();
617 }
618
619 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
620 $ret['credits'] = SpecialPage::getTitleFor(
621 'Version',
622 "Credits/{$ext['name']}"
623 )->getLinkURL();
624 }
625 }
626 $data[] = $ret;
627 }
628 }
629
630 $this->getResult()->setIndexedTagName( $data, 'ext' );
631
632 return $this->getResult()->addValue( 'query', $property, $data );
633 }
634
635 protected function appendRightsInfo( $property ) {
636 $config = $this->getConfig();
637 $title = Title::newFromText( $config->get( 'RightsPage' ) );
638 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $config->get( 'RightsUrl' );
639 $text = $config->get( 'RightsText' );
640 if ( !$text && $title ) {
641 $text = $title->getPrefixedText();
642 }
643
644 $data = array(
645 'url' => $url ? $url : '',
646 'text' => $text ? $text : ''
647 );
648
649 return $this->getResult()->addValue( 'query', $property, $data );
650 }
651
652 protected function appendRestrictions( $property ) {
653 $config = $this->getConfig();
654 $data = array(
655 'types' => $config->get( 'RestrictionTypes' ),
656 'levels' => $config->get( 'RestrictionLevels' ),
657 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
658 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
659 );
660
661 $this->getResult()->setIndexedTagName( $data['types'], 'type' );
662 $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
663 $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
664 $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
665
666 return $this->getResult()->addValue( 'query', $property, $data );
667 }
668
669 public function appendLanguages( $property ) {
670 $params = $this->extractRequestParams();
671 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
672 $langNames = Language::fetchLanguageNames( $langCode );
673
674 $data = array();
675
676 foreach ( $langNames as $code => $name ) {
677 $lang = array( 'code' => $code );
678 ApiResult::setContent( $lang, $name );
679 $data[] = $lang;
680 }
681 $this->getResult()->setIndexedTagName( $data, 'lang' );
682
683 return $this->getResult()->addValue( 'query', $property, $data );
684 }
685
686 public function appendSkins( $property ) {
687 $data = array();
688 $allowed = Skin::getAllowedSkins();
689 $default = Skin::normalizeKey( 'default' );
690 foreach ( Skin::getSkinNames() as $name => $displayName ) {
691 $skin = array( 'code' => $name );
692 ApiResult::setContent( $skin, $displayName );
693 if ( !isset( $allowed[$name] ) ) {
694 $skin['unusable'] = '';
695 }
696 if ( $name === $default ) {
697 $skin['default'] = '';
698 }
699 $data[] = $skin;
700 }
701 $this->getResult()->setIndexedTagName( $data, 'skin' );
702
703 return $this->getResult()->addValue( 'query', $property, $data );
704 }
705
706 public function appendExtensionTags( $property ) {
707 global $wgParser;
708 $wgParser->firstCallInit();
709 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
710 $this->getResult()->setIndexedTagName( $tags, 't' );
711
712 return $this->getResult()->addValue( 'query', $property, $tags );
713 }
714
715 public function appendFunctionHooks( $property ) {
716 global $wgParser;
717 $wgParser->firstCallInit();
718 $hooks = $wgParser->getFunctionHooks();
719 $this->getResult()->setIndexedTagName( $hooks, 'h' );
720
721 return $this->getResult()->addValue( 'query', $property, $hooks );
722 }
723
724 public function appendVariables( $property ) {
725 $variables = MagicWord::getVariableIDs();
726 $this->getResult()->setIndexedTagName( $variables, 'v' );
727
728 return $this->getResult()->addValue( 'query', $property, $variables );
729 }
730
731 public function appendProtocols( $property ) {
732 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
733 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
734 $this->getResult()->setIndexedTagName( $protocols, 'p' );
735
736 return $this->getResult()->addValue( 'query', $property, $protocols );
737 }
738
739 public function appendDefaultOptions( $property ) {
740 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
741 }
742
743 private function formatParserTags( $item ) {
744 return "<{$item}>";
745 }
746
747 public function appendSubscribedHooks( $property ) {
748 $hooks = $this->getConfig()->get( 'Hooks' );
749 $myWgHooks = $hooks;
750 ksort( $myWgHooks );
751
752 $data = array();
753 foreach ( $myWgHooks as $name => $subscribers ) {
754 $arr = array(
755 'name' => $name,
756 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $subscribers ),
757 );
758
759 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
760 $data[] = $arr;
761 }
762
763 $this->getResult()->setIndexedTagName( $data, 'hook' );
764
765 return $this->getResult()->addValue( 'query', $property, $data );
766 }
767
768 public function getCacheMode( $params ) {
769 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
770 if (
771 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
772 !is_null( $params['prop'] ) &&
773 in_array( 'interwikimap', $params['prop'] )
774 ) {
775 return 'anon-public-user-private';
776 }
777
778 return 'public';
779 }
780
781 public function getAllowedParams() {
782 return array(
783 'prop' => array(
784 ApiBase::PARAM_DFLT => 'general',
785 ApiBase::PARAM_ISMULTI => true,
786 ApiBase::PARAM_TYPE => array(
787 'general',
788 'namespaces',
789 'namespacealiases',
790 'specialpagealiases',
791 'magicwords',
792 'interwikimap',
793 'dbrepllag',
794 'statistics',
795 'usergroups',
796 'extensions',
797 'fileextensions',
798 'rightsinfo',
799 'restrictions',
800 'languages',
801 'skins',
802 'extensiontags',
803 'functionhooks',
804 'showhooks',
805 'variables',
806 'protocols',
807 'defaultoptions',
808 )
809 ),
810 'filteriw' => array(
811 ApiBase::PARAM_TYPE => array(
812 'local',
813 '!local',
814 )
815 ),
816 'showalldb' => false,
817 'numberingroup' => false,
818 'inlanguagecode' => null,
819 );
820 }
821
822 public function getParamDescription() {
823 $p = $this->getModulePrefix();
824
825 return array(
826 'prop' => array(
827 'Which sysinfo properties to get:',
828 ' general - Overall system information',
829 ' namespaces - List of registered namespaces and their canonical names',
830 ' namespacealiases - List of registered namespace aliases',
831 ' specialpagealiases - List of special page aliases',
832 ' magicwords - List of magic words and their aliases',
833 ' statistics - Returns site statistics',
834 ' interwikimap - Returns interwiki map ' .
835 "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
836 ' dbrepllag - Returns database server with the highest replication lag',
837 ' usergroups - Returns user groups and the associated permissions',
838 ' extensions - Returns extensions installed on the wiki',
839 ' fileextensions - Returns list of file extensions allowed to be uploaded',
840 ' rightsinfo - Returns wiki rights (license) information if available',
841 ' restrictions - Returns information on available restriction (protection) types',
842 ' languages - Returns a list of languages MediaWiki supports' .
843 "(optionally localised by using {$p}inlanguagecode)",
844 ' skins - Returns a list of all enabled skins',
845 ' extensiontags - Returns a list of parser extension tags',
846 ' functionhooks - Returns a list of parser function hooks',
847 ' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
848 ' variables - Returns a list of variable IDs',
849 ' protocols - Returns a list of protocols that are allowed in external links.',
850 ' defaultoptions - Returns the default values for user preferences.',
851 ),
852 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
853 'showalldb' => 'List all database servers, not just the one lagging the most',
854 'numberingroup' => 'Lists the number of users in user groups',
855 'inlanguagecode' => 'Language code for localised language names ' .
856 '(best effort, use CLDR extension)',
857 );
858 }
859
860 public function getDescription() {
861 return 'Return general information about the site.';
862 }
863
864 public function getPossibleErrors() {
865 return array_merge( parent::getPossibleErrors(), array( array(
866 'code' => 'includeAllDenied',
867 'info' => 'Cannot view all servers info unless $wgShowHostnames is true'
868 ), ) );
869 }
870
871 public function getExamples() {
872 return array(
873 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
874 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
875 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb=',
876 );
877 }
878
879 public function getHelpUrls() {
880 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';
881 }
882 }