Passed
Branch master (a62c84)
by Salah
02:38
created

Str   F

Complexity

Total Complexity 59

Size/Duplication

Total Lines 665
Duplicated Lines 8.12 %

Importance

Changes 0
Metric Value
dl 54
loc 665
rs 2.3727
c 0
b 0
f 0
wmc 59

30 Methods

Rating   Name   Duplication   Size   Complexity  
A camel() 0 7 2
A start() 0 5 1
A parseCallback() 0 3 2
A quickRandom() 0 9 2
A random() 0 13 2
A ucfirst() 0 3 1
A plural() 0 3 1
A slug() 0 16 2
A ascii() 0 7 2
A substr() 0 3 1
A singular() 0 3 1
A contains() 9 9 4
B charsArray() 0 122 2
A snake() 0 15 3
A limit() 0 7 2
A endsWith() 9 9 3
A lower() 0 3 1
A length() 0 7 2
A kebab() 0 3 1
A startsWith() 9 9 4
A studly() 0 11 2
A title() 0 3 1
A replaceArray() 0 7 2
A finish() 0 5 1
A replaceLast() 9 9 2
A is() 0 14 2
A upper() 0 3 1
A words() 0 9 3
A after() 0 13 3
A replaceFirst() 13 13 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Str often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Str, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * Copyright (c) 2017 Salah Alkhwlani <[email protected]>
5
 *
6
 * For the full copyright and license information, please view
7
 * the LICENSE file that was distributed with this source code.
8
 */
