Completed
Push — master ( c29848...6d2813 )
by Gabriel
02:24
created

Str::isJson()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
cc 3
nc 3
nop 3
crap 3
1
<?php
2
3
namespace Nip\Utility;
4
5
/**
6
 * Class Str
7
 * @package Nip\Utility
8
 */
9
class Str
10
{
11
12
    /**
13
     * The cache of snake-cased words.
14
     *
15
     * @var array
16
     */
17
    protected static $snakeCache = [];
18
19
    /**
20
     * The cache of camel-cased words.
21
     *
22
     * @var array
23
     */
24
    protected static $camelCache = [];
25
26
    /**
27
     * The cache of studly-cased words.
28
     *
29
     * @var array
30
     */
31
    protected static $studlyCache = [];
32
33
    /**
34
     * Return the remainder of a string after the first occurrence of a given value.
35
     *
36
     * @param string $subject
37
     * @param string $search
38
     * @return string
39
     */
40
    public static function after($subject, $search)
41
    {
42
        return $search === '' ? $subject : array_reverse(explode($search, $subject, 2))[0];
43
    }
44
45
    /**
46
     * Return the remainder of a string after the last occurrence of a given value.
47
     *
48
     * @param string $subject
49
     * @param string $search
50
     * @return string
51
     */
52
    public static function afterLast($subject, $search)
53
    {
54
        if ($search === '') {
55
            return $subject;
56
        }
57
58
        $position = strrpos($subject, (string)$search);
59
60
        if ($position === false) {
61
            return $subject;
62
        }
63
64
        return substr($subject, $position + strlen($search));
65
    }
66
67
68
    /**
69
     * Get the portion of a string before the first occurrence of a given value.
70
     *
71
     * @param string $subject
72
     * @param string $search
73
     * @return string
74
     */
75
    public static function before($subject, $search)
76
    {
77
        return $search === '' ? $subject : explode($search, $subject)[0];
78
    }
79
80
    /**
81
     * Get the portion of a string before the last occurrence of a given value.
82
     *
83
     * @param string $subject
84
     * @param string $search
85
     * @return string
86
     */
87
    public static function beforeLast($subject, $search)
88
    {
89
        if ($search === '') {
90
            return $subject;
91
        }
92
93
        $pos = mb_strrpos($subject, $search);
94
95
        if ($pos === false) {
96
            return $subject;
97
        }
98
99
        return static::substr($subject, 0, $pos);
100
    }
101
102
    /**
103
     * Convert a value to camel case.
104
     *
105
     * @param string $value
106
     * @return string
107
     */
108
    public static function camel($value)
109
    {
110
        if (isset(static::$camelCache[$value])) {
111
            return static::$camelCache[$value];
112
        }
113
        return static::$camelCache[$value] = lcfirst(static::studly($value));
114
    }
115
116
    /**
117
     * Convert a value to studly caps case.
118
     *
119
     * @param string $value
120
     * @return string
121
     */
122
    public static function studly($value)
123
    {
124
        $key = $value;
125
        if (isset(static::$studlyCache[$key])) {
126
            return static::$studlyCache[$key];
127
        }
128
        $value = ucwords(str_replace(['-', '_'], ' ', $value));
129
        return static::$studlyCache[$key] = str_replace(' ', '', $value);
130
    }
131
132
    /**
133
     * Determine if a given string ends with a given substring.
134
     *
135
     * @param string $haystack
136
     * @param string|array $needles
137
     * @return bool
138
     */
139
    public static function endsWith($haystack, $needles)
140
    {
141
        foreach ((array)$needles as $needle) {
142
            if (substr($haystack, -strlen($needle)) === (string)$needle) {
143
                return true;
144
            }
145
        }
146
        return false;
147
    }
148
149
    /**
150
     * Cap a string with a single instance of a given value.
151
     *
152
     * @param string $value
153
     * @param string $cap
154
     * @return string
155
     */
156
    public static function finish($value, $cap)
157
    {
158
        $quoted = preg_quote($cap, '/');
159
        return preg_replace('/(?:' . $quoted . ')+$/u', '', $value) . $cap;
160
    }
161
162
    /**
163
     * Determine if a given string matches a given pattern.
164
     *
165
     * @param string $pattern
166
     * @param string $value
167
     * @return bool
168
     */
169
    public static function is($pattern, $value)
170
    {
171
        if ($pattern == $value) {
172
            return true;
173
        }
174
        $pattern = preg_quote($pattern, '#');
175
        // Asterisks are translated into zero-or-more regular expression wildcards
176
        // to make it convenient to check if the strings starts with the given
177
        // pattern such as "library/*", making any string check convenient.
178
        $pattern = str_replace('\*', '.*', $pattern);
179
        return (bool)preg_match('#^' . $pattern . '\z#u', $value);
180
    }
181
182
    /**
183
     * Convert a string to kebab case.
184
     *
185
     * @param string $value
186
     * @return string
187
     */
188
    public static function kebab($value)
189
    {
190
        return static::snake($value, '-');
191
    }
192
193
    /**
194
     * Convert a string to snake case.
195
     *
196
     * @param string $value
197
     * @param string $delimiter
198
     * @return string
199
     */
200
    public static function snake($value, $delimiter = '_')
201
    {
202
        $key = $value;
203
        if (isset(static::$snakeCache[$key][$delimiter])) {
204
            return static::$snakeCache[$key][$delimiter];
205
        }
206
        if (!ctype_lower($value)) {
207
            $value = preg_replace('/\s+/u', '', $value);
208
            $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
209
        }
210
        return static::$snakeCache[$key][$delimiter] = $value;
211
    }
212
213
    /**
214
     * Convert the given string to lower-case.
215
     *
216
     * @param string $value
217
     * @return string
218
     */
219
    public static function lower($value)
220
    {
221
        return mb_strtolower($value, 'UTF-8');
222
    }
223
224
    /**
225
     * Limit the number of characters in a string.
226
     *
227
     * @param string $value
228
     * @param int $limit
229
     * @param string $end
230
     * @return string
231
     */
232
    public static function limit($value, $limit = 100, $end = '...')
233
    {
234
        if (mb_strwidth($value, 'UTF-8') <= $limit) {
235
            return $value;
236
        }
237
        return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')) . $end;
238
    }
239
240
    /**
241
     * Limit the number of words in a string.
242
     *
243
     * @param string $value
244
     * @param int $words
245
     * @param string $end
246
     * @return string
247
     */
248
    public static function words($value, $words = 100, $end = '...')
249
    {
250
        preg_match('/^\s*+(?:\S++\s*+){1,' . $words . '}/u', $value, $matches);
251
        if (!isset($matches[0]) || static::length($value) === static::length($matches[0])) {
252
            return $value;
253
        }
254
        return rtrim($matches[0]) . $end;
255
    }
256
257
    /**
258
     * Return the length of the given string.
259
     *
260
     * @param string $value
261
     * @return int
262
     */
263
    public static function length($value)
264
    {
265
        return mb_strlen($value);
266
    }
267
268
    /**
269
     * Parse a Class@method style callback into class and method.
270
     *
271
     * @param string $callback
272
     * @param string|null $default
273
     * @return array
274
     */
275
    public static function parseCallback($callback, $default = null)
276
    {
277
        return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
278
    }
279
280
    /**
281
     * Determine if a given string contains a given substring.
282
     *
283
     * @param string $haystack
284
     * @param string|array $needles
285
     * @return bool
286
     */
287
    public static function contains($haystack, $needles)
288
    {
289
        foreach ((array)$needles as $needle) {
290
            if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
291
                return true;
292
            }
293
        }
294
        return false;
295
    }
