Passed
Push — main ( 132b3b...272bc9 )
by Andrey
14:05 queued 12:17
created

Str   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 462
Duplicated Lines 0 %

Test Coverage

Coverage 94.85%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 82
dl 0
loc 462
ccs 92
cts 97
cp 0.9485
rs 5.04
c 4
b 0
f 0
wmc 57

24 Methods

Rating   Name   Duplication   Size   Complexity  
A replace() 0 3 1
A length() 0 5 2
A camel() 0 7 2
A startsWith() 0 9 4
A removeSpaces() 0 3 1
A snake() 0 15 3
A e() 0 7 2
A before() 0 3 2
A isEmpty() 0 5 5
A doesntEmpty() 0 3 1
A upper() 0 3 1
A after() 0 3 2
A lower() 0 3 1
A contains() 0 9 4
A ascii() 0 3 1
A endsWith() 0 9 4
A slug() 0 19 3
A finish() 0 5 1
A studly() 0 11 2
A substr() 0 3 1
A de() 0 3 1
B choice() 0 25 9
A start() 0 5 1
A title() 0 7 3

How to fix   Complexity   

Complex Class

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
namespace Helldar\Support\Helpers;
4
5
use Helldar\Support\Facades\Helpers\Call as CallHelper;
6
use Illuminate\Contracts\Support\DeferringDisplayableValue;
0 ignored issues
show
Bug introduced by
The type Illuminate\Contracts\Sup...ferringDisplayableValue 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...
7
use Illuminate\Contracts\Support\Htmlable;
0 ignored issues
show
Bug introduced by
The type Illuminate\Contracts\Support\Htmlable 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...
8
use voku\helper\ASCII;
9
10
final class Str
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
    protected $escaping_methods = [
34
        DeferringDisplayableValue::class => 'resolveDisplayableValue',
35
        Htmlable::class                  => 'toHtml',
36
    ];
37
38
    /**
39
     * Escape HTML special characters in a string.
40
     *
41
     * @param  string|null  $value
42
     * @param  bool  $double
43
     *
44
     * @return string|null
45
     */
46 2
    public function e(?string $value, bool $double = true): ?string
47
    {
48 2
        if ($escaped = CallHelper::runOf($this->escaping_methods, $value)) {
49
            return $escaped;
50
        }
51
52 2
        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', $double);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of htmlspecialchars() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

52
        return htmlspecialchars(/** @scrutinizer ignore-type */ $value, ENT_QUOTES, 'UTF-8', $double);
Loading history...
53
    }
54
55
    /**
56
     * Convert special HTML entities back to characters.
57
     *
58
     * @param  string|null  $value
59
     *
60
     * @return string|null
61
     */
62 2
    public function de(?string $value): ?string
63
    {
64 2
        return htmlspecialchars_decode($value, ENT_QUOTES);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of htmlspecialchars_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

64
        return htmlspecialchars_decode(/** @scrutinizer ignore-type */ $value, ENT_QUOTES);
Loading history...
65
    }
66
67
    /**
68
     * Replacing multiple spaces with a single space.
69
     *
70
     * @param  string|null  $value
71
     *
72
     * @return string|null
73
     */
74 2
    public function removeSpaces(?string $value): ?string
75
    {
76 2
        return preg_replace('!\s+!', ' ', $value);
77
    }
78
79
    /**
80
     * Get a string according to an integer value.
81
     *
82
     * @param  float  $number
83
     * @param  array  $choice
84
     * @param  string|null  $extra
85
     *
86
     * @return string
87
     */
88 2
    public function choice(float $number, array $choice = [], string $extra = null): string