9
10
namespace Yemenifree\PickServices\Helpers;
11
12
class Str
13
{
14
    /**
15
     * The cache of snake-cased words.
16
     *
17
     * @var array
18
     */
19
    protected static $snakeCache = [];
20
21
    /**
22
     * The cache of camel-cased words.
23
     *
24
     * @var array
25
     */
26
    protected static $camelCache = [];
27
28
    /**
29
     * The cache of studly-cased words.
30
     *
31
     * @var array
32
     */
33
    protected static $studlyCache = [];
34
35
    /**
36
     * Return the remainder of a string after a given value.
37
     *
38
     * @param string $subject
39
     * @param string $search
40
     *
41
     * @return string
42
     */
43
    public static function after($subject, $search)
44
    {
45
        if ($search == '') {
46
            return $subject;
47
        }
48
49
        $pos = \strpos($subject, $search);
50
51
        if ($pos === false) {
52
            return $subject;
53
        }
54
55
        return \substr($subject, $pos + \strlen($search));
56
    }
57
58
    /**
59
     * Convert a value to camel case.
60
     *
61
     * @param string $value
62
     *
63
     * @return string
64
     */
65
    public static function camel($value)
66
    {
67
        if (isset(static::$camelCache[$value])) {
68
            return static::$camelCache[$value];
69
        }
70
71
        return static::$camelCache[$value] = \lcfirst(static::studly($value));
72
    }
73
74
    /**
75
     * Convert a value to studly caps case.
76
     *
77
     * @param string $value
78
     *
79
     * @return string
80
     */
81
    public static function studly($value)
82
    {
83
        $key = $value;
84
85
        if (isset(static::$studlyCache[$key])) {
86
            return static::$studlyCache[$key];
87
        }
88
89
        $value = \ucwords(\str_replace(['-', '_'], ' ', $value));
90
91
        return static::$studlyCache[$key] = \str_replace(' ', '', $value);
92
    }
93
94
    /**
95
     * Determine if a given string ends with a given substring.
96
     *
97
     * @param string       $haystack
98
     * @param string|array $needles
99
     *
100
     * @return bool
101
     */
102 View Code Duplication
    public static function endsWith($haystack, $needles)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
103
    {
104
        foreach ((array) $needles as $needle) {
105
            if (\substr($haystack, -\strlen($needle)) === (string) $needle) {
106
                return true;
107
            }
108
        }
109
110
        return false;
111
    }
112
113
    /**
114
     * Cap a string with a single instance of a given value.
115
     *
116
     * @param string $value
117
     * @param string $cap
118
     *
119
     * @return string
120
     */
121
    public static function finish($value, $cap)
122
    {
123
        $quoted = \preg_quote($cap, '/');
124
125
        return \preg_replace('/(?:' . $quoted . ')+$/u', '', $value) . $cap;
126
    }
127
128
    /**
129
     * Determine if a given string matches a given pattern.
130
     *
131
     * @param string $pattern
132
     * @param string $value
133
     *
134
     * @return bool
135
     */
136
    public static function is($pattern, $value)
137
    {
138
        if ($pattern == $value) {
139
            return true;
140
        }
141
142
        $pattern = \preg_quote($pattern, '#');
143
144
        // Asterisks are translated into zero-or-more regular expression wildcards
145
        // to make it convenient to check if the strings starts with the given
146
        // pattern such as "library/*", making any string check convenient.
147
        $pattern = \str_replace('\*', '.*', $pattern);
148
149
        return (bool) \preg_match('#^' . $pattern . '\z#u', $value);
150
    }
151
152
    /**
153
     * Convert a string to kebab case.
154
     *
155
     * @param string $value
156
     *
157
     * @return string
158
     */
159
    public static function kebab($value)
160
    {
161
        return static::snake($value, '-');
162
    }
163
164
    /**
165
     * Convert a string to snake case.
166
     *
167
     * @param string $value
168
     * @param string $delimiter
169
     *
170
     * @return string
171
     */
172
    public static function snake($value, $delimiter = '_')
173
    {
174
        $key = $value;
175
176
        if (isset(static::$snakeCache[$key][$delimiter])) {
177
            return static::$snakeCache[$key][$delimiter];
178
        }
179
180
        if (!\ctype_lower($value)) {
181
            $value = \preg_replace('/\s+/u', '', $value);
182
183
            $value = static::lower(\preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
184
        }
185
186
        return static::$snakeCache[$key][$delimiter] = $value;
187
    }
188
189
    /**
190
     * Convert the given string to lower-case.
191
     *
192
     * @param string $value
193
     *
194
     * @return string
195
     */
196
    public static function lower($value)
197
    {
198
        return \mb_strtolower($value, 'UTF-8');
199
    }
200
201
    /**
202
     * Limit the number of characters in a string.
203
     *
204
     * @param string $value
205
     * @param int    $limit
206
     * @param string $end
207
     *
208
     * @return string
209
     */
210
    public static function limit($value, $limit = 100, $end = '...')
211
    {
212
        if (\mb_strwidth($value, 'UTF-8') <= $limit) {
213
            return $value;
214
        }
215
216
        return \rtrim(\mb_strimwidth($value, 0, $limit, '', 'UTF-8')) . $end;
217
    }
218
219
    /**
220
     * Limit the number of words in a string.
221
     *
222
     * @param string $value
223
     * @param int    $words
224
     * @param string $end
225
     *
226
     * @return string
227
     */
228
    public static function words($value, $words = 100, $end = '...')
229
    {
230
        \preg_match('/^\s*+(?:\S++\s*+){1,' . $words . '}/u', $value, $matches);
231
232
        if (!isset($matches[0]) || static::length($value) === static::length($matches[0])) {
233
            return $value;
234
        }
235
236
        return \rtrim($matches[0]) . $end;
237
    }
238
239
    /**
240
     * Return the length of the given string.
241
     *
242
     * @param string $value
243
     * @param string $encoding
244
     *
245
     * @return int
246
     */
247
    public static function length($value, $encoding = null)
248
    {
249
        if ($encoding) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encoding of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
250
            return \mb_strlen($value, $encoding);
251
        }
252
253
        return \mb_strlen($value);
254
    }
255
256
    /**
257
     * Parse a Class@method style callback into class and method.
258
     *
259
     * @param string      $callback
260
     * @param string|null $default
261
     *
262
     * @return array
263
     */
264
    public static function parseCallback($callback, $default = null)
265
    {
266
        return static::contains($callback, '@') ? \explode('@', $callback, 2) : [$callback, $default];
267
    }
268
269
    /**
270
     * Determine if a given string contains a given substring.
271
     *
272
     * @param string       $haystack
273
     * @param string|array $needles
274
     *
275
     * @return bool
276
     */
277 View Code Duplication
    public static function contains($haystack, $needles)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
278
    {
279
        foreach ((array) $needles as $needle) {
280
            if ($needle != '' && \mb_strpos($haystack, $needle) !== false) {
281
                return true;
282
            }
283
        }
284
285
        return false;
286
    }
287
288
    /**
289
     * Get the plural form of an English word.
290
     *
291
     * @param string $value
292
     * @param int    $count
293
     *
294
     * @return string
295
     */
296
    public static function plural($value, $count = 2)
297
    {
298
        return Pluralizer::plural($value, $count);
0 ignored issues
show
Bug introduced by
The type Yemenifree\PickServices\Helpers\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...
299
    }
300
301
    /**
302
     * Generate a "random" alpha-numeric string.
303
     *
304
     * Should not be considered sufficient for cryptography, etc.
305
     *
306
     * @deprecated since version 5.3. Use the "random" method directly.
307
     *
308
     * @param int $length
309
     *
310
     * @return string
311
     */
312
    public static function quickRandom($length = 16)
313
    {
314
        if (PHP_MAJOR_VERSION > 5) {
315
            return static::random($length);
316
        }
317
318
        $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
319
320
        return \substr(\str_shuffle(\str_repeat($pool, $length)), 0, $length);
321
    }
322
323
    /**
324
     * Generate a more truly "random" alpha-numeric string.
325
     *
326
     * @param int $length
327
     *
328
     * @return string
329
     */
330
    public static function random($length = 16)
331
    {
332
        $string = '';
333
334
        while (($len = \strlen($string)) < $length) {
335
            $size = $length - $len;
336
337
            $bytes = \random_bytes($size);
338
339
            $string .= \substr(\str_replace(['/', '+', '='], '', \base64_encode($bytes)), 0, $size);
340
        }
341
342
        return $string;
343
    }
344
345
    /**
346
     * Replace a given value in the string sequentially with an array.
347
     *
348
     * @param string $search
349
     * @param array  $replace
350
     * @param string $subject
351
     *
352
     * @return string
353
     */
354
    public static function replaceArray($search, array $replace, $subject)
355
    {
356
        foreach ($replace as $value) {
357
            $subject = static::replaceFirst($search, $value, $subject);
358
        }
359
360
        return $subject;
361
    }
362
363
    /**
364
     * Replace the first occurrence of a given value in the string.
365
     *
366
     * @param string $search
367
     * @param string $replace
368
     * @param string $subject
369
     *
370
     * @return string
371
     */
372 View Code Duplication
    public static function replaceFirst($search, $replace, $subject)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
373
    {
374
        if ($search == '') {
375
            return $subject;
376
        }
377
378
        $position = \strpos($subject, $search);
379
380
        if ($position !== false) {
381
            return \substr_replace($subject, $replace, $position, \strlen($search));
382
        }
383
384
        return $subject;
385
    }
386
387
    /**
388
     * Replace the last occurrence of a given value in the string.
389
     *
390
     * @param string $search
391
     * @param string $replace
392
     * @param string $subject
393
     *
394
     * @return string
395
     */
396 View Code Duplication
    public static function replaceLast($search, $replace, $subject)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
397
    {
398
        $position = \strrpos($subject, $search);
399
400
        if ($position !== false) {
401
            return \substr_replace($subject, $replace, $position, \strlen($search));
402
        }
403
404
        return $subject;
405
    }
406
407
    /**
408
     * Begin a string with a single instance of a given value.
409
     *
410
     * @param string $value
411
     * @param string $prefix
412
     *
413
     * @return string
414
     */
415
    public static function start($value, $prefix)
416
    {
417
        $quoted = \preg_quote($prefix, '/');
418
419
        return $prefix . \preg_replace('/^(?:' . $quoted . ')+/u', '', $value);
420
    }
421
422
    /**
423
     * Convert the given string to title case.
424
     *
425
     * @param string $value
426
     *
427
     * @return string
428
     */
429
    public static function title($value)
430
    {
431
        return \mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
432
    }
433
434
    /**
435
     * Get the singular form of an English word.
436
     *
437
     * @param string $value
438
     *
439
     * @return string
440
     */
441
    public static function singular($value)
442
    {
443
        return Pluralizer::singular($value);
444
    }
445
446
    /**
447
     * Generate a URL friendly "slug" from a given string.
448
     *
449
     * @param string $title
450
     * @param string $separator
451
     *
452
     * @return string
453
     */
454
    public static function slug($title, $separator = '-')
455
    {
456
        $title = static::ascii($title);
457
458
        // Convert all dashes/underscores into separator
459
        $flip = $separator == '-' ? '_' : '-';
460
461
        $title = \preg_replace('![' . \preg_quote($flip) . ']+!u', $separator, $title);
462
463
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
464
        $title = \preg_replace('![^' . \preg_quote($separator) . '\pL\pN\s]+!u', '', \mb_strtolower($title));
465
466
        // Replace all separator characters and whitespace by a single separator
467
        $title = \preg_replace('![' . \preg_quote($separator) . '\s]+!u', $separator, $title);
468
469
        return \trim($title, $separator);
470
    }
471
472
    /**
473
     * Transliterate a UTF-8 value to ASCII.
474
     *
475
     * @param string $value
476
     *
477
     * @return string
478
     */
479
    public static function ascii($value)
480
    {
481
        foreach (static::charsArray() as $key => $val) {
482
            $value = \str_replace($val, $key, $value);
483
        }
484
485
        return \preg_replace('/[^\x20-\x7E]/u', '', $value);
486
    }
487
488
    /**
489
     * Returns the replacements for the ascii method.
490
     *
491
     * Note: Adapted from Stringy\Stringy.
492
     *
493
     * @see https://github.com/danielstjules/Stringy/blob/2.3.1/LICENSE.txt
494
     *
495
     * @return array
496
     */
497
    protected static function charsArray()
498
    {
499
        static $charsArray;
500
501
        if (isset($charsArray)) {
502
            return $charsArray;
503
        }
504
505
        return $charsArray = [
506
            '0' => ['°', '₀', '۰'],
507
            '1' => ['¹', '₁', '۱'],
508
            '2' => ['²', '₂', '۲'],
509
            '3' => ['³', '₃', '۳'],
510
            '4' => ['⁴', '₄', '۴', '٤'],
511
            '5' => ['⁵', '₅', '۵', '٥'],
512
            '6' => ['⁶', '₆', '۶', '٦'],
513
            '7' => ['⁷', '₇', '۷'],
514
            '8' => ['⁸', '₈', '۸'],
515
            '9' => ['⁹', '₉', '۹'],
516
            'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا'],
517
            'b' => ['б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'],
518
            'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
519
            'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ'],
520
            'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ'],
