GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Test Failed
Push — master ( f90a6a...460bda )
by Marios
15:29
created

StringsMethods::inflector()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 16
ccs 9
cts 9
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
declare(strict_types=1);
3
4
/*
5
 * This file is part of Underscore.php
6
 *
7
 * (c) Maxime Fabre <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Underscore\Methods;
14
15
use Doctrine\Inflector\CachedWordInflector;
16
use Doctrine\Inflector\Inflector;
17
use Doctrine\Inflector\Rules\English\Rules;
18
use Doctrine\Inflector\RulesetInflector;
19
use RuntimeException;
20
use Underscore\Types\Strings;
21
use function Symfony\Component\String\u;
22
23
/**
24
 * Methods to manage strings.
25
 */
26
class StringsMethods
27
{
28
29
    /**
30
     * Uncountable word forms.
31
     *
32
     * @var array
33
     */
34
    public static $uncountable = [
35
        'audio',
36
        'bison',
37
        'cattle',
38
        'chassis',
39
        'compensation',
40
        'coreopsis',
41
        'data',
42
        'deer',
43
        'education',
44
        'emoji',
45
        'equipment',
46
        'evidence',
47
        'feedback',
48
        'firmware',
49
        'fish',
50
        'furniture',
51
        'gold',
52
        'hardware',
53
        'information',
54
        'jedi',
55
        'kin',
56
        'knowledge',
57
        'love',
58
        'metadata',
59
        'money',
60
        'moose',
61
        'news',
62
        'nutrition',
63
        'offspring',
64
        'plankton',
65
        'pokemon',
66
        'police',
67
        'rain',
68
        'recommended',
69
        'related',
70
        'rice',
71
        'series',
72
        'sheep',
73
        'software',
74
        'species',
75
        'swine',
76
        'traffic',
77
        'wheat',
78
    ];
79
    ////////////////////////////////////////////////////////////////////
80
    ////////////////////////////// CREATE  /////////////////////////////
81
    ////////////////////////////////////////////////////////////////////
82
83
    /**
84
     * Create a string from a number.
85
     *
86
     * @param int    $count A number
87
     * @param string $many  If many
88
     * @param string $one   If one
89
     * @param string $zero  If one
90
     *
91
     * @return string A string
92
     */
93 3
    public static function accord($count, $many, $one, $zero = null) : string
94
    {
95 3
        if ($count === 1) {
96 1
            $output = $one;
97
        }
98 2
        elseif ($count === 0 && ! empty($zero)) {
99 1
            $output = $zero;
100
        }
101
        else {
102 1
            $output = $many;
103
        }
104
105 3
        return sprintf($output, $count);
106
    }
107
108
    /**
109
     * Generate a more truly "random" alpha-numeric string.
110
     *
111
     * @param int $length
112
     *
113
     * @throws \RuntimeException
114
     *
115
     * @return string
116
     *
117
     * @author Taylor Otwell
118
     */
119 10
    public static function random($length = 16) : string
120
    {
121 10
        if (\function_exists('openssl_random_pseudo_bytes')) {
122 10
            $bytes = openssl_random_pseudo_bytes($length * 2);
123
124 10
            if ($bytes === false) {
125
                throw new RuntimeException('Unable to generate random string.');
126
            }
127
128 10
            return substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $length);
129
        }
130
131
        return static::quickRandom($length);
132
    }
133
134
    /**
135
     * Generate a "random" alpha-numeric string.
136
     *
137
     * Should not be considered sufficient for cryptography, etc.
138
     *
139
     * @param int $length
140
     *
141
     * @return string
142
     *
143
     * @author Taylor Otwell
144
     */
145
    public static function quickRandom($length = 16) : string
146
    {
147
        $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
148
149
        return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
150
    }
151
152
    /**
153
     * Generates a random suite of words.
154
     *
155
     * @param int $words  The number of words
156
     * @param int $length The length of each word
157
     *
158
     * @return string
159
     */
