From 91361f52e7e67e14bc01f944e38a283bb21fad8b Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Fri, 5 Mar 2021 22:07:16 -0800 Subject: [PATCH] EnglishNumber - Add `toInt()` and `isNumeric()`. Add tests. --- CRM/Utils/EnglishNumber.php | 56 +++++++++++++++++++ tests/phpunit/CRM/Utils/EnglishNumberTest.php | 54 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 tests/phpunit/CRM/Utils/EnglishNumberTest.php diff --git a/CRM/Utils/EnglishNumber.php b/CRM/Utils/EnglishNumber.php index 08a7a2a1f1..c95bb6af21 100644 --- a/CRM/Utils/EnglishNumber.php +++ b/CRM/Utils/EnglishNumber.php @@ -122,4 +122,60 @@ class CRM_Utils_EnglishNumber { } } + /** + * Convert an English-style number to an int. + * + * @param string $english + * Ex: 'TwentyTwo' or 'forty-four' + * + * @return int + * 22 or 44 + */ + public static function toInt(string $english) { + $intBuf = 0; + $strBuf = strtolower(str_replace('-', '', $english)); + + foreach (self::$intervalsOfTen as $num => $name) { + if (CRM_Utils_String::startsWith($strBuf, strtolower($name))) { + $intBuf += 10 * $num; + $strBuf = substr($strBuf, strlen($name)); + break; + } + } + foreach (array_reverse(self::$lowNumbers, TRUE) as $num => $name) { + if (CRM_Utils_String::startsWith($strBuf, strtolower($name))) { + $intBuf += $num; + $strBuf = substr($strBuf, strlen($name)); + break; + } + } + + if (!empty($strBuf)) { + throw new InvalidArgumentException("Failed to parse english number: $strBuf"); + } + + return $intBuf; + } + + /** + * Determine if a string looks like + * + * @param string $english + * + * @return bool + */ + public static function isNumeric(string $english): bool { + static $pat; + if (empty($pat)) { + $words = array_map( + function($w) { + return preg_quote(strtolower($w)); + }, + array_merge(array_values(self::$lowNumbers), array_values(self::$intervalsOfTen)) + ); + $pat = '/^(\-|' . implode('|', $words) . ')+$/'; + } + return (bool) preg_match($pat, strtolower($english)); + } + } diff --git a/tests/phpunit/CRM/Utils/EnglishNumberTest.php b/tests/phpunit/CRM/Utils/EnglishNumberTest.php new file mode 100644 index 0000000000..24a301040c --- /dev/null +++ b/tests/phpunit/CRM/Utils/EnglishNumberTest.php @@ -0,0 +1,54 @@ +useTransaction(); + } + + public function testRoundTrip() { + for ($i = 0; $i < 100; $i++) { + $camel = CRM_Utils_EnglishNumber::toCamelCase($i); + $camelToInt = CRM_Utils_EnglishNumber::toInt($camel); + $this->assertEquals($camelToInt, $i); + + $hyphen = CRM_Utils_EnglishNumber::toHyphen($i); + $hyphenToInt = CRM_Utils_EnglishNumber::toInt($hyphen); + $this->assertEquals($hyphenToInt, $i); + } + } + + public function testCamel() { + $this->assertEquals('Seven', CRM_Utils_EnglishNumber::toCamelCase(7)); + $this->assertEquals('Nineteen', CRM_Utils_EnglishNumber::toCamelCase(19)); + $this->assertEquals('Thirty', CRM_Utils_EnglishNumber::toCamelCase(30)); + $this->assertEquals('FiftyFour', CRM_Utils_EnglishNumber::toCamelCase(54)); + $this->assertEquals('NinetyNine', CRM_Utils_EnglishNumber::toCamelCase(99)); + } + + public function testHyphen() { + $this->assertEquals('seven', CRM_Utils_EnglishNumber::toHyphen(7)); + $this->assertEquals('nineteen', CRM_Utils_EnglishNumber::toHyphen(19)); + $this->assertEquals('thirty', CRM_Utils_EnglishNumber::toHyphen(30)); + $this->assertEquals('fifty-four', CRM_Utils_EnglishNumber::toHyphen(54)); + $this->assertEquals('ninety-nine', CRM_Utils_EnglishNumber::toHyphen(99)); + } + + public function testIsNumeric() { + $assertNumeric = function($expectBool, $string) { + $this->assertEquals($expectBool, CRM_Utils_EnglishNumber::isNumeric($string), "isNumeric($string) should return " . (int) $expectBool); + }; + $assertNumeric(TRUE, 'FiveThirtyEight'); + $assertNumeric(TRUE, 'Seventeen'); + $assertNumeric(TRUE, 'four-one-one'); + $assertNumeric(FALSE, 'Eleventy'); + $assertNumeric(FALSE, 'Bazillions'); + } + +} -- 2.25.1