Skip to content

Acronym not correctly transformed by snake (and kebab too) #61015

Open
@unsiteavous

Description

@unsiteavous

Symfony version(s) affected

7.3

Description

Hello,
I hope I write it to the good place... If not, my apologies.

Currently, when we use a slugger to transform a string in a snake or kebab format, there is a little bug with acronyms.

How to reproduce

for example :

use Symfony\Component\String\Slugger\SluggerInterface;
// [...]
private readonly SluggerInterface $slugger;
// [...]
$string = "CV Pauline";
echo $this->slugger->slug($string)->snake()->toString();
// currently return "c_vpauline", while I was waiting for "cv_pauline"

Possible Solution

The problem seems to come from camel() function, that doesn't return expected response :

$string = "CV Pauline";
echo $this->slugger->slug($string)->camel()->toString();
// currently return "CVpauline", while I was waiting for "CVPauline" (or "CvPauline", as the function's name suggests)

public function camel(): static

I propose this code below to fix this bug :

public function camel(): static
    {
        $str = clone $this;

        $string = preg_replace('/[^\pL0-9]++/u', ' ', $this->string);

        // convert in lowercase except acronyms
        $string = preg_replace_callback('/\b(\p{Lu}+)(?:\s+|$)/u', function ($m) {
            return $m[1]; // keep acronyms in uppercase
        }, $string);

        $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?!\p{Lu})/u', function ($m) {
            static $i = 0;
            return 1 === ++$i ?
                ('İ' === $m[0] ? '' : mb_strtolower($m[0], 'UTF-8')) :
                mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
        }, $string));

        return $str;
    }

Now, for "CV Pauline" :

camel() snake()
Before : CVpauline c_vpauline
After : CVPauline cv_pauline

This is what I expected, nice !
However, one question remains : why camel() begins with capital letter ? this is normally PascalCase, no ? It's absolutely not important, but I prefer say it anyway, in order to adapt perhaps it later ;)

Thanks to your attention.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions