Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
47.02% |
71 / 151 |
|
50.00% |
3 / 6 |
CRAP | |
0.00% |
0 / 1 |
SiteLibrary | |
47.02% |
71 / 151 |
|
50.00% |
3 / 6 |
144.59 | |
0.00% |
0 / 1 |
register | |
41.25% |
33 / 80 |
|
0.00% |
0 / 1 |
35.54 | |||
pagesInCategory | |
78.26% |
18 / 23 |
|
0.00% |
0 / 1 |
5.26 | |||
pagesInNamespace | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
usersInGroup | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getNsIndex | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
interwikiMap | |
31.71% |
13 / 41 |
|
0.00% |
0 / 1 |
34.80 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\Scribunto\Engines\LuaCommon; |
4 | |
5 | use MediaWiki\Category\Category; |
6 | use MediaWiki\MainConfigNames; |
7 | use MediaWiki\MediaWikiServices; |
8 | use MediaWiki\SiteStats\SiteStats; |
9 | use MediaWiki\Specials\SpecialVersion; |
10 | use MediaWiki\Title\Title; |
11 | |
12 | class SiteLibrary extends LibraryBase { |
13 | /** @var string|null */ |
14 | private static $namespacesCacheLang = null; |
15 | /** @var array[]|null */ |
16 | private static $namespacesCache = null; |
17 | /** @var array[] */ |
18 | private static $interwikiMapCache = []; |
19 | /** @var int[][] */ |
20 | private $pagesInCategoryCache = []; |
21 | |
22 | public function register() { |
23 | $lib = [ |
24 | 'getNsIndex' => [ $this, 'getNsIndex' ], |
25 | 'pagesInCategory' => [ $this, 'pagesInCategory' ], |
26 | 'pagesInNamespace' => [ $this, 'pagesInNamespace' ], |
27 | 'usersInGroup' => [ $this, 'usersInGroup' ], |
28 | 'interwikiMap' => [ $this, 'interwikiMap' ], |
29 | ]; |
30 | $parser = $this->getParser(); |
31 | $services = MediaWikiServices::getInstance(); |
32 | $config = $services->getMainConfig(); |
33 | $contLang = $services->getContentLanguage(); |
34 | $info = [ |
35 | 'siteName' => $config->get( MainConfigNames::Sitename ), |
36 | 'server' => $config->get( MainConfigNames::Server ), |
37 | 'scriptPath' => $config->get( MainConfigNames::ScriptPath ), |
38 | 'stylePath' => $config->get( MainConfigNames::StylePath ), |
39 | 'currentVersion' => SpecialVersion::getVersion( |
40 | '', $parser ? $parser->getTargetLanguage() : $contLang |
41 | ), |
42 | ]; |
43 | |
44 | if ( !self::$namespacesCache || self::$namespacesCacheLang !== $contLang->getCode() ) { |
45 | $namespaces = []; |
46 | $namespacesByName = []; |
47 | $namespaceInfo = $services->getNamespaceInfo(); |
48 | foreach ( $contLang->getFormattedNamespaces() as $ns => $title ) { |
49 | $canonical = $namespaceInfo->getCanonicalName( $ns ); |
50 | $namespaces[$ns] = [ |
51 | 'id' => $ns, |
52 | 'name' => $title, |
53 | 'canonicalName' => strtr( $canonical, '_', ' ' ), |
54 | 'hasSubpages' => $namespaceInfo->hasSubpages( $ns ), |
55 | 'hasGenderDistinction' => $namespaceInfo->hasGenderDistinction( $ns ), |
56 | 'isCapitalized' => $namespaceInfo->isCapitalized( $ns ), |
57 | 'isContent' => $namespaceInfo->isContent( $ns ), |
58 | 'isIncludable' => !$namespaceInfo->isNonincludable( $ns ), |
59 | 'isMovable' => $namespaceInfo->isMovable( $ns ), |
60 | 'isSubject' => $namespaceInfo->isSubject( $ns ), |
61 | 'isTalk' => $namespaceInfo->isTalk( $ns ), |
62 | 'defaultContentModel' => $namespaceInfo->getNamespaceContentModel( $ns ), |
63 | 'aliases' => [], |
64 | ]; |
65 | if ( $ns >= NS_MAIN ) { |
66 | $namespaces[$ns]['subject'] = $namespaceInfo->getSubject( $ns ); |
67 | $namespaces[$ns]['talk'] = $namespaceInfo->getTalk( $ns ); |
68 | $namespaces[$ns]['associated'] = $namespaceInfo->getAssociated( $ns ); |
69 | } else { |
70 | $namespaces[$ns]['subject'] = $ns; |
71 | } |
72 | $namespacesByName[strtr( $title, ' ', '_' )] = $ns; |
73 | if ( $canonical ) { |
74 | $namespacesByName[$canonical] = $ns; |
75 | } |
76 | } |
77 | |
78 | $namespaceAliases = $config->get( MainConfigNames::NamespaceAliases ); |
79 | $aliases = array_merge( $namespaceAliases, $contLang->getNamespaceAliases() ); |
80 | foreach ( $aliases as $title => $ns ) { |
81 | if ( !isset( $namespacesByName[$title] ) && isset( $namespaces[$ns] ) ) { |
82 | $ct = count( $namespaces[$ns]['aliases'] ); |
83 | $namespaces[$ns]['aliases'][$ct + 1] = $title; |
84 | $namespacesByName[$title] = $ns; |
85 | } |
86 | } |
87 | |
88 | $namespaces[NS_MAIN]['displayName'] = wfMessage( 'blanknamespace' )->inContentLanguage()->text(); |
89 | |
90 | self::$namespacesCache = $namespaces; |
91 | self::$namespacesCacheLang = $contLang->getCode(); |
92 | } |
93 | $info['namespaces'] = self::$namespacesCache; |
94 | |
95 | if ( defined( 'MW_PHPUNIT_TEST' ) ) { |
96 | $info['stats'] = [ |
97 | 'pages' => 1, |
98 | 'articles' => 1, |
99 | 'files' => 0, |
100 | 'edits' => 1, |
101 | 'users' => 1, |
102 | 'activeUsers' => 1, |
103 | 'admins' => 1, |
104 | ]; |
105 | } else { |
106 | $info['stats'] = [ |
107 | 'pages' => (int)SiteStats::pages(), |
108 | 'articles' => (int)SiteStats::articles(), |
109 | 'files' => (int)SiteStats::images(), |
110 | 'edits' => (int)SiteStats::edits(), |
111 | 'users' => (int)SiteStats::users(), |
112 | 'activeUsers' => (int)SiteStats::activeUsers(), |
113 | 'admins' => (int)SiteStats::numberingroup( 'sysop' ), |
114 | ]; |
115 | } |
116 | |
117 | return $this->getEngine()->registerInterface( 'mw.site.lua', $lib, $info ); |
118 | } |
119 | |
120 | /** |
121 | * Handler for pagesInCategory |
122 | * @internal |
123 | * @param string|null $category |
124 | * @param string|null $which |
125 | * @return int[]|int[][] |
126 | */ |
127 | public function pagesInCategory( $category = null, $which = null ) { |
128 | $this->checkType( 'pagesInCategory', 1, $category, 'string' ); |
129 | $this->checkTypeOptional( 'pagesInCategory', 2, $which, 'string', 'all' ); |
130 | |
131 | $title = Title::makeTitleSafe( NS_CATEGORY, $category ); |
132 | if ( !$title ) { |
133 | return [ 0 ]; |
134 | } |
135 | $cacheKey = $title->getDBkey(); |
136 | |
137 | if ( !isset( $this->pagesInCategoryCache[$cacheKey] ) ) { |
138 | $this->incrementExpensiveFunctionCount(); |
139 | $category = Category::newFromTitle( $title ); |
140 | $counts = [ |
141 | 'all' => $category->getMemberCount(), |
142 | 'subcats' => $category->getSubcatCount(), |
143 | 'files' => $category->getFileCount(), |
144 | 'pages' => $category->getPageCount( Category::COUNT_CONTENT_PAGES ), |
145 | ]; |
146 | $this->pagesInCategoryCache[$cacheKey] = $counts; |
147 | } |
148 | if ( $which === '*' ) { |
149 | return [ $this->pagesInCategoryCache[$cacheKey] ]; |
150 | } |
151 | if ( !isset( $this->pagesInCategoryCache[$cacheKey][$which] ) ) { |
152 | $this->checkType( |
153 | 'pagesInCategory', 2, $which, "one of '*', 'all', 'pages', 'subcats', or 'files'" |
154 | ); |
155 | } |
156 | return [ $this->pagesInCategoryCache[$cacheKey][$which] ]; |
157 | } |
158 | |
159 | /** |
160 | * Handler for pagesInNamespace |
161 | * @internal |
162 | * @param int|string|null $ns |
163 | * @return int[] |
164 | */ |
165 | public function pagesInNamespace( $ns = null ) { |
166 | $this->checkType( 'pagesInNamespace', 1, $ns, 'number' ); |
167 | return [ (int)SiteStats::pagesInNs( intval( $ns ) ) ]; |
168 | } |
169 | |
170 | /** |
171 | * Handler for usersInGroup |
172 | * @internal |
173 | * @param string|null $group |
174 | * @return int[] |
175 | */ |
176 | public function usersInGroup( $group = null ) { |
177 | $this->checkType( 'usersInGroup', 1, $group, 'string' ); |
178 | return [ (int)SiteStats::numberingroup( strtolower( $group ) ) ]; |
179 | } |
180 | |
181 | /** |
182 | * Handler for getNsIndex |
183 | * @internal |
184 | * @param string|null $name |
185 | * @return int[]|bool[] |
186 | */ |
187 | public function getNsIndex( $name = null ) { |
188 | $this->checkType( 'getNsIndex', 1, $name, 'string' ); |
189 | // PHP call is case-insensitive but chokes on non-standard spaces/underscores. |
190 | $name = trim( preg_replace( '/[\s_]+/', '_', $name ), '_' ); |
191 | return [ MediaWikiServices::getInstance()->getContentLanguage()->getNsIndex( $name ) ]; |
192 | } |
193 | |
194 | /** |
195 | * Handler for interwikiMap |
196 | * @internal |
197 | * @param string|null $filter |
198 | * @return array[] |
199 | */ |
200 | public function interwikiMap( $filter = null ) { |
201 | $this->checkTypeOptional( 'interwikiMap', 1, $filter, 'string', null ); |
202 | $local = null; |
203 | if ( $filter === 'local' ) { |
204 | $local = true; |
205 | } elseif ( $filter === '!local' ) { |
206 | $local = false; |
207 | } elseif ( $filter !== null ) { |
208 | throw new LuaError( |
209 | "bad argument #1 to 'interwikiMap' (unknown filter '$filter')" |
210 | ); |
211 | } |
212 | $cacheKey = $filter ?? 'null'; |
213 | if ( !isset( self::$interwikiMapCache[$cacheKey] ) ) { |
214 | // Not expensive because we can have a max of three cache misses in the |
215 | // entire page parse. |
216 | $interwikiMap = []; |
217 | |
218 | $services = MediaWikiServices::getInstance(); |
219 | $lookup = $services->getInterwikiLookup(); |
220 | $config = $services->getMainConfig(); |
221 | $urlUtils = $services->getUrlUtils(); |
222 | |
223 | $prefixes = $lookup->getAllPrefixes( $local ); |
224 | $localInterwikis = $config->get( MainConfigNames::LocalInterwikis ); |
225 | $extraInterlanguageLinkPrefixes = $config->get( MainConfigNames::ExtraInterlanguageLinkPrefixes ); |
226 | foreach ( $prefixes as $row ) { |
227 | $prefix = $row['iw_prefix']; |
228 | $val = [ |
229 | 'prefix' => $prefix, |
230 | 'url' => $urlUtils->expand( $row['iw_url'], PROTO_RELATIVE ) ?? false, |
231 | 'isProtocolRelative' => str_starts_with( $row['iw_url'], '//' ), |
232 | 'isLocal' => (bool)( $row['iw_local'] ?? false ), |
233 | 'isTranscludable' => (bool)( $row['iw_trans'] ?? false ), |
234 | 'isCurrentWiki' => in_array( $prefix, $localInterwikis ), |
235 | 'isExtraLanguageLink' => in_array( $prefix, $extraInterlanguageLinkPrefixes ), |
236 | ]; |
237 | if ( $val['isExtraLanguageLink'] ) { |
238 | $displayText = wfMessage( "interlanguage-link-$prefix" ); |
239 | if ( !$displayText->isDisabled() ) { |
240 | $val['displayText'] = $displayText->text(); |
241 | } |
242 | $tooltip = wfMessage( "interlanguage-link-sitename-$prefix" ); |
243 | if ( !$tooltip->isDisabled() ) { |
244 | $val['tooltip'] = $tooltip->text(); |
245 | } |
246 | } |
247 | $interwikiMap[$prefix] = $val; |
248 | } |
249 | self::$interwikiMapCache[$cacheKey] = $interwikiMap; |
250 | } |
251 | return [ self::$interwikiMapCache[$cacheKey] ]; |
252 | } |
253 | } |