521
            'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ'],
522
            'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'],
523
            'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'],
524
            'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ'],
525
            'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج'],
526
            'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'],
527
            'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'],
528
            'm' => ['м', 'μ', 'م', 'မ', 'მ'],
529
            'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ'],
530
            'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ'],
531
            'p' => ['п', 'π', 'ပ', 'პ', 'پ'],
532
            'q' => ['ყ'],
533
            'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'],
534
            's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს'],
535
            't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ'],
536
            'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ'],
537
            'v' => ['в', 'ვ', 'ϐ'],
538
            'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ'],
539
            'x' => ['χ', 'ξ'],
540
            'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ'],
541
            'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'],
542
            'aa' => ['ع', 'आ', 'آ'],
543
            'ae' => ['ä', 'æ', 'ǽ'],
544
            'ai' => ['ऐ'],
545
            'at' => ['@'],
546
            'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
547
            'dj' => ['ђ', 'đ'],
548
            'dz' => ['џ', 'ძ'],
549
            'ei' => ['ऍ'],
550
            'gh' => ['غ', 'ღ'],
551
            'ii' => ['ई'],
552
            'ij' => ['ij'],
553
            'kh' => ['х', 'خ', 'ხ'],
554
            'lj' => ['љ'],
555
            'nj' => ['њ'],
556
            'oe' => ['ö', 'œ', 'ؤ'],
