Skip to content

Commit

Permalink
formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Jan 7, 2024
1 parent 4fe8b96 commit 6edd3a3
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 90 deletions.
118 changes: 69 additions & 49 deletions src/Illuminate/Support/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,48 +110,6 @@ public static function afterLast($subject, $search)
return substr($subject, $position + strlen($search));
}

/**
* Convert the given string to APA-style case.
* Based on the rules provided by the APA:
* https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case
*
* @param string $value
* @return string
*/
public static function apa($value)
{
$minorWords = ['and', 'as', 'but', 'for', 'if', 'nor', 'or', 'so', 'yet', 'a', 'an', 'the', 'at', 'by', 'for', 'in', 'of', 'off', 'on', 'per', 'to', 'up', 'via'];
$endPunctuation = ['.', '!', '?', ':', '', ','];

$words = preg_split('/\s+/', $value, -1, PREG_SPLIT_NO_EMPTY);

$words[0] = ucfirst(mb_strtolower($words[0]));

for ($i = 0; $i < count($words); $i++) {
$lowercaseWord = mb_strtolower($words[$i]);

if (str_contains($lowercaseWord, '-')) {
$hyphenatedWords = explode('-', $lowercaseWord);
$hyphenatedWords = array_map(function ($part) use ($minorWords) {
return (in_array($part, $minorWords) && mb_strlen($part) <= 3) ? $part : ucfirst($part);
}, $hyphenatedWords);
$words[$i] = implode('-', $hyphenatedWords);
} else {
if (
in_array($lowercaseWord, $minorWords) &&
mb_strlen($lowercaseWord) <= 3 &&
!($i === 0 || in_array(mb_substr($words[$i - 1], -1), $endPunctuation))
) {
$words[$i] = $lowercaseWord;
} else {
$words[$i] = ucfirst($lowercaseWord);
}
}
}

return implode(' ', $words);
}

/**
* Transliterate a UTF-8 value to ASCII.
*
Expand Down Expand Up @@ -1280,33 +1238,95 @@ public static function upper($value)
}

/**
* Convert the given string to title case.
* Convert the given string to proper case.
*
* @param string $value
* @return string
*/
public static function title($value)
public static function properCase($value)
{
return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
}

/**
* Convert the given string to title case for each word.
* Convert the given string to proper case.
*
* @param string $value
* @return string
*/
public static function title($value)
{
return static::properCase($value);
}

/**
* Convert the given string to proper case for each word.
*
* @param string $value
* @param bool $title
* @return string
*/
public static function headline($value)
public static function headline($value, $title = false)
{
$parts = explode(' ', $value);

$method = $title ? 'lower' : 'properCase';

$parts = count($parts) > 1
? array_map([static::class, 'title'], $parts)
: array_map([static::class, 'title'], static::ucsplit(implode('_', $parts)));
? array_map([static::class, $method], $parts)
: array_map([static::class, $method], static::ucsplit(implode('_', $parts)));

$collapsed = static::replace(['-', '_', ' '], '_', implode('_', $parts));

return implode(' ', array_filter(explode('_', $collapsed)));
$headline = implode(' ', array_filter(explode('_', $collapsed)));

return $title ? Str::titleCase($headline) : $headline;
}

/**
* Convert the given string to APA-style title case.
*
* See: https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case
*
* @param string $value
* @return string
*/
public static function titleCase($value)
{
$minorWords = [
'and', 'as', 'but', 'for', 'if', 'nor', 'or', 'so', 'yet', 'a', 'an',
'the', 'at', 'by', 'for', 'in', 'of', 'off', 'on', 'per', 'to', 'up', 'via'
];

$endPunctuation = ['.', '!', '?', ':', '', ','];

$words = preg_split('/\s+/', $value, -1, PREG_SPLIT_NO_EMPTY);

$words[0] = ucfirst(mb_strtolower($words[0]));

for ($i = 0; $i < count($words); $i++) {
$lowercaseWord = mb_strtolower($words[$i]);

if (str_contains($lowercaseWord, '-')) {
$hyphenatedWords = explode('-', $lowercaseWord);

$hyphenatedWords = array_map(function ($part) use ($minorWords) {
return (in_array($part, $minorWords) && mb_strlen($part) <= 3) ? $part : ucfirst($part);
}, $hyphenatedWords);

$words[$i] = implode('-', $hyphenatedWords);
} else {
if (in_array($lowercaseWord, $minorWords) &&
mb_strlen($lowercaseWord) <= 3 &&
! ($i === 0 || in_array(mb_substr($words[$i - 1], -1), $endPunctuation))) {
$words[$i] = $lowercaseWord;
} else {
$words[$i] = ucfirst($lowercaseWord);
}
}
}

return implode(' ', $words);
}