296
297
    /**
298
     * Get the plural form of an English word.
299
     *
300
     * @param string $value
301
     * @param int $count
302
     * @return string
303
     */
304
    public static function plural($value, $count = 2)
305
    {
306
        return Pluralizer::plural($value, $count);
0 ignored issues
show
Bug introduced by
The type Nip\Utility\Pluralizer 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. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
307
    }
308
309
    /**
310
     * Generate a more truly "random" alpha-numeric string.
311
     *
312
     * @param int $length
313
     * @return string
314
     * @throws \Exception
315
     */
316
    public static function random($length = 16)
317
    {
318
        $string = '';
319
        while (($len = strlen($string)) < $length) {
320
            $size = $length - $len;
321
            $bytes = random_bytes($size);
322
            $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
323
        }
324
        return $string;
325
    }
326
327
    /**
328
     * Replace a given value in the string sequentially with an array.
329
     *
330
     * @param string $search
331
     * @param array $replace
332
     * @param string $subject
333
     * @return string
334
     */
335
    public static function replaceArray($search, array $replace, $subject)
336
    {
337
        foreach ($replace as $value) {
338
            $subject = static::replaceFirst($search, $value, $subject);
339
        }
340
        return $subject;
341
    }
342
343
    /**
344
     * Replace the first occurrence of a given value in the string.
345
     *
346
     * @param string $search
347
     * @param string $replace
348
     * @param string $subject
349
     * @return string
350
     */
