From 510bde79dd35bd96cc4a71be48e6bc18cbf74c13 Mon Sep 17 00:00:00 2001 From: Allan Kong Date: Mon, 18 Aug 2025 17:50:22 -0700 Subject: [PATCH 1/6] Tag Pushes --- app/Http/Controllers/CommentController.php | 2 +- .../ComputerScienceResourceController.php | 2 +- .../Controllers/ResourceEditsController.php | 2 +- .../Controllers/ResourceReviewController.php | 2 +- .../{Comment => }/StoreCommentRequest.php | 2 +- .../{ResourceEdit => }/StoreResourceEdit.php | 10 +++---- .../StoreResourceRequest.php | 8 +++--- .../StoreResourceReview.php | 2 +- config/computerScienceResource.php | 1 + .../ComputerScienceResourceFactory.php | 22 +++++++++++++--- database/factories/ResourceEditsFactory.php | 2 +- resources/js/Components/Form/TagSelector.vue | 26 +++++++++++++++---- tests/Feature/ResourceEditsTest.php | 6 ++--- .../ResourceEdit/StoreResourceEditFactory.php | 23 +++++++++++++--- 14 files changed, 80 insertions(+), 30 deletions(-) rename app/Http/Requests/{Comment => }/StoreCommentRequest.php (96%) rename app/Http/Requests/{ResourceEdit => }/StoreResourceEdit.php (86%) rename app/Http/Requests/{ComputerScienceResource => }/StoreResourceRequest.php (86%) rename app/Http/Requests/{ResourceReview => }/StoreResourceReview.php (97%) diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 744c52a6..ea05c076 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers; -use App\Http\Requests\Comment\StoreCommentRequest; +use App\Http\Requests\StoreCommentRequest; use App\Http\Resources\CommentResource; use App\Http\Resources\UserResource; use App\Services\CommentService; diff --git a/app/Http/Controllers/ComputerScienceResourceController.php b/app/Http/Controllers/ComputerScienceResourceController.php index 1cfdbba8..935c6ddf 100644 --- a/app/Http/Controllers/ComputerScienceResourceController.php +++ b/app/Http/Controllers/ComputerScienceResourceController.php @@ -3,7 +3,7 @@ namespace App\Http\Controllers; use App\Events\TagFrequencyChanged; -use App\Http\Requests\ComputerScienceResource\StoreResourceRequest; +use App\Http\Requests\StoreResourceRequest; use App\Models\ComputerScienceResource; use App\Models\NewsPost; use App\Models\ResourceEdits; diff --git a/app/Http/Controllers/ResourceEditsController.php b/app/Http/Controllers/ResourceEditsController.php index 43b70f18..363b26bd 100644 --- a/app/Http/Controllers/ResourceEditsController.php +++ b/app/Http/Controllers/ResourceEditsController.php @@ -3,7 +3,7 @@ namespace App\Http\Controllers; use App\Events\TagFrequencyChanged; -use App\Http\Requests\ResourceEdit\StoreResourceEdit; +use App\Http\Requests\StoreResourceEdit; use App\Models\ComputerScienceResource; use App\Models\ResourceEdits; use App\Services\DataNormalizationService; diff --git a/app/Http/Controllers/ResourceReviewController.php b/app/Http/Controllers/ResourceReviewController.php index ddf63396..ffb03c8f 100644 --- a/app/Http/Controllers/ResourceReviewController.php +++ b/app/Http/Controllers/ResourceReviewController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers; -use App\Http\Requests\ResourceReview\StoreResourceReview; +use App\Http\Requests\StoreResourceReview; use App\Models\ComputerScienceResource; use App\Models\ResourceReview; use Illuminate\Support\Facades\Auth; diff --git a/app/Http/Requests/Comment/StoreCommentRequest.php b/app/Http/Requests/StoreCommentRequest.php similarity index 96% rename from app/Http/Requests/Comment/StoreCommentRequest.php rename to app/Http/Requests/StoreCommentRequest.php index 57ba2c47..90e9e01b 100644 --- a/app/Http/Requests/Comment/StoreCommentRequest.php +++ b/app/Http/Requests/StoreCommentRequest.php @@ -1,6 +1,6 @@ ['nullable', 'string', 'url:http,https', 'max:255'], 'proposed_changes.difficulty' => ['nullable', 'string', Rule::in(config('computerScienceResource.difficulties'))], 'proposed_changes.pricing' => ['nullable', 'string', Rule::in(config('computerScienceResource.pricings'))], - 'proposed_changes.topic_tags' => ['nullable', 'array', 'min:2'], - 'proposed_changes.topic_tags.*' => ['required', 'distinct', 'string', 'max:50'], 'proposed_changes.image_file' => ['nullable', 'image', 'max:500'], // 500 kilobytes + 'proposed_changes.topic_tags' => ['nullable', 'array', 'min:2'], + 'proposed_changes.topic_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], 'proposed_changes.general_tags' => ['nullable', 'array'], - 'proposed_changes.general_tags.*' => ['required', 'distinct', 'string', 'max:50'], + 'proposed_changes.general_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], 'proposed_changes.programming_language_tags' => ['nullable', 'array'], - 'proposed_changes.programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50'], + 'proposed_changes.programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], ]; } } diff --git a/app/Http/Requests/ComputerScienceResource/StoreResourceRequest.php b/app/Http/Requests/StoreResourceRequest.php similarity index 86% rename from app/Http/Requests/ComputerScienceResource/StoreResourceRequest.php rename to app/Http/Requests/StoreResourceRequest.php index 699a1b05..1a67e2e5 100644 --- a/app/Http/Requests/ComputerScienceResource/StoreResourceRequest.php +++ b/app/Http/Requests/StoreResourceRequest.php @@ -1,6 +1,6 @@ ['required', 'string', Rule::in(config('computerScienceResource.difficulties'))], 'pricing' => ['required', 'string', Rule::in(config('computerScienceResource.pricings'))], 'topic_tags' => ['required', 'array', 'min:2'], - 'topic_tags.*' => ['required', 'distinct', 'string', 'max:50'], + 'topic_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], // Optional, can just be omitted 'image_file' => ['nullable', 'image', 'max:500'], // 500 kiloBytes 'general_tags' => ['array'], - 'general_tags.*' => ['required', 'distinct', 'string', 'max:50'], + 'general_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], 'programming_language_tags' => ['array'], - 'programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50'], + 'programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], ]; } } diff --git a/app/Http/Requests/ResourceReview/StoreResourceReview.php b/app/Http/Requests/StoreResourceReview.php similarity index 97% rename from app/Http/Requests/ResourceReview/StoreResourceReview.php rename to app/Http/Requests/StoreResourceReview.php index aa141b58..6966a860 100644 --- a/app/Http/Requests/ResourceReview/StoreResourceReview.php +++ b/app/Http/Requests/StoreResourceReview.php @@ -1,6 +1,6 @@ ['book', 'podcast', 'youtube_channel', 'blog', 'website', 'organization', 'service', 'bootcamp', 'newsletter', 'workshop', 'course', 'forum', 'mobile_app', 'desktop_app', 'magazine'], 'difficulties' => ['any', 'beginner', 'industry_simple', 'industry_standard', 'industry_professional', 'academic'], 'pricings' => ['free', 'paid', 'freemium', 'premium'], + "tags_regex" => "/^[a-z0-9-]+$/" ]; diff --git a/database/factories/ComputerScienceResourceFactory.php b/database/factories/ComputerScienceResourceFactory.php index 6bd041f8..f2057087 100644 --- a/database/factories/ComputerScienceResourceFactory.php +++ b/database/factories/ComputerScienceResourceFactory.php @@ -56,11 +56,27 @@ public function configure(): Factory return $this->afterCreating(function (ComputerScienceResource $resource) { $fakerTags = ['tag1', 'tag2', 'tag3', 'tag4', 'tag5', fake()->word(), fake()->word()]; - $resource->topic_tags = $this->topicTags ?? fake()->randomElements($fakerTags, fake()->numberBetween(3, count($fakerTags))); - $resource->programming_language_tags = $this->programmingLanguageTags ?? fake()->randomElements($fakerTags); - $resource->general_tags = $this->generalTags ?? fake()->randomElements($fakerTags); + // Sanitize all tags before assigning + $topicTags = $this->topicTags ?? fake()->randomElements($fakerTags, fake()->numberBetween(3, count($fakerTags))); + $topicTags = array_map([$this, 'sanitizeTag'], $topicTags); + + $programmingLanguageTags = $this->programmingLanguageTags ?? fake()->randomElements($fakerTags); + $programmingLanguageTags = array_map([$this, 'sanitizeTag'], $programmingLanguageTags); + + $generalTags = $this->generalTags ?? fake()->randomElements($fakerTags); + $generalTags = array_map([$this, 'sanitizeTag'], $generalTags); + + $resource->topic_tags = $topicTags; + $resource->programming_language_tags = $programmingLanguageTags; + $resource->general_tags = $generalTags; TagFrequencyChanged::dispatch(null, $resource->tagCounter()); }); } + + private function sanitizeTag(string $tag): string + { + // Lowercase, replace spaces with -, remove invalid chars + return strtolower(str_replace(' ', '-', $tag)); + } } diff --git a/database/factories/ResourceEditsFactory.php b/database/factories/ResourceEditsFactory.php index 7302e009..2687d964 100644 --- a/database/factories/ResourceEditsFactory.php +++ b/database/factories/ResourceEditsFactory.php @@ -32,7 +32,7 @@ public function definition(): array 'platforms' => $this->faker->randomElements($platforms, rand(1, 3)), 'difficulty' => $this->faker->randomElement($difficulties), 'pricing' => $this->faker->randomElement($pricings), - 'topic_tags' => ['data structures', 'algorithms'], + 'topic_tags' => ['data-structures', 'algorithms'], 'programming_language_tags' => ['python'], 'general_tags' => ['interactive', 'challenging'], ]; diff --git a/resources/js/Components/Form/TagSelector.vue b/resources/js/Components/Form/TagSelector.vue index a83fbd24..6690bf3b 100644 --- a/resources/js/Components/Form/TagSelector.vue +++ b/resources/js/Components/Form/TagSelector.vue @@ -25,10 +25,26 @@ watch( { immediate: true } ); +function sanitizeTag(tag) { + // Remove trailing spaces and lowercase + let transformedTag = tag.trim().toLowerCase(); + + // Apply rules from config('computerScienceResources.tags_rules') + // Transform the tag to lowercase and replace spaces with hyphens + transformedTag = transformedTag.replace(/\s+/g, "-"); + // Remove any characters that are not lowercase letters or hyphens + transformedTag = transformedTag.replace(/[^a-z-]/g, ""); + return transformedTag; +} + const addTag = (tag) => { - if (tag && !selectedTags.value.includes(tag)) { - selectedTags.value.push(tag); - model.value = [...selectedTags.value]; + if (tag) { + let transformedTag = sanitizeTag(tag); + + if (!selectedTags.value.includes(transformedTag)) { + selectedTags.value.push(transformedTag); + model.value = [...selectedTags.value]; + } } }; @@ -49,8 +65,8 @@ const handleSelect = (event) => { const handleKeydown = (event) => { if (event.key === "Enter") { - if (searchValue.value.trim()) { - addTag(searchValue.value.trim().toLowerCase()); + if (searchValue.value) { + addTag(searchValue.value); // Clear the input after adding via Enter nextTick(() => { searchValue.value = ""; diff --git a/tests/Feature/ResourceEditsTest.php b/tests/Feature/ResourceEditsTest.php index d0db1e47..391f8030 100644 --- a/tests/Feature/ResourceEditsTest.php +++ b/tests/Feature/ResourceEditsTest.php @@ -161,9 +161,9 @@ public function test_merged_edit_reflects_changes_on_original_resource(): void 'difficulty' => fake()->randomElement(config('computerScienceResource.difficulties')), 'platforms' => fake()->randomElements(config('computerScienceResource.platforms'), fake()->numberBetween(1, 3)), 'pricing' => fake()->randomElement(config('computerScienceResource.pricings')), - 'topic_tags' => ["{$i}_a", "{$i}_b", "{$i}_c"], - 'programming_language_tags' => ["{$i}_a", "{$i}_b", "{$i}_c"], - 'general_tags' => ["{$i}_a", "{$i}_b", "{$i}_c"], + 'topic_tags' => ["$i-a", "$i-b", "$i-c"], + 'programming_language_tags' => ["$i-a", "$i-b", "$i-c"], + 'general_tags' => ["$i-a", "$i-b", "$i-c"], ]; $this->makeAndApplyResourceEdits($resource->id, $changes); diff --git a/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php b/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php index 13f3c592..2101a815 100644 --- a/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php +++ b/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php @@ -12,11 +12,23 @@ public function definition(): array $difficulties = config('computerScienceResource.difficulties'); $pricings = config('computerScienceResource.pricings'); - // Ensure at least 3 unique topic tags + // Ensure at least 3 unique topic tags, all matching the regex do { $topicTags = array_unique($this->faker->words(mt_rand(4, 9))); + $topicTags = array_map([$this, 'sanitizeTag'], $topicTags); } while (count($topicTags) < 3); + // Ensure programming_language_tags and general_tags are sanitized and valid + do { + $programmingLanguageTags = array_unique($this->faker->words(mt_rand(1, 3))); + $programmingLanguageTags = array_map([$this, 'sanitizeTag'], $programmingLanguageTags); + } while (count($programmingLanguageTags) < 1); + + do { + $generalTags = array_unique($this->faker->words(mt_rand(1, 3))); + $generalTags = array_map([$this, 'sanitizeTag'], $generalTags); + } while (count($generalTags) < 1); + $possibleChanges = [ 'name' => $this->faker->words(mt_rand(2, 4), true), 'description' => $this->faker->paragraphs(2, true), @@ -26,8 +38,8 @@ public function definition(): array 'difficulty' => $this->faker->randomElement($difficulties), 'pricing' => $this->faker->randomElement($pricings), 'topic_tags' => array_values($topicTags), - 'programming_language_tags' => array_unique($this->faker->words(mt_rand(1, 3))), - 'general_tags' => array_unique($this->faker->words(mt_rand(1, 3))), + 'programming_language_tags' => array_values($programmingLanguageTags), + 'general_tags' => array_values($generalTags), ]; $proposedKeys = $this->faker->randomElements( @@ -46,4 +58,9 @@ public function definition(): array 'proposed_changes' => $proposedChanges, ]; } + + private function sanitizeTag(string $tag): string + { + return strtolower(str_replace(' ', '-', $tag)); + } } From 5effb949fff86c517b264bccbc15929c968946a7 Mon Sep 17 00:00:00 2001 From: AllanKoder <74692833+AllanKoder@users.noreply.github.com> Date: Tue, 19 Aug 2025 00:51:13 +0000 Subject: [PATCH 2/6] Apply automatic changes --- app/Http/Requests/StoreResourceEdit.php | 6 +++--- app/Http/Requests/StoreResourceRequest.php | 6 +++--- config/computerScienceResource.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/Http/Requests/StoreResourceEdit.php b/app/Http/Requests/StoreResourceEdit.php index e9ab3a73..fb9a189a 100644 --- a/app/Http/Requests/StoreResourceEdit.php +++ b/app/Http/Requests/StoreResourceEdit.php @@ -37,11 +37,11 @@ public function rules(): array 'proposed_changes.pricing' => ['nullable', 'string', Rule::in(config('computerScienceResource.pricings'))], 'proposed_changes.image_file' => ['nullable', 'image', 'max:500'], // 500 kilobytes 'proposed_changes.topic_tags' => ['nullable', 'array', 'min:2'], - 'proposed_changes.topic_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], + 'proposed_changes.topic_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:'.config('computerScienceResource.tags_regex')], 'proposed_changes.general_tags' => ['nullable', 'array'], - 'proposed_changes.general_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], + 'proposed_changes.general_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:'.config('computerScienceResource.tags_regex')], 'proposed_changes.programming_language_tags' => ['nullable', 'array'], - 'proposed_changes.programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], + 'proposed_changes.programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:'.config('computerScienceResource.tags_regex')], ]; } } diff --git a/app/Http/Requests/StoreResourceRequest.php b/app/Http/Requests/StoreResourceRequest.php index 1a67e2e5..0c2d35c5 100644 --- a/app/Http/Requests/StoreResourceRequest.php +++ b/app/Http/Requests/StoreResourceRequest.php @@ -32,14 +32,14 @@ public function rules(): array 'difficulty' => ['required', 'string', Rule::in(config('computerScienceResource.difficulties'))], 'pricing' => ['required', 'string', Rule::in(config('computerScienceResource.pricings'))], 'topic_tags' => ['required', 'array', 'min:2'], - 'topic_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], + 'topic_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:'.config('computerScienceResource.tags_regex')], // Optional, can just be omitted 'image_file' => ['nullable', 'image', 'max:500'], // 500 kiloBytes 'general_tags' => ['array'], - 'general_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], + 'general_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:'.config('computerScienceResource.tags_regex')], 'programming_language_tags' => ['array'], - 'programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:' . config("computerScienceResource.tags_regex")], + 'programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50', 'regex:'.config('computerScienceResource.tags_regex')], ]; } } diff --git a/config/computerScienceResource.php b/config/computerScienceResource.php index fc3b0da8..021298bf 100644 --- a/config/computerScienceResource.php +++ b/config/computerScienceResource.php @@ -4,5 +4,5 @@ 'platforms' => ['book', 'podcast', 'youtube_channel', 'blog', 'website', 'organization', 'service', 'bootcamp', 'newsletter', 'workshop', 'course', 'forum', 'mobile_app', 'desktop_app', 'magazine'], 'difficulties' => ['any', 'beginner', 'industry_simple', 'industry_standard', 'industry_professional', 'academic'], 'pricings' => ['free', 'paid', 'freemium', 'premium'], - "tags_regex" => "/^[a-z0-9-]+$/" + 'tags_regex' => '/^[a-z0-9-]+$/', ]; From 6985f22145df416de4406b4aea0bf5abd8c802d8 Mon Sep 17 00:00:00 2001 From: Allan Kong <74692833+AllanKoder@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:52:35 -0700 Subject: [PATCH 3/6] Update resources/js/Components/Form/TagSelector.vue Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- resources/js/Components/Form/TagSelector.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/js/Components/Form/TagSelector.vue b/resources/js/Components/Form/TagSelector.vue index 6690bf3b..f05aabe5 100644 --- a/resources/js/Components/Form/TagSelector.vue +++ b/resources/js/Components/Form/TagSelector.vue @@ -33,7 +33,8 @@ function sanitizeTag(tag) { // Transform the tag to lowercase and replace spaces with hyphens transformedTag = transformedTag.replace(/\s+/g, "-"); // Remove any characters that are not lowercase letters or hyphens - transformedTag = transformedTag.replace(/[^a-z-]/g, ""); + // Remove any characters that are not lowercase letters, numbers, or hyphens + transformedTag = transformedTag.replace(/[^a-z0-9-]/g, ""); return transformedTag; } From 881376b8572e5e76c3751b653f0cebbb747a266c Mon Sep 17 00:00:00 2001 From: Allan Kong <74692833+AllanKoder@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:52:56 -0700 Subject: [PATCH 4/6] Update tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../ResourceEdit/StoreResourceEditFactory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php b/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php index 2101a815..595a0df1 100644 --- a/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php +++ b/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php @@ -61,6 +61,8 @@ public function definition(): array private function sanitizeTag(string $tag): string { - return strtolower(str_replace(' ', '-', $tag)); + // Replace spaces with hyphens, lowercase, and remove invalid characters + $tag = strtolower(str_replace(' ', '-', $tag)); + return preg_replace('/[^a-z0-9-]/', '', $tag); } } From e9d3c1c1bb82d62aa52a210249e16c9e190e380d Mon Sep 17 00:00:00 2001 From: Allan Kong <74692833+AllanKoder@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:53:02 -0700 Subject: [PATCH 5/6] Update database/factories/ComputerScienceResourceFactory.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- database/factories/ComputerScienceResourceFactory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/database/factories/ComputerScienceResourceFactory.php b/database/factories/ComputerScienceResourceFactory.php index f2057087..b95fb53a 100644 --- a/database/factories/ComputerScienceResourceFactory.php +++ b/database/factories/ComputerScienceResourceFactory.php @@ -77,6 +77,8 @@ public function configure(): Factory private function sanitizeTag(string $tag): string { // Lowercase, replace spaces with -, remove invalid chars - return strtolower(str_replace(' ', '-', $tag)); + $tag = strtolower(str_replace(' ', '-', $tag)); + // Remove any character not a-z, 0-9, or hyphen + return preg_replace('/[^a-z0-9-]/', '', $tag); } } From 44559ce74e96c0551e23e17a264e36dc058f0c56 Mon Sep 17 00:00:00 2001 From: AllanKoder <74692833+AllanKoder@users.noreply.github.com> Date: Tue, 19 Aug 2025 00:53:24 +0000 Subject: [PATCH 6/6] Apply automatic changes --- database/factories/ComputerScienceResourceFactory.php | 1 + tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php | 1 + 2 files changed, 2 insertions(+) diff --git a/database/factories/ComputerScienceResourceFactory.php b/database/factories/ComputerScienceResourceFactory.php index b95fb53a..c992a03e 100644 --- a/database/factories/ComputerScienceResourceFactory.php +++ b/database/factories/ComputerScienceResourceFactory.php @@ -78,6 +78,7 @@ private function sanitizeTag(string $tag): string { // Lowercase, replace spaces with -, remove invalid chars $tag = strtolower(str_replace(' ', '-', $tag)); + // Remove any character not a-z, 0-9, or hyphen return preg_replace('/[^a-z0-9-]/', '', $tag); } diff --git a/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php b/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php index 595a0df1..81776f05 100644 --- a/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php +++ b/tests/RequestFactories/ResourceEdit/StoreResourceEditFactory.php @@ -63,6 +63,7 @@ private function sanitizeTag(string $tag): string { // Replace spaces with hyphens, lowercase, and remove invalid characters $tag = strtolower(str_replace(' ', '-', $tag)); + return preg_replace('/[^a-z0-9-]/', '', $tag); } }