160 1
    public static function randomStrings($words, $length = 10) : string
161
    {
162 1
        return Strings::from('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
163 1
                      ->shuffle()
0 ignored issues
show
Bug introduced by
The method shuffle() does not exist on Underscore\Types\Strings. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

163
                      ->/** @scrutinizer ignore-call */ shuffle()
Loading history...
164 1
                      ->split($length)
0 ignored issues
show
Bug introduced by
The method split() does not exist on Underscore\Types\Strings. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

164
                      ->/** @scrutinizer ignore-call */ split($length)
Loading history...
165 1
                      ->slice(0, $words)
0 ignored issues
show
Bug introduced by
The method slice() does not exist on Underscore\Types\Strings. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

165
                      ->/** @scrutinizer ignore-call */ slice(0, $words)
Loading history...
166 1
                      ->implode(' ')
0 ignored issues
show
Bug introduced by
The method implode() does not exist on Underscore\Types\Strings. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

166
                      ->/** @scrutinizer ignore-call */ implode(' ')
Loading history...
167 1
                      ->obtain();
168
    }
169
170
    ////////////////////////////////////////////////////////////////////
171
    ////////////////////////////// ANALYZE /////////////////////////////
172
    ////////////////////////////////////////////////////////////////////
173
174
    /**
175
     * Determine if a given string ends with a given substring.
176
     *
177
     * @param string       $haystack
178
     * @param string|array $needles
179
     *
180
     * @return bool
181
     *
182
     * @author Taylor Otwell
183
     */
184 1
    public static function endsWith($haystack, $needles) : bool
185
    {
186 1
        foreach ((array)$needles as $needle) {
187 1
            if ((string)$needle === substr($haystack, -\strlen($needle))) {
188 1
                return true;
189
            }
190
        }
191
192 1
        return false;
193
    }
194
195
    /**
196
     * Check if a string is an IP.
197
     *
198
     * @param $string
199
     *
200
     * @return bool
201
     */
202 1
    public static function isIp($string) : bool
203
    {
204 1
        return filter_var($string, FILTER_VALIDATE_IP) !== false;
205
    }
206
207
    /**
208
     * Check if a string is an email.
209
     *
210
     * @param $string
211
     *
212
     * @return bool
213
     */
214 1
    public static function isEmail($string) : bool
215
    {
216 1
        return filter_var($string, FILTER_VALIDATE_EMAIL) !== false;
217
    }
218
219
    /**
220
     * Check if a string is an url.
221
     *
222
     * @param $string
223
     *
224
     * @return bool
225
     */
226 1
    public static function isUrl($string) : bool
227
    {
228 1
        return filter_var($string, FILTER_VALIDATE_URL) !== false;
229
    }
230
231
    /**
232
     * Determine if a given string starts with a given substring.
233
     *
234
     * @param string       $haystack
235
     * @param string|array $needles
236
     *
237
     * @return bool
238
     *
239
     * @author Taylor Otwell
240
     */
241 1
    public static function startsWith($haystack, $needles) : bool
242
    {
243 1
        foreach ((array)$needles as $needle) {
244 1
            if ($needle !== '' && strpos($haystack, $needle) === 0) {
245 1
                return true;
246
            }
247
        }
248
249 1
        return false;
250
    }
251
252
    ////////////////////////////////////////////////////////////////////
253
    ///////////////////////////// FETCH FROM ///////////////////////////
254
    ////////////////////////////////////////////////////////////////////
255
256
    /**
257
     * Find one or more needles in one or more haystacks.
258
     *
259
     * @param array|string $string        The haystack(s) to search in
260
     * @param array|string $needle        The needle(s) to search for
261
     * @param bool         $caseSensitive Whether the function is case sensitive or not
262
     * @param bool         $absolute      Whether all needle need to be found or whether one is enough
263
     *
264
     * @return bool Found or not
265
     */
266 163
    public static function find($string, $needle, $caseSensitive = false, $absolute = false) : bool
267
    {
268
        // If several needles
269 163
        if (\is_array($needle) or \is_array($string)) {
270 9
            $sliceFrom = $string;
271 9
            $sliceTo   = $needle;
272
273 9
            if (\is_array($needle)) {
274 4
                $sliceFrom = $needle;
275 4
                $sliceTo   = $string;
276
            }
277
278 9
            $found = 0;
279 9
            foreach ($sliceFrom as $need) {
280 9
                if (static::find($sliceTo, $need, $absolute, $caseSensitive)) {
281 7
                    ++$found;
282
                }
283
            }
284
285 9
            return ($absolute) ? \count($sliceFrom) === $found : $found > 0;
0 ignored issues
show
Bug introduced by
It seems like $sliceFrom can also be of type string; however, parameter $value of count() does only seem to accept Countable|array, 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

285
            return ($absolute) ? \count(/** @scrutinizer ignore-type */ $sliceFrom) === $found : $found > 0;
Loading history...
286
        }
287
288
        // If not case sensitive
289 163
        if (!$caseSensitive) {
290 163
            $string = strtolower($string);
291 163
            $needle = strtolower($needle);
292
        }
293
294
        // If string found
295 163
        $pos = strpos($string, $needle);
296
297 163
        return !($pos === false);
298
    }
299
300
    /**
301
     * Slice a string with another string.
302
     *
303
     * @param $string
304
     * @param $slice
305
     *
306
     * @return array
307
     */
308 1
    public static function slice($string, $slice) : array
309
    {
310 1
        $sliceTo   = static::sliceTo($string, $slice);
311 1
        $sliceFrom = static::sliceFrom($string, $slice);
312
313 1
        return [$sliceTo, $sliceFrom];
314
    }
315
316
    /**
317
     * Slice a string from a certain point.
318
     *
319
     * @param $string
320
     * @param $slice
321
     *
322
     * @return false|string
323
     */
324 2
    public static function sliceFrom($string, $slice)
325
    {
326 2
        $slice = strpos($string, $slice);
327
328 2
        return substr($string, $slice);
329
    }
330
331
    /**
332
     * Slice a string up to a certain point.
333
     *
334
     * @param $string
335
     * @param $slice
336
     *
337
     * @return false|string
338
     */
339 2
    public static function sliceTo($string, $slice)
340
    {
341 2
        $slice = strpos($string, $slice);
342
343 2
        return substr($string, 0, $slice);
344
    }
345
346
    /**
347
     * Get the base class in a namespace.
348
     *
349
     * @param string $string
350
     *
351
     * @return string
352
     */
353 1
    public static function baseClass($string) : string
354
    {
355 1
        $string = static::replace($string, '\\', '/');
356
357 1
        return basename($string);
358
    }
359
360
    ////////////////////////////////////////////////////////////////////
361
    /////////////////////////////// ALTER //////////////////////////////
362
    ////////////////////////////////////////////////////////////////////
363
364
    /**
365
     * Prepend a string with another.
366
     *
367
     * @param string $string The string
368
     * @param string $with   What to prepend with
369
     *
370
     * @return string
371
     */
372 1
    public static function prepend($string, $with) : string
373
    {
374 1
        return $with.$string;
375
    }
376
377
    /**
378
     * Append a string to another.
379
     *
380
     * @param string $string The string
381
     * @param string $with   What to append with
382
     *
383
     * @return string
384
     */
385 1
    public static function append($string, $with) : string
386
    {
387 1
        return $string.$with;
388
    }
389
390
    /**
391
     * Limit the number of characters in a string.
392
     *
393
     * @param string $value
394
     * @param int    $limit
395
     * @param string $end
396
     *
397
     * @return string
398
     *
399
     * @author Taylor Otwell
400
     */
401 2
    public static function limit($value, $limit = 100, $end = '...') : string
402
    {
403 2
        if (mb_strlen($value) <= $limit) {
404 1
            return $value;
405
        }
406
407 2
        return rtrim(mb_substr($value, 0, $limit, 'UTF-8')).$end;
408
    }
409
410
    /**
411
     * Remove part of a string.
412
     *
413
     * @param $string
414
     * @param $remove
415
     *
416
     * @return string
417
     */
418 2
    public static function remove($string, $remove) : string
419
    {
420 2
        if (\is_array($remove)) {
421 1
            $string = preg_replace('#('.implode('|', $remove).')#', null, $string);
422
        }
423
424
        // Trim and return
425 2
        return trim(str_replace($remove, null, $string));
426
    }
427
428
    /**
429
     * Correct arguments order for str_replace.
430
     *
431
     * @param $string
432
     * @param $replace
433
     * @param $with
434
     *
435
     * @return string|string[]
436
     */
437 3
    public static function replace($string, $replace, $with)
438
    {
439 3
        return str_replace($replace, $with, $string);
440
    }
441
442
    /**
443
     * Toggles a string between two states.
444
     *
445
     * @param string $string The string to toggle
446
     * @param string $first  First value
447
     * @param string $second Second value
448
     * @param bool   $loose  Whether a string neither matching 1 or 2 should be changed
449
     *
450
     * @return string The toggled string
451
     */
452 3
    public static function toggle($string, $first, $second, $loose = false) : string
453
    {
454
        // If the string given match none of the other two, and we're in strict mode, return it
455 3
        if ( ! $loose and ! \in_array($string, [$first, $second], true)) {
456 1
            return $string;
457
        }
458
459 2
        return $string === $first ? $second : $first;
460
    }
461
462
    /**
463
     * Generate a URL friendly "slug" from a given string.
464
     *
465
     * @param string $title
466
     * @param string $separator
467
     *
468
     * @return string
469
     *
470
     * @author Taylor Otwell
471
     */
472 1
    protected static function slug($title, $separator = '-') : string
473
    {
474 1
        $title = u($title)->ascii()->toString();
475
        // Convert all dashes/underscores into separator
476 1
        $flip = $separator === '-' ? '_' : '-';
477
478 1
        $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);
479
480
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
481 1
        $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title));