351
    public static function replaceFirst($search, $replace, $subject)
352
    {
353
        $position = strpos($subject, $search);
354
        if ($position !== false) {
355
            return substr_replace($subject, $replace, $position, strlen($search));
356
        }
357
        return $subject;
358
    }
359
360
    /**
361
     * Replace the last occurrence of a given value in the string.
362
     *
363
     * @param string $search
364
     * @param string $replace
365
     * @param string $subject
366
     * @return string
367
     */
368
    public static function replaceLast($search, $replace, $subject)
369
    {
370
        $position = strrpos($subject, $search);
371
        if ($position !== false) {
372
            return substr_replace($subject, $replace, $position, strlen($search));
373
        }
374
        return $subject;
375
    }
376
377
    /**
378
     * Convert the given string to title case.
379
     *
380
     * @param string $value
381
     * @return string
382
     */
383
    public static function title($value)
384
    {
385
        return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
386
    }
387
388
    /**
389
     * Get the singular form of an English word.
390
     *
391
     * @param string $value
392
     * @return string
393
     */
394
    public static function singular($value)
395
    {
396
        return Pluralizer::singular($value);
397
    }
398
399
    /**
400
     * Generate a URL friendly "slug" from a given string.
401
     *
402
     * @param string $title
403
     * @param string $separator
404
     * @return string
405
     */
406
    public static function slug($title, $separator = '-')
407
    {
408
        $title = static::ascii($title);
409
        // Convert all dashes/underscores into separator
410
        $flip = $separator == '-' ? '_' : '-';
411
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
412
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
413
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', mb_strtolower($title));
414
        // Replace all separator characters and whitespace by a single separator
415
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
416
        return trim($title, $separator);
417
    }
418
419
    /**
420
     * Transliterate a UTF-8 value to ASCII.
421
     *
422
     * @param string $value
423
     * @return string
424
     */
425
    public static function ascii($value)
426
    {
427
        foreach (static::charsArray() as $key => $val) {
428
            $value = str_replace($val, $key, $value);
429
        }
430
        return preg_replace('/[^\x20-\x7E]/u', '', $value);
431
    }
432
433
    /**
434
     * Returns the replacements for the ascii method.
435
     *
436
     * Note: Adapted from Stringy\Stringy.
437
     *
438
     * @see https://github.com/danielstjules/Stringy/blob/2.3.1/LICENSE.txt
439
     *
440
     * @return array
441
     */
442
    protected static function charsArray()
