Passed
Push — master ( 10eb58...fde5dd )
by Sergey
02:06 queued 10s
created

Strings::segments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Flextype\Component\Strings;
6
7
use function abs;
8
use function array_reverse;
9
use function array_shift;
10
use function ctype_lower;
11
use function explode;
12
use function hash;
13
use function hash_algos;
14
use function implode;
15
use function in_array;
16
use function lcfirst;
17
use function ltrim;
18
use function mb_convert_case;
19
use function mb_strimwidth;
20
use function mb_strlen;
21
use function mb_strpos;
22
use function mb_strrpos;
23
use function mb_strtolower;
24
use function mb_strtoupper;
25
use function mb_strwidth;
26
use function mb_substr;
27
use function preg_match;
28
use function preg_quote;
29
use function preg_replace;
30
use function random_int;
31
use function rtrim;
32
use function str_pad;
33
use function str_replace;
34
use function str_word_count;
35
use function strlen;
36
use function strncmp;
37
use function strpos;
38
use function strrpos;
39
use function substr;
40
use function substr_replace;
41
use function trim;
42
use function ucwords;
43
44
use const MB_CASE_TITLE;
45
use const STR_PAD_BOTH;
46
use const STR_PAD_LEFT;
47
use const STR_PAD_RIGHT;
48
49
class Strings
50
{
51
    /**
52
     * The cache for words.
53
     *
54
     * @var array
55
     */
56
    protected static $cache = [];
57
58
    /**
59
     * Removes any leading and traling slashes from a string.
60
     *
61
     * @param  string $string String with slashes
62
     */
63
    public static function trimSlashes(string $string): string
64
    {
65
        return static::trim($string, '/');
66
    }
67
68
    /**
69
     * Reduces multiple slashes in a string to single slashes.
70
     *
71
     * @param  string $string String or array of strings with slashes
72
     */
73
    public static function reduceSlashes(string $string): string
74
    {
75
        return preg_replace('#(?<!:)//+#', '/', $string);
76
    }
77
78
    /**
79
     * Removes single and double quotes from a string.
80
     *
81
     * @param  string $str String with single and double quotes
82
     */
83
    public static function stripQuotes(string $string): string
84
    {
85
        return str_replace(['"', "'"], '', $string);
86
    }
87
88
    /**
89
     * Convert single and double quotes to entities.
90
     *
91
     * @param  string $string String with single and double quotes
92
     */
93
    public static function quotesToEntities(string $string): string
94
    {
95
        return str_replace(["\'", '"', "'", '"'], ['&#39;', '&quot;', '&#39;', '&quot;'], $string);
96
    }
97
98
    /**
99
     * Creates a random string of characters.
100
     *
101
     * @param  int    $length   The number of characters. Default is 16
102
     * @param  string $keyspace The keyspace
103
     */
104
    public static function random(int $length = 64, string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string
105
    {
106
        if ($length <= 0) {
107
            $length = 1;
108
        }
109
110
        $pieces = [];
111
        $max    = static::length($keyspace, '8bit') - 1;
112
113
        for ($i = 0; $i < $length; ++$i) {
114
            $pieces[] = $keyspace[random_int(0, $max)];
115
        }
116
117
        return implode('', $pieces);
118
    }
119
120
    /**
121
     * Add's _1 to a string or increment the ending number to allow _2, _3, etc.
122
     *
123
     * @param  string $string    String to increment
124
     * @param  int    $first     Start with
125
     * @param  string $separator Separator
126
     */
127
    public static function increment(string $string, int $first = 1, string $separator = '_'): string
128
    {
129
        preg_match('/(.+)' . $separator . '([0-9]+)$/', $string, $match);
130
131
        return isset($match[2]) ? $match[1] . $separator . ($match[2] + 1) : $string . $separator . $first;
132
    }
133
134
    /**
135
     * Return the length of the given string.
136
     *
137
     * @param  string      $string   String to check
138
     * @param  string|null $encoding String encoding
139
     */
140
    public static function length(string $string, ?string $encoding = null): int
141
    {
142
        if ($encoding) {
143
            return mb_strlen($string, $encoding);
144
        }
145
146
        return mb_strlen($string);
147
    }
148
149
    /**
150
     * Limit the number of characters in a string.
151
     *
152
     * @param  string $string String
153
     * @param  int    $limit  Limit of characters
154
     * @param  string $append Text to append to the string IF it gets truncated
155
     */
156
    public static function limit(string $string, int $limit = 100, string $append = '...'): string
157
    {
158
        if (mb_strwidth($string, 'UTF-8') <= $limit) {
159
            return $string;
160
        }
161
162
        return rtrim(mb_strimwidth($string, 0, $limit, '', 'UTF-8')) . $append;
163
    }
164
165
    /**
166
     * Convert the given string to lower-case.
167
     *
168
     * @param  string $string String
169
     */
170
    public static function lower(string $string): string
171
    {
172
        return mb_strtolower($string, 'UTF-8');
173
    }
174
175
    /**
176
     * Convert the given string to upper-case.
177
     *
178
     * @param  string $value
179
     */
180
    public static function upper(string $string): string
181
    {
182
        return mb_strtoupper($string, 'UTF-8');
183
    }
184
185
    /**
186
     * Returns the portion of string specified by the start and length parameters.
187
     *
188
     * @param  string   $string The string to extract the substring from.
189
     * @param  int      $start  If start is non-negative, the returned string will
190
     *                          start at the start'th position in $string, counting from zero.
191
     *                          For instance, in the string 'abcdef', the character at position
192
     *                          0 is 'a', the character at position 2 is 'c', and so forth.
193
     * @param  int|null $length Maximum number of characters to use from string.
194
     *                          If omitted or NULL is passed, extract all characters to the end of the string.
195
     */
196
    public static function substr(string $string, int $start, ?int $length = null): string
197
    {
198
        return mb_substr($string, $start, $length, 'UTF-8');
199
    }
200
201
    /**
202
     * Convert a string to studly caps case.
203
     *
204
     * @param  string $string String
205
     */
206
    public static function studly(string $string): string
207
    {
208
        $key = $string;
209
210
        if (isset(static::$cache['studly'][$key])) {
211
            return static::$cache['studly'][$key];
212
        }
213
214
        $string = ucwords(str_replace(['-', '_'], ' ', $string));
215
216
        return static::$cache['studly'][$key] = str_replace(' ', '', $string);
217
    }
218
219
    /**
220
     * Convert a string to snake case.
221
     *
222
     * @param  string $string    String
223
     * @param  string $delimiter Delimeter
224
     */
225
    public static function snake(string $string, string $delimiter = '_'): string
226
    {
227
        $key = $string;
228
229
        if (isset(static::$cache['snake'][$key][$delimiter])) {
230
            return static::$cache['snake'][$key][$delimiter];
231
        }
232
233
        if (! ctype_lower($string)) {
234
            $value = preg_replace('/\s+/u', '', ucwords($string));
0 ignored issues
show
Unused Code introduced by
The assignment to $value is dead and can be removed.
Loading history...
235
236
            $string = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $string));
237
        }
238
239
        return static::$cache['snake'][$key][$delimiter] = $string;
240
    }
