Completed
Push — master ( bb70a1...a8127b )
by
unknown
07:21
created

string.php ➔ str_contains_array()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Generate random string (password) from a different charset based on $secLevel.
5
 * $secLevel=0 [a-z] charset.
6
 * $secLevel=1 [a-z0-9] charset.
7
 * $secLevel=2 [A-Za-z0-9] charset.
8
 * $secLevel=3 [A-Za-z0-9-_$!+&%?=*#@] charset.
9
 * @param int $length
10
 * @param int $secLevel
11
 * @return string
12
 */
13
function generateRandomPassword(int $length = 10, int $secLevel = 2) : string
14
{
15
    $charset = 'abcdefghijklmnopqrstuvwxyz';
16
    if ($secLevel == 1) {
17
        $charset = 'abcdefghijklmnopqrstuvwxyz1234567890';
18
    } elseif ($secLevel == 2) {
19
        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
20
    } elseif ($secLevel >= 3) {
21
        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_$!+&%?=*#@';
22
    }
23
24
    return generateRandomString($length, '', $charset);
25
}
26
27
/**
28
 * Generate random string from [0-9A-Za-z] charset.
29
 * You may extend charset by passing $extChars (i.e. add these chars to existing).
30
 * Ex.: $extChars='-_$!' implies that the final charset is [0-9A-Za-z-_$!]
31
 * If $newChars is set, the default charset are replaced by this and $extChars was ignored.
32
 * Ex.: $newChars='0123456789' implies that the final charset is [0123456789]
33
 * @param int $length
34
 * @param string $extChars
35
 * @param string $newChars
36
 * @return string
37
 */
38
function generateRandomString(int $length = 10, string $extChars = '', string $newChars = '') : string
39
{
40
    if ($length < 1) {
41
        $length = 1;
42
    }
43
44
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
45
    if ($newChars !== null && $newChars != '') {
46
        $characters = $newChars;
47
    } elseif ($extChars !== null && $extChars != '') {
48
        $characters .= $extChars;
49
    }
50
51
    $charactersLength = strlen($characters);
52
    $randomString = '';
53
54
    for ($i = 0; $i < $length; $i++) {
55
        $randomString .= $characters[random_int(0, $charactersLength - 1)];
56
    }
57
58
    return $randomString;
59
}
60
61
/**
62
 * *****************************************************
63
 * LARAVEL STRING HELPERS
64
 * With some adjustments
65
 * *****************************************************
66
 */
67
68
if (!function_exists('preg_replace_sub')) {
69
    /**
70
     * Replace a given pattern with each value in the array in sequentially.
71
     *
72
     * @param  string $pattern
73
     * @param  array $replacements
74
     * @param  string $subject
75
     * @return string
76
     */
77
    function preg_replace_sub($pattern, &$replacements, $subject)
78
    {
79
        return preg_replace_callback($pattern, function () use (&$replacements) {
80
            return array_shift($replacements);
81
        }, $subject);
82
    }
83
}
84
85
if (!function_exists('snake_case')) {
86
    /**
87
     * Convert a string to snake case.
88
     *
89
     * @param  string $value
90
     * @param  string $delimiter
91
     * @return string
92
     */
93
    function snake_case($value, $delimiter = '_')
94
    {
95
        $snakeCache = [];
96
        $key = $value . $delimiter;
97
        if (isset($snakeCache[$key])) {
98
            return $snakeCache[$key];
99
        }
100
        if (!ctype_lower($value)) {
101
            $value = strtolower(preg_replace('/(.)(?=[A-Z])/', '$1' . $delimiter, $value));
102
        }
103
        return $snakeCache[$key] = $value;
104
    }
105
}
106
107
if (!function_exists('str_random')) {
108
    /**
109
     * Generate a more truly "random" alpha-numeric string with openssl.
110
     * If openssl_random_pseudo_bytes not exists, use simple legacy function
111
     *
112
     * @param  int $length
113
     * @return string
114
     *
115
     * @throws \RuntimeException
116
     */
117
    function str_random(int $length = 16)
118
    {
119
        if ($length < 0) {
120
            $length = 16;
121
        }
122
123
        if (!function_exists('openssl_random_pseudo_bytes')) {
124
            return generateRandomString($length);
125
        }
126
        $bytes = openssl_random_pseudo_bytes($length * 2);
127
        if ($bytes === false) {
128
            throw new RuntimeException('Unable to generate random string.');
129
        }
130
        return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
131
    }
132
}
133
134
if (!function_exists('ends_with')) {
135
    /**
136
     * Determine if a given string ends with a given substring.
137
     *
138
     * @param  string $haystack
139
     * @param  string|array $needles
140
     * @return bool
141
     */
142
    function ends_with($haystack, $needles)
143
    {
144
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
145
            return false;
146
        }
147
148
        foreach ((array)$needles as $needle) {
149
            if ((string)$needle === substr($haystack, -strlen($needle))) {
150
                return true;
151
            }
152
        }
153
        return false;
154
    }
155
}
156
157 View Code Duplication
if (!function_exists('ends_with_insensitive')) {
158
    /**
159
     * Determine if a given string ends with a given substring (case insensitive).
160
     *
161
     * @param  string $haystack
162
     * @param  string|array $needles
163
     * @return bool
164
     */
165
    function ends_with_insensitive($haystack, $needles)
166
    {
167
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
168
            return false;
169
        }
170
171
        $haystack = strtolower($haystack);
172
        $needles = strtolower($needles);
173
174
        return ends_with($haystack, $needles);
175
    }
176
}
177
178
if (!function_exists('starts_with')) {
179
    /**
180
     * Determine if a given string starts with a given substring.
181
     *
182
     * @param  string $haystack
183
     * @param  string|array $needles
184
     * @return bool
185
     */
186
    function starts_with($haystack, $needles)
187
    {
188
        if (isNullOrEmpty($haystack) || (!is_array($needles) && isNullOrEmpty($needles))) {
189
            return false;
190
        }
191
192
        foreach ((array)$needles as $needle) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
            if ($needle != '' && strpos($haystack, $needle) === 0) {
194
                return true;
195
            }
196
        }
197
        return false;
198
    }