89
    {
90 2
        $number = (int) $number;
91 2
        $mod    = $number % 10;
92
93
        switch (true) {
94 2
            case $mod === 0:
95 2
            case $mod >= 5 && $mod <= 9:
96 2
            case ($number % 100 >= 11) && ($number % 100 <= 20):
97 2
                $result = $choice[2] ?? '';
98 2
                break;
99
100 2
            case $mod >= 2 && $mod <= 4:
101
                $result = $choice[1] ?? '';
102
                break;
103
104
            default:
105 2
                $result = $choice[0] ?? '';
106
        }
107
108 2
        if (empty($extra)) {
109 2
            return trim($result);
110
        }
111
112 2
        return implode(' ', [trim($result), trim($extra)]);
113
    }
114
115
    /**
116
     * Begin a string with a single instance of a given value.
117
     *
118
     * @see https://github.com/illuminate/support/blob/master/Str.php
119
     *
120
     * @param  string|null  $value
121
     * @param  string  $prefix
122
     *
123
     * @return string
124
     */
125 2
    public function start(?string $value, string $prefix): string
126
    {
127 2
        $quoted = preg_quote($prefix, '/');
128
129 2
        return $prefix . preg_replace('/^(?:' . $quoted . ')+/u', '', $value);
130
    }
131
132
    /**
133
     * Cap a string with a single instance of a given value.
134
     *
135
     * @see https://github.com/illuminate/support/blob/master/Str.php
136
     *
137
     * @param  string  $value
138
     * @param  string  $cap
139
     *
140
     * @return string
141
     */
142 2
    public function finish(string $value, string $cap = '/'): string
143
    {
144 2
        $quoted = preg_quote($cap, '/');
145
146 2
        return preg_replace('/(?:' . $quoted . ')+$/u', '', $value) . $cap;
147
    }
148
149
    /**
150
     *  Determine if a given string starts with a given substring.
151
     *
152
     * @see https://github.com/illuminate/support/blob/master/Str.php
153
     *
154
     * @param  string  $haystack
155
     * @param  string|string[]  $needles
156
     *
157
     * @return bool
158
     */
159 94
    public function startsWith(string $haystack, $needles): bool
160
    {
161 94
        foreach ((array) $needles as $needle) {
162 94
            if ((string) $needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0) {
163 94
                return true;
164
            }
165
        }
166
167 92
        return false;
168
    }
169
170
    /**
171
     * Determine if a given string ends with a given substring.
172
     *
173
     * @see https://github.com/illuminate/support/blob/master/Str.php
174
     *
175
     * @param  string  $haystack
176
     * @param  string|string[]  $needles
177
     *
178
     * @return bool
179
     */
180 6
    public function endsWith(string $haystack, $needles): bool
181
    {
182 6
        foreach ((array) $needles as $needle) {
183 6
            if ($needle !== '' && substr($haystack, -strlen($needle)) === (string) $needle) {
184 6
                return true;
185
            }
186
        }
187
188 6
        return false;
189
    }
190
191
    /**
192
     * Convert the given string to lower-case.
193
     *
194
     * @see https://github.com/illuminate/support/blob/master/Str.php
195
     *
196
     * @param  string|null  $value
197
     *
198
     * @return string
199
     */
200 127
    public function lower(?string $value): string
201
    {
202 127
        return mb_strtolower($value, 'UTF-8');
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of mb_strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

202
        return mb_strtolower(/** @scrutinizer ignore-type */ $value, 'UTF-8');
Loading history...
203
    }
204
205
    /**
206
     * Convert the given string to upper-case.
207
     *
208
     * @see https://github.com/illuminate/support/blob/master/Str.php
209
     *
210
     * @param  string|null  $value
211
     *
212
     * @return string
213
     */
214 2
    public function upper(?string $value): ?string
215
    {
216 2
        return mb_strtoupper($value, 'UTF-8');
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of mb_strtoupper() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

216
        return mb_strtoupper(/** @scrutinizer ignore-type */ $value, 'UTF-8');
Loading history...
217
    }
218
219
    /**
220
     * Convert a value to studly caps case.
221
     *
222
     * @see https://github.com/illuminate/support/blob/master/Str.php
223
     *
224
     * @param  string|null  $value
225
     *
226
     * @return string|null
227
     */
