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