241
242
    /**
243
     * Convert a string to camel case.
244
     *
245
     * @param  string $string String
246
     */
247
    public static function camel(string $string): string
248
    {
249
        if (isset(static::$cache['camel'][$string])) {
250
            return static::$cache['camel'][$string];
251
        }
252
253
        return static::$cache['camel'][$string] = lcfirst(static::studly($string));
254
    }
255
256
    /**
257
     * Convert a string to kebab case.
258
     *
259
     * @param  string $string String
260
     */
261
    public static function kebab(string $string): string
262
    {
263
        return static::snake($string, '-');
264
    }
265
266
    /**
267
     * Limit the number of words in a string.
268
     *
269
     * @param  string $string String
270
     * @param  int    $words  Words limit
271
     * @param  string $append Text to append to the string IF it gets truncated
272
     */
273
    public static function words(string $string, int $words = 100, string $append = '...'): string
274
    {
275
        preg_match('/^\s*+(?:\S++\s*+){1,' . $words . '}/u', $string, $matches);
276
277
        if (! isset($matches[0]) || static::length($string) === static::length($matches[0])) {
278
            return $string;
279
        }
280
281
        return static::trimRight($matches[0]) . $append;
282
    }
283
284
    /**
285
     * Return information about words used in a string
286
     *
287
     * @param  string $string   String
288
     * @param  int    $format   Specify the return value of this function. The current supported values are:
289
     *                          0 - returns the number of words found
290
     *                          1 - returns an array containing all the words found inside the string
291
     *                          2 - returns an associative array, where the key is the numeric position of the word inside the string and the value is the actual word itself
292
     * @param  string $charlist A list of additional characters which will be considered as 'word'
293
     */