443
    {
444
        static $charsArray;
445
        if (isset($charsArray)) {
446
            return $charsArray;
447
        }
448
        return $charsArray = [
449
            '0' => ['°', '₀', '۰'],
450
            '1' => ['¹', '₁', '۱'],
451
            '2' => ['²', '₂', '۲'],
452
            '3' => ['³', '₃', '۳'],
453
            '4' => ['⁴', '₄', '۴', '٤'],
454
            '5' => ['⁵', '₅', '۵', '٥'],
455
            '6' => ['⁶', '₆', '۶', '٦'],
456
            '7' => ['⁷', '₇', '۷'],
457
            '8' => ['⁸', '₈', '۸'],
458
            '9' => ['⁹', '₉', '۹'],
459
            'a' => [
460
                'à',
461
                'á',
462
                'ả',
463
                'ã',
464
                'ạ',
465
                'ă',
466
                'ắ',
467
                'ằ',
468
                'ẳ',
469
                'ẵ',
470
                'ặ',
471
                'â',
472
                'ấ',
473
                'ầ',
474
                'ẩ',
475
                'ẫ',
476
                'ậ',
477
                'ā',
478
                'ą',
479
                'å',
480
                'α',
481
                'ά',
482
                'ἀ',
483
                'ἁ',
484
                'ἂ',
485
                'ἃ',
486
                'ἄ',
487
                'ἅ',
488
                'ἆ',
489
                'ἇ',
490
                'ᾀ',
491
                'ᾁ',
492
                'ᾂ',
493
                'ᾃ',
494
                'ᾄ',
495
                'ᾅ',
496
                'ᾆ',
497
                'ᾇ',
498
                'ὰ',
499
                'ά',
500
                'ᾰ',
501
                'ᾱ',
502
                'ᾲ',
503
                'ᾳ',
504
                'ᾴ',
505
                'ᾶ',
506
                'ᾷ',
507
                'а',
508
                'أ',
509
                'အ',
510
                'ာ',
511
                'ါ',
512
                'ǻ',
513
                'ǎ',
514
                'ª',
515
                'ა',
516
                'अ',
517
                'ا'
518
            ],
519
            'b' => ['б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'],
520
            'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
521
            'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ'],
522
            'e' => [
523
                'é',
524
                'è',
525
                'ẻ',
526
                'ẽ',
527
                'ẹ',
528
                'ê',
529
                'ế',
530
                'ề',
531
                'ể',
532
                'ễ',
533
                'ệ',
534
                'ë',
535
                'ē',
536
                'ę',
537
                'ě',
538
                'ĕ',
539
                'ė',
540
                'ε',
541
                'έ',
542
                'ἐ',
543
                'ἑ',
544
                'ἒ',
545
                'ἓ',
546
                'ἔ',
547
                'ἕ',
548
                'ὲ',
549
                'έ',
550
                'е',
551
                'ё',
552
                'э',
553
                'є',
554
                'ə',
555
                'ဧ',
556
                'ေ',
557
                'ဲ',
558
                'ე',
559
                'ए',
560
                'إ',
561
                'ئ'
562
            ],
563
            'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ'],
564
            'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'],
565
            'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'],
566
            'i' => [
567
                'í',
568
                'ì',
569
                'ỉ',
570
                'ĩ',
571
                'ị',
572
                'î',
573
                'ï',
574
                'ī',
575
                'ĭ',
576
                'į',
577
                'ı',
578
                'ι',
579
                'ί',
580
                'ϊ',
581
                'ΐ',
582
                'ἰ',
583
                'ἱ',
584
                'ἲ',
585
                'ἳ',
586
                'ἴ',
587
                'ἵ',
588
                'ἶ',
589
                'ἷ',
590
                'ὶ',
591
                'ί',
592
                'ῐ',
593
                'ῑ',
594
                'ῒ',
595
                'ΐ',
596
                'ῖ',
597
                'ῗ',
598
                'і',
599
                'ї',
600
                'и',
601
                'ဣ',
602
                'ိ',
603
                'ီ',
604
                'ည်',
605
                'ǐ',
606
                'ი',
607
                'इ'
608
            ],
