From 86deb399997c6fcde5e696962d0a8a0aaa27bdc4 Mon Sep 17 00:00:00 2001 From: Mauro Cassani Date: Thu, 30 Apr 2026 12:18:30 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20apply=20friendlySlug=20to=20project=5Fna?= =?UTF-8?q?me=20in=20CattoolController=20config=20##=20Summary=20Apply=20U?= =?UTF-8?q?tils::friendlySlug()=20to=20project=5Fname=20in=20CattoolContro?= =?UTF-8?q?ller=20view=20params,=20ensuring=20the=20slug=20used=20in=20the?= =?UTF-8?q?=20cattool=20config=20is=20sanitized=20consistently.=20Add=20ed?= =?UTF-8?q?ge=20case=20tests=20for=20friendlySlug()=20(empty=20string,=20A?= =?UTF-8?q?SCII=20symbol,=20extended=20ASCII=20graphic=20characters).=20##?= =?UTF-8?q?=20Type=20-=20[x]=20`fix`=20=E2=80=94=20bug=20fix=20-=20[x]=20`?= =?UTF-8?q?test`=20=E2=80=94=20test=20coverage=20##=20Changes=20|=20File?= =?UTF-8?q?=20|=20Change=20|=20|------|--------|=20|=20lib/Controller/View?= =?UTF-8?q?s/CattoolController.php=20|=20Wrap=20project=20name=20with=20Ut?= =?UTF-8?q?ils::friendlySlug()=20|=20|=20tests/unit/Utils/Tools/UtilsTest.?= =?UTF-8?q?php=20|=20Add=20edge=20case=20tests:=20empty=20string,=20valid?= =?UTF-8?q?=20ASCII=20symbol,=20graphic=20chars=20(=C2=AC,=20=E2=95=9A,=20?= =?UTF-8?q?=E2=95=90,=20=E2=96=91)=20|=20##=20Testing=20-=20[x]=20New=20te?= =?UTF-8?q?sts=20added=20for=20changed=20behavior=20-=20[x]=20phpstan:=20n?= =?UTF-8?q?o=20new=20errors=20introduced=20##=20AI=20Disclosure=20-=20[x]?= =?UTF-8?q?=20AI=20tools=20were=20used=20=E2=80=94=20GitHub=20Copilot=20(c?= =?UTF-8?q?laude-sonnet-4-20250514)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/Controller/Views/CattoolController.php | 2 +- tests/unit/Utils/Tools/UtilsTest.php | 39 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/Controller/Views/CattoolController.php b/lib/Controller/Views/CattoolController.php index c67468311b..45b8c43f80 100644 --- a/lib/Controller/Views/CattoolController.php +++ b/lib/Controller/Views/CattoolController.php @@ -186,7 +186,7 @@ public function renderView(): void 'pageTitle' => $this->buildPageTitle($revisionNumber, $chunkStruct), 'password' => $chunkStruct->password, 'project' => $chunkStruct->getProject(), - 'project_name' => $chunkStruct->getProject()->name, + 'project_name' => Utils::friendlySlug($chunkStruct->getProject()->name), 'quality_report_href' => AppConfig::$BASEURL . "revise-summary/$chunkStruct->id-$chunkStruct->password", 'review_extended' => new PHPTalBoolean(true), 'review_password' => $isRevision ? $chunkReviewStruct->review_password : (new ChunkReviewDao())->findChunkReviewsForSourcePage( diff --git a/tests/unit/Utils/Tools/UtilsTest.php b/tests/unit/Utils/Tools/UtilsTest.php index 6588659c35..952f801968 100644 --- a/tests/unit/Utils/Tools/UtilsTest.php +++ b/tests/unit/Utils/Tools/UtilsTest.php @@ -241,6 +241,45 @@ public function testFriendlySlugRemovesSpecialCharacters(): void $this->assertMatchesRegularExpression('/^[a-z0-9\-]+$/', $result); } + #[Test] + public function testFriendlySlugReturnsHyphenForEmptyStringInput(): void + { + $result = Utils::friendlySlug(''); + $this->assertEquals('-', $result); + } + + #[Test] + public function testFriendlySlugHandlesValidAsciiSymbol(): void + { + $result = Utils::friendlySlug('hello-world'); + $this->assertEquals('hello-world', $result); + } + + #[Test] + public function testFriendlySlugStripsLogicalNegationSymbol(): void + { + $result = Utils::friendlySlug('hello¬world'); + $this->assertMatchesRegularExpression('/^[a-z0-9\-]+$/', $result); + $this->assertStringNotContainsString('¬', $result); + } + + #[Test] + public function testFriendlySlugStripsBoxDrawingCharacter(): void + { + $result = Utils::friendlySlug('╚══test══╝'); + $this->assertMatchesRegularExpression('/^[a-z0-9\-]+$/', $result); + $this->assertStringNotContainsString('╚', $result); + $this->assertStringNotContainsString('═', $result); + } + + #[Test] + public function testFriendlySlugStripsBlockGraphicSymbol(): void + { + $result = Utils::friendlySlug('hello░world'); + $this->assertMatchesRegularExpression('/^[a-z0-9\-]+$/', $result); + $this->assertStringNotContainsString('░', $result); + } + // ========================================================================= // Tests for replace_accents() // =========================================================================