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