199
}
200
201 View Code Duplication
if (!function_exists('starts_with_insensitive')) {
202
    /**
203
     * Determine if a given string starts with a given substring (case insensitive).
204
     *
205
     * @param  string $haystack
206
     * @param  string|array $needles
207
     * @return bool
208
     */
209
    function starts_with_insensitive($haystack, $needles)
210
    {
211
        if (isNullOrEmpty($haystack) || (!is_array($needles) && isNullOrEmpty($needles))) {
212
            return false;
213
        }
214
215
        $haystack = strtolower($haystack);
216
        $needles = strtolower($needles);
217
218
        return starts_with($haystack, $needles);
219
    }
220
}
221
222
if (!function_exists('str_contains_array')) {
223
    /**
224
     * Determine if a given string contains one of the given substring.
225
     *
226
     * @param  string $haystack
227
     * @param  array $needles
228
     * @return bool
229
     */
230
    function str_contains_array(string $haystack, array $needles)
231
    {
232
        foreach ($needles as $needle) {
233
            if (str_contains($haystack,$needle)) {
234
                return true;
235
            }
236
        }
237
        return false;
238
    }
239
}
240
241
if (!function_exists('str_contains')) {
242
    /**
243
     * Determine if a given string contains a given substring.
244
     *
245
     * @param  string $haystack
246
     * @param  string|array $needles
247
     * @return bool
248
     */
249
    function str_contains(string $haystack, $needles)
250
    {
251
        if (isNullOrEmpty($haystack)) {
252
            return false;
253
        }
254
        if ((is_array($needles) && isNullOrEmptyArray($needles))
255
            || (!is_array($needles) && isNullOrEmpty($needles))
256
        ) {
257
            return false;
258
        }
259
260
        foreach ((array)$needles as $needle) {
261
            if ($needle != '' && strpos($haystack, $needle) !== false) {
262
                return true;
263
            }
264
        }
265
        return false;
266
    }
267
}
268
269 View Code Duplication
if (!function_exists('str_contains_insensitive')) {
270
    /**
271
     * Determine if a given string contains a given substring (case insensitive).
272
     *
273
     * @param  string $haystack
274
     * @param  string|array $needles
275
     * @return bool
276
     */
277
    function str_contains_insensitive($haystack, $needles)
278
    {
279
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
280
            return false;
281
        }
282
283
        $haystack = strtolower($haystack);
284
        $needles = strtolower($needles);
285
286
        return str_contains($haystack, $needles);
287
    }
288
}
289
290
if (!function_exists('str_finish')) {
291
    /**
292
     * Cap a string with a single instance of a given value.
293
     *
294
     * @param  string $value
295
     * @param  string $cap
296
     * @return string
297
     */
298
    function str_finish($value, $cap)
299
    {
300
        if (isNullOrEmpty($value) || isNullOrEmpty($cap)) {
301
            return false;
302
        }
303
304
        $quoted = preg_quote($cap, '/');
305
        return preg_replace('/(?:' . $quoted . ')+$/', '', $value) . $cap;
306
    }
307
}
308
309 View Code Duplication
if (!function_exists('str_finish_insensitive')) {
310
    /**
311
     * Cap a string with a single instance of a given value (Case Insensitive).
312
     *
313
     * @param  string $value
314
     * @param  string $cap
315
     * @return string
316
     */
317
    function str_finish_insensitive($value, $cap)
318
    {
319
        if (isNullOrEmpty($value) || isNullOrEmpty($cap)) {
320
            return false;
321
        }
322
323
        $value = strtolower($value);
324
        $cap = strtolower($cap);
325
326
        return str_finish($value, $cap);
327
    }
328
}
329
330
if (!function_exists('str_is')) {
331
    /**
332
     * Determine if a given string matches a given pattern.
333
     *
334
     * @param  string $pattern
335
     * @param  string $value
336
     * @return bool
337
     */
338
    function str_is($pattern, $value)
339
    {
340
        if ($pattern == $value) {
341
            return true;
342
        }
343
        $pattern = preg_quote($pattern, '#');
344
        // Asterisks are translated into zero-or-more regular expression wildcards
345
        // to make it convenient to check if the strings starts with the given
346
        // pattern such as "library/*", making any string check convenient.
347
        $pattern = str_replace('\*', '.*', $pattern) . '\z';
348
        return preg_match('#^' . $pattern . '#', $value) === 1;
349
    }
350
}
351
if (!function_exists('str_limit')) {
352
    /**
353
     * Limit the number of characters in a string.
354
     *
355
     * @param  string $value
356
     * @param  int $limit
357
     * @param  string $end append in
358
     * @param  bool $wordsafe if set to true, remove any truncated word in the end of string so the result no breaking words.
359
     * @return string
360
     */
361
    function str_limit(string $value, int $limit = 100, string $end = '...', bool $wordsafe = false) : string
362
    {
363
        $limit = max($limit, 0);
364
        if (mb_strlen($value) <= $limit) {
365
            return $value;
366
        }
367
368
        $string = rtrim(mb_substr($value, 0, $limit, 'UTF-8'));
369
        if ($wordsafe) {
370
            $string = preg_replace('/\s+?(\S+)?$/', '', $string);
371
        }
372
        return $string . $end;
373
    }
374
}
375
376
if (!function_exists('str_replace_array')) {
377
    /**
378
     * Replace a given value in the string sequentially with an array.
379
     *
380
     * @param  string $search
381
     * @param  array $replace
382
     * @param  string $subject
383
     * @return string
384
     */
385
    function str_replace_array($search, array $replace, $subject)
386
    {
387
        foreach ($replace as $value) {
388
            $subject = preg_replace('/' . $search . '/', $value, $subject, 1);
389
        }
390
        return $subject;
391
    }
392
}
393
394
if (!function_exists('studly_case')) {
395
    /**
396
     * Convert a value to studly caps case.
397
     *
398
     * @param  string $value
399
     * @return string
400
     */
401
    function studly_case($value)
402
    {
403
        $studlyCache = [];
404
        $key = $value;
405
        if (isset($studlyCache[$key])) {
406
            return $studlyCache[$key];
407
        }
408
        $value = ucwords(str_replace(array('-', '_'), ' ', $value));
409
        return $studlyCache[$key] = str_replace(' ', '', $value);
410
    }
411
}
412
413
if (!function_exists('studly')) {
414
    /**
415
     * Convert a value to studly caps case.
416
     * Alias of studly_case
417
     *
418
     * @param  string $value
419
     * @return string
420
     */
421
    function studly($value)
422
    {
423
        return studly_case($value);
424
    }
425
}
426
427
if (!function_exists('camel_case')) {
428
    /**
429
     * Convert a value to camel case.
430
     *
431
     * @param  string $value
432
     * @return string
433
     */
434
    function camel_case($value)
435
    {
436
        $camelCache = [];
437
        if (isset($camelCache[$value])) {
438
            return $camelCache[$value];
439
        }
440
        return $camelCache[$value] = lcfirst(studly($value));
441
    }
442
}
443
444
/**
445
 * Replace underscores with dashes in the string.
446
 * @param string $word
447
 * @return string
448
 */