609
            'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج'],
610
            'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'],
611
            'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'],
612
            'm' => ['м', 'μ', 'م', 'မ', 'მ'],
613
            'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ'],
614
            'o' => [
615
                'ó',
616
                'ò',
617
                'ỏ',
618
                'õ',
619
                'ọ',
620
                'ô',
621
                'ố',
622
                'ồ',
623
                'ổ',
624
                'ỗ',
625
                'ộ',
626
                'ơ',
627
                'ớ',
628
                'ờ',
629
                'ở',
630
                'ỡ',
631
                'ợ',
632
                'ø',
633
                'ō',
634
                'ő',
635
                'ŏ',
636
                'ο',
637
                'ὀ',
638
                'ὁ',
639
                'ὂ',
640
                'ὃ',
641
                'ὄ',
642
                'ὅ',
643
                'ὸ',
644
                'ό',
645
                'о',
646
                'و',
647
                'θ',
648
                'ို',
649
                'ǒ',
650
                'ǿ',
651
                'º',
652
                'ო',
653
                'ओ'
654
            ],
655
            'p' => ['п', 'π', 'ပ', 'პ', 'پ'],
656
            'q' => ['ყ'],
657
            'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'],
658
            's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს'],
659
            't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ'],
660
            'u' => [
661
                'ú',
662
                'ù',
663
                'ủ',
664
                'ũ',
665
                'ụ',
666
                'ư',
667
                'ứ',
668
                'ừ',
669
                'ử',
670
                'ữ',
671
                'ự',
672
                'û',
673
                'ū',
674
                'ů',
675
                'ű',
676
                'ŭ',
677
                'ų',
678
                'µ',
679
                'у',
680
                'ဉ',
681
                'ု',
682
                'ူ',
683
                'ǔ',
684
                'ǖ',
685
                'ǘ',
686
                'ǚ',
687
                'ǜ',
688
                'უ',
689
                'उ'
690
            ],
691
            'v' => ['в', 'ვ', 'ϐ'],
692
            'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ'],
693
            'x' => ['χ', 'ξ'],
694
            'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ'],
695
            'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'],
696
            'aa' => ['ع', 'आ', 'آ'],
697
            'ae' => ['ä', 'æ', 'ǽ'],
698
            'ai' => ['ऐ'],
699
            'at' => ['@'],
700
            'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
701
            'dj' => ['ђ', 'đ'],
702
            'dz' => ['џ', 'ძ'],
703
            'ei' => ['ऍ'],
704
            'gh' => ['غ', 'ღ'],
705
            'ii' => ['ई'],
706
            'ij' => ['ij'],
707
            'kh' => ['х', 'خ', 'ხ'],
708
            'lj' => ['љ'],
709
            'nj' => ['њ'],
710
            'oe' => ['ö', 'œ', 'ؤ'],
711
            'oi' => ['ऑ'],
712
            'oii' => ['ऒ'],
713
            'ps' => ['ψ'],
714
            'sh' => ['ш', 'შ', 'ش'],
715
            'shch' => ['щ'],
716
            'ss' => ['ß'],
717
            'sx' => ['ŝ'],
718
            'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
719
            'ts' => ['ц', 'ც', 'წ'],
720
            'ue' => ['ü'],
721
            'uu' => ['ऊ'],
722
            'ya' => ['я'],
723
            'yu' => ['ю'],
724
            'zh' => ['ж', 'ჟ', 'ژ'],
725
            '(c)' => ['©'],