/**
Expand Down
51 changes: 31 additions & 20 deletions src/Illuminate/Support/Stringable.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,6 @@ public function newLine($count = 1)
return $this->append(str_repeat(PHP_EOL, $count));
}

/**
* Convert the given string to APA-style case.
*
* @return static
*/
public function apa()
{
return new static(Str::apa($this->value));
}

/**
* Transliterate a UTF-8 value to ASCII.
*
Expand Down Expand Up @@ -798,35 +788,56 @@ public function upper()
}

/**
* Convert the given string to title case.
* Convert the given string to proper case.
*
* @return static
*/
public function properCase()
{
return new static(Str::properCase($this->value));
}

/**
* Convert the given string to proper case.
*
* @return static
*/
public function title()
{
return new static(Str::title($this->value));
return $this->properCase();
}

/**
* Transliterate a string to its closest ASCII representation.
* Convert the given string to proper case for each word.
*
* @param string|null $unknown
* @param bool|null $strict
* @param bool $title
* @return static
*/
public function transliterate($unknown = '?', $strict = false)
public function headline($title = false)
{
return new static(Str::transliterate($this->value, $unknown, $strict));
return new static(Str::headline($this->value, $title));
}

/**
* Convert the given string to title case for each word.
* Convert the given string to APA-style title case.
*
* @return static
*/
public function headline()
public function titleCase()
{
return new static(Str::headline($this->value));
return new static(Str::titleCase($this->value));
}

/**
* Transliterate a string to its closest ASCII representation.
*
* @param string|null $unknown
* @param bool|null $strict
* @return static
*/
public function transliterate($unknown = '?', $strict = false)
{
return new static(Str::transliterate($this->value, $unknown, $strict));
}