294
    public static function wordsCount(string $string, int $format = 0, string $charlist = '')
295
    {
296
        return str_word_count($string, $format, $charlist);
297
    }
298
299
    /**
300
     * Determine if a given string contains a given substring.
301
     *
302
     * @param  string          $haystack The string being checked.
303
     * @param  string|string[] $needles  The string to find in haystack.
304
     */
305
    public static function contains(string $haystack, $needles): bool
306
    {
307
        foreach ((array) $needles as $needle) {
308
            if ($needle !== '' && mb_strpos($haystack, $needle) !== false) {
309
                return true;
310
            }
311
        }
312
313
        return false;
314
    }
315
316
    /**
317
     * Determine if a given string contains all array values.
318
     *
319
     * @param  string   $haystack The string being checked.
320
     * @param  string[] $needles  The array of strings to find in haystack.
321
     */
322
    public static function containsAll(string $haystack, array $needles): bool
323
    {
324
        foreach ($needles as $needle) {
325
            if (! static::contains($haystack, $needle)) {
326
                return false;
327
            }
328
        }
329
330
        return true;
331
    }
332
333
    /**
334
     * Converts the first character of a string to upper case
335
     * and leaves the other characters unchanged.
336
     *
337
     * @param  string $string String
338
     */
339
    public static function ucfirst(string $string): string
340
    {
341
        return static::upper(static::substr($string, 0, 1)) . static::substr($string, 1);
342
    }
343
344
    /**
345
     * Converts the first character of every word of string to upper case and the others to lower case.
346
     *
347
     * @param  string $string String
348
     */
349
    public static function capitalize(string $string): string
350
    {
351
        return mb_convert_case($string, MB_CASE_TITLE, 'UTF-8');
352
    }
353
354
    /**
355
     * Strip whitespace (or other characters) from the beginning and end of a string.
356
     *
357
     * @param string $string         The string that will be trimmed.
358
     * @param string $character_mask Optionally, the stripped characters can also be
359
     *                               specified using the character_mask parameter..
360
     */
361
    public static function trim(string $string, string $character_mask = " \t\n\r\0\x0B"): string
362
    {
363
        return trim($string, $character_mask);
364
    }
365
366
    /**
367
     * Strip whitespace (or other characters) from the beginning of a string.
368
     *
369
     * @param string $string         The string that will be trimmed.
370
     * @param string $character_mask Optionally, the stripped characters can also be
371
     *                               specified using the character_mask parameter..
372
     */
373
    public static function trimLeft(string $string, string $character_mask = " \t\n\r\0\x0B"): string
374
    {
375
        return ltrim($string, $character_mask);
376
    }
377
378
    /**
379
     * Strip whitespace (or other characters) from the end of a string.
380
     *
381
     * @param string $string         The string that will be trimmed.
382
     * @param string $character_mask Optionally, the stripped characters can also be
383
     *                               specified using the character_mask parameter..
384
     */
385
    public static function trimRight(string $string, string $character_mask = " \t\n\r\0\x0B"): string
386
    {
387
        return rtrim($string, $character_mask);
388
    }
389
390
    /**
391
     * Reverses string.
392
     *
393
     * @param  string $string String
394
     */
395
    public static function reverse(string $string): string
396
    {
397
        $result = '';
398
399
        for ($i = static::length($string); $i >= 0; $i--) {
400
            $result .= static::substr($string, $i, 1);
401
        }
402
403
        return $result;
404
    }
405
406
    /**
407
     * Get array of segments from a string based on a delimiter.
408
     *
409
     * @param string $string    String
410
     * @param string $delimiter Delimeter
411
     */
412
    public static function segments(string $string, string $delimiter = ' '): array
