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