Skip to content

Commit d2d3c2c

Browse files
committed
Broadening special page check to be language-agnostic
1 parent e0f3fac commit d2d3c2c

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

includes/CrawlerProtectionService.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@
3838
*/
3939
class CrawlerProtectionService {
4040

41-
/** @var string Prefix for special page names */
42-
private const SPECIAL_PAGE_PREFIX = 'Special:';
43-
4441
/** @var string[] List of constructor options this class accepts */
4542
public const CONSTRUCTOR_OPTIONS = [
4643
'CrawlerProtectedSpecialPages',
@@ -135,18 +132,27 @@ public function checkSpecialPage(
135132
* Determine whether the given special page name is in the
136133
* configured list of protected special pages.
137134
*
135+
* Because this method is only called from the SpecialPageBeforeExecute
136+
* hook, any "Foo:" prefix on a configured value is necessarily the
137+
* "Special" namespace in English or its localized equivalent (e.g.
138+
* "Spezial:" in German). We therefore simply strip everything up to
139+
* and including the first colon rather than checking for a specific
140+
* namespace name, which keeps the logic language-agnostic.
141+
*
138142
* @param string $specialPageName
139143
* @return bool
140144
*/
141145
public function isProtectedSpecialPage( string $specialPageName ): bool {
142146
$protectedSpecialPages = $this->options->get( 'CrawlerProtectedSpecialPages' );
143147

144-
// Normalize protected special pages: lowercase and strip 'Special:' prefix
148+
// Normalize protected special pages: lowercase and strip any
149+
// namespace prefix (everything up to and including the first ':').
145150
$normalizedProtectedPages = array_map(
146151
static function ( string $p ): string {
147152
$lower = strtolower( $p );
148-
if ( strpos( $lower, strtolower( self::SPECIAL_PAGE_PREFIX ) ) === 0 ) {
149-
return substr( $lower, strlen( self::SPECIAL_PAGE_PREFIX ) );
153+
$colonPos = strpos( $lower, ':' );
154+
if ( $colonPos !== false ) {
155+
return substr( $lower, $colonPos + 1 );
150156
}
151157
return $lower;
152158
},

tests/phpunit/unit/CrawlerProtectionServiceTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,22 @@ public function testIsProtectedSpecialPageReturnsFalseForUnprotected() {
267267
$this->assertFalse( $service->isProtectedSpecialPage( 'Search' ) );
268268
}
269269

270+
/**
271+
* @covers ::isProtectedSpecialPage
272+
*/
273+
public function testIsProtectedSpecialPageStripsLocalizedPrefix() {
274+
$service = $this->buildService( [ 'Spezial:WhatLinksHere' ] );
275+
$this->assertTrue( $service->isProtectedSpecialPage( 'WhatLinksHere' ) );
276+
}
277+
278+
/**
279+
* @covers ::isProtectedSpecialPage
280+
*/
281+
public function testIsProtectedSpecialPageStripsAnyPrefix() {
282+
$service = $this->buildService( [ 'Especial:WhatLinksHere' ] );
283+
$this->assertTrue( $service->isProtectedSpecialPage( 'WhatLinksHere' ) );
284+
}
285+
270286
/**
271287
* Data provider for blocked special pages.
272288
*

0 commit comments

Comments
 (0)