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