449
function underscore2dash(string $word) : string
450
{
451
    return str_replace('_', '-', $word);
452
}
453
454
/**
455
 * Make an underscored, lowercase form from the expression in the string.
456
 * @param string $word
457
 * @return string
458
 */
459
function dash2underscore(string $word) : string
460
{
461
    $word = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
462
    $word = preg_replace('/([a-z])([A-Z])/', '\1_\2', $word);
463
    return str_replace('-', '_', strtolower($word));
464
}
465
466
if (!function_exists('str_replace_multiple_space')) {
467
468
    /**
469
     * Replace multiple spaces with one space.
470
     * If $withNbsp replaces "&nbsp;" with a single space before converts multiple sequential spaces.
471
     * @param string $str
472
     * @param bool $withNbsp
473
     * @return string
474
     */
475
    function str_replace_multiple_space(string $str, bool $withNbsp = false) : string
476
    {
477
        if ($withNbsp) {
478
            $str = str_replace('&nbsp;', ' ', $str);
479
        }
480
        return preg_replace('/\s+/', ' ', $str);
481
    }
482
}
483
484
if (!function_exists('str_replace_last')) {
485
    /**
486
     * Replace last occurrence ($search) of a string ($subject) with $replace string.
487
     * @param string $search
488
     * @param string $replace
489
     * @param string $subject
490
     * @return string
491
     */
492
    function str_replace_last(string $search, string $replace, string $subject) : string
493
    {
494
        if ($search == '') {
495
            return $subject;
496
        }
497
        $position = strrpos($subject, $search);
498
        if ($position === false) {
499
            return $subject;
500
        }
501
        return substr_replace($subject, $replace, $position, strlen($search));
502
    }
503
}
504
if (!function_exists('segment')) {
505
506
    /**
507
     * Get a segment from a string based on a delimiter.
508
     * Returns an empty string when the offset doesn't exist.
509
     * Use a negative index to start counting from the last element.
510
     *
511
     * @param string $delimiter
512
     * @param int $index
513
     * @param string $subject
514
     *
515
     * @return string
516
     * @see https://github.com/spatie/string/blob/master/src/Str.php
517
     */
518
    function segment($delimiter, $index, $subject)
519
    {
520
        $segments = explode($delimiter, $subject);
521
        if ($index < 0) {
522
            $segments = array_reverse($segments);
523
            $index = (int)abs($index) - 1;
524
        }
525
        $segment = isset($segments[$index]) ? $segments[$index] : '';
526
        return $segment;
527
    }
528
}
529
if (!function_exists('firstSegment')) {
530
531
    /**
532
     * Get the first segment from a string based on a delimiter.
533
     *
534
     * @param string $delimiter
535
     * @param string $subject
536
     *
537
     * @return string
538
     * @see https://github.com/spatie/string/blob/master/src/Str.php
539
     */
540
    function firstSegment($delimiter, $subject) : string
541
    {
542
        return segment($delimiter, 0, $subject);
543
    }
544
}
545
546
if (!function_exists('lastSegment')) {
547
548
    /**
549
     * Get the last segment from a string based on a delimiter.
550
     *
551
     * @param string $delimiter
552
     * @param string $subject
553
     *
554
     * @return string
555
     * @see https://github.com/spatie/string/blob/master/src/Str.php
556
     */
557
    function lastSegment($delimiter, $subject) : string
558
    {
559
        return segment($delimiter, -1, $subject);
560
    }
561
}
562
563
/**
564
 * Return true if $subject is null or the string representation(cast to string) of $subject is an empty string ('').
565
 * @param $subject
566
 * @param bool $withTrim if set to true (default) and $subject is a scalar then check if trim($subject)!='' too.
567
 * @return bool
568
 */
569
function isNullOrEmpty($subject, bool $withTrim = true) : bool
570
{
571
    return $subject === null || $subject === '' || ($withTrim === true && is_scalar($subject) && trim($subject) == '');
572
}
573
574
/**
575
 * Return true if $subject is not null and is not empty string ('').
576
 * @param $subject
577
 * @param bool $withTrim if set to true (default) check if trim()!='' too.
578
 * @return bool
579
 */
580
function isNotNullOrEmpty($subject, bool $withTrim = true) : bool
581
{
582
    return !isNullOrEmpty($subject, $withTrim);
583
}
584
585
586
/**
587
 * Convert number to word representation.
588
 *
589
 * @param int $number number to convert to word
590
 * @param string $locale default 'IT' support only IT or EN
591
 *
592
 * @return string converted string
593
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
594
 */