726
            'A' => [
727
                'Á',
728
                'À',
729
                'Ả',
730
                'Ã',
731
                'Ạ',
732
                'Ă',
733
                'Ắ',
734
                'Ằ',
735
                'Ẳ',
736
                'Ẵ',
737
                'Ặ',
738
                'Â',
739
                'Ấ',
740
                'Ầ',
741
                'Ẩ',
742
                'Ẫ',
743
                'Ậ',
744
                'Å',
745
                'Ā',
746
                'Ą',
747
                'Α',
748
                'Ά',
749
                'Ἀ',
750
                'Ἁ',
751
                'Ἂ',
752
                'Ἃ',
753
                'Ἄ',
754
                'Ἅ',
755
                'Ἆ',
756
                'Ἇ',
757
                'ᾈ',
758
                'ᾉ',
759
                'ᾊ',
760
                'ᾋ',
761
                'ᾌ',
762
                'ᾍ',
763
                'ᾎ',
764
                'ᾏ',
765
                'Ᾰ',
766
                'Ᾱ',
767
                'Ὰ',
768
                'Ά',
769
                'ᾼ',
770
                'А',
771
                'Ǻ',
772
                'Ǎ'
773
            ],
774
            'B' => ['Б', 'Β', 'ब'],
775
            'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
776
            'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
777
            'E' => [
778
                'É',
779
                'È',
780
                'Ẻ',
781
                'Ẽ',
782
                'Ẹ',
783
                'Ê',
784
                'Ế',
785
                'Ề',
786
                'Ể',
787
                'Ễ',
788
                'Ệ',
789
                'Ë',
790
                'Ē',
791
                'Ę',
792
                'Ě',
793
                'Ĕ',
794
                'Ė',
795
                'Ε',
796
                'Έ',
797
                'Ἐ',
798
                'Ἑ',
799
                'Ἒ',
800
                'Ἓ',
801
                'Ἔ',
802
                'Ἕ',
803
                'Έ',
804
                'Ὲ',
805
                'Е',
806
                'Ё',
807
                'Э',
808
                'Є',
809
                'Ə'
810
            ],
811
            'F' => ['Ф', 'Φ'],
812
            'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
813
            'H' => ['Η', 'Ή', 'Ħ'],
814
            'I' => [
815
                'Í',
816
                'Ì',
817
                'Ỉ',
818
                'Ĩ',
819
                'Ị',
820
                'Î',
821
                'Ï',
822
                'Ī',
823
                'Ĭ',
824
                'Į',
825
                'İ',
826
                'Ι',
827
                'Ί',
828
                'Ϊ',
829
                'Ἰ',
830
                'Ἱ',
831
                'Ἳ',
832
                'Ἴ',
833
                'Ἵ',
834
                'Ἶ',
835
                'Ἷ',
836
                'Ῐ',
837
                'Ῑ',
838
                'Ὶ',
839
                'Ί',
840
                'И',
841
                'І',
842
                'Ї',
843
                'Ǐ',
844
                'ϒ'
845
            ],
846
            'K' => ['К', 'Κ'],
847
            'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'],
848
            'M' => ['М', 'Μ'],
849
            'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
850
            'O' => [
851
                'Ó',
852
                'Ò',
853
                'Ỏ',
854
                'Õ',
855
                'Ọ',
856
                'Ô',
857
                'Ố',
858
                'Ồ',
859
                'Ổ',
860
                'Ỗ',
861
                'Ộ',
862
                'Ơ',
863
                'Ớ',
864
                'Ờ',
865
                'Ở',
866
                'Ỡ',
867
                'Ợ',
868
                'Ø',
869
                'Ō',
870
                'Ő',
871
                'Ŏ',
872
                'Ο',
873
                'Ό',
874
                'Ὀ',
875
                'Ὁ',
876
                'Ὂ',
877
                'Ὃ',
878
                'Ὄ',
879
                'Ὅ',
880
                'Ὸ',
881
                'Ό',
882
                'О',
883
                'Θ',
884
                'Ө',
885
                'Ǒ',
886
                'Ǿ'
887
            ],