557
            'oi' => ['ऑ'],
558
            'oii' => ['ऒ'],
559
            'ps' => ['ψ'],
560
            'sh' => ['ш', 'შ', 'ش'],
561
            'shch' => ['щ'],
562
            'ss' => ['ß'],
563
            'sx' => ['ŝ'],
564
            'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
565
            'ts' => ['ц', 'ც', 'წ'],
566
            'ue' => ['ü'],
567
            'uu' => ['ऊ'],
568
            'ya' => ['я'],
569
            'yu' => ['ю'],
570
            'zh' => ['ж', 'ჟ', 'ژ'],
571
            '(c)' => ['©'],
572
            'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ'],
573
            'B' => ['Б', 'Β', 'ब'],
574
            'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
575
            'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
576
            'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə'],
577
            'F' => ['Ф', 'Φ'],
578
            'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
579
            'H' => ['Η', 'Ή', 'Ħ'],
580
            'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ'],
581
            'K' => ['К', 'Κ'],
582
            'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'],
583
            'M' => ['М', 'Μ'],
584
            'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
585
            'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ'],
586
            'P' => ['П', 'Π'],
587
            'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
588
            'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
589
            'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
590
            'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ'],
591
            'V' => ['В'],
592
            'W' => ['Ω', 'Ώ', 'Ŵ'],
