Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
72.06% |
196 / 272 |
|
28.57% |
4 / 14 |
CRAP | |
0.00% |
0 / 1 |
SpecialPageFactory | |
72.06% |
196 / 272 |
|
28.57% |
4 / 14 |
193.45 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
getNames | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPageList | |
67.57% |
50 / 74 |
|
0.00% |
0 / 1 |
11.76 | |||
getAliasList | |
100.00% |
29 / 29 |
|
100.00% |
1 / 1 |
11 | |||
resolveAlias | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
2.01 | |||
exists | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getPage | |
85.00% |
17 / 20 |
|
0.00% |
0 / 1 |
6.12 | |||
getUsablePages | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
42 | |||
getRegularPages | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
30 | |||
getListedPages | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
executePath | |
58.33% |
21 / 36 |
|
0.00% |
0 / 1 |
22.42 | |||
capturePath | |
100.00% |
41 / 41 |
|
100.00% |
1 / 1 |
3 | |||
getLocalNameFor | |
70.37% |
19 / 27 |
|
0.00% |
0 / 1 |
14.15 | |||
getTitleForAlias | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 |
1 | <?php |
2 | /** |
3 | * Factory for handling the special page list and generating SpecialPage objects. |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | * @ingroup SpecialPage |
22 | * @defgroup SpecialPage SpecialPage |
23 | */ |
24 | |
25 | namespace MediaWiki\SpecialPage; |
26 | |
27 | use MediaWiki\Config\ServiceOptions; |
28 | use MediaWiki\Context\IContextSource; |
29 | use MediaWiki\Context\RequestContext; |
30 | use MediaWiki\HookContainer\HookContainer; |
31 | use MediaWiki\HookContainer\HookRunner; |
32 | use MediaWiki\Language\Language; |
33 | use MediaWiki\Linker\LinkRenderer; |
34 | use MediaWiki\MainConfigNames; |
35 | use MediaWiki\Page\PageReference; |
36 | use MediaWiki\Profiler\ProfilingContext; |
37 | use MediaWiki\Specials\Redirects\SpecialAllMyUploads; |
38 | use MediaWiki\Specials\Redirects\SpecialListAdmins; |
39 | use MediaWiki\Specials\Redirects\SpecialListBots; |
40 | use MediaWiki\Specials\Redirects\SpecialMycontributions; |
41 | use MediaWiki\Specials\Redirects\SpecialMylog; |
42 | use MediaWiki\Specials\Redirects\SpecialMypage; |
43 | use MediaWiki\Specials\Redirects\SpecialMytalk; |
44 | use MediaWiki\Specials\Redirects\SpecialMyuploads; |
45 | use MediaWiki\Specials\Redirects\SpecialTalkPage; |
46 | use MediaWiki\Specials\SpecialActiveUsers; |
47 | use MediaWiki\Specials\SpecialAllMessages; |
48 | use MediaWiki\Specials\SpecialAllPages; |
49 | use MediaWiki\Specials\SpecialAncientPages; |
50 | use MediaWiki\Specials\SpecialApiHelp; |
51 | use MediaWiki\Specials\SpecialApiSandbox; |
52 | use MediaWiki\Specials\SpecialAuthenticationPopupSuccess; |
53 | use MediaWiki\Specials\SpecialAutoblockList; |
54 | use MediaWiki\Specials\SpecialBlankpage; |
55 | use MediaWiki\Specials\SpecialBlock; |
56 | use MediaWiki\Specials\SpecialBlockList; |
57 | use MediaWiki\Specials\SpecialBookSources; |
58 | use MediaWiki\Specials\SpecialBotPasswords; |
59 | use MediaWiki\Specials\SpecialBrokenRedirects; |
60 | use MediaWiki\Specials\SpecialCategories; |
61 | use MediaWiki\Specials\SpecialChangeContentModel; |
62 | use MediaWiki\Specials\SpecialChangeCredentials; |
63 | use MediaWiki\Specials\SpecialChangeEmail; |
64 | use MediaWiki\Specials\SpecialChangePassword; |
65 | use MediaWiki\Specials\SpecialComparePages; |
66 | use MediaWiki\Specials\SpecialConfirmEmail; |
67 | use MediaWiki\Specials\SpecialContribute; |
68 | use MediaWiki\Specials\SpecialContributions; |
69 | use MediaWiki\Specials\SpecialCreateAccount; |
70 | use MediaWiki\Specials\SpecialDeadendPages; |
71 | use MediaWiki\Specials\SpecialDeletedContributions; |
72 | use MediaWiki\Specials\SpecialDeletePage; |
73 | use MediaWiki\Specials\SpecialDiff; |
74 | use MediaWiki\Specials\SpecialDoubleRedirects; |
75 | use MediaWiki\Specials\SpecialEditPage; |
76 | use MediaWiki\Specials\SpecialEditRecovery; |
77 | use MediaWiki\Specials\SpecialEditTags; |
78 | use MediaWiki\Specials\SpecialEditWatchlist; |
79 | use MediaWiki\Specials\SpecialEmailInvalidate; |
80 | use MediaWiki\Specials\SpecialEmailUser; |
81 | use MediaWiki\Specials\SpecialExpandTemplates; |
82 | use MediaWiki\Specials\SpecialExport; |
83 | use MediaWiki\Specials\SpecialFewestRevisions; |
84 | use MediaWiki\Specials\SpecialFileDuplicateSearch; |
85 | use MediaWiki\Specials\SpecialFilepath; |
86 | use MediaWiki\Specials\SpecialGoToInterwiki; |
87 | use MediaWiki\Specials\SpecialImport; |
88 | use MediaWiki\Specials\SpecialJavaScriptTest; |
89 | use MediaWiki\Specials\SpecialLinkAccounts; |
90 | use MediaWiki\Specials\SpecialLinkSearch; |
91 | use MediaWiki\Specials\SpecialListDuplicatedFiles; |
92 | use MediaWiki\Specials\SpecialListFiles; |
93 | use MediaWiki\Specials\SpecialListGrants; |
94 | use MediaWiki\Specials\SpecialListGroupRights; |
95 | use MediaWiki\Specials\SpecialListRedirects; |
96 | use MediaWiki\Specials\SpecialListUsers; |
97 | use MediaWiki\Specials\SpecialLockdb; |
98 | use MediaWiki\Specials\SpecialLog; |
99 | use MediaWiki\Specials\SpecialLonelyPages; |
100 | use MediaWiki\Specials\SpecialLongPages; |
101 | use MediaWiki\Specials\SpecialMediaStatistics; |
102 | use MediaWiki\Specials\SpecialMergeHistory; |
103 | use MediaWiki\Specials\SpecialMIMESearch; |
104 | use MediaWiki\Specials\SpecialMostCategories; |
105 | use MediaWiki\Specials\SpecialMostImages; |
106 | use MediaWiki\Specials\SpecialMostInterwikis; |
107 | use MediaWiki\Specials\SpecialMostLinked; |
108 | use MediaWiki\Specials\SpecialMostLinkedCategories; |
109 | use MediaWiki\Specials\SpecialMostLinkedTemplates; |
110 | use MediaWiki\Specials\SpecialMostRevisions; |
111 | use MediaWiki\Specials\SpecialMovePage; |
112 | use MediaWiki\Specials\SpecialMute; |
113 | use MediaWiki\Specials\SpecialMyLanguage; |
114 | use MediaWiki\Specials\SpecialNamespaceInfo; |
115 | use MediaWiki\Specials\SpecialNewFiles; |
116 | use MediaWiki\Specials\SpecialNewPages; |
117 | use MediaWiki\Specials\SpecialNewSection; |
118 | use MediaWiki\Specials\SpecialPageData; |
119 | use MediaWiki\Specials\SpecialPageHistory; |
120 | use MediaWiki\Specials\SpecialPageInfo; |
121 | use MediaWiki\Specials\SpecialPageLanguage; |
122 | use MediaWiki\Specials\SpecialPagesWithProp; |
123 | use MediaWiki\Specials\SpecialPasswordPolicies; |
124 | use MediaWiki\Specials\SpecialPasswordReset; |
125 | use MediaWiki\Specials\SpecialPermanentLink; |
126 | use MediaWiki\Specials\SpecialPreferences; |
127 | use MediaWiki\Specials\SpecialPrefixIndex; |
128 | use MediaWiki\Specials\SpecialProtectedPages; |
129 | use MediaWiki\Specials\SpecialProtectedTitles; |
130 | use MediaWiki\Specials\SpecialProtectPage; |
131 | use MediaWiki\Specials\SpecialPurge; |
132 | use MediaWiki\Specials\SpecialRandomInCategory; |
133 | use MediaWiki\Specials\SpecialRandomPage; |
134 | use MediaWiki\Specials\SpecialRandomRedirect; |
135 | use MediaWiki\Specials\SpecialRandomRootPage; |
136 | use MediaWiki\Specials\SpecialRecentChanges; |
137 | use MediaWiki\Specials\SpecialRecentChangesLinked; |
138 | use MediaWiki\Specials\SpecialRedirect; |
139 | use MediaWiki\Specials\SpecialRemoveCredentials; |
140 | use MediaWiki\Specials\SpecialRenameUser; |
141 | use MediaWiki\Specials\SpecialResetTokens; |
142 | use MediaWiki\Specials\SpecialRestSandbox; |
143 | use MediaWiki\Specials\SpecialRevisionDelete; |
144 | use MediaWiki\Specials\SpecialRunJobs; |
145 | use MediaWiki\Specials\SpecialSearch; |
146 | use MediaWiki\Specials\SpecialShortPages; |
147 | use MediaWiki\Specials\SpecialSpecialPages; |
148 | use MediaWiki\Specials\SpecialStatistics; |
149 | use MediaWiki\Specials\SpecialTags; |
150 | use MediaWiki\Specials\SpecialTrackingCategories; |
151 | use MediaWiki\Specials\SpecialUnblock; |
152 | use MediaWiki\Specials\SpecialUncategorizedCategories; |
153 | use MediaWiki\Specials\SpecialUncategorizedImages; |
154 | use MediaWiki\Specials\SpecialUncategorizedPages; |
155 | use MediaWiki\Specials\SpecialUncategorizedTemplates; |
156 | use MediaWiki\Specials\SpecialUndelete; |
157 | use MediaWiki\Specials\SpecialUnlinkAccounts; |
158 | use MediaWiki\Specials\SpecialUnlockdb; |
159 | use MediaWiki\Specials\SpecialUnusedCategories; |
160 | use MediaWiki\Specials\SpecialUnusedImages; |
161 | use MediaWiki\Specials\SpecialUnusedTemplates; |
162 | use MediaWiki\Specials\SpecialUnwatchedPages; |
163 | use MediaWiki\Specials\SpecialUpload; |
164 | use MediaWiki\Specials\SpecialUploadStash; |
165 | use MediaWiki\Specials\SpecialUserLogin; |
166 | use MediaWiki\Specials\SpecialUserLogout; |
167 | use MediaWiki\Specials\SpecialUserRights; |
168 | use MediaWiki\Specials\SpecialVersion; |
169 | use MediaWiki\Specials\SpecialWantedCategories; |
170 | use MediaWiki\Specials\SpecialWantedFiles; |
171 | use MediaWiki\Specials\SpecialWantedPages; |
172 | use MediaWiki\Specials\SpecialWantedTemplates; |
173 | use MediaWiki\Specials\SpecialWatchlist; |
174 | use MediaWiki\Specials\SpecialWhatLinksHere; |
175 | use MediaWiki\Specials\SpecialWithoutInterwiki; |
176 | use MediaWiki\Title\Title; |
177 | use MediaWiki\Title\TitleFactory; |
178 | use MediaWiki\User\User; |
179 | use Profiler; |
180 | use Wikimedia\DebugInfo\DebugInfoTrait; |
181 | use Wikimedia\ObjectFactory\ObjectFactory; |
182 | |
183 | /** |
184 | * Factory for handling the special page list and generating SpecialPage objects. |
185 | * |
186 | * To add a special page in an extension, add to $wgSpecialPages either |
187 | * an object instance or an array containing the name and constructor |
188 | * parameters. The latter is preferred for performance reasons. |
189 | * |
190 | * The object instantiated must be either an instance of SpecialPage or a |
191 | * sub-class thereof. It must have an execute() method, which sends the HTML |
192 | * for the special page to $wgOut. The parent class has an execute() method |
193 | * which distributes the call to the historical global functions. Additionally, |
194 | * execute() also checks if the user has the necessary access privileges |
195 | * and bails out if not. |
196 | * |
197 | * To add a core special page, use the similar static list in |
198 | * SpecialPageFactory::$list. To remove a core static special page at runtime, use |
199 | * a SpecialPage_initList hook. |
200 | * |
201 | * @ingroup SpecialPage |
202 | * @since 1.17 |
203 | */ |
204 | class SpecialPageFactory { |
205 | use DebugInfoTrait; |
206 | |
207 | /** |
208 | * List of special page names to the subclass of SpecialPage which handles them. |
209 | */ |
210 | private const CORE_LIST = [ |
211 | // Maintenance Reports |
212 | 'BrokenRedirects' => [ |
213 | 'class' => SpecialBrokenRedirects::class, |
214 | 'services' => [ |
215 | 'ContentHandlerFactory', |
216 | 'ConnectionProvider', |
217 | 'LinkBatchFactory', |
218 | ] |
219 | ], |
220 | 'Deadendpages' => [ |
221 | 'class' => SpecialDeadendPages::class, |
222 | 'services' => [ |
223 | 'NamespaceInfo', |
224 | 'ConnectionProvider', |
225 | 'LinkBatchFactory', |
226 | 'LanguageConverterFactory', |
227 | ] |
228 | ], |
229 | 'DoubleRedirects' => [ |
230 | 'class' => SpecialDoubleRedirects::class, |
231 | 'services' => [ |
232 | 'ContentHandlerFactory', |
233 | 'LinkBatchFactory', |
234 | 'ConnectionProvider', |
235 | ] |
236 | ], |
237 | 'Longpages' => [ |
238 | 'class' => SpecialLongPages::class, |
239 | 'services' => [ |
240 | // Same as for Shortpages |
241 | 'NamespaceInfo', |
242 | 'ConnectionProvider', |
243 | 'LinkBatchFactory', |
244 | ] |
245 | ], |
246 | 'Ancientpages' => [ |
247 | 'class' => SpecialAncientPages::class, |
248 | 'services' => [ |
249 | 'NamespaceInfo', |
250 | 'ConnectionProvider', |
251 | 'LinkBatchFactory', |
252 | 'LanguageConverterFactory', |
253 | ] |
254 | ], |
255 | 'Lonelypages' => [ |
256 | 'class' => SpecialLonelyPages::class, |
257 | 'services' => [ |
258 | 'NamespaceInfo', |
259 | 'ConnectionProvider', |
260 | 'LinkBatchFactory', |
261 | 'LanguageConverterFactory', |
262 | 'LinksMigration', |
263 | ] |
264 | ], |
265 | 'Fewestrevisions' => [ |
266 | 'class' => SpecialFewestRevisions::class, |
267 | 'services' => [ |
268 | // Same as for Mostrevisions |
269 | 'NamespaceInfo', |
270 | 'ConnectionProvider', |
271 | 'LinkBatchFactory', |
272 | 'LanguageConverterFactory', |
273 | ] |
274 | ], |
275 | 'Withoutinterwiki' => [ |
276 | 'class' => SpecialWithoutInterwiki::class, |
277 | 'services' => [ |
278 | 'NamespaceInfo', |
279 | 'ConnectionProvider', |
280 | 'LinkBatchFactory', |
281 | 'LanguageConverterFactory', |
282 | ] |
283 | ], |
284 | 'Protectedpages' => [ |
285 | 'class' => SpecialProtectedPages::class, |
286 | 'services' => [ |
287 | 'LinkBatchFactory', |
288 | 'ConnectionProvider', |
289 | 'CommentStore', |
290 | 'RowCommentFormatter', |
291 | 'RestrictionStore', |
292 | ] |
293 | ], |
294 | 'Protectedtitles' => [ |
295 | 'class' => SpecialProtectedTitles::class, |
296 | 'services' => [ |
297 | 'LinkBatchFactory', |
298 | 'ConnectionProvider', |
299 | ] |
300 | ], |
301 | 'Shortpages' => [ |
302 | 'class' => SpecialShortPages::class, |
303 | 'services' => [ |
304 | // Same as for Longpages |
305 | 'NamespaceInfo', |
306 | 'ConnectionProvider', |
307 | 'LinkBatchFactory', |
308 | ] |
309 | ], |
310 | 'Uncategorizedcategories' => [ |
311 | 'class' => SpecialUncategorizedCategories::class, |
312 | 'services' => [ |
313 | // Same as for SpecialUncategorizedPages and SpecialUncategorizedTemplates |
314 | 'NamespaceInfo', |
315 | 'ConnectionProvider', |
316 | 'LinkBatchFactory', |
317 | 'LanguageConverterFactory', |
318 | ] |
319 | ], |
320 | 'Uncategorizedimages' => [ |
321 | 'class' => SpecialUncategorizedImages::class, |
322 | 'services' => [ |
323 | 'ConnectionProvider', |
324 | ] |
325 | ], |
326 | 'Uncategorizedpages' => [ |
327 | 'class' => SpecialUncategorizedPages::class, |
328 | 'services' => [ |
329 | // Same as for SpecialUncategorizedCategories and SpecialUncategorizedTemplates |
330 | 'NamespaceInfo', |
331 | 'ConnectionProvider', |
332 | 'LinkBatchFactory', |
333 | 'LanguageConverterFactory', |
334 | ] |
335 | ], |
336 | 'Uncategorizedtemplates' => [ |
337 | 'class' => SpecialUncategorizedTemplates::class, |
338 | 'services' => [ |
339 | // Same as for SpecialUncategorizedCategories and SpecialUncategorizedPages |
340 | 'NamespaceInfo', |
341 | 'ConnectionProvider', |
342 | 'LinkBatchFactory', |
343 | 'LanguageConverterFactory', |
344 | ] |
345 | ], |
346 | 'Unusedcategories' => [ |
347 | 'class' => SpecialUnusedCategories::class, |
348 | 'services' => [ |
349 | 'ConnectionProvider', |
350 | 'LinkBatchFactory', |
351 | ] |
352 | ], |
353 | 'Unusedimages' => [ |
354 | 'class' => SpecialUnusedImages::class, |
355 | 'services' => [ |
356 | 'ConnectionProvider', |
357 | ] |
358 | ], |
359 | 'Unusedtemplates' => [ |
360 | 'class' => SpecialUnusedTemplates::class, |
361 | 'services' => [ |
362 | 'ConnectionProvider', |
363 | 'LinksMigration', |
364 | ] |
365 | ], |
366 | 'Unwatchedpages' => [ |
367 | 'class' => SpecialUnwatchedPages::class, |
368 | 'services' => [ |
369 | 'LinkBatchFactory', |
370 | 'ConnectionProvider', |
371 | 'LanguageConverterFactory', |
372 | ] |
373 | ], |
374 | 'Wantedcategories' => [ |
375 | 'class' => SpecialWantedCategories::class, |
376 | 'services' => [ |
377 | 'ConnectionProvider', |
378 | 'LinkBatchFactory', |
379 | 'LanguageConverterFactory', |
380 | ] |
381 | ], |
382 | 'Wantedfiles' => [ |
383 | 'class' => SpecialWantedFiles::class, |
384 | 'services' => [ |
385 | 'RepoGroup', |
386 | 'ConnectionProvider', |
387 | 'LinkBatchFactory', |
388 | ] |
389 | ], |
390 | 'Wantedpages' => [ |
391 | 'class' => SpecialWantedPages::class, |
392 | 'services' => [ |
393 | 'ConnectionProvider', |
394 | 'LinkBatchFactory', |
395 | 'LinksMigration', |
396 | ] |
397 | ], |
398 | 'Wantedtemplates' => [ |
399 | 'class' => SpecialWantedTemplates::class, |
400 | 'services' => [ |
401 | 'ConnectionProvider', |
402 | 'LinkBatchFactory', |
403 | 'LinksMigration', |
404 | ] |
405 | ], |
406 | |
407 | // List of pages |
408 | 'Allpages' => [ |
409 | 'class' => SpecialAllPages::class, |
410 | 'services' => [ |
411 | 'ConnectionProvider', |
412 | 'SearchEngineFactory', |
413 | 'PageStore', |
414 | ] |
415 | ], |
416 | 'Prefixindex' => [ |
417 | 'class' => SpecialPrefixIndex::class, |
418 | 'services' => [ |
419 | 'ConnectionProvider', |
420 | 'LinkCache', |
421 | ] |
422 | ], |
423 | 'Categories' => [ |
424 | 'class' => SpecialCategories::class, |
425 | 'services' => [ |
426 | 'LinkBatchFactory', |
427 | 'ConnectionProvider', |
428 | ] |
429 | ], |
430 | 'Listredirects' => [ |
431 | 'class' => SpecialListRedirects::class, |
432 | 'services' => [ |
433 | 'LinkBatchFactory', |
434 | 'ConnectionProvider', |
435 | 'WikiPageFactory', |
436 | 'RedirectLookup' |
437 | ] |
438 | ], |
439 | 'PagesWithProp' => [ |
440 | 'class' => SpecialPagesWithProp::class, |
441 | 'services' => [ |
442 | 'ConnectionProvider', |
443 | ] |
444 | ], |
445 | 'TrackingCategories' => [ |
446 | 'class' => SpecialTrackingCategories::class, |
447 | 'services' => [ |
448 | 'LinkBatchFactory', |
449 | 'TrackingCategories', |
450 | ] |
451 | ], |
452 | |
453 | // Authentication |
454 | 'Userlogin' => [ |
455 | 'class' => SpecialUserLogin::class, |
456 | 'services' => [ |
457 | 'AuthManager', |
458 | 'UserIdentityUtils', |
459 | ] |
460 | ], |
461 | 'Userlogout' => [ |
462 | 'class' => SpecialUserLogout::class, |
463 | 'services' => [ |
464 | 'TempUserConfig', |
465 | ], |
466 | ], |
467 | 'CreateAccount' => [ |
468 | 'class' => SpecialCreateAccount::class, |
469 | 'services' => [ |
470 | 'AuthManager', |
471 | 'FormatterFactory', |
472 | 'UserIdentityUtils', |
473 | ] |
474 | ], |
475 | 'LinkAccounts' => [ |
476 | 'class' => SpecialLinkAccounts::class, |
477 | 'services' => [ |
478 | 'AuthManager', |
479 | ] |
480 | ], |
481 | 'UnlinkAccounts' => [ |
482 | 'class' => SpecialUnlinkAccounts::class, |
483 | 'services' => [ |
484 | 'AuthManager', |
485 | ] |
486 | ], |
487 | 'ChangeCredentials' => [ |
488 | 'class' => SpecialChangeCredentials::class, |
489 | 'services' => [ |
490 | 'AuthManager', |
491 | ] |
492 | ], |
493 | 'RemoveCredentials' => [ |
494 | 'class' => SpecialRemoveCredentials::class, |
495 | 'services' => [ |
496 | 'AuthManager', |
497 | ] |
498 | ], |
499 | 'AuthenticationPopupSuccess' => [ |
500 | 'class' => SpecialAuthenticationPopupSuccess::class, |
501 | 'services' => [ |
502 | 'SkinFactory', |
503 | ] |
504 | ], |
505 | |
506 | // Users and rights |
507 | 'Activeusers' => [ |
508 | 'class' => SpecialActiveUsers::class, |
509 | 'services' => [ |
510 | 'LinkBatchFactory', |
511 | 'ConnectionProvider', |
512 | 'UserGroupManager', |
513 | 'UserIdentityLookup', |
514 | 'HideUserUtils', |
515 | ] |
516 | ], |
517 | 'Block' => [ |
518 | 'class' => SpecialBlock::class, |
519 | 'services' => [ |
520 | 'BlockUtils', |
521 | 'BlockPermissionCheckerFactory', |
522 | 'BlockUserFactory', |
523 | 'DatabaseBlockStore', |
524 | 'UserNameUtils', |
525 | 'UserNamePrefixSearch', |
526 | 'BlockActionInfo', |
527 | 'TitleFormatter', |
528 | 'NamespaceInfo' |
529 | ] |
530 | ], |
531 | 'Unblock' => [ |
532 | 'class' => SpecialUnblock::class, |
533 | 'services' => [ |
534 | 'UnblockUserFactory', |
535 | 'BlockUtils', |
536 | 'DatabaseBlockStore', |
537 | 'UserNameUtils', |
538 | 'UserNamePrefixSearch', |
539 | 'WatchlistManager', |
540 | ] |
541 | ], |
542 | 'BlockList' => [ |
543 | 'class' => SpecialBlockList::class, |
544 | 'services' => [ |
545 | 'LinkBatchFactory', |
546 | 'DatabaseBlockStore', |
547 | 'BlockRestrictionStore', |
548 | 'ConnectionProvider', |
549 | 'CommentStore', |
550 | 'BlockUtils', |
551 | 'HideUserUtils', |
552 | 'BlockActionInfo', |
553 | 'RowCommentFormatter', |
554 | ], |
555 | ], |
556 | 'AutoblockList' => [ |
557 | 'class' => SpecialAutoblockList::class, |
558 | 'services' => [ |
559 | 'LinkBatchFactory', |
560 | 'BlockRestrictionStore', |
561 | 'ConnectionProvider', |
562 | 'CommentStore', |
563 | 'BlockUtils', |
564 | 'HideUserUtils', |
565 | 'BlockActionInfo', |
566 | 'RowCommentFormatter', |
567 | ], |
568 | ], |
569 | 'ChangePassword' => [ |
570 | 'class' => SpecialChangePassword::class, |
571 | ], |
572 | 'BotPasswords' => [ |
573 | 'class' => SpecialBotPasswords::class, |
574 | 'services' => [ |
575 | 'PasswordFactory', |
576 | 'AuthManager', |
577 | 'CentralIdLookup', |
578 | 'GrantsInfo', |
579 | 'GrantsLocalization', |
580 | ] |
581 | ], |
582 | 'PasswordReset' => [ |
583 | 'class' => SpecialPasswordReset::class, |
584 | 'services' => [ |
585 | 'PasswordReset' |
586 | ] |
587 | ], |
588 | 'DeletedContributions' => [ |
589 | 'class' => SpecialDeletedContributions::class, |
590 | 'services' => [ |
591 | 'PermissionManager', |
592 | 'ConnectionProvider', |
593 | 'RevisionStore', |
594 | 'NamespaceInfo', |
595 | 'UserNameUtils', |
596 | 'UserNamePrefixSearch', |
597 | 'UserOptionsLookup', |
598 | 'CommentFormatter', |
599 | 'LinkBatchFactory', |
600 | 'UserFactory', |
601 | 'UserIdentityLookup', |
602 | 'DatabaseBlockStore', |
603 | 'TempUserConfig', |
604 | ] |
605 | ], |
606 | 'Preferences' => [ |
607 | 'class' => SpecialPreferences::class, |
608 | 'services' => [ |
609 | 'PreferencesFactory', |
610 | 'UserOptionsManager', |
611 | ] |
612 | ], |
613 | 'ResetTokens' => [ |
614 | 'class' => SpecialResetTokens::class, |
615 | ], |
616 | 'Contributions' => [ |
617 | 'class' => SpecialContributions::class, |
618 | 'services' => [ |
619 | 'LinkBatchFactory', |
620 | 'PermissionManager', |
621 | 'ConnectionProvider', |
622 | 'RevisionStore', |
623 | 'NamespaceInfo', |
624 | 'UserNameUtils', |
625 | 'UserNamePrefixSearch', |
626 | 'UserOptionsLookup', |
627 | 'CommentFormatter', |
628 | 'UserFactory', |
629 | 'UserIdentityLookup', |
630 | 'DatabaseBlockStore', |
631 | 'TempUserConfig', |
632 | ] |
633 | ], |
634 | 'Listgrouprights' => [ |
635 | 'class' => SpecialListGroupRights::class, |
636 | 'services' => [ |
637 | 'NamespaceInfo', |
638 | 'UserGroupManager', |
639 | 'LanguageConverterFactory', |
640 | 'GroupPermissionsLookup', |
641 | ] |
642 | ], |
643 | 'Listgrants' => [ |
644 | 'class' => SpecialListGrants::class, |
645 | 'services' => [ |
646 | 'GrantsLocalization', |
647 | ] |
648 | ], |
649 | 'Listusers' => [ |
650 | 'class' => SpecialListUsers::class, |
651 | 'services' => [ |
652 | 'LinkBatchFactory', |
653 | 'ConnectionProvider', |
654 | 'UserGroupManager', |
655 | 'UserIdentityLookup', |
656 | 'HideUserUtils', |
657 | ] |
658 | ], |
659 | 'Listadmins' => [ |
660 | 'class' => SpecialListAdmins::class, |
661 | ], |
662 | 'Listbots' => [ |
663 | 'class' => SpecialListBots::class, |
664 | ], |
665 | 'Userrights' => [ |
666 | 'class' => SpecialUserRights::class, |
667 | 'services' => [ |
668 | 'UserGroupManagerFactory', |
669 | 'UserNameUtils', |
670 | 'UserNamePrefixSearch', |
671 | 'UserFactory', |
672 | 'ActorStoreFactory', |
673 | 'WatchlistManager', |
674 | 'TempUserConfig', |
675 | ] |
676 | ], |
677 | 'EditWatchlist' => [ |
678 | 'class' => SpecialEditWatchlist::class, |
679 | 'services' => [ |
680 | 'WatchedItemStore', |
681 | 'TitleParser', |
682 | 'GenderCache', |
683 | 'LinkBatchFactory', |
684 | 'NamespaceInfo', |
685 | 'WikiPageFactory', |
686 | 'WatchlistManager', |
687 | ] |
688 | ], |
689 | 'PasswordPolicies' => [ |
690 | 'class' => SpecialPasswordPolicies::class, |
691 | 'services' => [ |
692 | 'UserGroupManager', |
693 | ] |
694 | ], |
695 | |
696 | // Recent changes and logs |
697 | 'Newimages' => [ |
698 | 'class' => SpecialNewFiles::class, |
699 | 'services' => [ |
700 | 'MimeAnalyzer', |
701 | 'GroupPermissionsLookup', |
702 | 'ConnectionProvider', |
703 | 'LinkBatchFactory', |
704 | ] |
705 | ], |
706 | 'Log' => [ |
707 | 'class' => SpecialLog::class, |
708 | 'services' => [ |
709 | 'LinkBatchFactory', |
710 | 'ConnectionProvider', |
711 | 'ActorNormalization', |
712 | 'UserIdentityLookup', |
713 | 'UserNameUtils', |
714 | 'LogFormatterFactory', |
715 | ] |
716 | ], |
717 | 'Watchlist' => [ |
718 | 'class' => SpecialWatchlist::class, |
719 | 'services' => [ |
720 | 'WatchedItemStore', |
721 | 'WatchlistManager', |
722 | 'UserOptionsLookup', |
723 | 'ChangeTagsStore', |
724 | 'UserIdentityUtils', |
725 | 'TempUserConfig', |
726 | ] |
727 | ], |
728 | 'Newpages' => [ |
729 | 'class' => SpecialNewPages::class, |
730 | 'services' => [ |
731 | 'LinkBatchFactory', |
732 | 'ContentHandlerFactory', |
733 | 'GroupPermissionsLookup', |
734 | 'RevisionLookup', |
735 | 'NamespaceInfo', |
736 | 'UserOptionsLookup', |
737 | 'RowCommentFormatter', |
738 | 'ChangeTagsStore', |
739 | 'TempUserConfig', |
740 | ] |
741 | ], |
742 | 'Recentchanges' => [ |
743 | 'class' => SpecialRecentChanges::class, |
744 | 'services' => [ |
745 | 'WatchedItemStore', |
746 | 'MessageCache', |
747 | 'UserOptionsLookup', |
748 | 'ChangeTagsStore', |
749 | 'UserIdentityUtils', |
750 | 'TempUserConfig', |
751 | ] |
752 | ], |
753 | 'Recentchangeslinked' => [ |
754 | 'class' => SpecialRecentChangesLinked::class, |
755 | 'services' => [ |
756 | 'WatchedItemStore', |
757 | 'MessageCache', |
758 | 'UserOptionsLookup', |
759 | 'SearchEngineFactory', |
760 | 'ChangeTagsStore', |
761 | 'UserIdentityUtils', |
762 | 'TempUserConfig', |
763 | ] |
764 | ], |
765 | 'Tags' => [ |
766 | 'class' => SpecialTags::class, |
767 | 'services' => [ |
768 | 'ChangeTagsStore', |
769 | ] |
770 | ], |
771 | |
772 | // Media reports and uploads |
773 | 'Listfiles' => [ |
774 | 'class' => SpecialListFiles::class, |
775 | 'services' => [ |
776 | 'RepoGroup', |
777 | 'ConnectionProvider', |
778 | 'CommentStore', |
779 | 'UserNameUtils', |
780 | 'UserNamePrefixSearch', |
781 | 'CommentFormatter', |
782 | 'LinkBatchFactory', |
783 | ] |
784 | ], |
785 | 'Filepath' => [ |
786 | 'class' => SpecialFilepath::class, |
787 | 'services' => [ |
788 | 'SearchEngineFactory', |
789 | ] |
790 | ], |
791 | 'MediaStatistics' => [ |
792 | 'class' => SpecialMediaStatistics::class, |
793 | 'services' => [ |
794 | 'MimeAnalyzer', |
795 | 'ConnectionProvider', |
796 | 'LinkBatchFactory', |
797 | ] |
798 | ], |
799 | 'MIMEsearch' => [ |
800 | 'class' => SpecialMIMESearch::class, |
801 | 'services' => [ |
802 | 'ConnectionProvider', |
803 | 'LinkBatchFactory', |
804 | 'LanguageConverterFactory', |
805 | ] |
806 | ], |
807 | 'FileDuplicateSearch' => [ |
808 | 'class' => SpecialFileDuplicateSearch::class, |
809 | 'services' => [ |
810 | 'LinkBatchFactory', |
811 | 'RepoGroup', |
812 | 'SearchEngineFactory', |
813 | 'LanguageConverterFactory', |
814 | ] |
815 | ], |
816 | 'Upload' => [ |
817 | 'class' => SpecialUpload::class, |
818 | 'services' => [ |
819 | 'RepoGroup', |
820 | 'UserOptionsLookup', |
821 | 'NamespaceInfo', |
822 | ] |
823 | ], |
824 | 'UploadStash' => [ |
825 | 'class' => SpecialUploadStash::class, |
826 | 'services' => [ |
827 | 'RepoGroup', |
828 | 'HttpRequestFactory', |
829 | 'UrlUtils', |
830 | 'ConnectionProvider', |
831 | ] |
832 | ], |
833 | 'ListDuplicatedFiles' => [ |
834 | 'class' => SpecialListDuplicatedFiles::class, |
835 | 'services' => [ |
836 | 'ConnectionProvider', |
837 | 'LinkBatchFactory', |
838 | ] |
839 | ], |
840 | |
841 | // Data and tools |
842 | 'ApiSandbox' => [ |
843 | 'class' => SpecialApiSandbox::class, |
844 | ], |
845 | 'RestSandbox' => [ |
846 | 'class' => SpecialRestSandbox::class, |
847 | 'services' => [ |
848 | 'UrlUtils', |
849 | ] |
850 | ], |
851 | 'Statistics' => [ |
852 | 'class' => SpecialStatistics::class, |
853 | 'services' => [ |
854 | 'UserGroupManager', |
855 | ] |
856 | ], |
857 | 'Allmessages' => [ |
858 | 'class' => SpecialAllMessages::class, |
859 | 'services' => [ |
860 | 'LanguageFactory', |
861 | 'LanguageNameUtils', |
862 | 'LocalisationCache', |
863 | 'ConnectionProvider', |
864 | ] |
865 | ], |
866 | 'Version' => [ |
867 | 'class' => SpecialVersion::class, |
868 | 'services' => [ |
869 | 'ParserFactory', |
870 | 'UrlUtils', |
871 | 'ConnectionProvider', |
872 | ] |
873 | ], |
874 | 'Lockdb' => [ |
875 | 'class' => SpecialLockdb::class, |
876 | ], |
877 | 'Unlockdb' => [ |
878 | 'class' => SpecialUnlockdb::class, |
879 | ], |
880 | 'NamespaceInfo' => [ |
881 | 'class' => SpecialNamespaceInfo::class, |
882 | 'services' => [ |
883 | 'NamespaceInfo', |
884 | ], |
885 | ], |
886 | |
887 | // Redirecting special pages |
888 | 'LinkSearch' => [ |
889 | 'class' => SpecialLinkSearch::class, |
890 | 'services' => [ |
891 | 'ConnectionProvider', |
892 | 'LinkBatchFactory', |
893 | 'UrlUtils', |
894 | ] |
895 | ], |
896 | 'Randompage' => [ |
897 | 'class' => SpecialRandomPage::class, |
898 | 'services' => [ |
899 | 'ConnectionProvider', |
900 | 'NamespaceInfo', |
901 | ] |
902 | ], |
903 | 'RandomInCategory' => [ |
904 | 'class' => SpecialRandomInCategory::class, |
905 | 'services' => [ |
906 | 'ConnectionProvider', |
907 | ] |
908 | ], |
909 | 'Randomredirect' => [ |
910 | 'class' => SpecialRandomRedirect::class, |
911 | 'services' => [ |
912 | 'ConnectionProvider', |
913 | 'NamespaceInfo', |
914 | ] |
915 | ], |
916 | 'Randomrootpage' => [ |
917 | 'class' => SpecialRandomRootPage::class, |
918 | 'services' => [ |
919 | 'ConnectionProvider', |
920 | 'NamespaceInfo', |
921 | ] |
922 | ], |
923 | 'GoToInterwiki' => [ |
924 | 'class' => SpecialGoToInterwiki::class, |
925 | ], |
926 | |
927 | // High use pages |
928 | 'Mostlinkedcategories' => [ |
929 | 'class' => SpecialMostLinkedCategories::class, |
930 | 'services' => [ |
931 | 'ConnectionProvider', |
932 | 'LinkBatchFactory', |
933 | 'LanguageConverterFactory', |
934 | ] |
935 | ], |
936 | 'Mostimages' => [ |
937 | 'class' => SpecialMostImages::class, |
938 | 'services' => [ |
939 | 'ConnectionProvider', |
940 | 'LanguageConverterFactory', |
941 | ] |
942 | ], |
943 | 'Mostinterwikis' => [ |
944 | 'class' => SpecialMostInterwikis::class, |
945 | 'services' => [ |
946 | 'NamespaceInfo', |
947 | 'ConnectionProvider', |
948 | 'LinkBatchFactory', |
949 | ] |
950 | ], |
951 | 'Mostlinked' => [ |
952 | 'class' => SpecialMostLinked::class, |
953 | 'services' => [ |
954 | 'ConnectionProvider', |
955 | 'LinkBatchFactory', |
956 | 'LinksMigration', |
957 | ] |
958 | ], |
959 | 'Mostlinkedtemplates' => [ |
960 | 'class' => SpecialMostLinkedTemplates::class, |
961 | 'services' => [ |
962 | 'ConnectionProvider', |
963 | 'LinkBatchFactory', |
964 | 'LinksMigration', |
965 | ] |
966 | ], |
967 | 'Mostcategories' => [ |
968 | 'class' => SpecialMostCategories::class, |
969 | 'services' => [ |
970 | 'NamespaceInfo', |
971 | 'ConnectionProvider', |
972 | 'LinkBatchFactory', |
973 | ] |
974 | ], |
975 | 'Mostrevisions' => [ |
976 | 'class' => SpecialMostRevisions::class, |
977 | 'services' => [ |
978 | // Same as for Fewestrevisions |
979 | 'NamespaceInfo', |
980 | 'ConnectionProvider', |
981 | 'LinkBatchFactory', |
982 | 'LanguageConverterFactory', |
983 | ] |
984 | ], |
985 | |
986 | // Page tools |
987 | 'ComparePages' => [ |
988 | 'class' => SpecialComparePages::class, |
989 | 'services' => [ |
990 | 'RevisionLookup', |
991 | 'ContentHandlerFactory', |
992 | ] |
993 | ], |
994 | 'Export' => [ |
995 | 'class' => SpecialExport::class, |
996 | 'services' => [ |
997 | 'ConnectionProvider', |
998 | 'WikiExporterFactory', |
999 | 'TitleFormatter', |
1000 | 'LinksMigration', |
1001 | ] |
1002 | ], |
1003 | 'Import' => [ |
1004 | 'class' => SpecialImport::class, |
1005 | 'services' => [ |
1006 | 'WikiImporterFactory', |
1007 | ] |
1008 | ], |
1009 | 'Undelete' => [ |
1010 | 'class' => SpecialUndelete::class, |
1011 | 'services' => [ |
1012 | 'PermissionManager', |
1013 | 'RevisionStore', |
1014 | 'RevisionRenderer', |
1015 | 'ContentHandlerFactory', |
1016 | 'ChangeTagDefStore', |
1017 | 'LinkBatchFactory', |
1018 | 'RepoGroup', |
1019 | 'ConnectionProvider', |
1020 | 'UserOptionsLookup', |
1021 | 'WikiPageFactory', |
1022 | 'SearchEngineFactory', |
1023 | 'UndeletePageFactory', |
1024 | 'ArchivedRevisionLookup', |
1025 | 'CommentFormatter', |
1026 | 'WatchlistManager', |
1027 | ], |
1028 | ], |
1029 | 'Whatlinkshere' => [ |
1030 | 'class' => SpecialWhatLinksHere::class, |
1031 | 'services' => [ |
1032 | 'ConnectionProvider', |
1033 | 'LinkBatchFactory', |
1034 | 'ContentHandlerFactory', |
1035 | 'SearchEngineFactory', |
1036 | 'NamespaceInfo', |
1037 | 'TitleFactory', |
1038 | 'LinksMigration', |
1039 | ] |
1040 | ], |
1041 | 'MergeHistory' => [ |
1042 | 'class' => SpecialMergeHistory::class, |
1043 | 'services' => [ |
1044 | 'MergeHistoryFactory', |
1045 | 'LinkBatchFactory', |
1046 | 'ConnectionProvider', |
1047 | 'RevisionStore', |
1048 | 'CommentFormatter', |
1049 | ] |
1050 | ], |
1051 | 'ExpandTemplates' => [ |
1052 | 'class' => SpecialExpandTemplates::class, |
1053 | 'services' => [ |
1054 | 'ParserFactory', |
1055 | 'UserOptionsLookup', |
1056 | 'Tidy', |
1057 | ], |
1058 | ], |
1059 | 'ChangeContentModel' => [ |
1060 | 'class' => SpecialChangeContentModel::class, |
1061 | 'services' => [ |
1062 | 'ContentHandlerFactory', |
1063 | 'ContentModelChangeFactory', |
1064 | 'SpamChecker', |
1065 | 'RevisionLookup', |
1066 | 'WikiPageFactory', |
1067 | 'SearchEngineFactory', |
1068 | 'CollationFactory', |
1069 | ], |
1070 | ], |
1071 | |
1072 | // Other |
1073 | 'Booksources' => [ |
1074 | 'class' => SpecialBookSources::class, |
1075 | 'services' => [ |
1076 | 'RevisionLookup', |
1077 | 'TitleFactory', |
1078 | ] |
1079 | ], |
1080 | |
1081 | // Unlisted / redirects |
1082 | 'ApiHelp' => [ |
1083 | 'class' => SpecialApiHelp::class, |
1084 | 'services' => [ |
1085 | 'UrlUtils', |
1086 | ] |
1087 | ], |
1088 | 'Blankpage' => [ |
1089 | 'class' => SpecialBlankpage::class, |
1090 | ], |
1091 | 'DeletePage' => [ |
1092 | 'class' => SpecialDeletePage::class, |
1093 | 'services' => [ |
1094 | 'SearchEngineFactory', |
1095 | ] |
1096 | ], |
1097 | 'Diff' => [ |
1098 | 'class' => SpecialDiff::class, |
1099 | ], |
1100 | 'EditPage' => [ |
1101 | 'class' => SpecialEditPage::class, |
1102 | 'services' => [ |
1103 | 'SearchEngineFactory', |
1104 | ] |
1105 | ], |
1106 | 'EditTags' => [ |
1107 | 'class' => SpecialEditTags::class, |
1108 | 'services' => [ |
1109 | 'PermissionManager', |
1110 | 'ChangeTagsStore', |
1111 | ], |
1112 | ], |
1113 | 'Emailuser' => [ |
1114 | 'class' => SpecialEmailUser::class, |
1115 | 'services' => [ |
1116 | 'UserNameUtils', |
1117 | 'UserNamePrefixSearch', |
1118 | 'UserOptionsLookup', |
1119 | 'EmailUserFactory', |
1120 | 'UserFactory', |
1121 | ] |
1122 | ], |
1123 | 'Movepage' => [ |
1124 | 'class' => SpecialMovePage::class, |
1125 | 'services' => [ |
1126 | 'MovePageFactory', |
1127 | 'PermissionManager', |
1128 | 'UserOptionsLookup', |
1129 | 'ConnectionProvider', |
1130 | 'ContentHandlerFactory', |
1131 | 'NamespaceInfo', |
1132 | 'LinkBatchFactory', |
1133 | 'RepoGroup', |
1134 | 'WikiPageFactory', |
1135 | 'SearchEngineFactory', |
1136 | 'WatchlistManager', |
1137 | 'RestrictionStore', |
1138 | 'TitleFactory', |
1139 | 'DeletePageFactory', |
1140 | ] |
1141 | ], |
1142 | 'Mycontributions' => [ |
1143 | 'class' => SpecialMycontributions::class, |
1144 | 'services' => [ |
1145 | 'TempUserConfig', |
1146 | ], |
1147 | ], |
1148 | 'MyLanguage' => [ |
1149 | 'class' => SpecialMyLanguage::class, |
1150 | 'services' => [ |
1151 | 'LanguageNameUtils', |
1152 | 'RedirectLookup' |
1153 | ] |
1154 | ], |
1155 | 'Mylog' => [ |
1156 | 'class' => SpecialMylog::class, |
1157 | 'services' => [ |
1158 | 'TempUserConfig', |
1159 | ], |
1160 | ], |
1161 | 'Mypage' => [ |
1162 | 'class' => SpecialMypage::class, |
1163 | 'services' => [ |
1164 | 'TempUserConfig', |
1165 | ], |
1166 | ], |
1167 | 'Mytalk' => [ |
1168 | 'class' => SpecialMytalk::class, |
1169 | 'services' => [ |
1170 | 'TempUserConfig', |
1171 | ], |
1172 | ], |
1173 | 'PageHistory' => [ |
1174 | 'class' => SpecialPageHistory::class, |
1175 | 'services' => [ |
1176 | 'SearchEngineFactory', |
1177 | ] |
1178 | ], |
1179 | 'PageInfo' => [ |
1180 | 'class' => SpecialPageInfo::class, |
1181 | 'services' => [ |
1182 | 'SearchEngineFactory', |
1183 | ] |
1184 | ], |
1185 | 'ProtectPage' => [ |
1186 | 'class' => SpecialProtectPage::class, |
1187 | 'services' => [ |
1188 | 'SearchEngineFactory', |
1189 | ] |
1190 | ], |
1191 | 'Purge' => [ |
1192 | 'class' => SpecialPurge::class, |
1193 | 'services' => [ |
1194 | 'SearchEngineFactory', |
1195 | ] |
1196 | ], |
1197 | 'Myuploads' => [ |
1198 | 'class' => SpecialMyuploads::class, |
1199 | 'services' => [ |
1200 | 'TempUserConfig', |
1201 | ], |
1202 | ], |
1203 | 'AllMyUploads' => [ |
1204 | 'class' => SpecialAllMyUploads::class, |
1205 | ], |
1206 | 'NewSection' => [ |
1207 | 'class' => SpecialNewSection::class, |
1208 | 'services' => [ |
1209 | 'SearchEngineFactory', |
1210 | ] |
1211 | ], |
1212 | 'PermanentLink' => [ |
1213 | 'class' => SpecialPermanentLink::class, |
1214 | ], |
1215 | 'Redirect' => [ |
1216 | 'class' => SpecialRedirect::class, |
1217 | 'services' => [ |
1218 | 'RepoGroup', |
1219 | 'UserFactory', |
1220 | ] |
1221 | ], |
1222 | 'Renameuser' => [ |
1223 | 'class' => SpecialRenameUser::class, |
1224 | 'services' => [ |
1225 | 'ConnectionProvider', |
1226 | 'MovePageFactory', |
1227 | 'PermissionManager', |
1228 | 'TitleFactory', |
1229 | 'UserFactory', |
1230 | 'UserNamePrefixSearch', |
1231 | 'UserNameUtils', |
1232 | ] |
1233 | ], |
1234 | 'Revisiondelete' => [ |
1235 | 'class' => SpecialRevisionDelete::class, |
1236 | 'services' => [ |
1237 | 'PermissionManager', |
1238 | 'RepoGroup', |
1239 | ], |
1240 | ], |
1241 | 'RunJobs' => [ |
1242 | 'class' => SpecialRunJobs::class, |
1243 | 'services' => [ |
1244 | 'JobRunner', |
1245 | 'ReadOnlyMode', |
1246 | ] |
1247 | ], |
1248 | 'Specialpages' => [ |
1249 | 'class' => SpecialSpecialPages::class, |
1250 | ], |
1251 | 'PageData' => [ |
1252 | 'class' => SpecialPageData::class, |
1253 | ], |
1254 | 'Contribute' => [ |
1255 | 'class' => SpecialContribute::class, |
1256 | ], |
1257 | 'TalkPage' => [ |
1258 | 'class' => SpecialTalkPage::class, |
1259 | 'services' => [ |
1260 | 'MainConfig', |
1261 | 'TitleParser', |
1262 | ], |
1263 | ], |
1264 | ]; |
1265 | |
1266 | /** @var array Special page name => class name */ |
1267 | private $list; |
1268 | |
1269 | /** @var array */ |
1270 | private $aliases; |
1271 | |
1272 | /** @var ServiceOptions */ |
1273 | private $options; |
1274 | |
1275 | /** @var Language */ |
1276 | private $contLang; |
1277 | |
1278 | /** |
1279 | * @var ObjectFactory |
1280 | * @noVarDump |
1281 | */ |
1282 | private $objectFactory; |
1283 | |
1284 | /** |
1285 | * @var HookContainer |
1286 | * @noVarDump |
1287 | */ |
1288 | private $hookContainer; |
1289 | |
1290 | /** |
1291 | * @var HookRunner |
1292 | * @noVarDump |
1293 | */ |
1294 | private $hookRunner; |
1295 | |
1296 | /** |
1297 | * @internal For use by ServiceWiring |
1298 | */ |
1299 | public const CONSTRUCTOR_OPTIONS = [ |
1300 | MainConfigNames::DisableInternalSearch, |
1301 | MainConfigNames::EmailAuthentication, |
1302 | MainConfigNames::EnableEmail, |
1303 | MainConfigNames::EnableJavaScriptTest, |
1304 | MainConfigNames::EnableSpecialMute, |
1305 | MainConfigNames::EnableEditRecovery, |
1306 | MainConfigNames::PageLanguageUseDB, |
1307 | MainConfigNames::SpecialPages, |
1308 | ]; |
1309 | |
1310 | /** |
1311 | * @var TitleFactory |
1312 | */ |
1313 | private $titleFactory; |
1314 | |
1315 | /** |
1316 | * @param ServiceOptions $options |
1317 | * @param Language $contLang |
1318 | * @param ObjectFactory $objectFactory |
1319 | * @param TitleFactory $titleFactory |
1320 | * @param HookContainer $hookContainer |
1321 | */ |
1322 | public function __construct( |
1323 | ServiceOptions $options, |
1324 | Language $contLang, |
1325 | ObjectFactory $objectFactory, |
1326 | TitleFactory $titleFactory, |
1327 | HookContainer $hookContainer |
1328 | ) { |
1329 | $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); |
1330 | $this->options = $options; |
1331 | $this->contLang = $contLang; |
1332 | $this->objectFactory = $objectFactory; |
1333 | $this->titleFactory = $titleFactory; |
1334 | $this->hookContainer = $hookContainer; |
1335 | $this->hookRunner = new HookRunner( $hookContainer ); |
1336 | } |
1337 | |
1338 | /** |
1339 | * Returns a list of canonical special page names. |
1340 | * May be used to iterate over all registered special pages. |
1341 | * |
1342 | * @return string[] |
1343 | */ |
1344 | public function getNames(): array { |
1345 | return array_keys( $this->getPageList() ); |
1346 | } |
1347 | |
1348 | /** |
1349 | * Get the special page list as an array |
1350 | * |
1351 | * @return array |
1352 | */ |
1353 | private function getPageList(): array { |
1354 | if ( !is_array( $this->list ) ) { |
1355 | $this->list = self::CORE_LIST; |
1356 | |
1357 | if ( !$this->options->get( MainConfigNames::DisableInternalSearch ) ) { |
1358 | $this->list['Search'] = [ |
1359 | 'class' => SpecialSearch::class, |
1360 | 'services' => [ |
1361 | 'SearchEngineConfig', |
1362 | 'SearchEngineFactory', |
1363 | 'NamespaceInfo', |
1364 | 'ContentHandlerFactory', |
1365 | 'InterwikiLookup', |
1366 | 'ReadOnlyMode', |
1367 | 'UserOptionsManager', |
1368 | 'LanguageConverterFactory', |
1369 | 'RepoGroup', |
1370 | 'SearchResultThumbnailProvider', |
1371 | 'TitleMatcher', |
1372 | ] |
1373 | ]; |
1374 | } |
1375 | |
1376 | if ( $this->options->get( MainConfigNames::EmailAuthentication ) ) { |
1377 | $this->list['Confirmemail'] = [ |
1378 | 'class' => SpecialConfirmEmail::class, |
1379 | 'services' => [ |
1380 | 'UserFactory', |
1381 | ] |
1382 | ]; |
1383 | $this->list['Invalidateemail'] = [ |
1384 | 'class' => SpecialEmailInvalidate::class, |
1385 | 'services' => [ |
1386 | 'UserFactory', |
1387 | ] |
1388 | ]; |
1389 | } |
1390 | |
1391 | if ( $this->options->get( MainConfigNames::EnableEmail ) ) { |
1392 | $this->list['ChangeEmail'] = [ |
1393 | 'class' => SpecialChangeEmail::class, |
1394 | 'services' => [ |
1395 | 'AuthManager', |
1396 | ], |
1397 | ]; |
1398 | } |
1399 | |
1400 | if ( $this->options->get( MainConfigNames::EnableJavaScriptTest ) ) { |
1401 | $this->list['JavaScriptTest'] = [ |
1402 | 'class' => SpecialJavaScriptTest::class |
1403 | ]; |
1404 | } |
1405 | |
1406 | if ( $this->options->get( MainConfigNames::EnableSpecialMute ) ) { |
1407 | $this->list['Mute'] = [ |
1408 | 'class' => SpecialMute::class, |
1409 | 'services' => [ |
1410 | 'CentralIdLookup', |
1411 | 'UserOptionsManager', |
1412 | 'UserIdentityLookup', |
1413 | 'UserIdentityUtils', |
1414 | ] |
1415 | ]; |
1416 | } |
1417 | |
1418 | if ( $this->options->get( MainConfigNames::PageLanguageUseDB ) ) { |
1419 | $this->list['PageLanguage'] = [ |
1420 | 'class' => SpecialPageLanguage::class, |
1421 | 'services' => [ |
1422 | 'ContentHandlerFactory', |
1423 | 'LanguageNameUtils', |
1424 | 'ConnectionProvider', |
1425 | 'SearchEngineFactory', |
1426 | ] |
1427 | ]; |
1428 | } |
1429 | |
1430 | if ( $this->options->get( MainConfigNames::EnableEditRecovery ) ) { |
1431 | $this->list['EditRecovery'] = [ |
1432 | 'class' => SpecialEditRecovery::class, |
1433 | 'services' => [ |
1434 | 'UserOptionsLookup', |
1435 | ], |
1436 | ]; |
1437 | } |
1438 | |
1439 | // Add extension special pages |
1440 | $this->list = array_merge( $this->list, |
1441 | $this->options->get( MainConfigNames::SpecialPages ) ); |
1442 | |
1443 | // This hook can be used to disable unwanted core special pages |
1444 | // or conditionally register special pages. |
1445 | $this->hookRunner->onSpecialPage_initList( $this->list ); |
1446 | } |
1447 | |
1448 | return $this->list; |
1449 | } |
1450 | |
1451 | /** |
1452 | * Initialise and return the list of special page aliases. Returns an array where |
1453 | * the key is an alias, and the value is the canonical name of the special page. |
1454 | * All registered special pages are guaranteed to map to themselves. |
1455 | * @return array |
1456 | */ |
1457 | private function getAliasList(): array { |
1458 | if ( $this->aliases === null ) { |
1459 | $aliases = $this->contLang->getSpecialPageAliases(); |
1460 | $pageList = $this->getPageList(); |
1461 | |
1462 | $this->aliases = []; |
1463 | $keepAlias = []; |
1464 | |
1465 | // Force every canonical name to be an alias for itself. |
1466 | foreach ( $pageList as $name => $stuff ) { |
1467 | $caseFoldedAlias = $this->contLang->caseFold( $name ); |
1468 | $this->aliases[$caseFoldedAlias] = $name; |
1469 | $keepAlias[$caseFoldedAlias] = 'canonical'; |
1470 | } |
1471 | |
1472 | // Check for $aliases being an array since Language::getSpecialPageAliases can return null |
1473 | if ( is_array( $aliases ) ) { |
1474 | foreach ( $aliases as $realName => $aliasList ) { |
1475 | $first = true; |
1476 | foreach ( $aliasList as $alias ) { |
1477 | $caseFoldedAlias = $this->contLang->caseFold( $alias ); |
1478 | |
1479 | if ( isset( $this->aliases[$caseFoldedAlias] ) && |
1480 | $realName === $this->aliases[$caseFoldedAlias] |
1481 | ) { |
1482 | $first = false; |
1483 | // Ignore same-realName conflicts |
1484 | continue; |
1485 | } |
1486 | |
1487 | if ( !isset( $keepAlias[$caseFoldedAlias] ) ) { |
1488 | $this->aliases[$caseFoldedAlias] = $realName; |
1489 | if ( $first ) { |
1490 | $keepAlias[$caseFoldedAlias] = 'first'; |
1491 | } |
1492 | } elseif ( $first ) { |
1493 | wfWarn( "First alias '$alias' for $realName conflicts with " . |
1494 | "{$keepAlias[$caseFoldedAlias]} alias for " . |
1495 | $this->aliases[$caseFoldedAlias] |
1496 | ); |
1497 | } |
1498 | $first = false; |
1499 | } |
1500 | } |
1501 | } |
1502 | } |
1503 | |
1504 | return $this->aliases; |
1505 | } |
1506 | |
1507 | /** |
1508 | * Given a special page name with a possible subpage, return an array |
1509 | * where the first element is the special page name and the second is the |
1510 | * subpage. |
1511 | * |
1512 | * @param string $alias |
1513 | * @return array [ String, String|null ], or [ null, null ] if the page is invalid |
1514 | */ |
1515 | public function resolveAlias( $alias ) { |
1516 | $bits = explode( '/', $alias, 2 ); |
1517 | |
1518 | $caseFoldedAlias = $this->contLang->caseFold( $bits[0] ); |
1519 | $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias ); |
1520 | $aliases = $this->getAliasList(); |
1521 | if ( !isset( $aliases[$caseFoldedAlias] ) ) { |
1522 | return [ null, null ]; |
1523 | } |
1524 | $name = $aliases[$caseFoldedAlias]; |
1525 | $par = $bits[1] ?? null; // T4087 |
1526 | |
1527 | return [ $name, $par ]; |
1528 | } |
1529 | |
1530 | /** |
1531 | * Check if a given name exist as a special page or as a special page alias |
1532 | * |
1533 | * @param string $name Name of a special page |
1534 | * @return bool True if a special page exists with this name |
1535 | */ |
1536 | public function exists( $name ) { |
1537 | [ $title, /*...*/ ] = $this->resolveAlias( $name ); |
1538 | |
1539 | $specialPageList = $this->getPageList(); |
1540 | return isset( $specialPageList[$title] ); |
1541 | } |
1542 | |
1543 | /** |
1544 | * Find the object with a given name and return it (or NULL) |
1545 | * |
1546 | * @param string $name Special page name, may be localised and/or an alias |
1547 | * @return SpecialPage|null SpecialPage object or null if the page doesn't exist |
1548 | */ |
1549 | public function getPage( $name ) { |
1550 | [ $realName, /*...*/ ] = $this->resolveAlias( $name ); |
1551 | |
1552 | $specialPageList = $this->getPageList(); |
1553 | |
1554 | if ( isset( $specialPageList[$realName] ) ) { |
1555 | $rec = $specialPageList[$realName]; |
1556 | |
1557 | if ( is_array( $rec ) || is_string( $rec ) || is_callable( $rec ) ) { |
1558 | $page = $this->objectFactory->createObject( |
1559 | $rec, |
1560 | [ |
1561 | 'allowClassName' => true, |
1562 | 'allowCallable' => true |
1563 | ] |
1564 | ); |
1565 | } else { |
1566 | $page = null; |
1567 | } |
1568 | |
1569 | if ( $page instanceof SpecialPage ) { |
1570 | $page->setHookContainer( $this->hookContainer ); |
1571 | $page->setContentLanguage( $this->contLang ); |
1572 | $page->setSpecialPageFactory( $this ); |
1573 | return $page; |
1574 | } |
1575 | |
1576 | // It's not a classname, nor a callback, nor a legacy constructor array, |
1577 | // nor a special page object. Give up. |
1578 | wfLogWarning( "Cannot instantiate special page $realName: bad spec!" ); |
1579 | } |
1580 | |
1581 | return null; |
1582 | } |
1583 | |
1584 | /** |
1585 | * Get listed special pages available to the current user. |
1586 | * |
1587 | * This includes both unrestricted pages, and restricted pages |
1588 | * that the current user has the required permissions for. |
1589 | * |
1590 | * @param User $user User object to check permissions provided |
1591 | * @return SpecialPage[] |
1592 | */ |
1593 | public function getUsablePages( User $user ): array { |
1594 | $pages = []; |
1595 | foreach ( $this->getPageList() as $name => $rec ) { |
1596 | $page = $this->getPage( $name ); |
1597 | if ( $page ) { // not null |
1598 | $page->setContext( RequestContext::getMain() ); |
1599 | if ( $page->isListed() |
1600 | && ( !$page->isRestricted() || $page->userCanExecute( $user ) ) |
1601 | ) { |
1602 | $pages[$name] = $page; |
1603 | } |
1604 | } |
1605 | } |
1606 | |
1607 | return $pages; |
1608 | } |
1609 | |
1610 | /** |
1611 | * Get listed special pages available to everyone by default. |
1612 | * |
1613 | * @return array<string,SpecialPage> |
1614 | */ |
1615 | public function getRegularPages(): array { |
1616 | $pages = []; |
1617 | foreach ( $this->getPageList() as $name => $rec ) { |
1618 | $page = $this->getPage( $name ); |
1619 | if ( $page && $page->isListed() && !$page->isRestricted() ) { |
1620 | $pages[$name] = $page; |
1621 | } |
1622 | } |
1623 | |
1624 | return $pages; |
1625 | } |
1626 | |
1627 | /** |
1628 | * Get listed special pages, including those that may require user rights. |
1629 | * |
1630 | * @since 1.42 |
1631 | * @return array<string,SpecialPage> |
1632 | */ |
1633 | public function getListedPages(): array { |
1634 | $pages = []; |
1635 | foreach ( $this->getPageList() as $name => $rec ) { |
1636 | $page = $this->getPage( $name ); |
1637 | if ( $page && $page->isListed() ) { |
1638 | $pages[$name] = $page; |
1639 | } |
1640 | } |
1641 | return $pages; |
1642 | } |
1643 | |
1644 | /** |
1645 | * Execute a special page path. |
1646 | * The path may contain parameters, e.g. Special:Name/Params |
1647 | * Extracts the special page name and call the execute method, passing the parameters |
1648 | * |
1649 | * Returns a title object if the page is redirected, false if there was no such special |
1650 | * page, and true if it was successful. |
1651 | * |
1652 | * @param PageReference|string $path |
1653 | * @param IContextSource $context |
1654 | * @param bool $including Bool output is being captured for use in {{special:whatever}} |
1655 | * @param LinkRenderer|null $linkRenderer (since 1.28) |
1656 | * |
1657 | * @return bool|Title |
1658 | */ |
1659 | public function executePath( $path, IContextSource $context, $including = false, |
1660 | ?LinkRenderer $linkRenderer = null |
1661 | ) { |
1662 | if ( $path instanceof PageReference ) { |
1663 | $path = $path->getDBkey(); |
1664 | } |
1665 | |
1666 | $bits = explode( '/', $path, 2 ); |
1667 | $name = $bits[0]; |
1668 | $par = $bits[1] ?? null; // T4087 |
1669 | |
1670 | $page = $this->getPage( $name ); |
1671 | if ( !$page ) { |
1672 | // Emulate SpecialPage::setHeaders() |
1673 | $context->getOutput()->setArticleRelated( false ); |
1674 | $context->getOutput()->setRobotPolicy( 'noindex,nofollow' ); |
1675 | |
1676 | if ( $context->getConfig()->get( MainConfigNames::Send404Code ) ) { |
1677 | $context->getOutput()->setStatusCode( 404 ); |
1678 | } |
1679 | |
1680 | $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); |
1681 | |
1682 | return false; |
1683 | } |
1684 | |
1685 | if ( !$including ) { |
1686 | ProfilingContext::singleton()->init( MW_ENTRY_POINT, $page->getName() ); |
1687 | // Narrow DB query expectations for this HTTP request |
1688 | $trxLimits = $context->getConfig()->get( MainConfigNames::TrxProfilerLimits ); |
1689 | $trxProfiler = Profiler::instance()->getTransactionProfiler(); |
1690 | if ( $context->getRequest()->wasPosted() && !$page->doesWrites() ) { |
1691 | $trxProfiler->setExpectations( $trxLimits['POST-nonwrite'], __METHOD__ ); |
1692 | } |
1693 | } |
1694 | |
1695 | // Page exists, set the context |
1696 | $page->setContext( $context ); |
1697 | |
1698 | if ( !$including ) { |
1699 | // Redirect to canonical alias for GET commands |
1700 | // Not for POST, we'd lose the post data, so it's best to just distribute |
1701 | // the request. Such POST requests are possible for old extensions that |
1702 | // generate self-links without being aware that their default name has |
1703 | // changed. |
1704 | if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) { |
1705 | $query = $context->getRequest()->getQueryValues(); |
1706 | unset( $query['title'] ); |
1707 | $title = $page->getPageTitle( $par ?? false ); |
1708 | $url = $title->getFullURL( $query ); |
1709 | $context->getOutput()->redirect( $url ); |
1710 | |
1711 | return $title; |
1712 | } |
1713 | |
1714 | // @phan-suppress-next-line PhanUndeclaredMethod |
1715 | $context->setTitle( $page->getPageTitle( $par ?? false ) ); |
1716 | } elseif ( !$page->isIncludable() ) { |
1717 | return false; |
1718 | } |
1719 | |
1720 | $page->including( $including ); |
1721 | if ( $linkRenderer ) { |
1722 | $page->setLinkRenderer( $linkRenderer ); |
1723 | } |
1724 | |
1725 | // Execute special page |
1726 | $page->run( $par ); |
1727 | |
1728 | return true; |
1729 | } |
1730 | |
1731 | /** |
1732 | * Just like executePath() but will override global variables and execute |
1733 | * the page in "inclusion" mode. Returns true if the execution was |
1734 | * successful or false if there was no such special page, or a title object |
1735 | * if it was a redirect. |
1736 | * |
1737 | * Also saves the current $wgTitle, $wgOut, $wgRequest, $wgUser and $wgLang |
1738 | * variables so that the special page will get the context it'd expect on a |
1739 | * normal request, and then restores them to their previous values after. |
1740 | * |
1741 | * @param PageReference $page |
1742 | * @param IContextSource $context |
1743 | * @param LinkRenderer|null $linkRenderer (since 1.28) |
1744 | * @return bool|Title |
1745 | */ |
1746 | public function capturePath( |
1747 | PageReference $page, IContextSource $context, ?LinkRenderer $linkRenderer = null |
1748 | ) { |
1749 | // phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser,MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgTitle |
1750 | global $wgTitle, $wgOut, $wgRequest, $wgUser, $wgLang; |
1751 | $main = RequestContext::getMain(); |
1752 | |
1753 | // Save current globals and main context |
1754 | $glob = [ |
1755 | 'title' => $wgTitle, |
1756 | 'output' => $wgOut, |
1757 | 'request' => $wgRequest, |
1758 | 'user' => $wgUser, |
1759 | 'language' => $wgLang, |
1760 | ]; |
1761 | $ctx = [ |
1762 | 'title' => $main->getTitle(), |
1763 | 'output' => $main->getOutput(), |
1764 | 'request' => $main->getRequest(), |
1765 | 'user' => $main->getUser(), |
1766 | 'language' => $main->getLanguage(), |
1767 | ]; |
1768 | if ( $main->canUseWikiPage() ) { |
1769 | $ctx['wikipage'] = $main->getWikiPage(); |
1770 | } |
1771 | |
1772 | // just needed for $wgTitle and RequestContext::setTitle |
1773 | $title = $this->titleFactory->castFromPageReference( $page ); |
1774 | |
1775 | // Override |
1776 | $wgTitle = $title; |
1777 | $wgOut = $context->getOutput(); |
1778 | $wgRequest = $context->getRequest(); |
1779 | $wgUser = $context->getUser(); |
1780 | $wgLang = $context->getLanguage(); |
1781 | // FIXME: Once reasonably certain that no SpecialPage subclasses |
1782 | // rely on direct RequestContext::getMain instead of their local |
1783 | // context getters, these can be removed (T323184) |
1784 | // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged |
1785 | @$main->setTitle( $title ); |
1786 | $main->setOutput( $context->getOutput() ); |
1787 | $main->setRequest( $context->getRequest() ); |
1788 | $main->setUser( $context->getUser() ); |
1789 | $main->setLanguage( $context->getLanguage() ); |
1790 | |
1791 | try { |
1792 | // The useful part |
1793 | return $this->executePath( $page, $context, true, $linkRenderer ); |
1794 | } finally { |
1795 | // Restore old globals and context |
1796 | $wgTitle = $glob['title']; |
1797 | $wgOut = $glob['output']; |
1798 | $wgRequest = $glob['request']; |
1799 | $wgUser = $glob['user']; |
1800 | $wgLang = $glob['language']; |
1801 | // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged |
1802 | @$main->setTitle( $ctx['title'] ); |
1803 | $main->setOutput( $ctx['output'] ); |
1804 | $main->setRequest( $ctx['request'] ); |
1805 | $main->setUser( $ctx['user'] ); |
1806 | $main->setLanguage( $ctx['language'] ); |
1807 | if ( isset( $ctx['wikipage'] ) ) { |
1808 | $main->setWikiPage( $ctx['wikipage'] ); |
1809 | } |
1810 | } |
1811 | } |
1812 | |
1813 | /** |
1814 | * Get the local name for a specified canonical name |
1815 | * |
1816 | * @param string $name |
1817 | * @param string|false|null $subpage |
1818 | * @return string |
1819 | */ |
1820 | public function getLocalNameFor( $name, $subpage = false ) { |
1821 | $aliases = $this->contLang->getSpecialPageAliases(); |
1822 | $aliasList = $this->getAliasList(); |
1823 | |
1824 | // Find the first alias that maps back to $name |
1825 | if ( isset( $aliases[$name] ) ) { |
1826 | $found = false; |
1827 | foreach ( $aliases[$name] as $alias ) { |
1828 | $caseFoldedAlias = $this->contLang->caseFold( $alias ); |
1829 | $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias ); |
1830 | if ( isset( $aliasList[$caseFoldedAlias] ) && |
1831 | $aliasList[$caseFoldedAlias] === $name |
1832 | ) { |
1833 | $name = $alias; |
1834 | $found = true; |
1835 | break; |
1836 | } |
1837 | } |
1838 | if ( !$found ) { |
1839 | wfWarn( "Did not find a usable alias for special page '$name'. " . |
1840 | "It seems all defined aliases conflict?" ); |
1841 | } |
1842 | } else { |
1843 | // Check if someone misspelled the correct casing |
1844 | if ( is_array( $aliases ) ) { |
1845 | foreach ( $aliases as $n => $values ) { |
1846 | if ( strcasecmp( $name, $n ) === 0 ) { |
1847 | wfWarn( "Found alias defined for $n when searching for " . |
1848 | "special page aliases for $name. Case mismatch?" ); |
1849 | return $this->getLocalNameFor( $n, $subpage ); |
1850 | } |
1851 | } |
1852 | } |
1853 | |
1854 | wfWarn( "Did not find alias for special page '$name'. " . |
1855 | "Perhaps no aliases are defined for it?" ); |
1856 | } |
1857 | |
1858 | if ( $subpage !== false && $subpage !== null ) { |
1859 | // Make sure it's in dbkey form |
1860 | $subpage = str_replace( ' ', '_', $subpage ); |
1861 | $name = "$name/$subpage"; |
1862 | } |
1863 | |
1864 | return $this->contLang->ucfirst( $name ); |
1865 | } |
1866 | |
1867 | /** |
1868 | * Get a title for a given alias |
1869 | * |
1870 | * @param string $alias |
1871 | * @return Title|null Title or null if there is no such alias |
1872 | */ |
1873 | public function getTitleForAlias( $alias ) { |
1874 | [ $name, $subpage ] = $this->resolveAlias( $alias ); |
1875 | if ( $name != null ) { |
1876 | return SpecialPage::getTitleFor( $name, $subpage ); |
1877 | } |
1878 | |
1879 | return null; |
1880 | } |
1881 | } |