From 30d174208230cf7643c0b0d4b7c44656bc0f6fe1 Mon Sep 17 00:00:00 2001 From: "Daniel St. Jules" Date: Wed, 27 Apr 2016 22:06:04 -0700 Subject: [PATCH] Work on full support with mbstring module --- README.md | 8 ++-- src/Stringy.php | 100 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 84 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index feac539..e303d9b 100644 --- a/README.md +++ b/README.md @@ -239,9 +239,9 @@ integer, boolean, etc. ```php use Stringy\StaticStringy as S; -// Translates to Stringy::create('fòôbàř', 'UTF-8')->slice(0, 3); +// Translates to Stringy::create('fòôbàř')->slice(0, 3); // Returns a Stringy object with the string "fòô" -S::slice('fòôbàř', 0, 3, 'UTF-8'); +S::slice('fòôbàř', 0, 3); ``` ## Class methods @@ -255,7 +255,7 @@ then returns the initialized object. Throws an InvalidArgumentException if the first argument is an array or object without a __toString method. ```php -$stringy = S::create('fòôbàř', 'UTF-8'); // 'fòôbàř' +$stringy = S::create('fòôbàř'); // 'fòôbàř' ``` ## Instance Methods @@ -420,7 +420,7 @@ s('fòôbàř')->first(3); // 'fòô' Returns the encoding used by the Stringy object. ```php -s('fòôbàř', 'UTF-8')->getEncoding(); // 'UTF-8' +s('fòôbàř')->getEncoding(); // 'UTF-8' ``` ##### hasLowerCase() diff --git a/src/Stringy.php b/src/Stringy.php index 9b51493..b1399f9 100644 --- a/src/Stringy.php +++ b/src/Stringy.php @@ -316,15 +316,14 @@ class Stringy implements Countable, IteratorAggregate, ArrayAccess */ public function delimit($delimiter) { - // Save current regex encoding so we can reset it after - $regexEncoding = \mb_regex_encoding(); - \mb_regex_encoding($this->encoding); + $regexEncoding = $this->regexEncoding(); + $this->regexEncoding($this->encoding); - $str = \mb_ereg_replace('\B([A-Z])', '-\1', $this->trim()); + $str = $this->eregReplace('\B([A-Z])', '-\1', $this->trim()); $str = \mb_strtolower($str, $this->encoding); - $str = \mb_ereg_replace('[-_\s]+', $delimiter, $str); + $str = $this->eregReplace('[-_\s]+', $delimiter, $str); - \mb_regex_encoding($regexEncoding); + $this->regexEncoding($regexEncoding); return static::create($str, $this->encoding); } @@ -692,7 +691,7 @@ class Stringy implements Countable, IteratorAggregate, ArrayAccess */ public function lines() { - $array = \mb_split('[\r\n]{1,2}', $this->str); + $array = $this->split('[\r\n]{1,2}', $this->str); for ($i = 0; $i < count($array); $i++) { $array[$i] = static::create($array[$i], $this->encoding); } @@ -983,11 +982,11 @@ class Stringy implements Countable, IteratorAggregate, ArrayAccess */ public function regexReplace($pattern, $replacement, $options = 'msr') { - $regexEncoding = \mb_regex_encoding(); - \mb_regex_encoding($this->encoding); + $regexEncoding = $this->regexEncoding(); + $this->regexEncoding($this->encoding); - $str = \mb_ereg_replace($pattern, $replacement, $this->str, $options); - \mb_regex_encoding($regexEncoding); + $str = $this->eregReplace($pattern, $replacement, $this->str, $options); + $this->regexEncoding($regexEncoding); return static::create($str, $this->encoding); } @@ -1214,19 +1213,30 @@ class Stringy implements Countable, IteratorAggregate, ArrayAccess } // mb_split errors when supplied an empty pattern in < PHP 5.4.13 - // and current versions of HHVM (3.8 and below) + // and HHVM < 3.8 if ($pattern === '') { return array(static::create($this->str, $this->encoding)); } - $regexEncoding = \mb_regex_encoding(); - \mb_regex_encoding($this->encoding); + $regexEncoding = $this->regexEncoding(); + $this->regexEncoding($this->encoding); // mb_split returns the remaining unsplit string in the last index when // supplying a limit $limit = ($limit > 0) ? $limit += 1 : -1; - $array = \mb_split($pattern, $this->str, $limit); - \mb_regex_encoding($regexEncoding); + + static $functionExists; + if ($functionExists === null) { + $functionExists = function_exists('\mb_split'); + } + + if ($functionExists) { + $array = \mb_split($pattern, $this->str, $limit); + } else if ($this->supportsEncoding()) { + $array = \preg_split("/$pattern/", $this->str, $limit); + } + + $this->regexEncoding($regexEncoding); if ($limit > 0 && count($array) === $limit) { array_pop($array); @@ -1632,7 +1642,8 @@ class Stringy implements Countable, IteratorAggregate, ArrayAccess 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ', 'ی'), 'j' => array('ĵ', 'ј', 'Ј', 'ჯ', 'ج'), - 'k' => array('ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'), + 'k' => array('ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', + 'ک'), 'l' => array('ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'), 'm' => array('м', 'μ', 'م', 'မ', 'მ'), 'n' => array('ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', @@ -1795,12 +1806,61 @@ class Stringy implements Countable, IteratorAggregate, ArrayAccess */ private function matchesPattern($pattern) { - $regexEncoding = \mb_regex_encoding(); - \mb_regex_encoding($this->encoding); + $regexEncoding = $this->regexEncoding(); + $this->regexEncoding($this->encoding); $match = \mb_ereg_match($pattern, $this->str); - \mb_regex_encoding($regexEncoding); + $this->regexEncoding($regexEncoding); return $match; } + + /** + * Alias for mb_ereg_replace with a fallback to preg_replace if the + * mbstring module is not installed. + */ + private function eregReplace($pattern, $replacement, $string, $option = 'msr') + { + static $functionExists; + if ($functionExists === null) { + $functionExists = function_exists('\mb_split'); + } + + if ($functionExists) { + return \mb_ereg_replace($pattern, $replacement, $string, $option); + } else if ($this->supportsEncoding()) { + $option = str_replace('r', '', $option); + return \preg_replace("/$pattern/u$option", $replacement, $string); + } + } + + /** + * Alias for mb_regex_encoding which default to a noop if the mbstring + * module is not installed. + */ + private function regexEncoding() + { + static $functionExists; + + if ($functionExists === null) { + $functionExists = function_exists('\mb_regex_encoding'); + } + + if ($functionExists) { + $args = func_get_args(); + return call_user_func_array('\mb_regex_encoding', $args); + } + } + + private function supportsEncoding() + { + $supported = array('UTF-8' => true, 'ASCII' => true); + + if (isset($supported[$this->encoding])) { + return true; + } else { + throw new \RuntimeExpception('Stringy method requires the ' . + 'mbstring module for encodings other than ASCII and UTF-8'); + } + } }