888
            'P' => ['П', 'Π'],
889
            'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
890
            'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
891
            'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
892
            'U' => [
893
                'Ú',
894
                'Ù',
895
                'Ủ',
896
                'Ũ',
897
                'Ụ',
898
                'Ư',
899
                'Ứ',
900
                'Ừ',
901
                'Ử',
902
                'Ữ',
903
                'Ự',
904
                'Û',
905
                'Ū',
906
                'Ů',
907
                'Ű',
908
                'Ŭ',
909
                'Ų',
910
                'У',
911
                'Ǔ',
912
                'Ǖ',
913
                'Ǘ',
914
                'Ǚ',
915
                'Ǜ'
916
            ],
917
            'V' => ['В'],
918
            'W' => ['Ω', 'Ώ', 'Ŵ'],
919
            'X' => ['Χ', 'Ξ'],
920
            'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
921
            'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
922
            'AE' => ['Ä', 'Æ', 'Ǽ'],
923
            'CH' => ['Ч'],
924
            'DJ' => ['Ђ'],
925
            'DZ' => ['Џ'],
926
            'GX' => ['Ĝ'],
927
            'HX' => ['Ĥ'],
928
            'IJ' => ['IJ'],
929
            'JX' => ['Ĵ'],
930
            'KH' => ['Х'],
931
            'LJ' => ['Љ'],
932
            'NJ' => ['Њ'],
933
            'OE' => ['Ö', 'Œ'],
934
            'PS' => ['Ψ'],
935
            'SH' => ['Ш'],
936
            'SHCH' => ['Щ'],
937
            'SS' => ['ẞ'],
938
            'TH' => ['Þ'],
939
            'TS' => ['Ц'],
940
            'UE' => ['Ü'],
941
            'YA' => ['Я'],
942
            'YU' => ['Ю'],
943
            'ZH' => ['Ж'],
944
            ' ' => [
945
                "\xC2\xA0",
946
                "\xE2\x80\x80",
947
                "\xE2\x80\x81",
948
                "\xE2\x80\x82",
949
                "\xE2\x80\x83",
950
                "\xE2\x80\x84",
951
                "\xE2\x80\x85",
952
                "\xE2\x80\x86",
953
                "\xE2\x80\x87",
954
                "\xE2\x80\x88",
955
                "\xE2\x80\x89",
956
                "\xE2\x80\x8A",
957
                "\xE2\x80\xAF",
958
                "\xE2\x81\x9F",
959
                "\xE3\x80\x80"
960
            ],
961
        ];
962
    }
963
964
    /**
965
     * Determine if a given string starts with a given substring.
966
     *
967
     * @param string $haystack
968
     * @param string|array $needles
969
     * @return bool
970
     */
971
    public static function startsWith($haystack, $needles)
972
    {
973
        foreach ((array)$needles as $needle) {
974
            if ($needle != '' && substr($haystack, 0, strlen($needle)) === (string)$needle) {
975
                return true;
976
            }
977
        }
978
        return false;
979
    }
980
981
    /**
982
     * Make a string's first character uppercase.
983
     *
984
     * @param string $string
985
     * @return string
986
     */
987
    public static function ucfirst($string)
988
    {
989
        return static::upper(static::substr($string, 0, 1)) . static::substr($string, 1);
990
    }
991
992
    /**
993
     * Convert the given string to upper-case.
994
     *
995
     * @param string $value
996
     * @return string
997
     */
998
    public static function upper($value)
999
    {
1000
        return mb_strtoupper($value, 'UTF-8');
1001
    }
1002
1003
    /**
1004
     * Returns the portion of string specified by the start and length parameters.
1005
     *
1006
     * @param string $string
1007
     * @param int $start
1008
     * @param int|null $length
1009
     * @return string
1010
     */
1011
    public static function substr($string, $start, $length = null)
1012
    {
1013
        return mb_substr($string, $start, $length, 'UTF-8');
1014
    }