595
function numberToWord(int $number, string $locale = 'IT') : string
596
{
597
    if (isNullOrEmpty($locale) || (strtoupper($locale) != 'IT' && strtoupper($locale) != 'EN')) {
598
        $locale = 'IT';
599
    } else {
600
        $locale = strtoupper($locale);
601
    }
602
603
    $hyphen = $locale == 'EN' ? '-' : '';
604
    $conjunction = $locale == 'EN' ? ' and ' : ' ';
605
    $separator = ', ';
606
    $negative = $locale == 'EN' ? 'negative ' : 'negativo ';
607
    $decimal = $locale == 'EN' ? ' point ' : ' punto ';
608
    $fraction = null;
609
    $dictionary = $locale == 'EN' ? NUMBERS_EN_ARR : NUMBERS_ITA_ARR;
610
    if (!is_numeric($number)) {
611
        return '';
612
    }
613
    if (!isInteger($number, false, true)) {
614
        trigger_error('numberToWord only accepts numbers between -' . PHP_INT_MAX . ' and ' . PHP_INT_MAX,
615
            E_USER_WARNING);
616
        return '';
617
    }
618
    if ($number < 0) {
619
        return $negative . numberToWord(abs($number), $locale);
620
    }
621
    if (strpos($number, '.') !== false) {
622
        list($number, $fraction) = explode('.', $number);
623
    }
624
    switch (true) {
625
        case $number < 21:
626
            $string = $dictionary[$number];
627
            break;
628
        case $number < 100:
629
            $tens = ((int)($number / 10)) * 10;
630
            $units = $number % 10;
631
            $string = $dictionary[$tens];
632
            if ($units) {
633
                $string .= $hyphen . $dictionary[$units];
634
            }
635
            break;
636
        case $number < 1000:
637
            $hundreds = $number / 100;
638
            $remainder = $number % 100;
639
            $string = $dictionary[$hundreds] . ' ' . $dictionary[100];
640
            if ($remainder) {
641
                $string .= $conjunction . numberToWord($remainder, $locale);
642
            }
643
            break;
644
        default:
645
            $baseUnit = pow(1000, floor(log($number, 1000)));
646
            $numBaseUnits = (int)($number / $baseUnit);
647
            $remainder = $number % $baseUnit;
648
            $string = numberToWord($numBaseUnits, $locale) . ' ' . $dictionary[$baseUnit];
649
            if ($remainder) {
650
                $string .= $remainder < 100 ? $conjunction : $separator;
651
                $string .= numberToWord($remainder, $locale);
652
            }
653
            break;
654
    }
655
    if (null !== $fraction && is_numeric($fraction)) {
656
        $string .= $decimal;
657
        $words = [];
658
        foreach (str_split((string)$fraction) as $number) {
659
            $words[] = $dictionary[$number];
660
        }
661
        $string .= implode(' ', $words);
662
    }
663
    return $string;
664
}
665
666
/**
667
 * Convert seconds to real time.
668
 *
669
 * @param int $seconds time in seconds
670
 * @param bool $returnAsWords return time in words (example one minute and 20 seconds) if value is True or (1 minute and 20 seconds) if value is false, default false
671
 * @param string $locale 'IT' default, or 'EN'
672
 *
673
 * @return string
674
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
675
 */
676
function secondsToText(int $seconds, bool $returnAsWords = false, string $locale = 'IT') : string
677
{
678
    $parts = [];
679
    $arrPeriod = ($locale == 'EN' ? PERIOD_IN_SECONDS_EN_ARR : PERIOD_IN_SECONDS_ITA_ARR);
680
    foreach ($arrPeriod as $name => $dur) {
681
        $div = floor($seconds / $dur);
682
        if ($div == 0) {
683
            continue;
684
        }
685
        if ($div == 1) {
686
            $parts[] = ($returnAsWords ? numberToWord($div, $locale) : $div) . ' ' . $name;
687
        } else {
688
            $parts[] = ($returnAsWords ? numberToWord($div,
689
                    $locale) : $div) . ' ' . ($locale == 'EN' ? $name : PERIOD_SINGULAR_PLURAL_ITA_ARR[$name]) . (strtoupper($locale) == 'EN' ? 's' : '');
690
        }
691
        $seconds %= $dur;
692
    }
693
    $last = array_pop($parts);
694
    if (isNullOrEmptyArray($parts)) {
695
        return $last;
696
    }
697
    return implode(', ', $parts) . (strtoupper($locale) == 'EN' ? ' and ' : ' e ') . $last;
698
}
699
700
701
/**
702
 * Convert minutes to real time.
703
 *
704
 * @param float $minutes time in minutes
705
 * @param bool $returnAsWords return time in words (example one hour and 20 minutes) if value is True or (1 hour and 20 minutes) if value is false, default false
706
 * @param string $locale 'IT' (default) or 'EN'
707
 *
708
 * @return string
709
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
710
 */
711
function minutesToText(float $minutes, bool $returnAsWords = false, string $locale = 'IT') : string
712
{
713
    $seconds = $minutes * 60;
714
    return secondsToText($seconds, $returnAsWords, $locale);
715
}
716
717
/**
718
 * Convert hours to real time.
719
 *
720
 * @param float $hours time in hours
721
 * @param bool $returnAsWords return time in words (example one hour) if value is True or (1 hour) if value is false, default false
722
 * @param string $locale 'IT' (default) or 'EN'
723
 *
724
 * @return string
725
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
726
 */
