2013-02-01 20:48:18 +00:00
|
|
|
<?php
|
|
|
|
|
2022-08-03 12:31:15 +00:00
|
|
|
namespace MediaWiki\Extension\Scribunto\Engines\LuaCommon;
|
|
|
|
|
2023-05-12 14:33:14 +00:00
|
|
|
use MediaWiki\Category\Category;
|
2024-03-10 12:42:04 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
2018-06-07 18:40:08 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2024-01-05 18:24:06 +00:00
|
|
|
use MediaWiki\SiteStats\SiteStats;
|
|
|
|
use MediaWiki\Specials\SpecialVersion;
|
2023-08-19 04:19:07 +00:00
|
|
|
use MediaWiki\Title\Title;
|
2018-06-07 18:40:08 +00:00
|
|
|
|
2022-08-03 12:31:15 +00:00
|
|
|
class SiteLibrary extends LibraryBase {
|
2020-12-18 19:04:17 +00:00
|
|
|
/** @var string|null */
|
2015-02-19 22:12:49 +00:00
|
|
|
private static $namespacesCacheLang = null;
|
2020-12-18 19:04:17 +00:00
|
|
|
/** @var array[]|null */
|
2013-02-01 20:48:18 +00:00
|
|
|
private static $namespacesCache = null;
|
2020-12-18 19:04:17 +00:00
|
|
|
/** @var array[] */
|
2017-06-15 17:19:00 +00:00
|
|
|
private static $interwikiMapCache = [];
|
2020-12-18 19:04:17 +00:00
|
|
|
/** @var int[][] */
|
2017-06-15 17:19:00 +00:00
|
|
|
private $pagesInCategoryCache = [];
|
2013-02-01 20:48:18 +00:00
|
|
|
|
2018-11-09 19:31:08 +00:00
|
|
|
public function register() {
|
2017-06-15 17:19:00 +00:00
|
|
|
$lib = [
|
|
|
|
'getNsIndex' => [ $this, 'getNsIndex' ],
|
|
|
|
'pagesInCategory' => [ $this, 'pagesInCategory' ],
|
|
|
|
'pagesInNamespace' => [ $this, 'pagesInNamespace' ],
|
|
|
|
'usersInGroup' => [ $this, 'usersInGroup' ],
|
|
|
|
'interwikiMap' => [ $this, 'interwikiMap' ],
|
|
|
|
];
|
2016-02-23 22:10:39 +00:00
|
|
|
$parser = $this->getParser();
|
2021-06-03 16:33:54 +00:00
|
|
|
$services = MediaWikiServices::getInstance();
|
2024-03-10 12:42:04 +00:00
|
|
|
$config = $services->getMainConfig();
|
2021-06-03 16:33:54 +00:00
|
|
|
$contLang = $services->getContentLanguage();
|
2017-06-15 17:19:00 +00:00
|
|
|
$info = [
|
2024-03-10 12:42:04 +00:00
|
|
|
'siteName' => $config->get( MainConfigNames::Sitename ),
|
|
|
|
'server' => $config->get( MainConfigNames::Server ),
|
|
|
|
'scriptPath' => $config->get( MainConfigNames::ScriptPath ),
|
|
|
|
'stylePath' => $config->get( MainConfigNames::StylePath ),
|
2016-02-23 22:10:39 +00:00
|
|
|
'currentVersion' => SpecialVersion::getVersion(
|
2020-03-14 19:57:09 +00:00
|
|
|
'', $parser ? $parser->getTargetLanguage() : $contLang
|
2016-02-23 22:10:39 +00:00
|
|
|
),
|
2017-06-15 17:19:00 +00:00
|
|
|
];
|
2013-02-01 20:48:18 +00:00
|
|
|
|
2020-03-14 19:57:09 +00:00
|
|
|
if ( !self::$namespacesCache || self::$namespacesCacheLang !== $contLang->getCode() ) {
|
2017-06-15 17:19:00 +00:00
|
|
|
$namespaces = [];
|
|
|
|
$namespacesByName = [];
|
2021-06-03 16:33:54 +00:00
|
|
|
$namespaceInfo = $services->getNamespaceInfo();
|
2020-03-14 19:57:09 +00:00
|
|
|
foreach ( $contLang->getFormattedNamespaces() as $ns => $title ) {
|
2021-06-03 16:33:54 +00:00
|
|
|
$canonical = $namespaceInfo->getCanonicalName( $ns );
|
2017-06-15 17:19:00 +00:00
|
|
|
$namespaces[$ns] = [
|
2013-02-01 20:48:18 +00:00
|
|
|
'id' => $ns,
|
|
|
|
'name' => $title,
|
|
|
|
'canonicalName' => strtr( $canonical, '_', ' ' ),
|
2021-06-03 16:33:54 +00:00
|
|
|
'hasSubpages' => $namespaceInfo->hasSubpages( $ns ),
|
|
|
|
'hasGenderDistinction' => $namespaceInfo->hasGenderDistinction( $ns ),
|
|
|
|
'isCapitalized' => $namespaceInfo->isCapitalized( $ns ),
|
|
|
|
'isContent' => $namespaceInfo->isContent( $ns ),
|
|
|
|
'isIncludable' => !$namespaceInfo->isNonincludable( $ns ),
|
|
|
|
'isMovable' => $namespaceInfo->isMovable( $ns ),
|
|
|
|
'isSubject' => $namespaceInfo->isSubject( $ns ),
|
|
|
|
'isTalk' => $namespaceInfo->isTalk( $ns ),
|
|
|
|
'defaultContentModel' => $namespaceInfo->getNamespaceContentModel( $ns ),
|
2017-06-15 17:19:00 +00:00
|
|
|
'aliases' => [],
|
|
|
|
];
|
2013-02-01 20:48:18 +00:00
|
|
|
if ( $ns >= NS_MAIN ) {
|
2021-06-03 16:33:54 +00:00
|
|
|
$namespaces[$ns]['subject'] = $namespaceInfo->getSubject( $ns );
|
|
|
|
$namespaces[$ns]['talk'] = $namespaceInfo->getTalk( $ns );
|
|
|
|
$namespaces[$ns]['associated'] = $namespaceInfo->getAssociated( $ns );
|
2013-02-01 20:48:18 +00:00
|
|
|
} else {
|
|
|
|
$namespaces[$ns]['subject'] = $ns;
|
|
|
|
}
|
|
|
|
$namespacesByName[strtr( $title, ' ', '_' )] = $ns;
|
|
|
|
if ( $canonical ) {
|
|
|
|
$namespacesByName[$canonical] = $ns;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-10 12:42:04 +00:00
|
|
|
$namespaceAliases = $config->get( MainConfigNames::NamespaceAliases );
|
|
|
|
$aliases = array_merge( $namespaceAliases, $contLang->getNamespaceAliases() );
|
2013-02-01 20:48:18 +00:00
|
|
|
foreach ( $aliases as $title => $ns ) {
|
2014-06-17 18:20:34 +00:00
|
|
|
if ( !isset( $namespacesByName[$title] ) && isset( $namespaces[$ns] ) ) {
|
2013-02-01 20:48:18 +00:00
|
|
|
$ct = count( $namespaces[$ns]['aliases'] );
|
2017-08-11 04:28:16 +00:00
|
|
|
$namespaces[$ns]['aliases'][$ct + 1] = $title;
|
2013-02-01 20:48:18 +00:00
|
|
|
$namespacesByName[$title] = $ns;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-30 15:44:47 +00:00
|
|
|
$namespaces[NS_MAIN]['displayName'] = wfMessage( 'blanknamespace' )->inContentLanguage()->text();
|
2013-02-01 20:48:18 +00:00
|
|
|
|
|
|
|
self::$namespacesCache = $namespaces;
|
2020-03-14 19:57:09 +00:00
|
|
|
self::$namespacesCacheLang = $contLang->getCode();
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
$info['namespaces'] = self::$namespacesCache;
|
|
|
|
|
2023-08-31 16:28:08 +00:00
|
|
|
if ( defined( 'MW_PHPUNIT_TEST' ) ) {
|
|
|
|
$info['stats'] = [
|
|
|
|
'pages' => 1,
|
|
|
|
'articles' => 1,
|
|
|
|
'files' => 0,
|
|
|
|
'edits' => 1,
|
|
|
|
'users' => 1,
|
|
|
|
'activeUsers' => 1,
|
|
|
|
'admins' => 1,
|
|
|
|
];
|
|
|
|
} else {
|
|
|
|
$info['stats'] = [
|
|
|
|
'pages' => (int)SiteStats::pages(),
|
|
|
|
'articles' => (int)SiteStats::articles(),
|
|
|
|
'files' => (int)SiteStats::images(),
|
|
|
|
'edits' => (int)SiteStats::edits(),
|
|
|
|
'users' => (int)SiteStats::users(),
|
|
|
|
'activeUsers' => (int)SiteStats::activeUsers(),
|
|
|
|
'admins' => (int)SiteStats::numberingroup( 'sysop' ),
|
|
|
|
];
|
|
|
|
}
|
2013-03-15 21:08:54 +00:00
|
|
|
|
2014-09-26 18:11:21 +00:00
|
|
|
return $this->getEngine()->registerInterface( 'mw.site.lua', $lib, $info );
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 19:31:08 +00:00
|
|
|
/**
|
|
|
|
* Handler for pagesInCategory
|
|
|
|
* @internal
|
|
|
|
* @param string|null $category
|
|
|
|
* @param string|null $which
|
2019-03-21 04:18:51 +00:00
|
|
|
* @return int[]|int[][]
|
2018-11-09 19:31:08 +00:00
|
|
|
*/
|
2013-02-01 20:48:18 +00:00
|
|
|
public function pagesInCategory( $category = null, $which = null ) {
|
|
|
|
$this->checkType( 'pagesInCategory', 1, $category, 'string' );
|
|
|
|
$this->checkTypeOptional( 'pagesInCategory', 2, $which, 'string', 'all' );
|
|
|
|
|
|
|
|
$title = Title::makeTitleSafe( NS_CATEGORY, $category );
|
|
|
|
if ( !$title ) {
|
2017-06-15 17:19:00 +00:00
|
|
|
return [ 0 ];
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
$cacheKey = $title->getDBkey();
|
|
|
|
|
|
|
|
if ( !isset( $this->pagesInCategoryCache[$cacheKey] ) ) {
|
|
|
|
$this->incrementExpensiveFunctionCount();
|
|
|
|
$category = Category::newFromTitle( $title );
|
2017-06-15 17:19:00 +00:00
|
|
|
$counts = [
|
2022-02-06 15:07:26 +00:00
|
|
|
'all' => $category->getMemberCount(),
|
|
|
|
'subcats' => $category->getSubcatCount(),
|
|
|
|
'files' => $category->getFileCount(),
|
|
|
|
'pages' => $category->getPageCount( Category::COUNT_CONTENT_PAGES ),
|
2017-06-15 17:19:00 +00:00
|
|
|
];
|
2013-02-01 20:48:18 +00:00
|
|
|
$this->pagesInCategoryCache[$cacheKey] = $counts;
|
|
|
|
}
|
|
|
|
if ( $which === '*' ) {
|
2017-06-15 17:19:00 +00:00
|
|
|
return [ $this->pagesInCategoryCache[$cacheKey] ];
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
if ( !isset( $this->pagesInCategoryCache[$cacheKey][$which] ) ) {
|
2016-05-17 14:52:05 +00:00
|
|
|
$this->checkType(
|
|
|
|
'pagesInCategory', 2, $which, "one of '*', 'all', 'pages', 'subcats', or 'files'"
|
|
|
|
);
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
2017-06-15 17:19:00 +00:00
|
|
|
return [ $this->pagesInCategoryCache[$cacheKey][$which] ];
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 19:31:08 +00:00
|
|
|
/**
|
|
|
|
* Handler for pagesInNamespace
|
|
|
|
* @internal
|
|
|
|
* @param int|string|null $ns
|
|
|
|
* @return int[]
|
|
|
|
*/
|
2013-02-01 20:48:18 +00:00
|
|
|
public function pagesInNamespace( $ns = null ) {
|
|
|
|
$this->checkType( 'pagesInNamespace', 1, $ns, 'number' );
|
2017-06-15 17:19:00 +00:00
|
|
|
return [ (int)SiteStats::pagesInNs( intval( $ns ) ) ];
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 19:31:08 +00:00
|
|
|
/**
|
|
|
|
* Handler for usersInGroup
|
|
|
|
* @internal
|
|
|
|
* @param string|null $group
|
|
|
|
* @return int[]
|
|
|
|
*/
|
2013-02-01 20:48:18 +00:00
|
|
|
public function usersInGroup( $group = null ) {
|
|
|
|
$this->checkType( 'usersInGroup', 1, $group, 'string' );
|
2017-06-15 17:19:00 +00:00
|
|
|
return [ (int)SiteStats::numberingroup( strtolower( $group ) ) ];
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 19:31:08 +00:00
|
|
|
/**
|
|
|
|
* Handler for getNsIndex
|
|
|
|
* @internal
|
|
|
|
* @param string|null $name
|
|
|
|
* @return int[]|bool[]
|
|
|
|
*/
|
2013-02-01 20:48:18 +00:00
|
|
|
public function getNsIndex( $name = null ) {
|
|
|
|
$this->checkType( 'getNsIndex', 1, $name, 'string' );
|
2013-10-31 15:09:16 +00:00
|
|
|
// PHP call is case-insensitive but chokes on non-standard spaces/underscores.
|
|
|
|
$name = trim( preg_replace( '/[\s_]+/', '_', $name ), '_' );
|
2020-03-14 19:57:09 +00:00
|
|
|
return [ MediaWikiServices::getInstance()->getContentLanguage()->getNsIndex( $name ) ];
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|
2014-12-21 14:53:19 +00:00
|
|
|
|
2018-11-09 19:31:08 +00:00
|
|
|
/**
|
|
|
|
* Handler for interwikiMap
|
|
|
|
* @internal
|
|
|
|
* @param string|null $filter
|
|
|
|
* @return array[]
|
|
|
|
*/
|
2014-12-21 14:53:19 +00:00
|
|
|
public function interwikiMap( $filter = null ) {
|
|
|
|
$this->checkTypeOptional( 'interwikiMap', 1, $filter, 'string', null );
|
|
|
|
$local = null;
|
|
|
|
if ( $filter === 'local' ) {
|
2022-02-26 21:28:29 +00:00
|
|
|
$local = true;
|
2014-12-21 14:53:19 +00:00
|
|
|
} elseif ( $filter === '!local' ) {
|
2022-02-26 21:28:29 +00:00
|
|
|
$local = false;
|
2014-12-21 14:53:19 +00:00
|
|
|
} elseif ( $filter !== null ) {
|
2022-08-03 12:31:15 +00:00
|
|
|
throw new LuaError(
|
2014-12-21 14:53:19 +00:00
|
|
|
"bad argument #1 to 'interwikiMap' (unknown filter '$filter')"
|
|
|
|
);
|
|
|
|
}
|
2022-04-16 21:09:10 +00:00
|
|
|
$cacheKey = $filter ?? 'null';
|
2014-12-21 14:53:19 +00:00
|
|
|
if ( !isset( self::$interwikiMapCache[$cacheKey] ) ) {
|
|
|
|
// Not expensive because we can have a max of three cache misses in the
|
|
|
|
// entire page parse.
|
2017-06-15 17:19:00 +00:00
|
|
|
$interwikiMap = [];
|
2024-09-08 06:16:58 +00:00
|
|
|
|
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
$lookup = $services->getInterwikiLookup();
|
|
|
|
$config = $services->getMainConfig();
|
|
|
|
$urlUtils = $services->getUrlUtils();
|
|
|
|
|
2018-06-07 18:40:08 +00:00
|
|
|
$prefixes = $lookup->getAllPrefixes( $local );
|
2024-03-10 12:42:04 +00:00
|
|
|
$localInterwikis = $config->get( MainConfigNames::LocalInterwikis );
|
|
|
|
$extraInterlanguageLinkPrefixes = $config->get( MainConfigNames::ExtraInterlanguageLinkPrefixes );
|
2014-12-21 14:53:19 +00:00
|
|
|
foreach ( $prefixes as $row ) {
|
|
|
|
$prefix = $row['iw_prefix'];
|
2017-06-15 17:19:00 +00:00
|
|
|
$val = [
|
2014-12-21 14:53:19 +00:00
|
|
|
'prefix' => $prefix,
|
2024-09-08 06:16:58 +00:00
|
|
|
'url' => $urlUtils->expand( $row['iw_url'], PROTO_RELATIVE ) ?? false,
|
2024-08-26 15:33:39 +00:00
|
|
|
'isProtocolRelative' => str_starts_with( $row['iw_url'], '//' ),
|
|
|
|
'isLocal' => (bool)( $row['iw_local'] ?? false ),
|
|
|
|
'isTranscludable' => (bool)( $row['iw_trans'] ?? false ),
|
2024-03-10 12:42:04 +00:00
|
|
|
'isCurrentWiki' => in_array( $prefix, $localInterwikis ),
|
|
|
|
'isExtraLanguageLink' => in_array( $prefix, $extraInterlanguageLinkPrefixes ),
|
2017-06-15 17:19:00 +00:00
|
|
|
];
|
2014-12-21 14:53:19 +00:00
|
|
|
if ( $val['isExtraLanguageLink'] ) {
|
|
|
|
$displayText = wfMessage( "interlanguage-link-$prefix" );
|
|
|
|
if ( !$displayText->isDisabled() ) {
|
|
|
|
$val['displayText'] = $displayText->text();
|
|
|
|
}
|
|
|
|
$tooltip = wfMessage( "interlanguage-link-sitename-$prefix" );
|
|
|
|
if ( !$tooltip->isDisabled() ) {
|
|
|
|
$val['tooltip'] = $tooltip->text();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$interwikiMap[$prefix] = $val;
|
|
|
|
}
|
|
|
|
self::$interwikiMapCache[$cacheKey] = $interwikiMap;
|
|
|
|
}
|
2017-06-15 17:19:00 +00:00
|
|
|
return [ self::$interwikiMapCache[$cacheKey] ];
|
2014-12-21 14:53:19 +00:00
|
|
|
}
|
2013-02-01 20:48:18 +00:00
|
|
|
}
|