Skip to content

Commit

Permalink
Added Hyperf\Stringable\Str::apa() method (#6576)
Browse files Browse the repository at this point in the history
  • Loading branch information
huangdijia authored Mar 10, 2024
1 parent 1046533 commit b79f720
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,56 @@ public static function afterLast($subject, $search)
return substr($subject, $position + strlen($search));
}

/**
* 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 apa($value)
{
if (trim($value) === '') {
return $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
10 changes: 10 additions & 0 deletions src/Stringable.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ public function afterLast($search)
return new static(Str::afterLast($this->value, $search));
}

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

/**
* Append the given values to the string.
*
Expand Down
34 changes: 34 additions & 0 deletions tests/StrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,40 @@
#[CoversNothing]
class StrTest extends TestCase
{
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('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('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('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('Self-Report', Str::apa('self-report'));
$this->assertSame('Self-Report', Str::apa('Self-report'));
$this->assertSame('Self-Report', Str::apa('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('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('', Str::apa(''));
$this->assertSame(' ', Str::apa(' '));
}

public function testCharAt()
{
$this->assertEquals('р', Str::charAt('Привет, мир!', 1));
Expand Down

0 comments on commit b79f720

Please sign in to comment.