727
function hoursToText(float $hours, bool $returnAsWords = false, string $locale = 'IT') : string
728
{
729
    $seconds = $hours * 3600;
730
    return secondsToText($seconds, $returnAsWords, $locale);
731
}
732
733
if (!function_exists('str_html_compress')) {
734
735
    /**
736
     * Removes whitespace from html and compact it.
737
     * @param string $value
738
     * @return string
739
     */
740
    function str_html_compress(string $value) : string
741
    {
742
        return preg_replace(array('/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s'), array('>', '<', '\\1'), $value);
743
    }
744
}
745
746
if (!function_exists('str_word_count_utf8')) {
747
748
    /**
749
     * Count number of words in string.
750
     * Return zero if an error occourred.
751
     * @param string $str
752
     * @return int
753
     * @see https://github.com/ifsnop/lpsf/blob/master/src/Ifsnop/functions.inc.php
754
     */
755
    function str_word_count_utf8(string $str) : int
756
    {
757
        $result = preg_match_all("/\p{L}[\p{L}\p{Mn}\p{Pd}'\x{2019}]*/u", $str, $matches);
758
        return $result === false ? 0 : $result;
759
    }
760
}
761
762
if (!function_exists('slugify')) {
763
764
    /**
765
     * Generate a URL friendly "slug" from a given string.
766
     * Converts the string into an URL slug. This includes replacing non-ASCII
767
     * characters with their closest ASCII equivalents, removing remaining
768
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
769
     * $replacement. The replacement defaults to a single dash, and the string
770
     * is also converted to lowercase.
771
     * @param string $title
772
     * @param string $separator
773
     * @return string
774
     * @see normalizeUtf8String in https://github.com/padosoft/support/blob/master/src/sanitize.php#L150
775
     * @see https://github.com/illuminate/support/blob/master/Str.php
776
     */
777
    function slugify(string $title, string $separator = '-') : string
778
    {
779
        // Remove all characters that are degrees or math power exponetial
780
        $title = preg_replace('[°₀۰¹₁²₂³₃⁴₄⁵₅⁶₆⁷₇⁸₈⁹₉]', '', mb_strtolower($title));
781
782
        //removes all diacritics (marks like accents) from a given UTF8-encoded
783
        //texts and returns ASCii-text equivalent(if possible).
784
        $title = normalizeUtf8String($title);
785
786
        // Convert all dashes/underscores into separator
787
        $flip = $separator == '-' ? '_' : '-';
788
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
789
790
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
791
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', mb_strtolower($title));
792
793
        // Replace all separator characters and whitespace by a single separator
794
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
795
796
        return trim($title, $separator);
797
    }
798
}
799
800
if (!function_exists('charsArray')) {
801
    /**
802
     * Returns the replacements for the non-Ascii chars.
803
     *
804
     * @return array An array of replacements.
805
     * @see https://github.com/danielstjules/Stringy/blob/master/src/Stringy.php
806
     */
807
    function charsArray()
808
    {
809
        return array(
810
            '0' => array('°', '₀', '۰'),
811
            '1' => array('¹', '₁', '۱'),
812
            '2' => array('²', '₂', '۲'),
813
            '3' => array('³', '₃', '۳'),
814
            '4' => array('⁴', '₄', '۴', '٤'),
815
            '5' => array('⁵', '₅', '۵', '٥'),
816
            '6' => array('⁶', '₆', '۶', '٦'),
817
            '7' => array('⁷', '₇', '۷'),
818
            '8' => array('⁸', '₈', '۸'),
819
            '9' => array('⁹', '₉', '۹'),
820
            'a' => array(
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
                'ἃ',
847
                'ἄ',
848
                'ἅ',
849
                'ἆ',
850
                'ἇ',
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
            'b' => array('б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'),
881
            'c' => array('ç', 'ć', 'č', 'ĉ', 'ċ'),
882
            'd' => array(
883
                'ď',
884
                'ð',
885
                'đ',
886
                'ƌ',
887
                'ȡ',
888
                'ɖ',
889
                'ɗ',
890
                'ᵭ',
891
                'ᶁ',
892
                'ᶑ',
893
                'д',
894
                'δ',
895
                'د',
896
                'ض',
897
                'ဍ',
898
                'ဒ',
899
                'დ'
900
            ),
901
            'e' => array(
902
                'é',
903
                'è',
904
                'ẻ',
905
                'ẽ',
906
                'ẹ',
907
                'ê',
908
                'ế',
909
                'ề',
910
                'ể',
911
                'ễ',
912
                'ệ',
913
                'ë',
914
                'ē',
915
                'ę',
916
                'ě',
917
                'ĕ',
918
                'ė',
919
                'ε',
920
                'έ',
921
                'ἐ',
922
                'ἑ',
923
                'ἒ',
924
                'ἓ',
925
                'ἔ',
926
                'ἕ',
927
                'ὲ',
928
                'έ',
929
                'е',
930
                'ё',
931
                'э',
932
                'є',
933
                'ə',
934
                'ဧ',
935
                'ေ',
936
                'ဲ',
937
                'ე',
938
                'ए',
939
                'إ',
940
                'ئ'
941
            ),
942
            'f' => array('ф', 'φ', 'ف', 'ƒ', 'ფ'),
943
            'g' => array('ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'),
944
            'h' => array('ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'),
945
            'i' => array(
946
                'í',
947
                'ì',
948
                'ỉ',
949
                'ĩ',
950
                'ị',
951
                'î',
952
                'ï',
953
                'ī',
954
                'ĭ',
955
                'į',
956
                'ı',
957
                'ι',
958
                'ί',
959
                'ϊ',
960
                'ΐ',
961
                'ἰ',
962
                'ἱ',
963
                'ἲ',
964
                'ἳ',
965
                'ἴ',
966
                'ἵ',
967
                'ἶ',
968
                'ἷ',
969
                'ὶ',
970
                'ί',
971
                'ῐ',
972
                'ῑ',
973
                'ῒ',
974
                'ΐ',
975
                'ῖ',
976
                'ῗ',
977
                'і',
978
                'ї',
979
                'и',
980
                'ဣ',
981
                'ိ',
982
                'ီ',
983
                'ည်',
984
                'ǐ',
985
                'ი',
986
                'इ',
987
                'ی'
988
            ),
989
            'j' => array('ĵ', 'ј', 'Ј', 'ჯ', 'ج'),
990
            'k' => array(
991
                'ķ',
992
                'ĸ',
993
                'к',
994
                'κ',
995
                'Ķ',
996
                'ق',
997
                'ك',
998
                'က',
999
                'კ',
1000
                'ქ',
1001
                'ک'
1002
            ),
1003
            'l' => array('ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'),
1004
            'm' => array('м', 'μ', 'م', 'မ', 'მ'),
1005
            'n' => array(
1006
                'ñ',
1007
                'ń',
1008
                'ň',
1009
                'ņ',
1010
                'ʼn',
1011
                'ŋ',
1012
                'ν',
1013
                'н',
1014
                'ن',
1015
                'န',
1016
                'ნ'
1017
            ),
1018
            'o' => array(
1019
                'ó',
1020
                'ò',
1021
                'ỏ',
1022
                'õ',
1023
                'ọ',
1024
                'ô',
1025
                'ố',
1026
                'ồ',
1027
                'ổ',
1028
                'ỗ',
1029
                'ộ',
1030
                'ơ',
1031
                'ớ',
1032
                'ờ',
1033
                'ở',
1034
                'ỡ',
1035
                'ợ',
1036
                'ø',
1037
                'ō',
1038
                'ő',
1039
                'ŏ',
1040
                'ο',
1041
                'ὀ',
1042
                'ὁ',
1043
                'ὂ',
1044
                'ὃ',
1045
                'ὄ',
1046
                'ὅ',
1047
                'ὸ',
1048
                'ό',
1049
                'о',
1050
                'و',
1051
                'θ',
1052
                'ို',
1053
                'ǒ',
1054
                'ǿ',
1055
                'º',
1056
                'ო',
1057
                'ओ'
1058
            ),
1059
            'p' => array('п', 'π', 'ပ', 'პ', 'پ'),
1060
            'q' => array('ყ'),
1061
            'r' => array('ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'),
1062
            's' => array(
1063
                'ś',
1064
                'š',
1065
                'ş',
1066
                'с',
1067
                'σ',
1068
                'ș',
1069
                'ς',
1070
                'س',
1071
                'ص',
1072
                'စ',
1073
                'ſ',
1074
                'ს'
1075
            ),
1076
            't' => array(
1077
                'ť',
1078
                'ţ',
1079
                'т',
1080
                'τ',
1081
                'ț',
1082
                'ت',
1083
                'ط',
1084
                'ဋ',
1085
                'တ',
1086
                'ŧ',
1087
                'თ',
1088
                'ტ'
1089
            ),
1090
            'u' => array(
1091
                'ú',
1092
                'ù',
1093
                'ủ',
1094
                'ũ',
1095
                'ụ',
1096
                'ư',
1097
                'ứ',
1098
                'ừ',
1099
                'ử',
1100
                'ữ',
1101
                'ự',
1102
                'û',
1103
                'ū',
1104
                'ů',
1105
                'ű',
1106
                'ŭ',
1107
                'ų',
1108
                'µ',
1109
                'у',
1110
                'ဉ',
1111
                'ု',
1112
                'ူ',
1113
                'ǔ',
1114
                'ǖ',
1115
                'ǘ',
1116
                'ǚ',
1117
                'ǜ',
1118
                'უ',
1119
                'उ'
1120
            ),
1121
            'v' => array('в', 'ვ', 'ϐ'),
1122
            'w' => array('ŵ', 'ω', 'ώ', 'ဝ', 'ွ'),
1123
            'x' => array('χ', 'ξ'),
1124
            'y' => array(
1125
                'ý',
1126
                'ỳ',
1127
                'ỷ',
1128
                'ỹ',
1129
                'ỵ',
1130
                'ÿ',
1131
                'ŷ',
1132
                'й',
1133
                'ы',
1134
                'υ',
1135
                'ϋ',
1136
                'ύ',
1137
                'ΰ',
1138
                'ي',
1139
                'ယ'
1140
            ),
1141
            'z' => array('ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'),
1142
            'aa' => array('ع', 'आ', 'آ'),
1143
            'ae' => array('ä', 'æ', 'ǽ'),
1144
            'ai' => array('ऐ'),
1145
            'at' => array('@'),
1146
            'ch' => array('ч', 'ჩ', 'ჭ', 'چ'),
1147
            'dj' => array('ђ', 'đ'),
1148
            'dz' => array('џ', 'ძ'),
1149
            'ei' => array('ऍ'),
1150
            'gh' => array('غ', 'ღ'),
1151
            'ii' => array('ई'),
1152
            'ij' => array('ij'),
1153
            'kh' => array('х', 'خ', 'ხ'),
1154
            'lj' => array('љ'),
1155
            'nj' => array('њ'),
1156
            'oe' => array('ö', 'œ', 'ؤ'),
1157
            'oi' => array('ऑ'),
1158
            'oii' => array('ऒ'),
1159
            'ps' => array('ψ'),
1160
            'sh' => array('ш', 'შ', 'ش'),
1161
            'shch' => array('щ'),
1162
            'ss' => array('ß'),
1163
            'sx' => array('ŝ'),
1164
            'th' => array('þ', 'ϑ', 'ث', 'ذ', 'ظ'),
1165
            'ts' => array('ц', 'ც', 'წ'),
1166
            'ue' => array('ü'),
1167
            'uu' => array('ऊ'),
1168
            'ya' => array('я'),
1169
            'yu' => array('ю'),
1170
            'zh' => array('ж', 'ჟ', 'ژ'),
1171
            '(c)' => array('©'),
1172
            'A' => array(
1173
                'Á',
1174
                'À',
1175
                'Ả',
1176
                'Ã',
1177
                'Ạ',
1178
                'Ă',
1179
                'Ắ',
1180
                'Ằ',
1181
                'Ẳ',
1182
                'Ẵ',
1183
                'Ặ',
1184
                'Â',
1185
                'Ấ',
1186
                'Ầ',
1187
                'Ẩ',
1188
                'Ẫ',
1189
                'Ậ',
1190
                'Å',
1191
                'Ā',
1192
                'Ą',
1193
                'Α',
1194
                'Ά',
1195
                'Ἀ',
1196
                'Ἁ',
1197
                'Ἂ',
1198
                'Ἃ',
1199
                'Ἄ',
1200
                'Ἅ',
1201
                'Ἆ',
1202
                'Ἇ',
1203
                'ᾈ',
1204
                'ᾉ',
1205
                'ᾊ',
1206
                'ᾋ',
1207
                'ᾌ',
1208
                'ᾍ',
1209
                'ᾎ',
1210
                'ᾏ',
1211
                'Ᾰ',
1212
                'Ᾱ',
1213
                'Ὰ',
1214
                'Ά',
1215
                'ᾼ',
1216
                'А',
1217
                'Ǻ',
1218
                'Ǎ'
1219
            ),
1220
            'B' => array('Б', 'Β', 'ब'),
1221
            'C' => array('Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'),
1222
            'D' => array('Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'),
1223
            'E' => array(
1224
                'É',
1225
                'È',
1226
                'Ẻ',
1227
                'Ẽ',
1228
                'Ẹ',
1229
                'Ê',
1230
                'Ế',
1231
                'Ề',
1232
                'Ể',
1233
                'Ễ',
1234
                'Ệ',
1235
                'Ë',
1236
                'Ē',
1237
                'Ę',
1238
                'Ě',
1239
                'Ĕ',
1240
                'Ė',
1241
                'Ε',
1242
                'Έ',
1243
                'Ἐ',
1244
                'Ἑ',
1245
                'Ἒ',
1246
                'Ἓ',
1247
                'Ἔ',
1248
                'Ἕ',
1249
                'Έ',
1250
                'Ὲ',
1251
                'Е',
1252
                'Ё',
1253
                'Э',
1254
                'Є',
1255
                'Ə'
1256
            ),
1257
            'F' => array('Ф', 'Φ'),
1258
            'G' => array('Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'),
1259
            'H' => array('Η', 'Ή', 'Ħ'),
1260
            'I' => array(
1261
                'Í',
1262
                'Ì',
1263
                'Ỉ',
1264
                'Ĩ',
1265
                'Ị',
1266
                'Î',
1267
                'Ï',
1268
                'Ī',
1269
                'Ĭ',
1270
                'Į',
1271
                'İ',
1272
                'Ι',
1273
                'Ί',
1274
                'Ϊ',
1275
                'Ἰ',
1276
                'Ἱ',
1277
                'Ἳ',
1278
                'Ἴ',
1279
                'Ἵ',
1280
                'Ἶ',
1281
                'Ἷ',
1282
                'Ῐ',
1283
                'Ῑ',
1284
                'Ὶ',
1285
                'Ί',
1286
                'И',
1287
                'І',
1288
                'Ї',
1289
                'Ǐ',
1290
                'ϒ'
1291
            ),
1292
            'K' => array('К', 'Κ'),
1293
            'L' => array('Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'),
1294
            'M' => array('М', 'Μ'),
1295
            'N' => array('Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'),
1296
            'O' => array(
1297
                'Ó',
1298
                'Ò',
1299
                'Ỏ',
1300
                'Õ',
1301
                'Ọ',
1302
                'Ô',
1303
                'Ố',
1304
                'Ồ',
1305
                'Ổ',
1306
                'Ỗ',
1307
                'Ộ',
1308
                'Ơ',
1309
                'Ớ',
1310
                'Ờ',
1311
                'Ở',
1312
                'Ỡ',
1313
                'Ợ',
1314
                'Ø',
1315
                'Ō',
1316
                'Ő',
1317
                'Ŏ',
1318
                'Ο',
1319
                'Ό',
1320
                'Ὀ',
1321
                'Ὁ',
1322
                'Ὂ',
1323
                'Ὃ',
1324
                'Ὄ',
1325
                'Ὅ',
1326
                'Ὸ',
1327
                'Ό',
1328
                'О',
1329
                'Θ',
1330
                'Ө',
1331
                'Ǒ',
1332
                'Ǿ'
1333
            ),
1334
            'P' => array('П', 'Π'),
1335
            'R' => array('Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'),
1336
            'S' => array('Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'),
1337
            'T' => array('Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'),
1338
            'U' => array(
1339
                'Ú',
1340
                'Ù',
1341
                'Ủ',
1342
                'Ũ',
1343
                'Ụ',
1344
                'Ư',
1345
                'Ứ',
1346
                'Ừ',
1347
                'Ử',
1348
                'Ữ',
1349
                'Ự',
1350
                'Û',
1351
                'Ū',
1352
                'Ů',
1353
                'Ű',
1354
                'Ŭ',
1355
                'Ų',
1356
                'У',
1357
                'Ǔ',
1358
                'Ǖ',
1359
                'Ǘ',
1360
                'Ǚ',
1361
                'Ǜ'
1362
            ),
1363
            'V' => array('В'),
1364
            'W' => array('Ω', 'Ώ', 'Ŵ'),
1365
            'X' => array('Χ', 'Ξ'),
1366
            'Y' => array(
1367
                'Ý',
1368
                'Ỳ',
1369
                'Ỷ',
1370
                'Ỹ',
1371
                'Ỵ',
1372
                'Ÿ',
1373
                'Ῠ',
1374
                'Ῡ',
1375
                'Ὺ',
1376
                'Ύ',
1377
                'Ы',
1378
                'Й',
1379
                'Υ',
1380
                'Ϋ',
1381
                'Ŷ'
1382
            ),
1383
            'Z' => array('Ź', 'Ž', 'Ż', 'З', 'Ζ'),
1384
            'AE' => array('Ä', 'Æ', 'Ǽ'),
1385
            'CH' => array('Ч'),
1386
            'DJ' => array('Ђ'),
1387
            'DZ' => array('Џ'),
1388
            'GX' => array('Ĝ'),
1389
            'HX' => array('Ĥ'),
1390
            'IJ' => array('IJ'),
1391
            'JX' => array('Ĵ'),
1392
            'KH' => array('Х'),
1393
            'LJ' => array('Љ'),
1394
            'NJ' => array('Њ'),
1395
            'OE' => array('Ö', 'Œ'),
1396
            'PS' => array('Ψ'),
1397
            'SH' => array('Ш'),
1398
            'SHCH' => array('Щ'),
1399
            'SS' => array('ẞ'),
1400
            'TH' => array('Þ'),
1401
            'TS' => array('Ц'),
1402
            'UE' => array('Ü'),
1403
            'YA' => array('Я'),
1404
            'YU' => array('Ю'),
1405
            'ZH' => array('Ж'),
1406
            ' ' => array(
1407
                "\xC2\xA0",
1408
                "\xE2\x80\x80",
1409
                "\xE2\x80\x81",
1410
                "\xE2\x80\x82",
1411
                "\xE2\x80\x83",
1412
                "\xE2\x80\x84",
1413
                "\xE2\x80\x85",
1414
                "\xE2\x80\x86",
1415
                "\xE2\x80\x87",
1416
                "\xE2\x80\x88",
1417
                "\xE2\x80\x89",
1418
                "\xE2\x80\x8A",
1419
                "\xE2\x80\xAF",
1420
                "\xE2\x81\x9F",
1421
                "\xE3\x80\x80"
1422
            ),
1423
        );
1424
    }
1425
}
1426
if (!function_exists('charsArrayRegEx')) {
1427
    /**
1428
     * Returns regex to replacements for diacritics, German chars, and non ASCII chars.
1429
     *
1430
     * @return array An array of regex.
1431
     */
1432
    function charsArrayRegEx()
1433
    {
1434
        return array(
1435
            // maps German (umlauts) and other European characters onto two characters
1436
            // before just removing diacritics
1437
            "AE" => '/\x{00c4}/u', // umlaut Ä => AE
1438
            "OE" => '/\x{00d6}/u', // umlaut Ö => OE
1439
            "UE" => '/\x{00dc}/u', // umlaut Ü => UE
1440
            "ae" => '/\x{00e4}/u', // umlaut ä => ae
1441
            "oe" => '/\x{00f6}/u', // umlaut ö => oe
1442
            "ue" => '/\x{00fc}/u', // umlaut ü => ue
1443
            "ny" => '/\x{00f1}/u', // ñ => ny
1444
            "yu" => '/\x{00ff}/u', // ÿ => yu
1445
1446
            "" => '/\pM/u', // removes diacritics
1447
1448
            "ss" => '/\x{00df}/u', // maps German ß onto ss
1449
            "AE" => '/\x{00c6}/u', // Æ => AE
1450
            "ae" => '/\x{00e6}/u', // æ => ae
1451
            "IJ" => '/\x{0132}/u', // ? => IJ
1452
            "ij" => '/\x{0133}/u', // ? => ij
1453
            "OE" => '/\x{0152}/u', // Œ => OE
1454
            "oe" => '/\x{0153}/u', // œ => oe
1455
1456
            "D" => '/\x{00d0}/u', // Ð => D
1457
            "D" => '/\x{0110}/u', // Ð => D
1458
            "d" => '/\x{00f0}/u', // ð => d
1459
            "d" => '/\x{0111}/u', // d => d
1460
            "H" => '/\x{0126}/u', // H => H
1461
            "h" => '/\x{0127}/u', // h => h
1462
            "i" => '/\x{0131}/u', // i => i
1463
            "k" => '/\x{0138}/u', // ? => k
1464
            "L" => '/\x{013f}/u', // ? => L
1465
            "L" => '/\x{0141}/u', // L => L
1466
            "l" => '/\x{0140}/u', // ? => l
1467
            "l" => '/\x{0142}/u', // l => l
1468
            "N" => '/\x{014a}/u', // ? => N
1469
            "n" => '/\x{0149}/u', // ? => n
1470
            "n" => '/\x{014b}/u', // ? => n
1471
            "O" => '/\x{00d8}/u', // Ø => O
1472
            "o" => '/\x{00f8}/u', // ø => o
1473
            "s" => '/\x{017f}/u', // ? => s
1474
            "T" => '/\x{00de}/u', // Þ => T
1475
            "T" => '/\x{0166}/u', // T => T
1476
            "t" => '/\x{00fe}/u', // þ => t
1477
            "t" => '/\x{0167}/u', // t => t
1478
1479
            '' => '/[^\x20-\x7E]/u', // remove all non-ASCii characters
1480
            '' => '/[^\0-\x80]/u', // remove all non-ASCii characters
1481
        );
1482
    }
1483
}
1484
1485
if (!function_exists('firstStringBetween')) {
1486
1487
    /**
1488
     * Returns the first string there is between the strings from the parameter start and end.
1489
     * Example:
1490
     * firstStringBetween('This is a [custom] string', '[', ']'); // return 'custom'
1491
     * if start char and/or end char doesn't exists, return ''.
1492
     *
1493
     * @param $haystack
1494
     * @param $start
1495
     * @param $end
1496
     * @return bool|string
1497
     */
1498
    function firstStringBetween($haystack, $start, $end)
1499
    {
1500
        $char = strpos($haystack, $start);
1501
        if (!$char) {
1502
            return '';
1503
        }
1504
1505
        $endchar = strpos($haystack, $end);
1506
        if (!$endchar) {
1507
            return '';
1508
        }
1509
1510
        $char += strlen($start);
1511
        $len = strpos($haystack, $end, $char) - $char;
1512
1513
        return substr($haystack, $char, $len);
1514
    }
1515
}
1516