228 37
    public function studly(?string $value): ?string
229
    {
230 37
        $key = $value;
231
232 37
        if (isset(self::$studlyCache[$key])) {
233 3
            return self::$studlyCache[$key];
234
        }
235
236 34
        $value = ucwords(str_replace(['-', '_'], ' ', $value));
237
238 34
        return self::$studlyCache[$key] = str_replace(' ', '', $value);
239
    }
240
241
    /**
242
     * Convert a value to camel case.
243
     *
244
     * @see https://github.com/illuminate/support/blob/master/Str.php
245
     *
246
     * @param  string|null  $value
247
     *
248
     * @return string|null
249
     */
250 34
    public function camel(?string $value): ?string
251
    {
252 34
        if (isset(self::$camelCache[$value])) {
253 1
            return self::$camelCache[$value];
254
        }
255
256 33
        return self::$camelCache[$value] = lcfirst($this->studly($value));
257
    }
258
259
    /**
260
     * Convert a string to snake case.
261
     *
262
     * @see https://github.com/illuminate/support/blob/master/Str.php
263
     *
264
     * @param  string|null  $value
265
     * @param  string  $delimiter
266
     *
267
     * @return string|null
268
     */
269 2
    public function snake(?string $value, string $delimiter = '_'): ?string
270
    {
271 2
        $key = $value;
272
273 2
        if (isset(self::$snakeCache[$key][$delimiter])) {
274 1
            return self::$snakeCache[$key][$delimiter];
275
        }
276
277 1
        if (! ctype_lower($value)) {
278 1
            $value = preg_replace('/\s+/u', '', ucwords($value));
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of ucwords() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

278
            $value = preg_replace('/\s+/u', '', ucwords(/** @scrutinizer ignore-type */ $value));
Loading history...
279
280 1
            $value = $this->lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
281
        }
282
283 1
        return self::$snakeCache[$key][$delimiter] = $value;
284
    }
285
286
    /**
287
     * Generate a URL friendly "slug" from a given string.
288
     *
289
     * @see https://github.com/illuminate/support/blob/master/Str.php
290
     *
291
     * @param  string  $title
292
     * @param  string  $separator
293
     * @param  string|null  $language
294
     *
295
     * @return string
296
     */
297 2
    public function slug(string $title, string $separator = '-', ?string $language = 'en')
298
    {
299 2
        $title = $language ? $this->ascii($title, $language) : $title;
300
301
        // Convert all dashes/underscores into separator
302 2
        $flip = $separator === '-' ? '_' : '-';
303
304 2
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
305
306
        // Replace @ with the word 'at'
307 2
        $title = str_replace('@', $separator . 'at' . $separator, $title);
308
309
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
310 2
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', $this->lower($title));
311
312
        // Replace all separator characters and whitespace by a single separator
313 2
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
314
315 2
        return trim($title, $separator);
316
    }
317
318
    /**
319
     * Convert the given string to title case.
320
     *
321
     * @see https://github.com/illuminate/support/blob/master/Str.php
322
     *
323
     * @param  string|null  $value
324
     *
325
     * @return string|null
326
     */
327 2
    public function title(?string $value): ?string
328
    {
329 2
        if (is_numeric($value)) {
330 2
            return $value;
331
        }
332
333 2
        return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8') ?: null;
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of mb_convert_case() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

333
        return mb_convert_case(/** @scrutinizer ignore-type */ $value, MB_CASE_TITLE, 'UTF-8') ?: null;
Loading history...
334
    }
335
336
    /**
337
     * Return the length of the given string.
338
     *
339
     * @see https://github.com/illuminate/support/blob/master/Str.php
340
     *
341
     * @param  string|null  $value
342
     * @param  string|null  $encoding
343
     *
344
     * @return int
345
     */
346 2
    public function length(?string $value, string $encoding = null): int
