Allow interlanguage link prefixes that are not language codes
[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['description'] ) ) {
556 $ret['description'] = $ext['description'];
557 }
558 if ( isset( $ext['descriptionmsg'] ) ) {
559 // Can be a string or array( key, param1, param2, ... )
560 if ( is_array( $ext['descriptionmsg'] ) ) {
561 $ret['descriptionmsg'] = $ext['descriptionmsg'][0];
562 $ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
563 $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
564 } else {
565 $ret['descriptionmsg'] = $ext['descriptionmsg'];
566 }
567 }
568 if ( isset( $ext['author'] ) ) {
569 $ret['author'] = is_array( $ext['author'] ) ?
570 implode( ', ', $ext['author'] ) : $ext['author'];
571 }
572 if ( isset( $ext['url'] ) ) {
573 $ret['url'] = $ext['url'];
574 }
575 if ( isset( $ext['version'] ) ) {
576 $ret['version'] = $ext['version'];
577 } elseif ( isset( $ext['svn-revision'] ) &&
578 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
579 $ext['svn-revision'], $m )
580 ) {
581 $ret['version'] = 'r' . $m[1];
582 }
583 if ( isset( $ext['path'] ) ) {
584 $extensionPath = dirname( $ext['path'] );
585 $gitInfo = new GitInfo( $extensionPath );
586 $vcsVersion = $gitInfo->getHeadSHA1();
587 if ( $vcsVersion !== false ) {
588 $ret['vcs-system'] = 'git';
589 $ret['vcs-version'] = $vcsVersion;
590 $ret['vcs-url'] = $gitInfo->getHeadViewUrl();
591 $vcsDate = $gitInfo->getHeadCommitDate();
592 if ( $vcsDate !== false ) {
593 $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
594 }
595 } else {
596 $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
597 if ( $svnInfo !== false ) {
598 $ret['vcs-system'] = 'svn';
599 $ret['vcs-version'] = $svnInfo['checkout-rev'];
600 $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
601 }
602 }
603
604 if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
605 $ret['license-name'] = isset( $ext['license-name'] ) ? $ext['license-name'] : '';
606 $ret['license'] = SpecialPage::getTitleFor(
607 'Version',
608 "License/{$ext['name']}"
609 )->getLinkURL();
610 }
611
612 if ( SpecialVersion::getExtAuthorsFileName( $extensionPath ) ) {
613 $ret['credits'] = SpecialPage::getTitleFor(
614 'Version',
615 "Credits/{$ext['name']}"
616 )->getLinkURL();
617 }
618 }
619 $data[] = $ret;
620 }
621 }
622
623 $this->getResult()->setIndexedTagName( $data, 'ext' );
624
625 return $this->getResult()->addValue( 'query', $property, $data );
626 }
627
628 protected function appendRightsInfo( $property ) {
629 $config = $this->getConfig();
630 $title = Title::newFromText( $config->get( 'RightsPage' ) );
631 $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $config->get( 'RightsUrl' );
632 $text = $config->get( 'RightsText' );
633 if ( !$text && $title ) {
634 $text = $title->getPrefixedText();
635 }
636
637 $data = array(
638 'url' => $url ? $url : '',
639 'text' => $text ? $text : ''
640 );
641
642 return $this->getResult()->addValue( 'query', $property, $data );
643 }
644
645 protected function appendRestrictions( $property ) {
646 $config = $this->getConfig();
647 $data = array(
648 'types' => $config->get( 'RestrictionTypes' ),
649 'levels' => $config->get( 'RestrictionLevels' ),
650 'cascadinglevels' => $config->get( 'CascadingRestrictionLevels' ),
651 'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
652 );
653
654 $this->getResult()->setIndexedTagName( $data['types'], 'type' );
655 $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
656 $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
657 $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
658
659 return $this->getResult()->addValue( 'query', $property, $data );
660 }
661
662 public function appendLanguages( $property ) {
663 $params = $this->extractRequestParams();
664 $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
665 $langNames = Language::fetchLanguageNames( $langCode );
666
667 $data = array();
668
669 foreach ( $langNames as $code => $name ) {
670 $lang = array( 'code' => $code );
671 ApiResult::setContent( $lang, $name );
672 $data[] = $lang;
673 }
674 $this->getResult()->setIndexedTagName( $data, 'lang' );
675
676 return $this->getResult()->addValue( 'query', $property, $data );
677 }
678
679 public function appendSkins( $property ) {
680 $data = array();
681 $allowed = Skin::getAllowedSkins();
682 $default = Skin::normalizeKey( 'default' );
683 foreach ( Skin::getSkinNames() as $name => $displayName ) {
684 $skin = array( 'code' => $name );
685 ApiResult::setContent( $skin, $displayName );
686 if ( !isset( $allowed[$name] ) ) {
687 $skin['unusable'] = '';
688 }
689 if ( $name === $default ) {
690 $skin['default'] = '';
691 }
692 $data[] = $skin;
693 }
694 $this->getResult()->setIndexedTagName( $data, 'skin' );
695
696 return $this->getResult()->addValue( 'query', $property, $data );
697 }
698
699 public function appendExtensionTags( $property ) {
700 global $wgParser;
701 $wgParser->firstCallInit();
702 $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
703 $this->getResult()->setIndexedTagName( $tags, 't' );
704
705 return $this->getResult()->addValue( 'query', $property, $tags );
706 }
707
708 public function appendFunctionHooks( $property ) {
709 global $wgParser;
710 $wgParser->firstCallInit();
711 $hooks = $wgParser->getFunctionHooks();
712 $this->getResult()->setIndexedTagName( $hooks, 'h' );
713
714 return $this->getResult()->addValue( 'query', $property, $hooks );
715 }
716
717 public function appendVariables( $property ) {
718 $variables = MagicWord::getVariableIDs();
719 $this->getResult()->setIndexedTagName( $variables, 'v' );
720
721 return $this->getResult()->addValue( 'query', $property, $variables );
722 }
723
724 public function appendProtocols( $property ) {
725 // Make a copy of the global so we don't try to set the _element key of it - bug 45130
726 $protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
727 $this->getResult()->setIndexedTagName( $protocols, 'p' );
728
729 return $this->getResult()->addValue( 'query', $property, $protocols );
730 }
731
732 public function appendDefaultOptions( $property ) {
733 return $this->getResult()->addValue( 'query', $property, User::getDefaultOptions() );
734 }
735
736 private function formatParserTags( $item ) {
737 return "<{$item}>";
738 }
739
740 public function appendSubscribedHooks( $property ) {
741 $hooks = $this->getConfig()->get( 'Hooks' );
742 $myWgHooks = $hooks;
743 ksort( $myWgHooks );
744
745 $data = array();
746 foreach ( $myWgHooks as $name => $subscribers ) {
747 $arr = array(
748 'name' => $name,
749 'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $subscribers ),
750 );
751
752 $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
753 $data[] = $arr;
754 }
755
756 $this->getResult()->setIndexedTagName( $data, 'hook' );
757
758 return $this->getResult()->addValue( 'query', $property, $data );
759 }
760
761 public function getCacheMode( $params ) {
762 // Messages for $wgExtraInterlanguageLinkPrefixes depend on user language
763 if (
764 count( $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' ) ) &&
765 !is_null( $params['prop'] ) &&
766 in_array( 'interwikimap', $params['prop'] )
767 ) {
768 return 'anon-public-user-private';
769 }
770
771 return 'public';
772 }
773
774 public function getAllowedParams() {
775 return array(
776 'prop' => array(
777 ApiBase::PARAM_DFLT => 'general',
778 ApiBase::PARAM_ISMULTI => true,
779 ApiBase::PARAM_TYPE => array(
780 'general',
781 'namespaces',
782 'namespacealiases',
783 'specialpagealiases',
784 'magicwords',
785 'interwikimap',
786 'dbrepllag',
787 'statistics',
788 'usergroups',
789 'extensions',
790 'fileextensions',
791 'rightsinfo',
792 'restrictions',
793 'languages',
794 'skins',
795 'extensiontags',
796 'functionhooks',
797 'showhooks',
798 'variables',
799 'protocols',
800 'defaultoptions',
801 )
802 ),
803 'filteriw' => array(
804 ApiBase::PARAM_TYPE => array(
805 'local',
806 '!local',
807 )
808 ),
809 'showalldb' => false,
810 'numberingroup' => false,
811 'inlanguagecode' => null,
812 );
813 }
814
815 public function getParamDescription() {
816 $p = $this->getModulePrefix();
817
818 return array(
819 'prop' => array(
820 'Which sysinfo properties to get:',
821 ' general - Overall system information',
822 ' namespaces - List of registered namespaces and their canonical names',
823 ' namespacealiases - List of registered namespace aliases',
824 ' specialpagealiases - List of special page aliases',
825 ' magicwords - List of magic words and their aliases',
826 ' statistics - Returns site statistics',
827 ' interwikimap - Returns interwiki map ' .
828 "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
829 ' dbrepllag - Returns database server with the highest replication lag',
830 ' usergroups - Returns user groups and the associated permissions',
831 ' extensions - Returns extensions installed on the wiki',
832 ' fileextensions - Returns list of file extensions allowed to be uploaded',
833 ' rightsinfo - Returns wiki rights (license) information if available',
834 ' restrictions - Returns information on available restriction (protection) types',
835 ' languages - Returns a list of languages MediaWiki supports' .
836 "(optionally localised by using {$p}inlanguagecode)",
837 ' skins - Returns a list of all enabled skins',
838 ' extensiontags - Returns a list of parser extension tags',
839 ' functionhooks - Returns a list of parser function hooks',
840 ' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
841 ' variables - Returns a list of variable IDs',
842 ' protocols - Returns a list of protocols that are allowed in external links.',
843 ' defaultoptions - Returns the default values for user preferences.',
844 ),
845 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
846 'showalldb' => 'List all database servers, not just the one lagging the most',
847 'numberingroup' => 'Lists the number of users in user groups',
848 'inlanguagecode' => 'Language code for localised language names ' .
849 '(best effort, use CLDR extension)',
850 );
851 }
852
853 public function getDescription() {
854 return 'Return general information about the site.';
855 }
856
857 public function getPossibleErrors() {
858 return array_merge( parent::getPossibleErrors(), array( array(
859 'code' => 'includeAllDenied',
860 'info' => 'Cannot view all servers info unless $wgShowHostnames is true'
861 ), ) );
862 }
863
864 public function getExamples() {
865 return array(
866 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
867 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
868 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb=',
869 );
870 }
871
872 public function getHelpUrls() {
873 return 'https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si';
874 }
875 }