413
    {
414
        return explode($delimiter, $string);
415
    }
416
417
    /**
418
     * Get a segment from a string based on a delimiter.
419
     * Returns an empty string when the offset doesn't exist.
420
     * Use a negative index to start counting from the last element.
421
     *
422
     * @param string $string    String
423
     * @param int    $index     Index
424
     * @param string $delimiter Delimeter
425
     */
426
    public static function segment(string $string, int $index, string $delimiter = ' '): string
427
    {
428
        $segments = explode($delimiter, $string);
429
430
        if ($index < 0) {
431
            $segments = array_reverse($segments);
432
            $index    = abs($index) - 1;
433
        }
434
435
        return $segments[$index] ?? '';
436
    }
437
438
    /**
439
     * Get the first segment from a string based on a delimiter.
440
     *
441
     * @param string $string    String
442
     * @param string $delimiter Delimeter
443
     */
444
    public static function firstSegment(string $string, string $delimiter = ' '): string
445
    {
446
        return static::segment($string, 0, $delimiter);
447
    }
448
449
    /**
450
     * Get the last segment from a string based on a delimiter.
451
     *
452
     * @param string $string    String
453
     * @param string $delimiter Delimeter
454
     */
455
    public static function lastSegment(string $string, string $delimiter = ' '): string
456
    {
457
        return static::segment($string, -1, $delimiter);
458
    }
459
460
    /**
461
     * Get the portion of a string before the first occurrence of a given value.
462
     *
463
     * @param string $string String
464
     * @param string $search Search
465
     */
466
    public static function before(string $string, string $search): string
467
    {
468
        return $search === '' ? $string : explode($search, $string)[0];
469
    }
470
471
    /**
472
     * Get the portion of a string before the last occurrence of a given value.
473
     *
474
     * @param string $string String
475
     * @param string $search Search
476
     */
477
    public static function beforeLast(string $string, string $search): string
478
    {
479
        if ($search === '') {
480
            return $string;
481
        }
482
483
        $position = mb_strrpos($string, $search);
484
485
        if ($position === false) {
486
            return $string;
487
        }
488
489
        return static::substr($string, 0, $position);
490
    }
491
492
    /**
493
     * Return the remainder of a string after the first occurrence of a given value.
494
     *
495
     * @param string $string String
496
     * @param string $search Search
497
     */
498
    public static function after(string $string, string $search): string
499
    {
500
        return $search === '' ? $string : array_reverse(explode($search, $string, 2))[0];
501
    }
502
503
    /**
504
     * Return the remainder of a string after the last occurrence of a given value.
505
     *
506
     * @param string $string String
507
     * @param string $search Search
508
     */
509
    public static function afterLast(string $string, string $search): string
510
    {
511
        if ($search === '') {
512
            return $string;
513
        }
514
515
        $position = mb_strrpos($string, (string) $search);
516
517
        if ($position === false) {
518
            return $string;
519
        }
520
521
        return static::substr($string, $position + static::length($search));
522
    }
523
524
    /**
525
     * Pad both sides of a string with another.
526
     *
527
     * @param  string $string The input string.
528
     * @param  int    $length If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place, and input will be returned.
529
     * @param  string $pad    The pad string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length.
530
     */
531
    public static function padBoth(string $string, int $length, string $pad = ' '): string
532
    {
533
        return str_pad($string, $length, $pad, STR_PAD_BOTH);
534
    }
535
536
    /**
537
     * Pad the left side of a string with another.
538
     *
539
     * @param  string $string The input string.
540
     * @param  int    $length If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place, and input will be returned.
541
     * @param  string $pad    The pad string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length.
542
     */
543
    public static function padLeft(string $string, int $length, string $pad = ' '): string
544
    {
545
        return str_pad($string, $length, $pad, STR_PAD_LEFT);
546
    }
547
548
    /**
549
     * Pad the right side of a string with another.
550
     *
551
     * @param  string $string The input string.
552
     * @param  int    $length If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place, and input will be returned.
553
     * @param  string $pad    The pad string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length.
554
     */
555
    public static function padRight(string $string, int $length, string $pad = ' '): string
556
    {
557
        return str_pad($string, $length, $pad, STR_PAD_RIGHT);
558
    }