347
    {
348 2
        return $encoding
349 2
            ? mb_strlen($value, $encoding)
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $string of mb_strlen() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

349
            ? mb_strlen(/** @scrutinizer ignore-type */ $value, $encoding)
Loading history...
350 2
            : mb_strlen($value);
351
    }
352
353
    /**
354
     * Returns the portion of string specified by the start and length parameters.
355
     *
356
     * @see https://github.com/illuminate/support/blob/master/Str.php
357
     *
358
     * @param  string  $string
359
     * @param  int  $start
360
     * @param  int|null  $length
361
     *
362
     * @return string|null
363
     */
364 2
    public function substr(string $string, int $start, int $length = null): ?string
365
    {
366 2
        return mb_substr($string, $start, $length, 'UTF-8');
367
    }
368
369
    /**
370
     * Replace all occurrences of the search string with the replacement string.
371
     *
372
     * @param  string  $template
373
     * @param  array  $values
374
     *
375
     * @return string
376
     */
377 2
    public function replace(string $template, array $values): string
378
    {
379 2
        return str_replace(array_keys($values), array_values($values), $template);
380
    }
381
382
    /**
383
     * Get the portion of a string before the first occurrence of a given value.
384
     *
385
     * @see https://github.com/illuminate/support/blob/master/Str.php
386
     *
387
     * @param  string  $subject
388
     * @param  string  $search
389
     *
390
     * @return string
391
     */
392
    public function before(string $subject, string $search): ?string
393
    {
394
        return ! empty($search) ? explode($search, $subject)[0] : null;
395
    }
396
397
    /**
398
     * Return the remainder of a string after the first occurrence of a given value.
399
     *
400
     * @see https://github.com/illuminate/support/blob/master/Str.php
401
     *
402
     * @param  string  $subject
403
     * @param  string  $search
404
     *
405
     * @return string
406
     */
407 88
    public function after(string $subject, string $search): ?string
408
    {
409 88
        return ! empty($search) ? array_reverse(explode($search, $subject, 2))[0] : null;
410
    }
411
412
    /**
413
     * Determine if a given string contains a given substring.
414
     *
415
     * @see https://github.com/illuminate/support/blob/master/Str.php
416
     *
417
     * @param  string  $haystack
418
     * @param  string|string[]  $needles
419
     *
420
     * @return bool
421
     */
422 24
    public function contains(string $haystack, $needles): bool
423
    {
424 24
        foreach ((array) $needles as $needle) {
425 24
            if (! empty($needle) && mb_strpos($haystack, $needle) !== false) {
426 22
                return true;
427
            }
428
        }
429
430 4
        return false;
431
    }
432
433
    /**
434
     * Determines if the value is empty.
435
     *
436
     * @param  mixed  $value
437
     *
438
     * @return bool
439
     */
440 8
    public function isEmpty($value): bool
441
    {
442 8
        $value = is_string($value) ? trim($value) : $value;
443
444 8
        return empty($value) && ! is_numeric($value) && (is_string($value) || is_null($value));
445
    }
446
447
    /**
448
     * Determines if the value is doesn't empty.
449
     *
450
     * @param  mixed  $value
451
     *
452
     * @return bool
453
     */
454 2
    public function doesntEmpty($value): bool
455
    {
456 2
        return ! $this->isEmpty($value);
457
    }
458
459
    /**
460
     * Transliterate a UTF-8 value to ASCII.
461
     *
462
     * @see https://github.com/illuminate/support/blob/master/Str.php
463
     *
464
     * @param  string|null  $value
465
     * @param  string|null  $language
466
     *
467
     * @return string
468
     */
469 4
    public function ascii(?string $value, ?string $language = 'en'): string
470
    {
471 4
        return ASCII::to_ascii((string) $value, $language);
0 ignored issues
show
Bug introduced by
It seems like $language can also be of type null; however, parameter $language of voku\helper\ASCII::to_ascii() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

471
        return ASCII::to_ascii((string) $value, /** @scrutinizer ignore-type */ $language);
Loading history...
472
    }
473
}
474