1015
1016
    /**
1017
     * @param $data
1018
     * @param bool $strict
1019
     * @return bool
1020
     */
1021
    public static function isSerialized($data, $strict = true)
1022
    {
1023
        // if it isn't a string, it isn't serialized.
1024
        if (!is_string($data)) {
1025
            return false;
1026
        }
1027
        $data = trim($data);
1028
        if ('N;' == $data) {
1029
            return true;
1030
        }
1031
        if (strlen($data) < 4) {
1032
            return false;
1033
        }
1034
        if (':' !== $data[1]) {
1035
            return false;
1036
        }
1037
        if ($strict) {
1038
            $lastc = substr($data, -1);
1039
            if (';' !== $lastc && '}' !== $lastc) {
1040
                return false;
1041
            }
1042
        } else {
1043
            $semicolon = strpos($data, ';');
1044
            $brace = strpos($data, '}');
1045
            // Either ; or } must exist.
1046
            if (false === $semicolon && false === $brace) {
1047
                return false;
1048
            }
1049
            // But neither must be in the first X characters.
1050
            if (false !== $semicolon && $semicolon < 3) {
1051
                return false;
1052
            }
1053
            if (false !== $brace && $brace < 4) {
1054
                return false;
1055
            }
1056
        }
1057
        $token = $data[0];
1058
        switch ($token) {
1059
            case 's':
1060
                if ($strict) {
1061
                    if ('"' !== substr($data, -2, 1)) {
1062
                        return false;
1063
                    }
1064
                } elseif (false === strpos($data, '"')) {
1065
                    return false;
1066
                }
1067
            // or else fall through
1068
            case 'a':
1069
            case 'O':
1070
                return (bool)preg_match("/^{$token}:[0-9]+:/s", $data);
1071
            case 'b':
1072
            case 'i':
1073
            case 'd':
1074
                $end = $strict ? '$' : '';
1075
                return (bool)preg_match("/^{$token}:[0-9.E-]+;$end/", $data);
1076
        }
1077
        return false;
1078
    }
1079
1080
    /**
1081
     * @param $str
1082
     * @param $first
1083
     * @param $last
1084
     * @return string
1085
     */
1086 9
    public static function mask($str, $first = 0, $last = 0)
1087
    {
1088 9
        $len = strlen($str);
1089 9
        $toShow = $first + $last;
1090 9
        return substr($str, 0, $len <= $toShow ? 0 : $first)
1091 9
            . str_repeat("*", $len - ($len <= $toShow ? 0 : $toShow))
1092 9
            . substr($str, $len - $last, $len <= $toShow ? 0 : $last);
1093
    }
1094
1095
    /**
1096
     * @param $name
1097
     * @param string $separator
1098
     * @return string
1099
     */
1100 3
    public static function initials($name, $separator = '.')
1101
    {
1102 3
        $name = str_replace(['-', '_'], ' ', $name);
1103 3
        $split = explode(" ", $name);
1104 3
        $initials = [];
1105 3
        foreach ($split as $part) {
1106 3
            $initials[] = ucfirst($part[0]);
1107
        }
1108
1109 3
        return implode($separator, $initials) . $separator;
1110
    }
1111
1112
    /**
1113
     * @param string $string
1114
     * @param bool $return
1115
     * @param array $params
1116
     * @return bool|mixed
1117
     */
1118 5
    public static function isJson(string $string, $return = false, ...$params)
1119
    {
1120 5
        $data = json_decode($string, ...$params);
0 ignored issues
show
Bug introduced by
$params is expanded, but the parameter $assoc of json_decode() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1120
        $data = json_decode($string, /** @scrutinizer ignore-type */ ...$params);
Loading history...
1121 5
        if (json_last_error() !== JSON_ERROR_NONE) {
1122 1
            return false;
1123
        }
1124 4
        return $return ? $data : true;
1125
    }
1126
}
1127