482
483
        // Replace all separator characters and whitespace by a single separator
484 1
        $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
485
486 1
        return trim($title, $separator);
487
    }
488
489
    /**
490
     * Slugifies a string.
491
     *
492
     * @param        $string
493
     * @param string $separator
494
     *
495
     * @return string
496
     */
497 1
    public static function slugify($string, $separator = '-') : string
498
    {
499 1
        $string = str_replace('_', ' ', $string);
500
501 1
        return static::slug($string, $separator);
502
    }
503
504
    /**
505
     * Explode a string into an array.
506
     *
507
     * @param      $string
508
     * @param      $with
509
     * @param null $limit
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $limit is correct as it would always require null to be passed?
Loading history...
510
     *
511
     * @return array
512
     */
513 2
    public static function explode($string, $with, $limit = null) : array
514
    {
515 2
        if ( ! $limit) {
0 ignored issues
show
introduced by
$limit is of type null, thus it always evaluated to false.
Loading history...
516 2
            return explode($with, $string);
517
        }
518
519 1
        return explode($with, $string, $limit);
520
    }
521
522
    /**
523
     * Lowercase a string.
524
     *
525
     * @param string $string
526
     *
527
     * @return string
528
     */
529 2
    public static function lower($string) : string
530
    {
531 2
        return mb_strtolower($string, 'UTF-8');
532
    }
