Passed
Pull Request — main (#121)
by Andrey
12:11
created

Str::end()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 5
ccs 2
cts 2
cp 1
crap 1
rs 10
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
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
     * Get a new stringable object from the given string.
41
     *
42
     * @see https://github.com/illuminate/support/blob/master/Str.php
43
     *
44
     * @param  string|null  $value
45
     *
46
     * @return \Helldar\Support\Helpers\Ables\Stringable
47
     */
48 6
    public function of(?string $value): Ables\Stringable
49
    {
50 6
        return new Ables\Stringable($value);
51
    }
52
53
    /**
54
     * Escape HTML special characters in a string.
55
     *
56
     * @param  string|null  $value
57
     * @param  bool  $double
58
     *
59
     * @return string|null
60
     */
61 2
    public function e(?string $value, bool $double = true): ?string
62
    {
63 2
        if ($escaped = CallHelper::runOf($this->escaping_methods, $value)) {
64
            return $escaped;
65
        }
66
67 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

67
        return htmlspecialchars(/** @scrutinizer ignore-type */ $value, ENT_QUOTES, 'UTF-8', $double);
Loading history...
68
    }
69
70
    /**
71
     * Convert special HTML entities back to characters.
72
     *
73
     * @param  string|null  $value
74
     *
75
     * @return string|null
76
     */
77 2
    public function de(?string $value): ?string
78
    {
79 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

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

228
        return mb_strtolower(/** @scrutinizer ignore-type */ $value, 'UTF-8');
Loading history...
229
    }
230
231
    /**
232
     * Convert the given string to upper-case.
233
     *
234
     * @see https://github.com/illuminate/support/blob/master/Str.php
235
     *
236
     * @param  string|null  $value
237
     *
238
     * @return string
239 48
     */
240
    public function upper(?string $value): ?string
241 48
    {
242
        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

242
        return mb_strtoupper(/** @scrutinizer ignore-type */ $value, 'UTF-8');
Loading history...
243 48
    }
244 11
245
    /**
246
     * Convert a value to studly caps case.
247 38
     *
248
     * @see https://github.com/illuminate/support/blob/master/Str.php
249 38
     *
250
     * @param  string|null  $value
251
     *
252
     * @return string|null
253
     */
254
    public function studly(?string $value): ?string
255
    {
256
        $key = $value;
257
258
        if (isset(self::$studlyCache[$key])) {
259
            return self::$studlyCache[$key];
260
        }
261 40
262
        $value = ucwords(str_replace(['-', '_'], ' ', $value));
263 40
264 4
        return self::$studlyCache[$key] = str_replace(' ', '', $value);
265
    }
266
267 36
    /**
268
     * Convert a value to camel case.
269
     *
270
     * @see https://github.com/illuminate/support/blob/master/Str.php
271
     *
272
     * @param  string|null  $value
273
     *
274
     * @return string|null
275
     */
276
    public function camel(?string $value): ?string
277
    {
278
        if (isset(self::$camelCache[$value])) {
279
            return self::$camelCache[$value];
280 4
        }
281
282 4
        return self::$camelCache[$value] = lcfirst($this->studly($value));
283
    }
284 4
285 3
    /**
286
     * Convert a string to snake case.
287
     *
288 1
     * @see https://github.com/illuminate/support/blob/master/Str.php
289 1
     *
290
     * @param  string|null  $value
291 1
     * @param  string  $delimiter
292
     *
293
     * @return string|null
294 1
     */
295
    public function snake(?string $value, string $delimiter = '_'): ?string
296
    {
297
        $key = $value;
298
299
        if (isset(self::$snakeCache[$key][$delimiter])) {
300
            return self::$snakeCache[$key][$delimiter];
301
        }
302
303
        if (! ctype_lower($value)) {
304
            $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

304
            $value = preg_replace('/\s+/u', '', ucwords(/** @scrutinizer ignore-type */ $value));
Loading history...
305
306
            $value = $this->lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
307
        }
308 8
309
        return self::$snakeCache[$key][$delimiter] = $value;
310 8
    }
311
312
    /**
313 8
     * Generate a URL friendly "slug" from a given string.
314
     *
315 8
     * @see https://github.com/illuminate/support/blob/master/Str.php
316
     *
317
     * @param  string  $title
318 8
     * @param  string  $separator
319
     * @param  string|null  $language
320
     *
321 8
     * @return string
322
     */
323
    public function slug(string $title, string $separator = '-', ?string $language = 'en')
324 8
    {
325
        $title = $language ? $this->ascii($title, $language) : $title;
326 8
327
        // Convert all dashes/underscores into separator
328
        $flip = $separator === '-' ? '_' : '-';
329
330
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
331
332
        // Replace @ with the word 'at'
333
        $title = str_replace('@', $separator . 'at' . $separator, $title);
334
335
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
336
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', $this->lower($title));
337
338 4
        // Replace all separator characters and whitespace by a single separator
339
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
340 4
341 4
        return trim($title, $separator);
342
    }
343
344 4
    /**
345
     * Convert the given string to title case.
346
     *
347
     * @see https://github.com/illuminate/support/blob/master/Str.php
348
     *
349
     * @param  string|null  $value
350
     *
351
     * @return string|null
352
     */
353
    public function title(?string $value): ?string
354
    {
355
        if (is_numeric($value)) {
356
            return $value;
357 2
        }
358
359 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

359
        return mb_convert_case(/** @scrutinizer ignore-type */ $value, MB_CASE_TITLE, 'UTF-8') ?: null;
Loading history...
360 2
    }
361 2
362
    /**
363
     * Return the length of the given string.
364
     *
365
     * @see https://github.com/illuminate/support/blob/master/Str.php
366
     *
367
     * @param  string|null  $value
368
     * @param  string|null  $encoding
369
     *
370
     * @return int
371
     */
372
    public function length(?string $value, string $encoding = null): int
373
    {
374
        return $encoding
375 4
            ? 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

375
            ? mb_strlen(/** @scrutinizer ignore-type */ $value, $encoding)
Loading history...
376
            : mb_strlen($value);
377 4
    }
378
379
    /**
380
     * Returns the portion of string specified by the start and length parameters.
381
     *
382
     * @see https://github.com/illuminate/support/blob/master/Str.php
383
     *
384
     * @param  string  $string
385
     * @param  int  $start
386
     * @param  int|null  $length
387
     *
388
     * @return string|null
389 22
     */
390
    public function substr(string $string, int $start, int $length = null): ?string
391 22
    {
392
        return mb_substr($string, $start, $length, 'UTF-8');
393 22
    }
394
395
    /**
396
     * Replace all occurrences of the search string with the replacement string.
397
     *
398
     * @param  string  $template
399
     * @param  array  $values
400
     * @param  string|null  $key_format
401
     *
402
     * @return string
403
     */
404
    public function replace(string $template, array $values, string $key_format = null): string
405
    {
406 6
        $keys = Replace::toFormatArray(array_keys($values), $key_format);
407
408 6
        return str_replace($keys, array_values($values), $template);
409
    }
410
411
    /**
412
     * Get the portion of a string before the first occurrence of a given value.
413
     *
414
     * @see https://github.com/illuminate/support/blob/master/Str.php
415
     *
416
     * @param  string  $subject
417
     * @param  string  $search
418
     *
419
     * @return string
420
     */
421 98
    public function before(string $subject, string $search): ?string
422
    {
423 98
        return ! empty($search) ? explode($search, $subject)[0] : null;
424
    }
425
426
    /**
427
     * Return the remainder of a string after the first occurrence of a given value.
428
     *
429
     * @see https://github.com/illuminate/support/blob/master/Str.php
430
     *
431
     * @param  string  $subject
432
     * @param  string  $search
433
     *
434 30
     * @return string
435
     */
436 30
    public function after(string $subject, string $search): ?string
437 30
    {
438 28
        return ! empty($search) ? array_reverse(explode($search, $subject, 2))[0] : null;
439
    }
440
441
    /**
442 8
     * Determine if a given string contains a given substring.
443
     *
444
     * @param  string  $haystack
445
     * @param  string|string[]  $needles
446
     *
447
     * @return bool
448
     */
449
    public function contains(string $haystack, $needles): bool
450
    {
451
        foreach ((array) $needles as $needle) {
452
            if ((string) $needle !== '' && str_contains($haystack, $needle)) {
453
                return true;
454
            }
455
        }
456 2
457
        return false;
458 2
    }
459
460 2
    /**
461 2
     * Generate a more truly "random" alpha-numeric string.
462
     *
463 2
     * @see https://github.com/illuminate/support/blob/master/Str.php
464
     *
465 2
     * @param  int  $length
466
     *
467
     * @throws \Exception
468 2
     *
469
     * @return string
470
     */
471
    public function random(int $length = 16): string
472
    {
473
        $string = '';
474
475
        while (($len = strlen($string)) < $length) {
476
            $size = $length - $len;
477
478
            $bytes = random_bytes($size);
479
480
            $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
481 4
        }
482
483 4
        return $string;
484
    }
485 4
486
    /**
487
     * Get the string matching the given pattern.
488
     *
489
     * @see https://github.com/illuminate/support/blob/master/Str.php
490
     *
491
     * @param  string  $value
492
     * @param  string  $pattern
493
     *
494
     * @return string|null
495
     */
496
    public function match(string $value, string $pattern): ?string
497 10
    {
498
        preg_match($pattern, $value, $matches);
499 10
500
        return ! $matches ? null : ($matches[1] ?? $matches[0]);
501
    }
502
503
    /**
504
     * Replace a given value in the string.
505
     *
506
     * @param  string|null  $value
507
     * @param  string  $pattern
508
     * @param  string  $replacement
509 8
     *
510
     * @return string|null
511 8
     */
512
    public function pregReplace(?string $value, string $pattern, string $replacement): ?string
513 8
    {
514
        return preg_replace($pattern, $replacement, $value);
515
    }
516
517
    /**
518
     * Determines if the value is empty.
519
     *
520
     * @param  mixed  $value
521
     *
522
     * @return bool
523 2
     */
524
    public function isEmpty($value): bool
525 2
    {
526
        $value = is_string($value) ? trim($value) : $value;
527
528
        return empty($value) && ! is_numeric($value) && (is_string($value) || is_null($value));
529
    }
530
531
    /**
532
     * Determines if the value is doesn't empty.
533
     *
534
     * @param  mixed  $value
535
     *
536
     * @return bool
537
     */
538 12
    public function doesntEmpty($value): bool
539
    {
540 12
        return ! $this->isEmpty($value);
541
    }
542
543
    /**
544
     * Transliterate a UTF-8 value to ASCII.
545
     *
546
     * @see https://github.com/illuminate/support/blob/master/Str.php
547
     *
548
     * @param  string|null  $value
549
     * @param  string|null  $language
550 2
     *
551
     * @return string
552 2
     */
553
    public function ascii(?string $value, ?string $language = 'en'): string
554
    {
555
        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

555
        return ASCII::to_ascii((string) $value, /** @scrutinizer ignore-type */ $language);
Loading history...
556
    }
557
558
    /**
559
     * Converts a value to a string.
560
     *
561
     * @param  string|null  $value
562
     *
563
     * @return string
564
     */
565
    public function convertToString(?string $value): string
566
    {
567
        return is_null($value) ? 'null' : $value;
568
    }
569
}
570