/**
Expand Down
45 changes: 24 additions & 21 deletions tests/Support/SupportStrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,14 @@ public function testStringHeadline()
$this->assertSame('Jefferson Costella', Str::headline('jefFErson coSTella'));
$this->assertSame('Jefferson Costella Uses Laravel', Str::headline('jefferson_costella uses-_Laravel'));
$this->assertSame('Jefferson Costella Uses Laravel', Str::headline('jefferson_costella uses__Laravel'));
$this->assertSame('Jefferson Costella in the Laravel', Str::headline('jefferson_costella in_the__Laravel', title: true));
$this->assertSame('Jefferson Costella In The Laravel', Str::headline('jefferson_costella in_the__Laravel', title: false));

$this->assertSame('Laravel P H P Framework', Str::headline('laravel_p_h_p_framework'));
$this->assertSame('Laravel P H P Framework', Str::headline('laravel _p _h _p _framework'));
$this->assertSame('Laravel Php Framework', Str::headline('laravel_php_framework'));
$this->assertSame('Laravel Ph P Framework', Str::headline('laravel-phP-framework'));
$this->assertSame('Laravel Ph P Framework', Str::headline('laravel-phP-framework', title: true));
$this->assertSame('Laravel Php Framework', Str::headline('laravel -_- php -_- framework '));

$this->assertSame('Foo Bar', Str::headline('fooBar'));
Expand All @@ -69,33 +72,33 @@ public function testStringHeadline()

public function testStringApa()
{
$this->assertSame('Tom and Jerry', Str::apa('tom and jerry'));
$this->assertSame('Tom and Jerry', Str::apa('TOM AND JERRY'));
$this->assertSame('Tom and Jerry', Str::apa('Tom And Jerry'));
$this->assertSame('Tom and Jerry', Str::titleCase('tom and jerry'));
$this->assertSame('Tom and Jerry', Str::titleCase('TOM AND JERRY'));
$this->assertSame('Tom and Jerry', Str::titleCase('Tom And Jerry'));

$this->assertSame('Back to the Future', Str::apa('back to the future'));
$this->assertSame('Back to the Future', Str::apa('BACK TO THE FUTURE'));
$this->assertSame('Back to the Future', Str::apa('Back To The Future'));
$this->assertSame('Back to the Future', Str::titleCase('back to the future'));
$this->assertSame('Back to the Future', Str::titleCase('BACK TO THE FUTURE'));
$this->assertSame('Back to the Future', Str::titleCase('Back To The Future'));

$this->assertSame('This, Then That', Str::apa('this, then that'));
$this->assertSame('This, Then That', Str::apa('THIS, THEN THAT'));
$this->assertSame('This, Then That', Str::apa('This, Then That'));
$this->assertSame('This, Then That', Str::titleCase('this, then that'));
$this->assertSame('This, Then That', Str::titleCase('THIS, THEN THAT'));
$this->assertSame('This, Then That', Str::titleCase('This, Then That'));

$this->assertSame('Bond. James Bond.', Str::apa('bond. james bond.'));
$this->assertSame('Bond. James Bond.', Str::apa('BOND. JAMES BOND.'));
$this->assertSame('Bond. James Bond.', Str::apa('Bond. James Bond.'));
$this->assertSame('Bond. James Bond.', Str::titleCase('bond. james bond.'));
$this->assertSame('Bond. James Bond.', Str::titleCase('BOND. JAMES BOND.'));
$this->assertSame('Bond. James Bond.', Str::titleCase('Bond. James Bond.'));

$this->assertSame('Self-Report', Str::apa('self-report'));
$this->assertSame('Self-Report', Str::apa('Self-report'));
$this->assertSame('Self-Report', Str::apa('SELF-REPORT'));
$this->assertSame('Self-Report', Str::titleCase('self-report'));
$this->assertSame('Self-Report', Str::titleCase('Self-report'));
$this->assertSame('Self-Report', Str::titleCase('SELF-REPORT'));

$this->assertSame('As the World Turns, So Are the Days of Our Lives', Str::apa('as the world turns, so are the days of our lives'));
$this->assertSame('As the World Turns, So Are the Days of Our Lives', Str::apa('AS THE WORLD TURNS, SO ARE THE DAYS OF OUR LIVES'));
$this->assertSame('As the World Turns, So Are the Days of Our Lives', Str::apa('As The World Turns, So Are The Days Of Our Lives'));
$this->assertSame('As the World Turns, So Are the Days of Our Lives', Str::titleCase('as the world turns, so are the days of our lives'));
$this->assertSame('As the World Turns, So Are the Days of Our Lives', Str::titleCase('AS THE WORLD TURNS, SO ARE THE DAYS OF OUR LIVES'));
$this->assertSame('As the World Turns, So Are the Days of Our Lives', Str::titleCase('As The World Turns, So Are The Days Of Our Lives'));

$this->assertSame('To Kill a Mockingbird', Str::apa('to kill a mockingbird'));
$this->assertSame('To Kill a Mockingbird', Str::apa('TO KILL A MOCKINGBIRD'));
$this->assertSame('To Kill a Mockingbird', Str::apa('To Kill A Mockingbird'));
$this->assertSame('To Kill a Mockingbird', Str::titleCase('to kill a mockingbird'));
$this->assertSame('To Kill a Mockingbird', Str::titleCase('TO KILL A MOCKINGBIRD'));
$this->assertSame('To Kill a Mockingbird', Str::titleCase('To Kill A Mockingbird'));
}

public function testStringWithoutWordsDoesntProduceError()
Expand Down

0 comments on commit 6edd3a3

Please sign in to comment.