533
534
    /**
535
     * Get the plural form of an English word.
536
     *
537
     * @param string $value
538
     * @param int    $count
539
     *
540
     * @return string
541
     */
542 1
    public static function plural($value)
543
    {
544 1
        if (static::uncountable($value)) {
545
            return $value;
546
        }
547
548 1
        $plural = static::inflector()->pluralize($value);
549
550 1
        return static::matchCase($plural, $value);
551
    }
552
553
    /**
554
     * Get the singular form of an English word.
555
     *
556
     * @param string $value
557
     * @return string
558
     */
559
    public static function singular($value)
560
    {
561
        $singular = static::inflector()->singularize($value);
562
563
        return static::matchCase($singular, $value);
564
    }
565
566
    /**
567
     * Lowercase a string.
568
     *
569
     * @param string $string
570
     *
571
     * @return string
572
     */
573 1
    public static function upper($string) : string
574
    {
575 1
        return mb_strtoupper($string, 'UTF-8');
576
    }
577
578
    /**
579
     * Convert a string to title case.
580
     *
581
     * @param string $string
582
     *
583
     * @return string
584
     */
585 2
    public static function title($string) : string
586
    {
587 2
        return mb_convert_case($string, MB_CASE_TITLE, 'UTF-8');
588
    }
589
590
    /**
591
     * Limit the number of words in a string.
592
     *
593
     * @param string $value
594
     * @param int    $words
595
     * @param string $end
596
     *
597
     * @return string
598
     *
599
     * @author Taylor Otwell
600
     */
