diff --git a/src/TitleFormatter.php b/src/TitleFormatter.php index e280051..e08965f 100644 --- a/src/TitleFormatter.php +++ b/src/TitleFormatter.php @@ -6,38 +6,28 @@ class TitleFormatter { /** * The title that we need to format and return. - * - * @var string|null */ - protected $title; + protected ?string $title = null; /** * The separator character for in between words. - * - * @var string */ - protected $separator = ' '; + protected string $separator = ' '; /** * Encoding used for mb_ functions. - * - * @var string */ - protected $encoding = 'UTF-8'; + protected string $encoding = 'UTF-8'; /** * Collection of words generated from the original title. - * - * @var array */ - protected $indexedWords = []; + protected array $indexedWords = []; /** * Words that should be ignored from capitalization. - * - * @var array */ - protected $ignoredWords = [ + protected array $ignoredWords = [ 'a', 'an', 'and', @@ -59,11 +49,7 @@ class TitleFormatter 'via', ]; - /** - * @param string $title - * @param string $separator - */ - private function __construct($title, $separator = ' ') + private function __construct(?string $title = null, string $separator = ' ') { $this->setTitle($title); $this->separator = $separator; @@ -71,10 +57,8 @@ private function __construct($title, $separator = ' ') /** * Converts the initial title to a correctly formatted one. - * - * @return string */ - public function convertTitle() + public function convertTitle(): string { if ($this->title === null) { return ''; @@ -86,31 +70,25 @@ public function convertTitle() } } - return $this->title; + return $this->title ?? ''; } /** * Returns the newly formatted title. - * - * @param string $title - * @param string $separator - * @return string */ - public static function titleCase($title, $separator = ' ') + public static function titleCase(?string $title = null, string $separator = ' '): string { return (new self($title, $separator))->convertTitle(); } /** * Sets the title after cleaning up extra spaces. - * - * @param string $title */ - protected function setTitle($title) + protected function setTitle(?string $title = null): void { $title = trim(preg_replace('/\s\s+/', ' ', str_replace("\n", ' ', $title))); - if ($title != '') { + if ($title !== '') { $this->title = $title; } } @@ -118,14 +96,13 @@ protected function setTitle($title) /** * Creates an array of words from the title to be formatted. */ - protected function splitWords() + protected function splitWords(): array { $indexedWords = []; $offset = 0; - $words = explode($this->separator, $this->title); - foreach ($words as $word) { - if (mb_strlen($word, $this->encoding) == 0) { + foreach (explode($this->separator, $this->title) as $word) { + if (mb_strlen($word, $this->encoding) === 0) { continue; } @@ -145,12 +122,8 @@ protected function splitWords() /** * Finds the correct index of the word within the title. - * - * @param $word - * @param $offset - * @return int */ - protected function getWordIndex($word, $offset) + protected function getWordIndex(string $word, int $offset): int { $index = mb_strpos($this->title, $word, $offset, $this->encoding); @@ -159,22 +132,16 @@ protected function getWordIndex($word, $offset) /** * Corrects the potential offset issue with some UTF-8 characters. - * - * @param $index - * @return int */ - protected function correctIndexOffset($index) + protected function correctIndexOffset(?int $index): int { return mb_strlen(mb_substr($this->title, 0, $index, $this->encoding), $this->encoding); } /** * Replaces a formatted word within the current title. - * - * @param int $index - * @param string $word */ - protected function rebuildTitle($index, $word) + protected function rebuildTitle(int $index, string $word): void { $this->title = mb_substr($this->title, 0, $index, $this->encoding) . @@ -189,11 +156,8 @@ protected function rebuildTitle($index, $word) /** * Performs the uppercase action on the given word. - * - * @param $word - * @return string */ - protected function uppercaseWord($word) + protected function uppercaseWord(string $word): string { // see if first characters are special $prefix = ''; @@ -213,31 +177,24 @@ protected function uppercaseWord($word) /** * Condition to see if the given word should be uppercase. - * - * @param $index - * @param $word - * @return bool */ - protected function wordShouldBeUppercase($index, $word) + protected function wordShouldBeUppercase(int $index, string $word): bool { return ( $this->isFirstWordOfSentence($index) || $this->isLastWord($word) || - !$this->isIgnoredWord($word) + ! $this->isIgnoredWord($word) ) && ( - !$this->hasUppercaseLetter($word) + ! $this->hasUppercaseLetter($word) ); } /** * Checks to see if the word is the last word in the title. - * - * @param $word - * @return bool */ - protected function isLastWord($word) + protected function isLastWord(string $word): bool { if ($word === end($this->indexedWords)) { return true; @@ -247,14 +204,11 @@ protected function isLastWord($word) } /** - * Checks to see if the word the start of a new sentence. - * - * @param $index - * @return bool + * Checks to see if the word is the start of a new sentence. */ - protected function isFirstWordOfSentence($index) + protected function isFirstWordOfSentence(int $index): bool { - if ($index == 0) { + if ($index === 0) { return true; } @@ -269,47 +223,35 @@ protected function isFirstWordOfSentence($index) /** * Checks to see if the given string is a punctuation character. - * - * @param $string - * @return int */ - protected function isPunctuation($string) + protected function isPunctuation(string $string): int { return preg_match("/[\p{P}\p{S}]/u", $string); } /** * Checks if the given word should be ignored. - * - * @param $word - * @return bool */ - protected function isIgnoredWord($word) + protected function isIgnoredWord(string $word): bool { - return in_array($word, $this->ignoredWords); + return in_array($word, $this->ignoredWords, true); } /** * Checks to see if a word has an uppercase letter. - * - * @param $word - * @return int */ - protected function hasUppercaseLetter($word) + protected function hasUppercaseLetter(string $word): int { return preg_match('/[A-Z]/', $word); } /** * Checks to see if the word has a dash. - * - * @param $word - * @return int */ - protected function hasDash($word) + protected function hasDash(string $word): bool { $wordWithoutDashes = str_replace('-', '', $word); - return preg_match("/\-/", $word) && mb_strlen($wordWithoutDashes, $this->encoding) > 1; + return (bool) preg_match("/\-/", $word) && mb_strlen($wordWithoutDashes, $this->encoding) > 1; } } diff --git a/tests/TestCase.php b/tests/TestCase.php deleted file mode 100644 index 1b71e37..0000000 --- a/tests/TestCase.php +++ /dev/null @@ -1,9 +0,0 @@ -assertEquals($expected, TitleFormatter::titleCase($initial)); } - public function titleProvider() + public function titleProvider(): iterable { - return [ - [ - // tests single sentence with mid-word special character - 'this sh*t is a test', - 'This Sh*t is a Test', - ], - [ - // tests multiple sentences - 'is this sh*t is a test. for sure!!!', - 'Is This Sh*t is a Test. For Sure!!!', - ], - [ - // tests sentences in brackets - 'is this sh*t is a test. for sure. [yikes as example]', - 'Is This Sh*t is a Test. For Sure. [Yikes as Example]', - ], - [ - // tests dashed words - 'this should be a super-awesome post! cool? not-so-much!', - 'This Should Be a Super-Awesome Post! Cool? Not-So-Much!', - ], - [ - // tests sentence with extra spaces - ' this should be interesting ', - 'This Should Be Interesting', - ], - [ - // tests simple sentence - 'very simple sentence', - 'Very Simple Sentence', - ], - [ - // tests to make sure last word is capitalized - 'very simple sentence of', - 'Very Simple Sentence Of', - ], - [ - // tests words that have capital letters, they should be ignored - 'i think eBay is the greatest site! also, McCormick has the best spices!', - 'I Think eBay is the Greatest Site! Also, McCormick Has the Best Spices!', - ], - [ - // tests words with multiple punctuation prefixes - 'this post is $$$money', - 'This Post is $$$Money', - ], - [ - // tests for all CAPS words, they should be ignored - 'i really like playing with LEGOS, they are a lot of fun!', - 'I Really Like Playing With LEGOS, They Are a Lot of Fun!', - ], - [ - // tests for a bug in first words with apostrophes, should not capitalize second letter - 'it\'s really- something, isn\'t it?', - 'It\'s Really- Something, Isn\'t It?', - ], - [ - // tests for a bug with a dash separator - 'test - jet fighters', - 'Test - Jet Fighters', - ], - [ - // tests for a bug with multiple separators - 'test --- jet-- fighters - test ==== testtest', - 'Test --- Jet-- Fighters - Test ==== Testtest', - ], - [ - // tests numbers only - '1234 567', - '1234 567', - ], - [ - // tests colon - 'this is a test: cool, huh?', - 'This is a Test: Cool, Huh?', - ], - [ - // tests for a bug with empty title - '', - '', - ], - [ - // tests for a bug with null title - null, - '', - ], - [ - // tests for a bug with all spaces - ' ', - '', - ], - [ - // tests for a bug with all spaces, one word - ' test', - 'Test', - ], - [ - // tests one word - 'test', - 'Test', - ], - [ - // tests for a bug with special characters - 'get up and dance — 7 reasons why you should be… moving your feet to the beat', - 'Get Up and Dance — 7 Reasons Why You Should Be… Moving Your Feet to the Beat', - ], + yield 'single sentence with mid-word special character' => [ + 'initial' => 'this sh*t is a test', + 'expected' => 'This Sh*t is a Test', + ]; + + yield 'multiple sentences' => [ + 'initial' => 'is this sh*t is a test. for sure!!!', + 'expected' => 'Is This Sh*t is a Test. For Sure!!!', + ]; + + yield 'sentences in brackets' => [ + 'initial' => 'is this sh*t is a test. for sure. [yikes as example]', + 'expected' => 'Is This Sh*t is a Test. For Sure. [Yikes as Example]', + ]; + + yield 'dashed words' => [ + 'initial' => 'this should be a super-awesome post! cool? not-so-much!', + 'expected' => 'This Should Be a Super-Awesome Post! Cool? Not-So-Much!', + ]; + + yield 'sentence with extra spaces' => [ + 'initial' => ' this should be interesting ', + 'expected' => 'This Should Be Interesting', + ]; + + yield 'simple sentence' => [ + 'initial' => 'very simple sentence', + 'expected' => 'Very Simple Sentence', + ]; + + yield 'make sure last word is capitalized' => [ + 'initial' => 'very simple sentence of', + 'expected' => 'Very Simple Sentence Of', + ]; + + yield 'words that have capital letters, they should be ignored' => [ + 'initial' => 'i think eBay is the greatest site! also, McCormick has the best spices!', + 'expected' => 'I Think eBay is the Greatest Site! Also, McCormick Has the Best Spices!', + ]; + + yield 'words with multiple punctuation prefixes' => [ + 'initial' => 'this post is $$$money', + 'expected' => 'This Post is $$$Money', + ]; + + yield 'all CAPS words should be ignored' => [ + 'initial' => 'i really like playing with LEGOS, they are a lot of fun!', + 'expected' => 'I Really Like Playing With LEGOS, They Are a Lot of Fun!', + ]; + + yield 'bug in first words with apostrophes, should not capitalize second letter' => [ + 'initial' => 'it\'s really- something, isn\'t it?', + 'expected' => 'It\'s Really- Something, Isn\'t It?', + ]; + + yield 'bug with a dash separator' => [ + 'initial' => 'test - jet fighters', + 'expected' => 'Test - Jet Fighters', + ]; + + yield 'bug with multiple separators' => [ + 'initial' => 'test --- jet-- fighters - test ==== testtest', + 'expected' => 'Test --- Jet-- Fighters - Test ==== Testtest', + ]; + + yield 'numbers only' => [ + 'initial' => '1234 567', + 'expected' => '1234 567', + ]; + + yield 'colon' => [ + 'initial' => 'this is a test: cool, huh?', + 'expected' => 'This is a Test: Cool, Huh?', + ]; + + yield 'bug with empty title' => [ + 'initial' => '', + 'expected' => '', + ]; + + yield 'bug with null title' => [ + 'initial' => null, + 'expected' => '', + ]; + + yield 'bug with all spaces' => [ + 'initial' => ' ', + 'expected' => '', + ]; + + yield 'bug with all spaces, one word' => [ + 'initial' => ' test', + 'expected' => 'Test', + ]; + + yield 'one word' => [ + 'initial' => 'test', + 'expected' => 'Test', + ]; + + yield 'bug with special characters' => [ + 'initial' => 'get up and dance — 7 reasons why you should be… moving your feet to the beat', + 'expected' => 'Get Up and Dance — 7 Reasons Why You Should Be… Moving Your Feet to the Beat', ]; } }