diff --git a/CHANGELOG.md b/CHANGELOG.md index d3ce5e34bb9..cf4866890a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Auto-generated handles, slugs, etc. now update immediately when the source input is changed. ([#15754](https://github.com/craftcms/cms/issues/15754)) - Fixed a bug where Table fields’ Default Values table could lose existing rows if they only consisted of Dropdown columns without configured options. - Fixed a bug where custom fields’ `required` properties were always `false`. ([#15752](https://github.com/craftcms/cms/issues/15752)) +- Fixed a bug where `craft\helpers\StringHelper::toHandle()` was allowing non-alphanumeric/underscore characters through. ([#15772](https://github.com/craftcms/cms/pull/15772)) - Fixed a bug where it wasn’t possible to save nested entries via the `entries/save-entry` controller action. ([#15737](https://github.com/craftcms/cms/issues/15737)) - Fixed a bug where hyperlinks in Link field inputs could wrap unnecessarily. ([#15738](https://github.com/craftcms/cms/issues/15738)) - Fixed an error that occurred when running the `entrify/global-set` command. ([#15746](https://github.com/craftcms/cms/issues/15746)) diff --git a/src/helpers/StringHelper.php b/src/helpers/StringHelper.php index 397ec54168f..c1480a1205d 100644 --- a/src/helpers/StringHelper.php +++ b/src/helpers/StringHelper.php @@ -1816,6 +1816,9 @@ public static function toHandle(string $str): string // Handle must start with a letter $handle = preg_replace('/^[^a-z]+/', '', $handle); + // Replace any remaining non-alphanumeric or underscore characters with spaces + $handle = preg_replace('/[^a-z0-9_]/', ' ', $handle); + return static::toCamelCase($handle); } diff --git a/tests/unit/helpers/StringHelperTest.php b/tests/unit/helpers/StringHelperTest.php index 64de0c12932..b0daaca066a 100644 --- a/tests/unit/helpers/StringHelperTest.php +++ b/tests/unit/helpers/StringHelperTest.php @@ -2208,6 +2208,10 @@ public static function toHandleDataProvider(): array ['fooBar', 'Fo’o Bar'], ['fooBarBaz', 'Foo Ba’r Baz'], ['fooBar', '0 Foo Bar'], + ['fooBar', 'Foo!Bar'], + ['fooBar', 'Foo,Bar'], + ['fooBar', 'Foo/Bar'], + ['fooBar', 'Foo\\Bar'], ]; }