1 | <?php |
||||
2 | /** |
||||
3 | * This file is part of the O2System Framework package. |
||||
4 | * |
||||
5 | * For the full copyright and license information, please view the LICENSE |
||||
6 | * file that was distributed with this source code. |
||||
7 | * |
||||
8 | * @author Steeve Andrian Salim |
||||
9 | * @copyright Copyright (c) Steeve Andrian Salim |
||||
10 | */ |
||||
11 | // ------------------------------------------------------------------------ |
||||
12 | |||||
13 | if ( ! function_exists('text_split')) { |
||||
14 | /** |
||||
15 | * text_split |
||||
16 | * |
||||
17 | * Split text into array without losing any words. |
||||
18 | * |
||||
19 | * @params string $text |
||||
20 | * |
||||
21 | * @param string $text Text Source |
||||
22 | * @param string $splitter Split Text Marker |
||||
23 | * @param int $limit Split after num of limit characters |
||||
24 | * |
||||
25 | * @return string |
||||
26 | */ |
||||
27 | function text_split($text, $splitter = '<---text-split--->', $limit = 100) |
||||
28 | { |
||||
29 | $wrap_text = wordwrap($text, $limit, $splitter); |
||||
30 | $wrap_text = preg_split('[' . $splitter . ']', $wrap_text, -1, PREG_SPLIT_NO_EMPTY); |
||||
31 | |||||
32 | return implode('', $wrap_text); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
33 | } |
||||
34 | } |
||||
35 | // ------------------------------------------------------------------------ |
||||
36 | |||||
37 | if ( ! function_exists('text_columns')) { |
||||
38 | /** |
||||
39 | * text_columns |
||||
40 | * |
||||
41 | * Split a block of strings or text evenly across a number of columns. |
||||
42 | * |
||||
43 | * @param string $text Text Source |
||||
44 | * @param int $cols Number of columns |
||||
45 | * |
||||
46 | * @return array |
||||
47 | */ |
||||
48 | function text_columns($text, $cols) |
||||
49 | { |
||||
50 | $col_length = ceil(strlen($text) / $cols) + 3; |
||||
51 | $return = explode("\n", wordwrap(strrev($text), $col_length)); |
||||
0 ignored issues
–
show
$col_length of type double is incompatible with the type integer expected by parameter $width of wordwrap() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
52 | |||||
53 | if (count($return) > $cols) { |
||||
54 | $return[ $cols - 1 ] .= " " . $return[ $cols ]; |
||||
55 | unset($return[ $cols ]); |
||||
56 | } |
||||
57 | |||||
58 | $return = array_map("strrev", $return); |
||||
59 | |||||
60 | return array_reverse($return); |
||||
61 | } |
||||
62 | } |
||||
63 | // ------------------------------------------------------------------------ |
||||
64 | |||||
65 | if ( ! function_exists('text_wrap')) { |
||||
66 | /** |
||||
67 | * text_wrap |
||||
68 | * |
||||
69 | * Wrap the given string to a certain chars length and lines. |
||||
70 | * |
||||
71 | * @param string $text Text Source |
||||
72 | * @param int $chars 10 means wrap at 40 chars |
||||
73 | * @param int|bool $lines True or false $lines = false or $lines = 3, means truncate after 3 lines |
||||
74 | * |
||||
75 | * @return string |
||||
76 | */ |
||||
77 | function text_wrap($text, $chars = 10, $lines = false) |
||||
78 | { |
||||
79 | # the simple case - return wrapped words |
||||
80 | if ( ! $lines) { |
||||
81 | return wordwrap($text, $chars, "\n"); |
||||
82 | } |
||||
83 | # truncate to maximum possible number of characters |
||||
84 | $return = substr($text, 0, $chars * $lines); |
||||
85 | # apply wrapping and return first $lines lines |
||||
86 | $return = wordwrap($return, $chars, "\n"); |
||||
87 | preg_match("/(.+\n?){0,$lines}/", $return, $regs); |
||||
88 | |||||
89 | return $regs[ 0 ]; |
||||
90 | } |
||||
91 | } |
||||
92 | // ------------------------------------------------------------------------ |
||||
93 | |||||
94 | if ( ! function_exists('text_trim')) { |
||||
95 | /** |
||||
96 | * text_trim |
||||
97 | * |
||||
98 | * Cuts the given string to a certain length without breaking a word. |
||||
99 | * |
||||
100 | * @param string $text Text source |
||||
101 | * @param int $limit number of maximum characters leave remaining |
||||
102 | * @param string $break = "." break on dot ending or keep maximum set on ' ' |
||||
103 | * @param string $ending = '...' to display '...' on the end of the trimmed string |
||||
104 | * |
||||
105 | * @return string |
||||
106 | */ |
||||
107 | function text_trim($text, $limit, $break = '.', $ending = '.') |
||||
108 | { |
||||
109 | // return with no change if string is shorter than $limit |
||||
110 | if (strlen($text) <= $limit) { |
||||
111 | return $text; |
||||
112 | } |
||||
113 | // is $break present between $limit and the end of the string? |
||||
114 | if (false !== ($breakpoint = strpos($text, $break, $limit))) { |
||||
115 | if ($breakpoint < strlen($text) - 1) { |
||||
116 | $text = substr($text, 0, $breakpoint) . $ending; |
||||
117 | } |
||||
118 | } |
||||
119 | |||||
120 | return $text; |
||||
121 | } |
||||
122 | } |
||||
123 | |||||
124 | // ------------------------------------------------------------------------ |
||||
125 | |||||
126 | if ( ! function_exists('text_word_limiter')) { |
||||
127 | /** |
||||
128 | * text_word_limiter |
||||
129 | * |
||||
130 | * Limits a string to X number of words. |
||||
131 | * |
||||
132 | * @param string |
||||
133 | * @param int |
||||
134 | * @param string the end character. Usually an ellipsis |
||||
0 ignored issues
–
show
The type
the was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
135 | * |
||||
136 | * @return string |
||||
137 | */ |
||||
138 | function text_word_limiter($str, $limit = 100, $end_char = '…') |
||||
139 | { |
||||
140 | if (trim($str) === '') { |
||||
141 | return $str; |
||||
142 | } |
||||
143 | |||||
144 | preg_match('/^\s*+(?:\S++\s*+){1,' . (int)$limit . '}/', $str, $matches); |
||||
145 | |||||
146 | if (strlen($str) === strlen($matches[ 0 ])) { |
||||
147 | $end_char = ''; |
||||
148 | } |
||||
149 | |||||
150 | return rtrim($matches[ 0 ]) . $end_char; |
||||
151 | } |
||||
152 | } |
||||
153 | |||||
154 | // ------------------------------------------------------------------------ |
||||
155 | |||||
156 | if ( ! function_exists('text_character_limiter')) { |
||||
157 | /** |
||||
158 | * text_character_limiter |
||||
159 | * |
||||
160 | * Limits the string based on the character count. Preserves complete words |
||||
161 | * so the character count may not be exactly as specified. |
||||
162 | * |
||||
163 | * @param string |
||||
164 | * @param int |
||||
165 | * @param string the end character. Usually an ellipsis |
||||
166 | * |
||||
167 | * @return string |
||||
168 | */ |
||||
169 | function text_character_limiter($string, $n = 500, $end_char = '…') |
||||
170 | { |
||||
171 | if (mb_strlen($string) < $n) { |
||||
172 | return $string; |
||||
173 | } |
||||
174 | |||||
175 | // a bit complicated, but faster than preg_replace with \s+ |
||||
176 | $string = preg_replace('/ {2,}/', ' ', str_replace(["\r", "\n", "\t", "\x0B", "\x0C"], ' ', $string)); |
||||
177 | |||||
178 | if (mb_strlen($string) <= $n) { |
||||
179 | return $string; |
||||
180 | } |
||||
181 | |||||
182 | $out = ''; |
||||
183 | foreach (explode(' ', trim($string)) as $val) { |
||||
184 | $out .= $val . ' '; |
||||
185 | |||||
186 | if (mb_strlen($out) >= $n) { |
||||
187 | $out = trim($out); |
||||
188 | |||||
189 | return (mb_strlen($out) === mb_strlen($string)) ? $out : $out . $end_char; |
||||
190 | } |
||||
191 | } |
||||
192 | } |
||||
193 | } |
||||
194 | |||||
195 | // ------------------------------------------------------------------------ |
||||
196 | |||||
197 | if ( ! function_exists('text_censored')) { |
||||
198 | /** |
||||
199 | * text_censored |
||||
200 | * |
||||
201 | * Supply a string and an array of disallowed words and any |
||||
202 | * matched words will be converted to #### or to the replacement |
||||
203 | * word you've submitted. |
||||
204 | * |
||||
205 | * @param string the text string |
||||
206 | * @param string the array of censoered words |
||||
207 | * @param string the optional replacement value |
||||
208 | * |
||||
209 | * @return string |
||||
210 | */ |
||||
211 | function text_censored($string, $censored, $replacement = '') |
||||
212 | { |
||||
213 | if ( ! is_array($censored)) { |
||||
214 | return $string; |
||||
215 | } |
||||
216 | |||||
217 | $string = ' ' . $string . ' '; |
||||
218 | |||||
219 | // \w, \b and a few others do not match on a unicode character |
||||
220 | // set for performance reasons. As a result words like �ber |
||||
221 | // will not match on a word boundary. Instead, we'll assume that |
||||
222 | // a bad word will be bookeneded by any of these characters. |
||||
223 | $delim = '[-_\'\"`(){}<>\[\]|!?@#%&,.:;^~*+=\/ 0-9\n\r\t]'; |
||||
224 | |||||
225 | foreach ($censored as $badword) { |
||||
226 | if ($replacement !== '') { |
||||
227 | $string = preg_replace( |
||||
228 | "/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", |
||||
229 | "\\1{$replacement}\\3", |
||||
230 | $string |
||||
231 | ); |
||||
232 | } else { |
||||
233 | $string = preg_replace( |
||||
234 | "/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/ie", |
||||
235 | "'\\1'.str_repeat('#', strlen('\\2')).'\\3'", |
||||
236 | $string |
||||
237 | ); |
||||
238 | } |
||||
239 | } |
||||
240 | |||||
241 | return trim($string); |
||||
242 | } |
||||
243 | } |
||||
244 | |||||
245 | // ------------------------------------------------------------------------ |
||||
246 | |||||
247 | if ( ! function_exists('text_highlight_phrase')) { |
||||
248 | /** |
||||
249 | * text_highlight_phrase |
||||
250 | * |
||||
251 | * Highlights a phrase within a text string. |
||||
252 | * |
||||
253 | * @param string $string the text string |
||||
254 | * @param string $phrase the phrase you'd like to highlight |
||||
255 | * @param string $tag_open the openging tag to precede the phrase with |
||||
256 | * @param string $tag_close the closing tag to end the phrase with |
||||
257 | * |
||||
258 | * @return string |
||||
259 | */ |
||||
260 | function text_highlight_phrase($string, $phrase, $tag_open = '<mark>', $tag_close = '</mark>') |
||||
261 | { |
||||
262 | return ($string !== '' && $phrase !== '') |
||||
263 | ? preg_replace( |
||||
264 | '/(' . preg_quote($phrase, '/') . ')/i' . ('UTF8_ENABLED' ? 'u' : ''), |
||||
265 | $tag_open . '\\1' . $tag_close, |
||||
266 | $string |
||||
267 | ) |
||||
268 | : $string; |
||||
269 | } |
||||
270 | } |
||||
271 | |||||
272 | // ------------------------------------------------------------------------ |
||||
273 | |||||
274 | if ( ! function_exists('text_word_wrap')) { |
||||
275 | /** |
||||
276 | * text_word_wrap |
||||
277 | * |
||||
278 | * Wraps text at the specified character. Maintains the integrity of words. |
||||
279 | * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor |
||||
280 | * will URLs. |
||||
281 | * |
||||
282 | * @param string $string the text string |
||||
283 | * @param int $limit = 76 the number of characters to wrap at |
||||
284 | * |
||||
285 | * @return string |
||||
286 | */ |
||||
287 | function text_word_wrap($string, $limit = 76) |
||||
288 | { |
||||
289 | // Set the character limit |
||||
290 | is_numeric($limit) OR $limit = 76; |
||||
291 | |||||
292 | // Reduce multiple spaces |
||||
293 | $string = preg_replace('| +|', ' ', $string); |
||||
294 | |||||
295 | // Standardize newlines |
||||
296 | if (strpos($string, "\r") !== false) { |
||||
297 | $string = str_replace(["\r\n", "\r"], "\n", $string); |
||||
298 | } |
||||
299 | |||||
300 | // If the current word is surrounded by {unwrap} tags we'll |
||||
301 | // strip the entire chunk and replace it with a marker. |
||||
302 | $unwrap = []; |
||||
303 | if (preg_match_all('|\{unwrap\}(.+?)\{/unwrap\}|s', $string, $matches)) { |
||||
304 | for ($i = 0, $c = count($matches[ 0 ]); $i < $c; $i++) { |
||||
305 | $unwrap[] = $matches[ 1 ][ $i ]; |
||||
306 | $string = str_replace($matches[ 0 ][ $i ], '{{unwrapped' . $i . '}}', $string); |
||||
307 | } |
||||
308 | } |
||||
309 | |||||
310 | // Use PHP's native function to do the initial wordwrap. |
||||
311 | // We set the cut flag to FALSE so that any individual words that are |
||||
312 | // too long get left alone. In the next step we'll deal with them. |
||||
313 | $string = wordwrap($string, $limit, "\n", false); |
||||
314 | |||||
315 | // Split the string into individual lines of text and cycle through them |
||||
316 | $output = ''; |
||||
317 | foreach (explode("\n", $string) as $line) { |
||||
318 | // Is the line within the allowed character count? |
||||
319 | // If so we'll join it to the output and continue |
||||
320 | if (mb_strlen($line) <= $limit) { |
||||
321 | $output .= $line . "\n"; |
||||
322 | continue; |
||||
323 | } |
||||
324 | |||||
325 | $temp = ''; |
||||
326 | while (mb_strlen($line) > $limit) { |
||||
327 | // If the over-length word is a URL we won't wrap it |
||||
328 | if (preg_match('!\[url.+\]|://|www\.!', $line)) { |
||||
329 | break; |
||||
330 | } |
||||
331 | |||||
332 | // Trim the word down |
||||
333 | $temp .= mb_substr($line, 0, $limit - 1); |
||||
334 | $line = mb_substr($line, $limit - 1); |
||||
335 | } |
||||
336 | |||||
337 | // If $temp contains data it means we had to split up an over-length |
||||
338 | // word into smaller chunks so we'll add it back to our current line |
||||
339 | if ($temp !== '') { |
||||
340 | $output .= $temp . "\n" . $line . "\n"; |
||||
341 | } else { |
||||
342 | $output .= $line . "\n"; |
||||
343 | } |
||||
344 | } |
||||
345 | |||||
346 | // Put our markers back |
||||
347 | if (count($unwrap) > 0) { |
||||
348 | foreach ($unwrap as $key => $val) { |
||||
349 | $output = str_replace('{{unwrapped' . $key . '}}', $val, $output); |
||||
350 | } |
||||
351 | } |
||||
352 | |||||
353 | return $output; |
||||
354 | } |
||||
355 | } |
||||
356 | |||||
357 | // ------------------------------------------------------------------------ |
||||
358 | |||||
359 | if ( ! function_exists('text_ellipsis')) { |
||||
360 | /** |
||||
361 | * text_ellipsis |
||||
362 | * |
||||
363 | * This function will strip tags from a string, split it at its max_length and ellipsis |
||||
364 | * |
||||
365 | * @param string string to ellipsize |
||||
366 | * @param int max length of string |
||||
0 ignored issues
–
show
The type
max was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
367 | * @param mixed int (1|0) or float, .5, .2, etc for position to split |
||||
368 | * @param string ellipsis ; Default '...' |
||||
0 ignored issues
–
show
The type
ellipsis was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
369 | * |
||||
370 | * @return string ellipsis string |
||||
371 | */ |
||||
372 | function text_ellipsis($string, $max_length, $position = 1, $ellipsis = '…') |
||||
373 | { |
||||
374 | // Strip tags |
||||
375 | $string = trim(strip_tags($string)); |
||||
376 | |||||
377 | // Is the string long enough to ellipsis? |
||||
378 | if (mb_strlen($string) <= $max_length) { |
||||
379 | return $string; |
||||
380 | } |
||||
381 | |||||
382 | $beg = mb_substr($string, 0, floor($max_length * $position)); |
||||
0 ignored issues
–
show
floor($max_length * $position) of type double is incompatible with the type integer expected by parameter $length of mb_substr() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
383 | $position = ($position > 1) ? 1 : $position; |
||||
384 | |||||
385 | if ($position === 1) { |
||||
386 | $end = mb_substr($string, 0, -($max_length - mb_strlen($beg))); |
||||
387 | } else { |
||||
388 | $end = mb_substr($string, -($max_length - mb_strlen($beg))); |
||||
389 | } |
||||
390 | |||||
391 | return $beg . $ellipsis . $end; |
||||
392 | } |
||||
393 | } |
||||
394 | |||||
395 | // ------------------------------------------------------------------------ |
||||
396 | |||||
397 | if ( ! function_exists('text_excerpt')) { |
||||
398 | /** |
||||
399 | * text_excerpt |
||||
400 | * |
||||
401 | * Allows to extract a piece of text surrounding a word or phrase. |
||||
402 | * |
||||
403 | * @param string $string String to search the phrase |
||||
404 | * @param string $phrase Phrase that will be searched for. |
||||
405 | * @param int $radius The amount of characters returned arround the phrase. |
||||
406 | * @param string $ellipsis Ending that will be appended |
||||
407 | * |
||||
408 | * @return string |
||||
409 | * |
||||
410 | * If no $phrase is passed, will generate an excerpt of $radius characters |
||||
411 | * from the begining of $text. |
||||
412 | */ |
||||
413 | function text_excerpt($string, $phrase = null, $radius = 100, $ellipsis = '...') |
||||
414 | { |
||||
415 | if (isset($phrase)) { |
||||
416 | $phrase_pos = strpos(strtolower($string), strtolower($phrase)); |
||||
417 | $phrase_len = strlen($phrase); |
||||
418 | } elseif ( ! isset($phrase)) { |
||||
419 | $phrase_pos = $radius / 2; |
||||
420 | $phrase_len = 1; |
||||
421 | } |
||||
422 | $pre = explode(' ', substr($string, 0, $phrase_pos)); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
423 | $pos = explode(' ', substr($string, $phrase_pos + $phrase_len)); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
424 | $prev = ' '; |
||||
425 | $post = ' '; |
||||
426 | $count = 0; |
||||
427 | foreach (array_reverse($pre) as $pr => $e) { |
||||
428 | if ((strlen($e) + $count + 1) < $radius) { |
||||
429 | $prev = ' ' . $e . $prev; |
||||
430 | } |
||||
431 | $count = ++$count + strlen($e); |
||||
432 | } |
||||
433 | $count = 0; |
||||
434 | foreach ($pos as $po => $s) { |
||||
435 | if ((strlen($s) + $count + 1) < $radius) { |
||||
436 | $post .= $s . ' '; |
||||
437 | } |
||||
438 | $count = ++$count + strlen($s); |
||||
439 | } |
||||
440 | $ellPre = $phrase ? $ellipsis : ''; |
||||
441 | |||||
442 | return $ellPre . $prev . $phrase . $post . $ellipsis; |
||||
443 | } |
||||
444 | } |