|
14 | 14 | use Toolkit\Stdlib\Str\Traits\StringCheckHelperTrait;
|
15 | 15 | use Toolkit\Stdlib\Str\Traits\StringLengthHelperTrait;
|
16 | 16 | use Toolkit\Stdlib\Str\Traits\StringSplitHelperTrait;
|
| 17 | +use Toolkit\Stdlib\Str\Traits\StringTruncateHelperTrait; |
17 | 18 | use Toolkit\Stdlib\Util\UUID;
|
18 | 19 | use function array_merge;
|
19 | 20 | use function array_slice;
|
@@ -62,6 +63,7 @@ abstract class StringHelper
|
62 | 63 | use StringCheckHelperTrait;
|
63 | 64 | use StringLengthHelperTrait;
|
64 | 65 | use StringSplitHelperTrait;
|
| 66 | + use StringTruncateHelperTrait; |
65 | 67 |
|
66 | 68 | /**
|
67 | 69 | * @param string $str
|
@@ -192,302 +194,11 @@ public static function genUid(int $length = 7): string
|
192 | 194 | *
|
193 | 195 | * @return UUID
|
194 | 196 | */
|
195 |
| - public static function genUUID($version = 1, $node = null, $ns = null) |
| 197 | + public static function genUUID(int $version = 1, $node = null, $ns = null) |
196 | 198 | {
|
197 | 199 | return UUID::generate($version, $node, $ns);
|
198 | 200 | }
|
199 | 201 |
|
200 |
| - //////////////////////////////////////////////////////////////////////// |
201 |
| - /// Truncate |
202 |
| - //////////////////////////////////////////////////////////////////////// |
203 |
| - |
204 |
| - /** |
205 |
| - * @param string $str |
206 |
| - * @param int $start |
207 |
| - * @param int|null $length |
208 |
| - * @param string $encoding |
209 |
| - * |
210 |
| - * @return bool|string |
211 |
| - */ |
212 |
| - public static function substr(string $str, int $start, int $length = null, string $encoding = 'utf-8') |
213 |
| - { |
214 |
| - if (function_exists('mb_substr')) { |
215 |
| - return mb_substr($str, $start, ($length === null ? self::strlen($str) : (int)$length), $encoding); |
216 |
| - } |
217 |
| - |
218 |
| - return substr($str, $start, ($length === null ? self::strlen($str) : (int)$length)); |
219 |
| - } |
220 |
| - |
221 |
| - /** |
222 |
| - * @from web |
223 |
| - * utf-8编码下截取中文字符串,参数可以参照substr函数 |
224 |
| - * |
225 |
| - * @param string $str 要进行截取的字符串 |
226 |
| - * @param int $start 要进行截取的开始位置,负数为反向截取 |
227 |
| - * @param int $end 要进行截取的长度 |
228 |
| - * |
229 |
| - * @return string |
230 |
| - */ |
231 |
| - public static function utf8SubStr(string $str, int $start = 0, int $end = null): string |
232 |
| - { |
233 |
| - if (empty($str)) { |
234 |
| - return ''; |
235 |
| - } |
236 |
| - |
237 |
| - if (function_exists('mb_substr')) { |
238 |
| - if (func_num_args() >= 3) { |
239 |
| - $end = func_get_arg(2); |
240 |
| - |
241 |
| - return mb_substr($str, $start, $end, 'utf-8'); |
242 |
| - } |
243 |
| - |
244 |
| - mb_internal_encoding('UTF-8'); |
245 |
| - |
246 |
| - return mb_substr($str, $start); |
247 |
| - } |
248 |
| - |
249 |
| - $null = ''; |
250 |
| - preg_match_all('/./u', $str, $ar); |
251 |
| - |
252 |
| - if (func_num_args() >= 3) { |
253 |
| - $end = func_get_arg(2); |
254 |
| - return implode($null, array_slice($ar[0], $start, $end)); |
255 |
| - } |
256 |
| - |
257 |
| - return implode($null, array_slice($ar[0], $start)); |
258 |
| - } |
259 |
| - |
260 |
| - /** |
261 |
| - * @from web |
262 |
| - * 中文截取,支持gb2312,gbk,utf-8,big5 * |
263 |
| - * |
264 |
| - * @param string $str 要截取的字串 |
265 |
| - * @param int $start 截取起始位置 |
266 |
| - * @param int $length 截取长度 |
267 |
| - * @param string $charset utf-8|gb2312|gbk|big5 编码 |
268 |
| - * @param bool $suffix 是否加尾缀 |
269 |
| - * |
270 |
| - * @return string |
271 |
| - */ |
272 |
| - public static function zhSubStr($str, $start = 0, $length = 0, $charset = 'utf-8', $suffix = true): string |
273 |
| - { |
274 |
| - if (function_exists('mb_substr')) { |
275 |
| - if (mb_strlen($str, $charset) <= $length) { |
276 |
| - return $str; |
277 |
| - } |
278 |
| - |
279 |
| - $slice = mb_substr($str, $start, $length, $charset); |
280 |
| - } else { |
281 |
| - $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/"; |
282 |
| - $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/"; |
283 |
| - $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/"; |
284 |
| - $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/"; |
285 |
| - |
286 |
| - preg_match_all($re[$charset], $str, $match); |
287 |
| - if (count($match[0]) <= $length) { |
288 |
| - return $str; |
289 |
| - } |
290 |
| - |
291 |
| - $slice = implode('', array_slice($match[0], $start, $length)); |
292 |
| - } |
293 |
| - |
294 |
| - return (bool)$suffix ? $slice . '…' : $slice; |
295 |
| - } |
296 |
| - |
297 |
| - /** |
298 |
| - * Truncate strings |
299 |
| - * |
300 |
| - * @param string $str |
301 |
| - * @param int $maxLength Max length |
302 |
| - * @param string $suffix Suffix optional |
303 |
| - * |
304 |
| - * @return string $str truncated |
305 |
| - */ |
306 |
| - /* CAUTION : Use it only on module hookEvents. |
307 |
| - ** For other purposes use the smarty function instead */ |
308 |
| - public static function truncate(string $str, $maxLength, $suffix = '...'): string |
309 |
| - { |
310 |
| - if (self::strlen($str) <= $maxLength) { |
311 |
| - return $str; |
312 |
| - } |
313 |
| - |
314 |
| - $str = utf8_decode($str); |
315 |
| - |
316 |
| - return utf8_encode(substr($str, 0, $maxLength - self::strlen($suffix)) . $suffix); |
317 |
| - } |
318 |
| - |
319 |
| - /** |
320 |
| - * 字符截断输出 |
321 |
| - * |
322 |
| - * @param string $str |
323 |
| - * @param int $start |
324 |
| - * @param null|int $length |
325 |
| - * |
326 |
| - * @return string |
327 |
| - */ |
328 |
| - public static function truncate2(string $str, int $start, int $length = null): string |
329 |
| - { |
330 |
| - if (!$length) { |
331 |
| - $length = $start; |
332 |
| - $start = 0; |
333 |
| - } |
334 |
| - |
335 |
| - if (strlen($str) <= $length) { |
336 |
| - return $str; |
337 |
| - } |
338 |
| - |
339 |
| - if (function_exists('mb_substr')) { |
340 |
| - $str = mb_substr(strip_tags($str), $start, $length, 'utf-8'); |
341 |
| - } else { |
342 |
| - $str = substr($str, $start, $length) . '...'; |
343 |
| - } |
344 |
| - |
345 |
| - return $str; |
346 |
| - } |
347 |
| - |
348 |
| - /** |
349 |
| - * Copied from CakePHP String utility file |
350 |
| - * |
351 |
| - * @param string $text |
352 |
| - * @param int $length |
353 |
| - * @param array $options |
354 |
| - * |
355 |
| - * @return bool|string |
356 |
| - */ |
357 |
| - public static function truncate3(string $text, int $length = 120, array $options = []) |
358 |
| - { |
359 |
| - $default = [ |
360 |
| - 'ellipsis' => '...', |
361 |
| - 'exact' => true, |
362 |
| - 'html' => true |
363 |
| - ]; |
364 |
| - |
365 |
| - $options = array_merge($default, $options); |
366 |
| - $ellipsis = $options['ellipsis']; |
367 |
| - $exact = $options['exact']; |
368 |
| - $html = $options['html']; |
369 |
| - |
370 |
| - /** |
371 |
| - * @var string $ellipsis |
372 |
| - * @var bool $exact |
373 |
| - * @var bool $html |
374 |
| - */ |
375 |
| - if ($html) { |
376 |
| - if (self::strlen(\preg_replace('/<.*?>/', '', $text)) <= $length) { |
377 |
| - return $text; |
378 |
| - } |
379 |
| - |
380 |
| - $total_length = self::strlen(strip_tags($ellipsis)); |
381 |
| - $open_tags = $tags = []; |
382 |
| - $truncate = ''; |
383 |
| - preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER); |
384 |
| - |
385 |
| - foreach ($tags as $tag) { |
386 |
| - if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/', $tag[2])) { |
387 |
| - if (preg_match('/<[\w]+[^>]*>/', $tag[0])) { |
388 |
| - array_unshift($open_tags, $tag[2]); |
389 |
| - } elseif (preg_match('/<\/([\w]+)[^>]*>/', $tag[0], $close_tag)) { |
390 |
| - $pos = array_search($close_tag[1], $open_tags, true); |
391 |
| - if ($pos !== false) { |
392 |
| - array_splice($open_tags, $pos, 1); |
393 |
| - } |
394 |
| - } |
395 |
| - } |
396 |
| - $truncate .= $tag[1]; |
397 |
| - $content_length = self::strlen(preg_replace( |
398 |
| - '/&[0-9a-z]{2,8};|&#[\d]{1,7};|&#x[0-9a-f]{1,6};/i', |
399 |
| - ' ', |
400 |
| - $tag[3] |
401 |
| - )); |
402 |
| - |
403 |
| - if ($content_length + $total_length > $length) { |
404 |
| - $left = $length - $total_length; |
405 |
| - $entities_length = 0; |
406 |
| - |
407 |
| - if (preg_match_all( |
408 |
| - '/&[0-9a-z]{2,8};|&#[\d]{1,7};|&#x[0-9a-f]{1,6};/i', |
409 |
| - $tag[3], |
410 |
| - $entities, |
411 |
| - PREG_OFFSET_CAPTURE |
412 |
| - ) |
413 |
| - ) { |
414 |
| - foreach ((array)$entities[0] as $entity) { |
415 |
| - if ($entity[1] + 1 - $entities_length <= $left) { |
416 |
| - $left--; |
417 |
| - $entities_length += self::strlen($entity[0]); |
418 |
| - } else { |
419 |
| - break; |
420 |
| - } |
421 |
| - } |
422 |
| - } |
423 |
| - |
424 |
| - $truncate .= self::substr($tag[3], 0, $left + $entities_length); |
425 |
| - break; |
426 |
| - } |
427 |
| - |
428 |
| - $truncate .= $tag[3]; |
429 |
| - $total_length += $content_length; |
430 |
| - |
431 |
| - if ($total_length >= $length) { |
432 |
| - break; |
433 |
| - } |
434 |
| - } |
435 |
| - } else { |
436 |
| - if (self::strlen($text) <= $length) { |
437 |
| - return $text; |
438 |
| - } |
439 |
| - |
440 |
| - $truncate = self::substr($text, 0, $length - self::strlen($ellipsis)); |
441 |
| - } |
442 |
| - |
443 |
| - $open_tags = null; |
444 |
| - |
445 |
| - if (!$exact) { |
446 |
| - $spacepos = self::strrpos($truncate, ' '); |
447 |
| - if ($html) { |
448 |
| - $truncate_check = self::substr($truncate, 0, $spacepos); |
449 |
| - $last_open_tag = self::strrpos($truncate_check, '<'); |
450 |
| - $last_close_tag = self::strrpos($truncate_check, '>'); |
451 |
| - |
452 |
| - if ($last_open_tag > $last_close_tag) { |
453 |
| - preg_match_all('/<[\w]+[^>]*>/', $truncate, $last_tag_matches); |
454 |
| - $last_tag = array_pop($last_tag_matches[0]); |
455 |
| - $spacepos = self::strrpos($truncate, $last_tag) + self::strlen($last_tag); |
456 |
| - } |
457 |
| - |
458 |
| - $bits = self::substr($truncate, $spacepos); |
459 |
| - preg_match_all('/<\/([a-z]+)>/', $bits, $dropped_tags, PREG_SET_ORDER); |
460 |
| - |
461 |
| - /** @var array $dropped_tags */ |
462 |
| - if (!empty($dropped_tags)) { |
463 |
| - if (!empty($open_tags)) { |
464 |
| - foreach ($dropped_tags as $closing_tag) { |
465 |
| - if (!in_array($closing_tag[1], $open_tags, true)) { |
466 |
| - array_unshift($open_tags, $closing_tag[1]); |
467 |
| - } |
468 |
| - } |
469 |
| - } else { |
470 |
| - foreach ($dropped_tags as $closing_tag) { |
471 |
| - $open_tags[] = $closing_tag[1]; |
472 |
| - } |
473 |
| - } |
474 |
| - } |
475 |
| - } |
476 |
| - |
477 |
| - $truncate = self::substr($truncate, 0, $spacepos); |
478 |
| - } |
479 |
| - |
480 |
| - $truncate .= $ellipsis; |
481 |
| - |
482 |
| - if ($html && $open_tags) { |
483 |
| - foreach ((array)$open_tags as $tag) { |
484 |
| - $truncate .= '</' . $tag . '>'; |
485 |
| - } |
486 |
| - } |
487 |
| - |
488 |
| - return $truncate; |
489 |
| - } |
490 |
| - |
491 | 202 | ////////////////////////////////////////////////////////////////////////
|
492 | 203 | /// Format
|
493 | 204 | ////////////////////////////////////////////////////////////////////////
|
@@ -597,4 +308,26 @@ public static function deleteStripSpace($fileName, $type = 0)
|
597 | 308 |
|
598 | 309 | return preg_replace($preg_arr, '', $data);
|
599 | 310 | }
|
| 311 | + |
| 312 | + //////////////////////////////////////////////////////////// |
| 313 | + /// Other |
| 314 | + //////////////////////////////////////////////////////////// |
| 315 | + |
| 316 | + /** |
| 317 | + * @param string $arg |
| 318 | + * |
| 319 | + * @return string |
| 320 | + */ |
| 321 | + public static function shellQuote(string $arg): string |
| 322 | + { |
| 323 | + $quote = ''; |
| 324 | + |
| 325 | + if (strpos($arg, '"') !== false) { |
| 326 | + $quote = "'"; |
| 327 | + } elseif ($arg === '' || strpos($arg, "'") !== false || strpos($arg, ' ') !== false) { |
| 328 | + $quote = '"'; |
| 329 | + } |
| 330 | + |
| 331 | + return $quote ? $arg : "$quote{$arg}$quote"; |
| 332 | + } |
600 | 333 | }
|
0 commit comments