32 parent::__construct( $query, $moduleName,
'si' );
39 foreach ( $params[
'prop'] as $p ) {
42 $fit = $this->appendGeneralInfo( $p );
45 $fit = $this->appendNamespaces( $p );
47 case 'namespacealiases':
48 $fit = $this->appendNamespaceAliases( $p );
50 case 'specialpagealiases':
51 $fit = $this->appendSpecialPageAliases( $p );
54 $fit = $this->appendMagicWords( $p );
57 $fit = $this->appendInterwikiMap( $p, $params[
'filteriw'] );
60 $fit = $this->appendDbReplLagInfo( $p, $params[
'showalldb'] );
63 $fit = $this->appendStatistics( $p );
66 $fit = $this->appendUserGroups( $p, $params[
'numberingroup'] );
69 $fit = $this->appendInstalledLibraries( $p );
72 $fit = $this->appendExtensions( $p );
74 case 'fileextensions':
75 $fit = $this->appendFileExtensions( $p );
78 $fit = $this->appendRightsInfo( $p );
81 $fit = $this->appendRestrictions( $p );
84 $fit = $this->appendLanguages( $p );
86 case 'languagevariants':
87 $fit = $this->appendLanguageVariants( $p );
90 $fit = $this->appendSkins( $p );
93 $fit = $this->appendExtensionTags( $p );
96 $fit = $this->appendFunctionHooks( $p );
99 $fit = $this->appendSubscribedHooks( $p );
102 $fit = $this->appendVariables( $p );
105 $fit = $this->appendProtocols( $p );
107 case 'defaultoptions':
108 $fit = $this->appendDefaultOptions( $p );
111 $fit = $this->appendUploadDialog( $p );
120 array_diff( $params[
'prop'], $done ) ) );
127 protected function appendGeneralInfo( $property ) {
132 $data[
'mainpage'] = $mainPage->getPrefixedText();
134 $data[
'sitename'] = $config->get(
'Sitename' );
140 $data[
'generator'] =
"MediaWiki {$config->get( 'Version' )}";
142 $data[
'phpversion'] = PHP_VERSION;
143 $data[
'phpsapi'] = PHP_SAPI;
144 if ( defined(
'HHVM_VERSION' ) ) {
145 $data[
'hhvmversion'] = HHVM_VERSION;
147 $data[
'dbtype'] = $config->get(
'DBtype' );
148 $data[
'dbversion'] = $this->
getDB()->getServerVersion();
151 $allowException =
true;
152 if ( !$config->get(
'AllowExternalImages' ) ) {
153 $data[
'imagewhitelistenabled'] = (bool)$config->get(
'EnableImageWhitelist' );
154 $allowFrom = $config->get(
'AllowExternalImagesFrom' );
155 $allowException = !empty( $allowFrom );
157 if ( $allowException ) {
158 $data[
'externalimages'] = (array)$allowFrom;
162 $data[
'langconversion'] = !$config->get(
'DisableLangConversion' );
163 $data[
'titleconversion'] = !$config->get(
'DisableTitleConversion' );
165 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
166 if ( $contLang->linkPrefixExtension() ) {
170 $data[
'linkprefix'] =
"/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
172 $data[
'linkprefixcharset'] =
'';
173 $data[
'linkprefix'] =
'';
176 $linktrail = $contLang->linkTrail();
177 $data[
'linktrail'] = $linktrail ?:
'';
180 $data[
'invalidusernamechars'] = $config->get(
'InvalidUsernameCharacters' );
182 $data[
'allunicodefixes'] = (bool)$config->get(
'AllUnicodeFixes' );
183 $data[
'fixarabicunicode'] = (bool)$config->get(
'FixArabicUnicode' );
184 $data[
'fixmalayalamunicode'] = (bool)$config->get(
'FixMalayalamUnicode' );
189 $data[
'git-hash'] = $git;
190 $data[
'git-branch'] =
195 $data[
'case'] = $config->get(
'CapitalLinks' ) ?
'first-letter' :
'case-sensitive';
196 $data[
'lang'] = $config->get(
'LanguageCode' );
199 foreach ( $contLang->getFallbackLanguages() as $code ) {
200 $fallbacks[] = [
'code' => $code ];
202 $data[
'fallback'] = $fallbacks;
205 if ( $contLang->hasVariants() ) {
207 foreach ( $contLang->getVariants() as $code ) {
210 'name' => $contLang->getVariantname( $code ),
213 $data[
'variants'] = $variants;
217 $data[
'rtl'] = $contLang->isRTL();
218 $data[
'fallback8bitEncoding'] = $contLang->fallback8bitEncoding();
221 if ( $data[
'readonly'] ) {
224 $data[
'writeapi'] =
true;
226 $data[
'maxarticlesize'] = $config->get(
'MaxArticleSize' ) * 1024;
228 $tz = $config->get(
'Localtimezone' );
229 $offset = $config->get(
'LocalTZoffset' );
230 $data[
'timezone'] = $tz;
231 $data[
'timeoffset'] = (int)$offset;
232 $data[
'articlepath'] = $config->get(
'ArticlePath' );
233 $data[
'scriptpath'] = $config->get(
'ScriptPath' );
234 $data[
'script'] = $config->get(
'Script' );
235 $data[
'variantarticlepath'] = $config->get(
'VariantArticlePath' );
237 $data[
'server'] = $config->get(
'Server' );
238 $data[
'servername'] = $config->get(
'ServerName' );
240 $data[
'time'] =
wfTimestamp( TS_ISO_8601, time() );
242 $data[
'misermode'] = (bool)$config->get(
'MiserMode' );
244 $data[
'uploadsenabled'] = UploadBase::isEnabled();
245 $data[
'maxuploadsize'] = UploadBase::getMaxUploadSize();
246 $data[
'minuploadchunksize'] = (int)$config->get(
'MinUploadChunkSize' );
248 $data[
'galleryoptions'] = $config->get(
'GalleryOptions' );
250 $data[
'thumblimits'] = $config->get(
'ThumbLimits' );
253 $data[
'imagelimits'] = [];
256 foreach ( $config->get(
'ImageLimits' ) as $k => $limit ) {
257 $data[
'imagelimits'][$k] = [
'width' => $limit[0],
'height' => $limit[1] ];
260 $favicon = $config->get(
'Favicon' );
261 if ( !empty( $favicon ) ) {
267 $data[
'centralidlookupprovider'] = $config->get(
'CentralIdLookupProvider' );
268 $providerIds = array_keys( $config->get(
'CentralIdLookupProviders' ) );
269 $data[
'allcentralidlookupproviders'] = $providerIds;
271 $data[
'interwikimagic'] = (bool)$config->get(
'InterwikiMagic' );
272 $data[
'magiclinks'] = $config->get(
'EnableMagicLinks' );
274 $data[
'categorycollation'] = $config->get(
'CategoryCollation' );
276 Hooks::run(
'APIQuerySiteInfoGeneralInfo', [ $this, &$data ] );
278 return $this->
getResult()->addValue(
'query', $property, $data );
281 protected function appendNamespaces( $property ) {
282 $nsProtection = $this->
getConfig()->get(
'NamespaceProtection' );
287 $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
289 MediaWikiServices::getInstance()->getContentLanguage()->getFormattedNamespaces()
294 'case' => $nsInfo->isCapitalized( $ns ) ?
'first-letter' :
'case-sensitive',
297 $canonical = $nsInfo->getCanonicalName( $ns );
299 $data[$ns][
'subpages'] = $nsInfo->hasSubpages( $ns );
302 $data[$ns][
'canonical'] = strtr( $canonical,
'_',
' ' );
305 $data[$ns][
'content'] = $nsInfo->isContent( $ns );
306 $data[$ns][
'nonincludable'] = $nsInfo->isNonincludable( $ns );
308 if ( isset( $nsProtection[$ns] ) ) {
309 if ( is_array( $nsProtection[$ns] ) ) {
310 $specificNs = implode(
"|", array_filter( $nsProtection[$ns] ) );
311 } elseif ( $nsProtection[$ns] !==
'' ) {
312 $specificNs = $nsProtection[$ns];
314 if ( isset( $specificNs ) && $specificNs !==
'' ) {
315 $data[$ns][
'namespaceprotection'] = $specificNs;
319 $contentmodel = $nsInfo->getNamespaceContentModel( $ns );
320 if ( $contentmodel ) {
321 $data[$ns][
'defaultcontentmodel'] = $contentmodel;
328 return $this->
getResult()->addValue(
'query', $property, $data );
331 protected function appendNamespaceAliases( $property ) {
332 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
333 $aliases = array_merge( $this->
getConfig()->
get(
'NamespaceAliases' ),
334 $contLang->getNamespaceAliases() );
335 $namespaces = $contLang->getNamespaces();
337 foreach ( $aliases as
$title => $ns ) {
338 if ( $namespaces[$ns] ==
$title ) {
353 return $this->
getResult()->addValue(
'query', $property, $data );
356 protected function appendSpecialPageAliases( $property ) {
358 $services = MediaWikiServices::getInstance();
359 $aliases = $services->getContentLanguage()->getSpecialPageAliases();
360 foreach ( $services->getSpecialPageFactory()->getNames() as $specialpage ) {
361 if ( isset( $aliases[$specialpage] ) ) {
362 $arr = [
'realname' => $specialpage,
'aliases' => $aliases[$specialpage] ];
369 return $this->
getResult()->addValue(
'query', $property, $data );
372 protected function appendMagicWords( $property ) {
375 MediaWikiServices::getInstance()->getContentLanguage()->getMagicWords()
376 as $magicword => $aliases
378 $caseSensitive = array_shift( $aliases );
379 $arr = [
'name' => $magicword,
'aliases' => $aliases ];
380 $arr[
'case-sensitive'] = (bool)$caseSensitive;
386 return $this->
getResult()->addValue(
'query', $property, $data );
389 protected function appendInterwikiMap( $property,
$filter ) {
392 } elseif (
$filter ===
'!local' ) {
400 $langCode = $params[
'inlanguagecode'] ??
'';
403 $getPrefixes = MediaWikiServices::getInstance()->getInterwikiLookup()->getAllPrefixes( $local );
404 $extraLangPrefixes = $this->
getConfig()->get(
'ExtraInterlanguageLinkPrefixes' );
405 $localInterwikis = $this->
getConfig()->get(
'LocalInterwikis' );
408 foreach ( $getPrefixes as $row ) {
409 $prefix = $row[
'iw_prefix'];
411 $val[
'prefix'] = $prefix;
412 if ( isset( $row[
'iw_local'] ) && $row[
'iw_local'] ==
'1' ) {
413 $val[
'local'] =
true;
415 if ( isset( $row[
'iw_trans'] ) && $row[
'iw_trans'] ==
'1' ) {
416 $val[
'trans'] =
true;
419 if ( isset( $langNames[$prefix] ) ) {
420 $val[
'language'] = $langNames[$prefix];
422 if ( in_array( $prefix, $localInterwikis ) ) {
423 $val[
'localinterwiki'] =
true;
425 if ( in_array( $prefix, $extraLangPrefixes ) ) {
426 $val[
'extralanglink'] =
true;
428 $linktext =
wfMessage(
"interlanguage-link-$prefix" );
429 if ( !$linktext->isDisabled() ) {
430 $val[
'linktext'] = $linktext->text();
433 $sitename =
wfMessage(
"interlanguage-link-sitename-$prefix" );
434 if ( !$sitename->isDisabled() ) {
435 $val[
'sitename'] = $sitename->text();
440 $val[
'protorel'] = substr( $row[
'iw_url'], 0, 2 ) ==
'//';
441 if ( isset( $row[
'iw_wikiid'] ) && $row[
'iw_wikiid'] !==
'' ) {
442 $val[
'wikiid'] = $row[
'iw_wikiid'];
444 if ( isset( $row[
'iw_api'] ) && $row[
'iw_api'] !==
'' ) {
445 $val[
'api'] = $row[
'iw_api'];
453 return $this->
getResult()->addValue(
'query', $property, $data );
456 protected function appendDbReplLagInfo( $property, $includeAll ) {
458 $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
459 $showHostnames = $this->
getConfig()->get(
'ShowHostnames' );
461 if ( !$showHostnames ) {
462 $this->
dieWithError(
'apierror-siteinfo-includealldenied',
'includeAllDenied' );
465 $lags = $lb->getLagTimes();
466 foreach ( $lags as $i => $lag ) {
468 'host' => $lb->getServerName( $i ),
473 list( , $lag, $index ) = $lb->getMaxLag();
475 'host' => $showHostnames
476 ? $lb->getServerName( $index )
484 return $this->
getResult()->addValue(
'query', $property, $data );
487 protected function appendStatistics( $property ) {
498 Hooks::run(
'APIQuerySiteInfoStatisticsInfo', [ &$data ] );
500 return $this->
getResult()->addValue(
'query', $property, $data );
503 protected function appendUserGroups( $property, $numberInGroup ) {
509 foreach ( $config->get(
'GroupPermissions' ) as $group => $permissions ) {
512 'rights' => array_keys( $permissions,
true ),
515 if ( $numberInGroup ) {
516 $autopromote = $config->get(
'Autopromote' );
518 if ( $group ==
'user' ) {
521 } elseif ( $group !==
'*' && !isset( $autopromote[$group] ) ) {
527 'add' => $config->get(
'AddGroups' ),
528 'remove' => $config->get(
'RemoveGroups' ),
529 'add-self' => $config->get(
'GroupsAddToSelf' ),
530 'remove-self' => $config->get(
'GroupsRemoveFromSelf' )
533 foreach ( $groupArr as
$type => $rights ) {
534 if ( isset( $rights[$group] ) ) {
535 if ( $rights[$group] ===
true ) {
536 $groups = $allGroups;
538 $groups = array_intersect( $rights[$group], $allGroups );
541 $arr[
$type] = $groups;
554 return $result->addValue(
'query', $property, $data );
557 protected function appendFileExtensions( $property ) {
559 foreach ( array_unique( $this->
getConfig()->
get(
'FileExtensions' ) ) as
$ext ) {
560 $data[] = [
'ext' =>
$ext ];
564 return $this->
getResult()->addValue(
'query', $property, $data );
567 protected function appendInstalledLibraries( $property ) {
569 $path =
"$IP/vendor/composer/installed.json";
570 if ( !file_exists(
$path ) ) {
576 foreach ( $installed->getInstalledDependencies() as $name => $info ) {
577 if ( strpos( $info[
'type'],
'mediawiki-' ) === 0 ) {
584 'version' => $info[
'version'],
589 return $this->
getResult()->addValue(
'query', $property, $data );
592 protected function appendExtensions( $property ) {
594 foreach ( $this->
getConfig()->
get(
'ExtensionCredits' ) as
$type => $extensions ) {
595 foreach ( $extensions as
$ext ) {
597 $ret[
'type'] =
$type;
598 if ( isset(
$ext[
'name'] ) ) {
599 $ret[
'name'] =
$ext[
'name'];
601 if ( isset(
$ext[
'namemsg'] ) ) {
602 $ret[
'namemsg'] =
$ext[
'namemsg'];
604 if ( isset(
$ext[
'description'] ) ) {
605 $ret[
'description'] =
$ext[
'description'];
607 if ( isset(
$ext[
'descriptionmsg'] ) ) {
609 if ( is_array(
$ext[
'descriptionmsg'] ) ) {
610 $ret[
'descriptionmsg'] =
$ext[
'descriptionmsg'][0];
611 $ret[
'descriptionmsgparams'] = array_slice(
$ext[
'descriptionmsg'], 1 );
614 $ret[
'descriptionmsg'] =
$ext[
'descriptionmsg'];
617 if ( isset(
$ext[
'author'] ) ) {
618 $ret[
'author'] = is_array(
$ext[
'author'] ) ?
619 implode(
', ',
$ext[
'author'] ) :
$ext[
'author'];
621 if ( isset(
$ext[
'url'] ) ) {
622 $ret[
'url'] =
$ext[
'url'];
624 if ( isset(
$ext[
'version'] ) ) {
625 $ret[
'version'] =
$ext[
'version'];
627 if ( isset(
$ext[
'path'] ) ) {
628 $extensionPath = dirname(
$ext[
'path'] );
629 $gitInfo =
new GitInfo( $extensionPath );
630 $vcsVersion = $gitInfo->getHeadSHA1();
631 if ( $vcsVersion !==
false ) {
632 $ret[
'vcs-system'] =
'git';
633 $ret[
'vcs-version'] = $vcsVersion;
634 $ret[
'vcs-url'] = $gitInfo->getHeadViewUrl();
635 $vcsDate = $gitInfo->getHeadCommitDate();
636 if ( $vcsDate !==
false ) {
637 $ret[
'vcs-date'] =
wfTimestamp( TS_ISO_8601, $vcsDate );
642 $ret[
'license-name'] =
$ext[
'license-name'] ??
'';
645 "License/{$ext['name']}"
652 "Credits/{$ext['name']}"
662 return $this->
getResult()->addValue(
'query', $property, $data );
665 protected function appendRightsInfo( $property ) {
667 $rightsPage = $config->get(
'RightsPage' );
668 if ( is_string( $rightsPage ) ) {
673 $url = $config->get(
'RightsUrl' );
675 $text = $config->get(
'RightsText' );
676 if (
$title && !strlen( $text ) ) {
677 $text =
$title->getPrefixedText();
681 'url' => (string)$url,
682 'text' => (
string)$text,
685 return $this->
getResult()->addValue(
'query', $property, $data );
688 protected function appendRestrictions( $property ) {
691 'types' => $config->get(
'RestrictionTypes' ),
692 'levels' => $config->get(
'RestrictionLevels' ),
693 'cascadinglevels' => $config->get(
'CascadingRestrictionLevels' ),
694 'semiprotectedlevels' => $config->get(
'SemiprotectedRestrictionLevels' ),
707 return $this->
getResult()->addValue(
'query', $property, $data );
710 public function appendLanguages( $property ) {
712 $langCode = $params[
'inlanguagecode'] ??
'';
717 foreach ( $langNames as $code => $name ) {
727 return $this->
getResult()->addValue(
'query', $property, $data );
732 public function appendLanguageVariants( $property ) {
733 $langNames = LanguageConverter::$languagesWithVariants;
734 if ( $this->
getConfig()->
get(
'DisableLangConversion' ) ) {
741 foreach ( $langNames as $langCode ) {
748 $data[$langCode] = [];
752 $variants =
$lang->getVariants();
754 foreach ( $variants as $v ) {
755 $fallbacks =
$lang->getConverter()->getVariantFallbacks( $v );
756 if ( !is_array( $fallbacks ) ) {
757 $fallbacks = [ $fallbacks ];
759 $data[$langCode][$v] = [
760 'fallbacks' => $fallbacks,
763 $data[$langCode][$v][
'fallbacks'],
'variant'
770 return $this->
getResult()->addValue(
'query', $property, $data );
773 public function appendSkins( $property ) {
778 $msg = $this->
msg(
"skinname-{$name}" );
781 $msg->inLanguage( $code );
783 $msg->inContentLanguage();
785 if ( $msg->exists() ) {
786 $displayName = $msg->text();
788 $skin = [
'code' => $name ];
790 if ( !isset( $allowed[$name] ) ) {
791 $skin[
'unusable'] =
true;
793 if ( $name === $default ) {
794 $skin[
'default'] =
true;
800 return $this->
getResult()->addValue(
'query', $property, $data );
803 public function appendExtensionTags( $property ) {
808 MediaWikiServices::getInstance()->getParser()->getTags()
813 return $this->
getResult()->addValue(
'query', $property, $tags );
816 public function appendFunctionHooks( $property ) {
817 $hooks = MediaWikiServices::getInstance()->getParser()->getFunctionHooks();
821 return $this->
getResult()->addValue(
'query', $property, $hooks );
824 public function appendVariables( $property ) {
825 $variables = MediaWikiServices::getInstance()->getMagicWordFactory()->getVariableIDs();
829 return $this->
getResult()->addValue(
'query', $property, $variables );
832 public function appendProtocols( $property ) {
834 $protocols = array_values( $this->
getConfig()->
get(
'UrlProtocols' ) );
838 return $this->
getResult()->addValue(
'query', $property, $protocols );
841 public function appendDefaultOptions( $property ) {
844 return $this->
getResult()->addValue(
'query', $property, $options );
847 public function appendUploadDialog( $property ) {
848 $config = $this->
getConfig()->get(
'UploadDialog' );
849 return $this->
getResult()->addValue(
'query', $property, $config );
852 public function appendSubscribedHooks( $property ) {
853 $hooks = $this->
getConfig()->get(
'Hooks' );
858 foreach ( $myWgHooks as $name => $subscribers ) {
861 'subscribers' => array_map( [ SpecialVersion::class,
'arrayToString' ], $subscribers ),
871 return $this->
getResult()->addValue(
'query', $property, $data );
877 count( $this->
getConfig()->
get(
'ExtraInterlanguageLinkPrefixes' ) ) &&
878 !is_null( $params[
'prop'] ) &&
879 in_array(
'interwikimap', $params[
'prop'] )
881 return 'anon-public-user-private';
896 'specialpagealiases',
926 'showalldb' =>
false,
927 'numberingroup' =>
false,
928 'inlanguagecode' =>
null,
934 'action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics'
935 =>
'apihelp-query+siteinfo-example-simple',
936 'action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local'
937 =>
'apihelp-query+siteinfo-example-interwiki',
938 'action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb='
939 =>
'apihelp-query+siteinfo-example-replag',
944 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Siteinfo';