From 6ff9bda72722d002dea7c5b9bf44e895ad93d27f Mon Sep 17 00:00:00 2001 From: Jorge Castro Date: Sat, 6 Jun 2020 14:37:34 -0400 Subject: [PATCH] * 1.16 New methods Text::wildcardComparison() and Text::endsWith() --- README.md | 2 + composer.json | 2 +- lib/Text.php | 195 +++++++++++++++++++++++++++++++++++++--------- test/TextTest.php | 15 ++++ 4 files changed, 175 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 7933072..fe2e0fd 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,8 @@ Text::addParenthesis('(hello)'); ## Version list +* 1.16 New methods Text::wildcardComparison() and Text::endsWith() +* 1.15 New method Text::parseArg2() * 1.14 Text::camelCase() solved a small bug * 1.13 Text::replaceCurlyVariable() updated * 1.12 diff --git a/composer.json b/composer.json index 002442a..9ee1452 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "eftec/mapache-commons", "description": "It's a set of useful functions for PHP. The name is a pun.", - "version": "1.14", + "version": "1.16", "type": "library", "keywords": [ "collection", diff --git a/lib/Text.php b/lib/Text.php index c589dfd..cc69a2d 100644 --- a/lib/Text.php +++ b/lib/Text.php @@ -6,12 +6,13 @@ * Class Text * * @package mapache_commons - * @version 1.14 2020-feb-12 + * @version 1.16 2020-06-06 * @copyright Jorge Castro Castillo * @license Apache-2.0 * @see https://github.com/EFTEC/mapache-commons */ -class Text { +class Text +{ /** * Returns true if the str is (completelly) uppercase @@ -105,13 +106,13 @@ public static function removeParenthesis($txt, $start = '(', $end = ')') { return false; } foreach ($start as $k => $v) { - if (substr($txt, 0, 1) === $v && substr($txt, -1) === $end[$k]) { - return substr($txt, 1, strlen($txt) - 2); + if ($txt[0] === $v && substr($txt, -1) === $end[$k]) { + return substr($txt, 1, -1); } } } else { - if (substr($txt, 0, 1) === $start && substr($txt, -1) === $end) { - return substr($txt, 1, strlen($txt) - 2); + if ($txt[0] === $start && substr($txt, -1) === $end) { + return substr($txt, 1, -1); } } return $txt; @@ -152,19 +153,18 @@ public static function replaceBetween( $offset = $ini + $len; return substr_replace($haystack, $replaceText, $ini, $len); - } else { - $ini += strlen($startNeedle); - $len = $p1 - $ini; - $offset = $ini + $len; - return substr_replace($haystack, $replaceText, $ini, $len); } + $ini += strlen($startNeedle); + $len = $p1 - $ini; + $offset = $ini + $len; + return substr_replace($haystack, $replaceText, $ini, $len); } /** * Remove the first character(s) for a string * - * @param string $str The input text + * @param string $str The input text * @param int $length The amount of characters to remove * * @return bool|string @@ -176,7 +176,7 @@ public static function removeFirstChars($str, $length = 1) { /** * Remove the last character(s) for a string * - * @param string $str The input text + * @param string $str The input text * @param int $length The amount of characters to remove * * @return bool|string @@ -215,14 +215,14 @@ public static function getArgument($str, $set = '=', $trimValue = true) { /** * It returns the first non-space position inside a string. * - * @param string $str input string - * @param int $offset offset position + * @param string $str input string + * @param int $offset offset position * @param string $charlist list of characters considered as space * * @return int the position of the first non-space */ - public static function strPosNotSpace($str, $offset = 0, $charlist=" \t\n\r\0\x0B") { - $txtTmp = substr($str, 0, $offset) . ltrim(substr($str, $offset),$charlist); + public static function strPosNotSpace($str, $offset = 0, $charlist = " \t\n\r\0\x0B") { + $txtTmp = substr($str, 0, $offset) . ltrim(substr($str, $offset), $charlist); return strlen($str) - strlen($txtTmp) + $offset; } @@ -259,6 +259,7 @@ public static function strposArray($haystack, $needles, $offset = 0, $last = fal /** * It transforms a text = 'a1=1,a2=2' into an associative array
* It uses the method parse_str() to do the conversion
+ * Note: It doesn't work with quotes or double quotes. a1="aa,bb",bb=30 doesn't work * * @param string $text The input string with the initial values * @param string $separator The separator @@ -268,7 +269,7 @@ public static function strposArray($haystack, $needles, $offset = 0, $last = fal public static function parseArg($text, $separator = ',') { $tmpToken = '¶|¶'; $output = []; - if ($separator == '&') { + if ($separator === '&') { parse_str($text, $output); return $output; } @@ -280,6 +281,54 @@ public static function parseArg($text, $separator = ',') { return $output; } + /** + * It's the same than parseArg() but it's x3 times slower.
+ * It also considers quotes and doubles quotes.
+ * Example: + *
+     * Text::parseArg2("a1=1,a2=2,a3="aa,bb"); // ["a1"=>1,"a2"=>2,"a3"=>""aa,bb""]
+     * Text::parseArg("a1=1,a2=2,a3="aa,bb"); // ["a1"=>1,"a2"=>2,"a3"=>""aa","bb""=>""]
+     * 
+ * + * @param string $text The input string with the initial values + * @param string $separator The separator. It does not separates text inside quotes or double-quotes. + * + * @return array An associative array + */ + public static function parseArg2($text, $separator = ',') { + + $chars = str_split($text); + $parts = []; + $nextpart = ""; + $strL = count($chars); + for ($i = 0; $i < $strL; $i++) { + $char = $chars[$i]; + if ($char === '"' || $char === "'") { + $inext = strpos($text, $char, $i + 1); + $inext = $inext === false ? $strL : $inext; + $nextpart .= substr($text, $i, $inext - $i + 1); + $i = $inext; + } else { + $nextpart .= $char; + } + if ($char === $separator) { + $parts[] = substr($nextpart, 0, -1); + $nextpart = ""; + } + } + if (strlen($nextpart) > 0) { + $parts[] = $nextpart; + } + $result = []; + foreach ($parts as $part) { + $r = explode('=', $part, 2); + if (count($r) == 2) { + $result[trim($r[0])] = trim($r[1]); + } + } + return $result; + } + /** * It parses a natural string and returns a declarative array
* Example: natural("v1 obj obj1 type type1"
@@ -321,7 +370,7 @@ public static function naturalArg($txt, $separators) { } // validation foreach ($result as $k => $item) { - if ($separators[$k] == 'req' && $result[$k] === null) { + if ($separators[$k] === 'req' && $result[$k] === null) { // it misses one required value. return null; } @@ -329,6 +378,73 @@ public static function naturalArg($txt, $separators) { return $result; } + /** + * It compares with wildcards (*) and returns true if both strings are equals
+ * The wildcards only works at the beginning or at the end of the string.
+ * Example:
+ *
+     * Text::wildCardComparison('abcdef','abc*'); // true
+     * Text::wildCardComparison('abcdef','*def'); // true
+     * Text::wildCardComparison('abcdef','*abc*'); // true
+     * Text::wildCardComparison('abcdef','*cde*'); // true
+     * Text::wildCardComparison('abcdef','*cde'); // false
+     *
+     * 
+ * + * @param string $text + * @param string|null $textWithWildcard + * + * @return bool + */ + public static function wildCardComparison($text,$textWithWildcard) { + if(($textWithWildcard===null && $textWithWildcard==='') + || $textWithWildcard==='**' + || strpos($textWithWildcard,'*')===false) { + // if the text with wildcard is null or empty or it contains two ** or it contains no * then.. + return $text==$textWithWildcard; + } + $c0=$textWithWildcard[0]; + $c1=substr($textWithWildcard, -1); + $textWithWildcardClean=str_replace('*','',$textWithWildcard); + $p0=strpos($text,$textWithWildcardClean); + if($p0===false) { + // no matches. + return false; + } + if($c0==='*' && $c1==='*') { + // $textWithWildcard='*asasasas*' + return true; + } + if($c1==='*') { + // $textWithWildcard='asasasas*' + return $p0===0; + } + // $textWithWildcard='*asasasas' + return static::endsWith($text,$textWithWildcardClean); + + } + + /** + * it returns true if $string ends with $endString
+ * Example:
+ *
+     * Text::endsWidth('hello world','world'); // true
+     * 
+ * + * @param $string + * @param $endString + * + * @return bool + */ + public static function endsWith($string, $endString) + { + $len = strlen($endString); + if ($len == 0) { + return true; + } + return (substr($string, -$len) === $endString); + } + /** * Replaces all variables defined between {{ }} by a variable inside the dictionary of values.
* Example:
@@ -336,23 +452,27 @@ public static function naturalArg($txt, $separators) { * replaceCurlyVariable('hello={{var}}',['varx'=>'world']) // hello=
* replaceCurlyVariable('hello={{var}}',['varx'=>'world'],true) // hello={{var}}
* - * @param string $string The input value. It could contains variables defined as {{namevar}} - * @param array $values The dictionary of values. - * @param bool $notFoundThenKeep [false] If true and the value is not found, then it keeps the value. - * Otherwise, it is replaced by an empty value + * @param string $string The input value. It could contains variables defined as {{namevar}} + * @param array $values The dictionary of values. + * @param bool $notFoundThenKeep [false] If true and the value is not found, then it keeps the value. + * Otherwise, it is replaced by an empty value * * @return string|string[]|null */ - public static function replaceCurlyVariable($string,$values,$notFoundThenKeep=false) { - if(strpos($string,'{{')===false) return $string; // nothing to replace. - return preg_replace_callback('/{{\s?(\w+)\s?}}/u', function ($matches) use ($values,$notFoundThenKeep) { + public static function replaceCurlyVariable($string, $values, $notFoundThenKeep = false) { + if (strpos($string, '{{') === false) { + return $string; + } // nothing to replace. + return preg_replace_callback('/{{\s?(\w+)\s?}}/u', function ($matches) use ($values, $notFoundThenKeep) { if (is_array($matches)) { - $item = substr($matches[0], 2, strlen($matches[0]) - 4); // removes {{ and }} - return isset($values[$item])? $values[$item] : ($notFoundThenKeep?$matches[0]:'') ; - } else { - $item = substr($matches, 2, strlen($matches) - 4); // removes {{ and }} - return isset($values[$item])? $values[$item] : ($notFoundThenKeep?$matches:'') ; + $item = substr($matches[0], 2, -2); // removes {{ and }} + /** @noinspection NullCoalescingOperatorCanBeUsedInspection */ + return isset($values[$item]) ? $values[$item] : ($notFoundThenKeep ? $matches[0] : ''); } + + $item = substr($matches, 2, -2); // removes {{ and }} + /** @noinspection NullCoalescingOperatorCanBeUsedInspection */ + return isset($values[$item]) ? $values[$item] : ($notFoundThenKeep ? $matches : ''); }, $string); } @@ -390,12 +510,12 @@ public static function hasParenthesis($txt, $start = '(', $end = ')') { return false; } foreach ($start as $k => $v) { - if (substr($txt, 0, 1) === $v && substr($txt, -1) === $end[$k]) { + if ($txt[0] === $v && substr($txt, -1) === $end[$k]) { return true; } } } else { - if (substr($txt, 0, 1) === $start && substr($txt, -1) === $end) { + if ($txt[0] === $start && substr($txt, -1) === $end) { return true; } } @@ -422,8 +542,8 @@ public static function camelCase($txt) { $l = strlen($txt); for ($i = 0; $i < $l; $i++) { $c = $txt[$i]; - if ($c == '_' || $c == ' ') { - if($i!=$l-1) { + if ($c === '_' || $c === ' ') { + if ($i != $l - 1) { $result .= strtoupper($txt[$i + 1]); $i++; } else { @@ -434,10 +554,9 @@ public static function camelCase($txt) { } } return $result; - } else { - // the text is simple. - return strtolower(substr($txt, 0, 1)) . substr($txt, 1); } +// the text is simple. + return strtolower($txt[0]) . substr($txt, 1); } } \ No newline at end of file diff --git a/test/TextTest.php b/test/TextTest.php index 8018f07..d207324 100644 --- a/test/TextTest.php +++ b/test/TextTest.php @@ -68,6 +68,14 @@ public function teststrPosNotSpace() { $this->assertEquals(2,Text::strPosNotSpace(" \nabc")); $this->assertEquals(1,Text::strPosNotSpace(" \nabc",0," ")); } + public function testWildCard() { + $this->assertEquals(true,Text::wildCardComparison('abcdef','abc*')); + $this->assertEquals(true,Text::wildCardComparison('abcdef','*def')); + $this->assertEquals(true,Text::wildCardComparison('abcdef','*abc*')); + $this->assertEquals(false,Text::wildCardComparison('abcdef','1abc*')); + $this->assertEquals(false,Text::wildCardComparison('abcdef','*1def')); + $this->assertEquals(false,Text::wildCardComparison('abcdef','*1abc*')); + } public function testReplaceBetween() { $this->assertEquals("Hello Wayne World",Text::replaceBetween('Hello Brave World','Hello','World',' Wayne ')); @@ -88,6 +96,13 @@ public function testReplaceBetween() public function testparseArg() { $this->assertEquals(['a'=>'1','b'=>'2'],Text::parseArg('a=1,b=2')); $this->assertEquals(['a'=>'1','b'=>'2'],Text::parseArg('a=1&b=2','&')); + $txt="a1=1,a2=2,a3='a1,bb'"; + $this->assertEquals([ + 'a1'=>'1' + ,'a2'=>'2' + ,'a3'=>"'a1" + ,"bb'"=>''],Text::parseArg($txt)); + $this->assertEquals(['a1'=>'1','a2'=>'2','a3'=>"'a1,bb'"],Text::parseArg2($txt)); } public function testReplaceCurlyVariable() { $this->assertEquals('hello=world',Text::replaceCurlyVariable('hello={{var}}',['var'=>'world']));