601 1
    public static function words($value, $words = 100, $end = '...') : string
602
    {
603 1
        preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
604
605 1
        if ( ! isset($matches[0]) || \strlen($value) === \strlen($matches[0])) {
606 1
            return $value;
607
        }
608
609 1
        return rtrim($matches[0]).$end;
610
    }
611
612
    ////////////////////////////////////////////////////////////////////
613
    /////////////////////////// CASE SWITCHERS /////////////////////////
614
    ////////////////////////////////////////////////////////////////////
615
616
    /**
617
     * Convert a string to PascalCase.
618
     *
619
     * @param string $string
620
     *
621
     * @return string
622
     */
623 1
    public static function toPascalCase($string) : string
624
    {
625 1
        return u($string)->camel()->title()->toString();
626
    }
627
628
    /**
629
     * Convert a string to snake_case.
630
     *
631
     * @param string $string
632
     *
633
     * @return string
634
     */
635 1
    public static function toSnakeCase($string) : string
636
    {
637 1
        return u($string)->snake()->toString();
638
    }
639
640
    /**
641
     * Convert a string to camelCase.
642
     *
643
     * @param string $string
644
     *
645
     * @return string
646
     */
647 1
    public static function toCamelCase($string) : string
648
    {
649 1
        return u($string)->camel()->toString();
650
    }
651
652
    /**
653
     * Get the inflector instance.
654
     *
655
     * @return \Doctrine\Inflector\Inflector
656
     */
657 1
    public static function inflector()
658
    {
659 1
        static $inflector;
660
661 1
        if (is_null($inflector)) {
662 1
            $inflector = new Inflector(
663 1
                new CachedWordInflector(new RulesetInflector(
664 1
                    Rules::getSingularRuleset()
665
                )),
666 1
                new CachedWordInflector(new RulesetInflector(
667 1
                    Rules::getPluralRuleset()
668
                ))
669
            );
670
        }
671
672 1
        return $inflector;
673
    }
674
675
    /**
676
     * Determine if the given value is uncountable.
677
     *
678
     * @param string $value
679
     *
680
     * @return bool
681
     */
682 1
    protected static function uncountable($value) : bool
683
    {
684 1
        return \in_array(strtolower($value), static::$uncountable, true);
685
    }
686
687
    /**
688
     * Attempt to match the case on two strings.
689
     *
690
     * @param string $value
691
     * @param string $comparison
692
     *
693
     * @return string
694
     */
695 1
    protected static function matchCase($value, $comparison) : string
696
    {
697 1
        $functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords'];
698
699 1
        foreach ($functions as $function) {
700 1
            if ($function($comparison) === $comparison) {
701 1
                return $function($value);
702
            }
703
        }
704
705
        return $value;
706
    }
707
708
}
709