593
            'X' => ['Χ', 'Ξ'],
594
            'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
595
            'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
596
            'AE' => ['Ä', 'Æ', 'Ǽ'],
597
            'CH' => ['Ч'],
598
            'DJ' => ['Ђ'],
599
            'DZ' => ['Џ'],
600
            'GX' => ['Ĝ'],
601
            'HX' => ['Ĥ'],
602
            'IJ' => ['IJ'],
603
            'JX' => ['Ĵ'],
604
            'KH' => ['Х'],
605
            'LJ' => ['Љ'],
606
            'NJ' => ['Њ'],
607
            'OE' => ['Ö', 'Œ'],
608
            'PS' => ['Ψ'],
609
            'SH' => ['Ш'],
610
            'SHCH' => ['Щ'],
611
            'SS' => ['ẞ'],
612
            'TH' => ['Þ'],
613
            'TS' => ['Ц'],
614
            'UE' => ['Ü'],
615
            'YA' => ['Я'],
616
            'YU' => ['Ю'],
617
            'ZH' => ['Ж'],
618
            ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80"],
619
        ];
620
    }
621
622
    /**
623
     * Determine if a given string starts with a given substring.
624
     *
625
     * @param string       $haystack
626
     * @param string|array $needles
627
     *
628
     * @return bool
629
     */
630 View Code Duplication
    public static function startsWith($haystack, $needles)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
631
    {
632
        foreach ((array) $needles as $needle) {
633
            if ($needle != '' && \substr($haystack, 0, \strlen($needle)) === (string) $needle) {
634
                return true;
635
            }
636
        }
637
638
        return false;
639
    }
640
641
    /**
642
     * Make a string's first character uppercase.
643
     *
644
     * @param string $string
645
     *
646
     * @return string
647
     */
648
    public static function ucfirst($string)
649
    {
650
        return static::upper(static::substr($string, 0, 1)) . static::substr($string, 1);
651
    }
652
653
    /**
654
     * Convert the given string to upper-case.
655
     *
656
     * @param string $value
657
     *
658
     * @return string
659
     */
660
    public static function upper($value)
661
    {
662
        return \mb_strtoupper($value, 'UTF-8');
663
    }
664
665
    /**
666
     * Returns the portion of string specified by the start and length parameters.
667
     *
668
     * @param string   $string
669
     * @param int      $start
670
     * @param int|null $length
671
     *
672
     * @return string
673
     */
674
    public static function substr($string, $start, $length = null)
675
    {
676
        return \mb_substr($string, $start, $length, 'UTF-8');
677
    }
678
}
679