/
StringHelper.php
293 lines (261 loc) · 10.6 KB
/
StringHelper.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
<?php
namespace luya\helpers;
use yii\helpers\BaseStringHelper;
/**
* Helper methods when dealing with Strings.
*
* Extends the {{yii\helpers\StringHelper}} class by some usefull functions like:
*
* + {{luya\helpers\StringHelper::typeCast()}}
* + {{luya\helpers\StringHelper::isFloat()}}
* + {{luya\helpers\StringHelper::replaceFirst()}}
* + {{luya\helpers\StringHelper::contains()}}
* + {{luya\helpers\StringHelper::startsWithWildcard()}}
* + {{luya\helpers\StringHelper::typeCastNumeric()}}
*
* @author Basil Suter <basil@nadar.io>
* @since 1.0.0
*/
class StringHelper extends BaseStringHelper
{
/**
* TypeCast a string to its specific types.
*
* Arrays will passed to to the {{luya\helpers\ArrayHelper::typeCast()}} class.
*
* @param mixed $string The input string to type cast. Arrays will be passted to {{luya\helpers\ArrayHelper::typeCast()}}.
* @return mixed The new type casted value, if the input is an array the output is the typecasted array.
*/
public static function typeCast($string)
{
if (is_numeric($string)) {
return static::typeCastNumeric($string);
} elseif (is_array($string)) {
return ArrayHelper::typeCast($string);
}
return $string;
}
/**
* Checke whether a strings starts with the wildcard symbole and compares the string before the wild card symbol *
* with the string provided, if there is NO wildcard symbold it always return false.
*
*
* @param string $string The string which should be checked with $with comperator
* @param string $with The with string which must end with the wildcard symbol * e.g. `foo*` would match string `foobar`.
* @param boolean $caseSensitive Whether to compare the starts with string as case sensitive or not, defaults to true.
* @return boolean Whether the string starts with the wildcard marked string or not, if no wildcard symbol is contained.
* in the $with it always returns false.
*/
public static function startsWithWildcard($string, $with, $caseSensitive = true)
{
if (substr($with, -1) != "*") {
return false;
}
return self::startsWith($string, rtrim($with, '*'), $caseSensitive);
}
/**
* TypeCast a numeric value to float or integer.
*
* If the given value is not a numeric or float value it will be returned as it is. In order to find out whether its float
* or not use {{luya\helpers\StringHelper::isFloat()}}.
*
* @param mixed $value The given value to parse.
* @return mixed Returns the original value if not numeric or integer, float casted value.
*/
public static function typeCastNumeric($value)
{
if (!self::isFloat($value)) {
return $value;
}
if (intval($value) == $value) {
return (int) $value;
}
return (float) $value;
}
/**
* Checks whether a string is a float value.
*
* Compared to `is_float` function of php, it only ensures whether the input variable is type float.
*
* @param mixed $value The value to check whether its float or not.
* @return boolean Whether its a float value or not.
*/
public static function isFloat($value)
{
if (is_float($value)) {
return true;
}
return ($value == (string)(float) $value);
}
/**
* Replace only the first occurance found inside the string.
*
* The replace first method is *case sensitive*.
*
* ```php
* StringHelper::replaceFirst('abc', '123', 'abc abc abc'); // returns "123 abc abc"
* ```
*
* @param string $search Search string to look for.
* @param string $replace Replacement value for the first found occurrence.
* @param string $subject The string you want to look up to replace the first element.
* @return mixed Replaced string
*/
public static function replaceFirst($search, $replace, $subject)
{
return preg_replace('/'.preg_quote($search, '/').'/', $replace, $subject, 1);
}
/**
* Check whether a char or word exists in a string or not.
*
* This method is case sensitive. The need can be an array with multiple chars or words who
* are going to look up in the haystack string.
*
* If an array of needle words is provided the $strict parameter defines whether all need keys must be found
* in the string to get the `true` response or if just one of the keys are found the response is already `true`.
*
* ```php
* if (StringHelper::contains('foo', 'the foo bar Bar'')) {
* echo "yes!";
* }
* ```
*
* check if one of the given needles exists:
*
* ```php
* if (StringHelper::contains(['jungle', 'hell0], 'Welcome to the jungle!)) {
* echo "yes!";
* }
* ```
*
* @param string|array $needle The char or word to find in the $haystack. Can be an array to multi find words or char in the string.
* @param string $haystack The haystack where the $needle string should be looked up. A string or phrase with words.
* @param boolean $strict If an array of needles is provided the $strict parameter defines whether all keys must be found ($strict = true) or just one result must be found ($strict = false).
* @return boolean If an array of values is provided the response may change depending on $findAll.
*/
public static function contains($needle, $haystack, $strict = false)
{
$needles = (array) $needle;
$state = false;
foreach ($needles as $item) {
$state = (strpos($haystack, $item) !== false);
if ($strict && !$state) {
return false;
}
if (!$strict && $state) {
return true;
}
}
return $state;
}
/**
* "Minify" html content.
*
* + remove space
* + remove tabs
* + remove newlines
* + remove html comments
*
* @param string $content The content to minify.
* @param array $options Optional arguments to provide for minification:
* - comments: boolean, where html comments should be removed or not. defaults to false
* @return mixed Returns the minified content.
* @since 1.0.7
*/
public static function minify($content, array $options = [])
{
$min = preg_replace(['/[\n\r]/', '/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s', ], ['', '>', '<', '\\1'], trim($content));
$min = str_replace(['> <'], ['><'], $min);
if (ArrayHelper::getValue($options, 'comments', false)) {
$min = preg_replace('/<!--(.*)-->/Uis', '', $min);
}
return $min;
}
/**
* Cut the given word/string from the content. Its truncates to the left side and to the right side of the word.
*
* An example of how a sentenced is cut:
*
* ```php
* $cut = StringHelper::truncateMiddle('the quick fox jumped over the lazy dog', 'jumped', 12);
* echo $cut; // ..e quick fox jumped over the la..
* ```
*
* @param string $content The content to cut the words from.
* @param string $word The word which should be in the middle of the string
* @param integer $length The amount of the chars to cut on the left and right side from the word.
* @param string $affix The chars which should be used for prefix and suffix when string is cuted.
* @param boolean $caseSensitive Whether the search word in the string even when lower/upper case is not correct.
* @since 1.0.12
*/
public static function truncateMiddle($content, $word, $length, $affix = '..', $caseSensitive = false)
{
$content = strip_tags($content);
$array = self::mb_str_split($content);
$first = mb_strpos($caseSensitive ? $content : mb_strtolower($content), $caseSensitive ? $word : mb_strtolower($word));
// we could not find any match, therefore use casual truncate method.
if ($first === false) {
// as the length value in truncate middle stands for to the left and to the right, we multiple this value with 2
return self::truncate($content, ($length*2), $affix);
}
$last = $first + mb_strlen($word);
// left and right array chars from word
$left = array_slice($array, 0, $first, true);
$right = array_slice($array, $last, null, true);
$middle = array_splice($array, $first, mb_strlen($word));
// string before
$before = (count($left) > $length) ? $affix.implode("", array_slice($left, -$length)) : implode("", $left);
$after = (count($right) > $length) ? implode("", array_slice($right, 0, $length)) . $affix : implode("", $right);
return $before . implode("", $middle) . $after;
}
/**
* Highlight a word within a content.
*
* Since version 1.0.14 an array of words to highlight is possible.
*
* > This function IS NOT case sensitive!
*
*
*
* @param string $content The content to find the word.
* @param string $word The word to find within the content.
* @param string $markup The markup used wrap the word to highlight.
* @since 1.0.12
*/
public static function highlightWord($content, $word, $markup = '<b>%s</b>')
{
$word = (array) $word;
$content = strip_tags($content);
$latest = null;
foreach ($word as $needle) {
preg_match_all("/".preg_quote($needle, '/')."+/i", $content, $matches);
if (is_array($matches[0]) && count($matches[0]) >= 1) {
foreach ($matches[0] as $match) {
// ensure if a word is found twice we don't replace again.
if ($latest === $match) {
continue;
}
$content = str_replace($match, sprintf($markup, $match), $content);
$latest = $match;
}
}
}
return $content;
}
/**
* Multibyte-safe str_split funciton.
*
* @param string $string The string to split into an array
* @param integer $length The length of the chars to cut.
* @since 1.0.12
*/
public static function mb_str_split($string, $length = 1)
{
$array = [];
$stringLength = mb_strlen($string, 'UTF-8');
for ($i = 0; $i < $stringLength; $i += $length) {
$array[] = mb_substr($string, $i, $length, 'UTF-8');
}
return $array;
}
}