Passed
Pull Request — main (#102)
by Andrey
12:10
created

Str::random()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 13
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Helldar\Support\Helpers;
4
5
use Helldar\Support\Facades\Helpers\Call as CallHelper;
6
use Helldar\Support\Facades\Tools\Replace;
7
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...
8
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...
9
use voku\helper\ASCII;
10
11
final class Str
12
{
13
    /**
14
     * The cache of snake-cased words.
15
     *
16
     * @var array
17
     */
18
    protected static $snakeCache = [];
19
20
    /**
21
     * The cache of camel-cased words.
22
     *
23
     * @var array
24
     */
25
    protected static $camelCache = [];
26
27
    /**
28
     * The cache of studly-cased words.
29
     *
30
     * @var array
31
     */
32
    protected static $studlyCache = [];
33
34
    protected $escaping_methods = [
35
        DeferringDisplayableValue::class => 'resolveDisplayableValue',
36
        Htmlable::class                  => 'toHtml',
37
    ];
38
39
    /**
40
     * Escape HTML special characters in a string.
41
     *
42
     * @param  string|null  $value
43
     * @param  bool  $double
44
     *
45
     * @return string|null
46
     */
47 2
    public function e(?string $value, bool $double = true): ?string
48
    {
49 2
        if ($escaped = CallHelper::runOf($this->escaping_methods, $value)) {
50
            return $escaped;
51
        }
52
53 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

53
        return htmlspecialchars(/** @scrutinizer ignore-type */ $value, ENT_QUOTES, 'UTF-8', $double);
Loading history...
54
    }
55
56
    /**
57
     * Convert special HTML entities back to characters.
58
     *
59
     * @param  string|null  $value
60
     *
61
     * @return string|null
62
     */
63 2
    public function de(?string $value): ?string
64
    {
65 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

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

199
        return mb_strtolower(/** @scrutinizer ignore-type */ $value, 'UTF-8');
Loading history...
200
    }
201
202
    /**
203
     * Convert the given string to upper-case.
204
     *
205
     * @see https://github.com/illuminate/support/blob/master/Str.php
206
     *
207
     * @param  string|null  $value
208
     *
209
     * @return string
210
     */
211 2
    public function upper(?string $value): ?string
212
    {
213 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

213
        return mb_strtoupper(/** @scrutinizer ignore-type */ $value, 'UTF-8');
Loading history...
214
    }
215
216
    /**
217
     * Convert a value to studly caps case.
218
     *
219
     * @see https://github.com/illuminate/support/blob/master/Str.php
220
     *
221
     * @param  string|null  $value
222
     *
223
     * @return string|null
224
     */
225 39
    public function studly(?string $value): ?string
226
    {
227 39
        $key = $value;
228
229 39
        if (isset(self::$studlyCache[$key])) {
230 5
            return self::$studlyCache[$key];
231
        }
232
233 35
        $value = ucwords(str_replace(['-', '_'], ' ', $value));
234
235 35
        return self::$studlyCache[$key] = str_replace(' ', '', $value);
236
    }
237
238
    /**
239
     * Convert a value to camel case.
240
     *
241
     * @see https://github.com/illuminate/support/blob/master/Str.php
242
     *
243
     * @param  string|null  $value
244
     *
245
     * @return string|null
246
     */
247 34
    public function camel(?string $value): ?string
248
    {
249 34
        if (isset(self::$camelCache[$value])) {
250 1
            return self::$camelCache[$value];
251
        }
252
253 33
        return self::$camelCache[$value] = lcfirst($this->studly($value));
254
    }
255
256
    /**
257
     * Convert a string to snake case.
258
     *
259
     * @see https://github.com/illuminate/support/blob/master/Str.php
260
     *
261
     * @param  string|null  $value
262
     * @param  string  $delimiter
263
     *
264
     * @return string|null
265
     */
266 2
    public function snake(?string $value, string $delimiter = '_'): ?string
267
    {
268 2
        $key = $value;
269
270 2
        if (isset(self::$snakeCache[$key][$delimiter])) {
271 1
            return self::$snakeCache[$key][$delimiter];
272
        }
273
274 1
        if (! ctype_lower($value)) {
275 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

275
            $value = preg_replace('/\s+/u', '', ucwords(/** @scrutinizer ignore-type */ $value));
Loading history...
276
277 1
            $value = $this->lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
278
        }
279
280 1
        return self::$snakeCache[$key][$delimiter] = $value;
281
    }
282
283
    /**
284
     * Generate a URL friendly "slug" from a given string.
285
     *
286
     * @see https://github.com/illuminate/support/blob/master/Str.php
287
     *
288
     * @param  string  $title
289
     * @param  string  $separator
290
     * @param  string|null  $language
291
     *
292
     * @return string
293
     */
294 2
    public function slug(string $title, string $separator = '-', ?string $language = 'en')
295
    {
296 2
        $title = $language ? $this->ascii($title, $language) : $title;
297
298
        // Convert all dashes/underscores into separator
299 2
        $flip = $separator === '-' ? '_' : '-';
300
301 2
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
302
303
        // Replace @ with the word 'at'
304 2
        $title = str_replace('@', $separator . 'at' . $separator, $title);
305
306
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
307 2
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', $this->lower($title));
308
309
        // Replace all separator characters and whitespace by a single separator
310 2
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
311
312 2
        return trim($title, $separator);
313
    }
314
315
    /**
316
     * Convert the given string to title case.
317
     *
318
     * @see https://github.com/illuminate/support/blob/master/Str.php
319
     *
320
     * @param  string|null  $value
321
     *
322
     * @return string|null
323
     */
324 2
    public function title(?string $value): ?string
325
    {
326 2
        if (is_numeric($value)) {
327 2
            return $value;
328
        }
329
330 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

330
        return mb_convert_case(/** @scrutinizer ignore-type */ $value, MB_CASE_TITLE, 'UTF-8') ?: null;
Loading history...
331
    }
332
333
    /**
334
     * Return the length of the given string.
335
     *
336
     * @see https://github.com/illuminate/support/blob/master/Str.php
337
     *
338
     * @param  string|null  $value
339
     * @param  string|null  $encoding
340
     *
341
     * @return int
342
     */
343 2
    public function length(?string $value, string $encoding = null): int
344
    {
345 2
        return $encoding
346 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

346
            ? mb_strlen(/** @scrutinizer ignore-type */ $value, $encoding)
Loading history...
347 2
            : mb_strlen($value);
348
    }
349
350
    /**
351
     * Returns the portion of string specified by the start and length parameters.
352
     *
353
     * @see https://github.com/illuminate/support/blob/master/Str.php
354
     *
355
     * @param  string  $string
356
     * @param  int  $start
357
     * @param  int|null  $length
358
     *
359
     * @return string|null
360
     */
361 2
    public function substr(string $string, int $start, int $length = null): ?string
362
    {
363 2
        return mb_substr($string, $start, $length, 'UTF-8');
364
    }
365
366
    /**
367
     * Replace all occurrences of the search string with the replacement string.
368
     *
369
     * @param  string  $template
370
     * @param  array  $values
371
     * @param  string|null  $key_format
372
     *
373
     * @return string
374
     */
375 18
    public function replace(string $template, array $values, string $key_format = null): string
376
    {
377 18
        $keys = Replace::toFormatArray(array_keys($values), $key_format);
378
379 18
        return str_replace($keys, 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
     * @param  string  $haystack
416
     * @param  string|string[]  $needles
417
     *
418
     * @return bool
419
     */
420 26
    public function contains(string $haystack, $needles): bool
421
    {
422 26
        foreach ((array) $needles as $needle) {
423 26
            if ((string) $needle !== '' && str_contains($haystack, $needle)) {
424 24
                return true;
425
            }
426
        }
427
428 4
        return false;
429
    }
430
431
    /**
432
     * Generate a more truly "random" alpha-numeric string.
433
     *
434
     * @see https://github.com/illuminate/support/blob/master/Str.php
435
     *
436
     * @param  int  $length
437
     *
438 8
     * @throws \Exception
439
     *
440 8
     * @return string
441
     */
442 8
    public function random(int $length = 16): string
443
    {
444
        $string = '';
445
446
        while (($len = strlen($string)) < $length) {
447
            $size = $length - $len;
448
449
            $bytes = random_bytes($size);
450
451
            $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
452 2
        }
453
454 2
        return $string;
455
    }
456
457
    /**
458
     * Determines if the value is empty.
459
     *
460
     * @param  mixed  $value
461
     *
462
     * @return bool
463
     */
464
    public function isEmpty($value): bool
465
    {
466
        $value = is_string($value) ? trim($value) : $value;
467 4
468
        return empty($value) && ! is_numeric($value) && (is_string($value) || is_null($value));
469 4
    }
470
471
    /**
472
     * Determines if the value is doesn't empty.
473
     *
474
     * @param  mixed  $value
475
     *
476
     * @return bool
477
     */
478
    public function doesntEmpty($value): bool
479
    {
480
        return ! $this->isEmpty($value);
481
    }
482
483
    /**
484
     * Transliterate a UTF-8 value to ASCII.
485
     *
486
     * @see https://github.com/illuminate/support/blob/master/Str.php
487
     *
488
     * @param  string|null  $value
489
     * @param  string|null  $language
490
     *
491
     * @return string
492
     */
493
    public function ascii(?string $value, ?string $language = 'en'): string
494
    {
495
        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

495
        return ASCII::to_ascii((string) $value, /** @scrutinizer ignore-type */ $language);
Loading history...
496
    }
497
}
498