559
560
    /**
561
     * Strip all whitespaces from the given string.
562
     *
563
     * @param string $string The string to strip
564
     */
565
    public static function stripSpaces(string $string): string
566
    {
567
        return preg_replace('/\s+/', '', $string);
568
    }
569
570
    /**
571
     * Replace a given value in the string sequentially with an array.
572
     *
573
     * @param  string $string  String
574
     * @param  string $search  Search
575
     * @param  array  $replace Replace
576
     */
577
    public static function replaceArray(string $string, string $search, array $replace): string
578
    {
579
        $segments = explode($search, $string);
580
581
        $result = array_shift($segments);
582
583
        foreach ($segments as $segment) {
584
            $result .= (array_shift($replace) ?? $search) . $segment;
585
        }
586
587
        return $result;
588
    }
589
590
    /**
591
     * Replace the first occurrence of a given value in the string.
592
     *
593
     * @param  string $string  String
594
     * @param  string $search  Search
595
     * @param  string $replace Replace
596
     */
597
    public static function replaceFirst(string $string, string $search, string $replace): string
598
    {
599
        if ($search === '') {
600
            return $string;
601
        }
602
603
        $position = strpos($string, $search);
604
605
        if ($position !== false) {
606
            return substr_replace($string, $replace, $position, strlen($search));
607
        }
608
609
        return $search;
610
    }
611
612
    /**
613
     * Replace the last occurrence of a given value in the string.
614
     *
615
     * @param  string $string  String
616
     * @param  string $search  Search
617
     * @param  string $replace Replace
618
     */
619
    public static function replaceLast(string $string, string $search, string $replace): string
620
    {
621
        $position = strrpos($string, $search);
622
623
        if ($position !== false) {
624
            return substr_replace($string, $replace, $position, strlen($search));
625
        }
626
627
        return $subject;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $subject seems to be never defined.
Loading history...
628
    }
629
630
    /**
631
     * Begin a string with a single instance of a given value.
632
     *
633
     * @param  string $string String
634
     * @param  string $prefix Prefix
635
     */
636
    public static function start(string $string, string $prefix): string
637
    {
638
        $quoted = preg_quote($prefix, '/');
639
640
        return $prefix . preg_replace('/^(?:' . $quoted . ')+/u', '', $string);
641
    }
642
643
    /**
644
     * Determine if a given string starts with a given substring.
645
     *
646
     * @param  string          $haystack Haystack
647
     * @param  string|string[] $needles  needles
648
     */
649
    public static function startsWith(string $haystack, $needles): bool
650
    {
651
        foreach ((array) $needles as $needle) {
652
            if ((string) $needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0) {
653
                return true;
654
            }
655
        }
656
657
        return false;
658
    }
659
660
    /**
661
     * Determine if a given string ends with a given substring.
662
     *
663
     * @param  string          $haystack Haystack
664
     * @param  string|string[] $needles  needles
665
     */
666
    public static function endsWith(string $haystack, $needles): bool
667
    {
668
        foreach ((array) $needles as $needle) {
669
            if ($needle !== '' && substr($haystack, -strlen($needle)) === (string) $needle) {
670
                return true;
671
            }
672
        }
673
674
        return false;
675
    }
676
677
    /**
678
     * Cap a string with a single instance of a given value.
679
     *
680
     * @param  string $string String
681
     * @param  string $cap    Cap
682
     */
683
    public static function finish(string $string, string $cap): string
684
    {
685
        $quoted = preg_quote($cap, '/');
686
687
        return preg_replace('/(?:' . $quoted . ')+$/u', '', $string) . $cap;
688
    }
689
690
    /**
691
     * Generate a hash string from the input string.
692
     *
693
     * @param  string $string     String
694
     * @param  string $algorithm  Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..).
695
     *                            For a list of supported algorithms see hash_algos(). Default is md5.
696
     * @param  string $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Default is FALSE
697
     */
698
    public static function hash(string $string, string $algorithm = 'md5', bool $raw_output = false): string
699
    {
700
        if (in_array($algorithm, hash_algos())) {
701
            return hash($algorithm, $string, $raw_output);
702
        }
703
704
        return $string;
705
    }
706
}
707