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