Passed
Branch dev (4fdc6d)
by Sergey
01:28
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
     * Determine if a given string contains any of array values.
335
     *
336
     * @param  string   $haystack The string being checked.
337
     * @param  string[] $needles  The array of strings to find in haystack.
338
     */
339
    public static function containsAny(string $haystack, array $needles): bool
340
    {
341
        foreach ($needles as $needle) {
342
            if (static::contains($haystack, $needle)) {
343
                return true;
344
            }
345
        }
346
347
        return false;
348
    }
349
350
    /**
351
     * Converts the first character of a string to upper case
352
     * and leaves the other characters unchanged.
353
     *
354
     * @param  string $string String
355
     */
356
    public static function ucfirst(string $string): string
357
    {
358
        return static::upper(static::substr($string, 0, 1)) . static::substr($string, 1);
359
    }
360
361
    /**
362
     * Converts the first character of every word of string to upper case and the others to lower case.
363
     *
364
     * @param  string $string String
365
     */
366
    public static function capitalize(string $string): string
367
    {
368
        return mb_convert_case($string, MB_CASE_TITLE, 'UTF-8');
369
    }
370
371
    /**
372
     * Strip whitespace (or other characters) from the beginning and end of a string.
373
     *
374
     * @param string $string         The string that will be trimmed.
375
     * @param string $character_mask Optionally, the stripped characters can also be
376
     *                               specified using the character_mask parameter..
377
     */
378
    public static function trim(string $string, string $character_mask = " \t\n\r\0\x0B"): string
379
    {
380
        return trim($string, $character_mask);
381
    }
382
383
    /**
384
     * Strip whitespace (or other characters) from the beginning of a string.
385
     *
386
     * @param string $string         The string that will be trimmed.
387
     * @param string $character_mask Optionally, the stripped characters can also be
388
     *                               specified using the character_mask parameter..
389
     */
390
    public static function trimLeft(string $string, string $character_mask = " \t\n\r\0\x0B"): string
391
    {
392
        return ltrim($string, $character_mask);
393
    }
394
395
    /**
396
     * Strip whitespace (or other characters) from the end of a string.
397
     *
398
     * @param string $string         The string that will be trimmed.
399
     * @param string $character_mask Optionally, the stripped characters can also be
400
     *                               specified using the character_mask parameter..
401
     */
402
    public static function trimRight(string $string, string $character_mask = " \t\n\r\0\x0B"): string
403
    {
404
        return rtrim($string, $character_mask);
405
    }
406
407
    /**
408
     * Reverses string.
409
     *
410
     * @param  string $string String
411
     */
412
    public static function reverse(string $string): string
413
    {
414
        $result = '';
415
416
        for ($i = static::length($string); $i >= 0; $i--) {
417
            $result .= static::substr($string, $i, 1);
418
        }
419
420
        return $result;
421
    }
422
423
    /**
424
     * Get array of segments from a string based on a delimiter.
425
     *
426
     * @param string $string    String
427
     * @param string $delimiter Delimeter
428
     */
429
    public static function segments(string $string, string $delimiter = ' '): array
430
    {
431
        return explode($delimiter, $string);
432
    }
433
434
    /**
435
     * Get a segment from a string based on a delimiter.
436
     * Returns an empty string when the offset doesn't exist.
437
     * Use a negative index to start counting from the last element.
438
     *
439
     * @param string $string    String
440
     * @param int    $index     Index
441
     * @param string $delimiter Delimeter
442
     */
443
    public static function segment(string $string, int $index, string $delimiter = ' '): string
444
    {
445
        $segments = explode($delimiter, $string);
446
447
        if ($index < 0) {
448
            $segments = array_reverse($segments);
449
            $index    = abs($index) - 1;
450
        }
451
452
        return $segments[$index] ?? '';
453
    }
454
455
    /**
456
     * Get the first segment from a string based on a delimiter.
457
     *
458
     * @param string $string    String
459
     * @param string $delimiter Delimeter
460
     */
461
    public static function firstSegment(string $string, string $delimiter = ' '): string
462
    {
463
        return static::segment($string, 0, $delimiter);
464
    }
465
466
    /**
467
     * Get the last segment from a string based on a delimiter.
468
     *
469
     * @param string $string    String
470
     * @param string $delimiter Delimeter
471
     */
472
    public static function lastSegment(string $string, string $delimiter = ' '): string
473
    {
474
        return static::segment($string, -1, $delimiter);
475
    }
476
477
    /**
478
     * Get the portion of a string before the first occurrence of a given value.
479
     *
480
     * @param string $string String
481
     * @param string $search Search
482
     */
483
    public static function before(string $string, string $search): string
484
    {
485
        return $search === '' ? $string : explode($search, $string)[0];
486
    }
487
488
    /**
489
     * Get the portion of a string before the last occurrence of a given value.
490
     *
491
     * @param string $string String
492
     * @param string $search Search
493
     */
494
    public static function beforeLast(string $string, string $search): string
495
    {
496
        if ($search === '') {
497
            return $string;
498
        }
499
500
        $position = mb_strrpos($string, $search);
501
502
        if ($position === false) {
503
            return $string;
504
        }
505
506
        return static::substr($string, 0, $position);
507
    }
508
509
    /**
510
     * Return the remainder of a string after the first occurrence of a given value.
511
     *
512
     * @param string $string String
513
     * @param string $search Search
514
     */
515
    public static function after(string $string, string $search): string
516
    {
517
        return $search === '' ? $string : array_reverse(explode($search, $string, 2))[0];
518
    }
519
520
    /**
521
     * Return the remainder of a string after the last occurrence of a given value.
522
     *
523
     * @param string $string String
524
     * @param string $search Search
525
     */
526
    public static function afterLast(string $string, string $search): string
527
    {
528
        if ($search === '') {
529
            return $string;
530
        }
531
532
        $position = mb_strrpos($string, (string) $search);
533
534
        if ($position === false) {
535
            return $string;
536
        }
537
538
        return static::substr($string, $position + static::length($search));
539
    }
540
541
    /**
542
     * Pad both sides of a string with another.
543
     *
544
     * @param  string $string The input string.
545
     * @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.
546
     * @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.
547
     */
548
    public static function padBoth(string $string, int $length, string $pad = ' '): string
549
    {
550
        return str_pad($string, $length, $pad, STR_PAD_BOTH);
551
    }
552
553
    /**
554
     * Pad the left side of a string with another.
555
     *
556
     * @param  string $string The input string.
557
     * @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.
558
     * @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.
559
     */
560
    public static function padLeft(string $string, int $length, string $pad = ' '): string
561
    {
562
        return str_pad($string, $length, $pad, STR_PAD_LEFT);
563
    }
564
565
    /**
566
     * Pad the right side of a string with another.
567
     *
568
     * @param  string $string The input string.
569
     * @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.
570
     * @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.
571
     */
572
    public static function padRight(string $string, int $length, string $pad = ' '): string
573
    {
574
        return str_pad($string, $length, $pad, STR_PAD_RIGHT);
575
    }
576
577
    /**
578
     * Strip all whitespaces from the given string.
579
     *
580
     * @param string $string The string to strip
581
     */
582
    public static function stripSpaces(string $string): string
583
    {
584
        return preg_replace('/\s+/', '', $string);
585
    }
586
587
    /**
588
     * Replace a given value in the string sequentially with an array.
589
     *
590
     * @param  string $string  String
591
     * @param  string $search  Search
592
     * @param  array  $replace Replace
593
     */
594
    public static function replaceArray(string $string, string $search, array $replace): string
595
    {
596
        $segments = explode($search, $string);
597
598
        $result = array_shift($segments);
599
600
        foreach ($segments as $segment) {
601
            $result .= (array_shift($replace) ?? $search) . $segment;
602
        }
603
604
        return $result;
605
    }
606
607
    /**
608
     * Replace the first occurrence of a given value in the string.
609
     *
610
     * @param  string $string  String
611
     * @param  string $search  Search
612
     * @param  string $replace Replace
613
     */
614
    public static function replaceFirst(string $string, string $search, string $replace): string
615
    {
616
        if ($search === '') {
617
            return $string;
618
        }
619
620
        $position = strpos($string, $search);
621
622
        if ($position !== false) {
623
            return substr_replace($string, $replace, $position, strlen($search));
624
        }
625
626
        return $search;
627
    }
628
629
    /**
630
     * Replace the last occurrence of a given value in the string.
631
     *
632
     * @param  string $string  String
633
     * @param  string $search  Search
634
     * @param  string $replace Replace
635
     */
636
    public static function replaceLast(string $string, string $search, string $replace): string
637
    {
638
        $position = strrpos($string, $search);
639
640
        if ($position !== false) {
641
            return substr_replace($string, $replace, $position, strlen($search));
642
        }
643
644
        return $subject;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $subject seems to be never defined.
Loading history...
645
    }
646
647
    /**
648
     * Begin a string with a single instance of a given value.
649
     *
650
     * @param  string $string String
651
     * @param  string $prefix Prefix
652
     */
653
    public static function start(string $string, string $prefix): string
654
    {
655
        $quoted = preg_quote($prefix, '/');
656
657
        return $prefix . preg_replace('/^(?:' . $quoted . ')+/u', '', $string);
658
    }
659
660
    /**
661
     * Determine if a given string starts with a given substring.
662
     *
663
     * @param  string          $haystack Haystack
664
     * @param  string|string[] $needles  needles
665
     */
666
    public static function startsWith(string $haystack, $needles): bool
667
    {
668
        foreach ((array) $needles as $needle) {
669
            if ((string) $needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0) {
670
                return true;
671
            }
672
        }
673
674
        return false;
675
    }
676
677
    /**
678
     * Determine if a given string ends with a given substring.
679
     *
680
     * @param  string          $haystack Haystack
681
     * @param  string|string[] $needles  needles
682
     */
683
    public static function endsWith(string $haystack, $needles): bool
684
    {
685
        foreach ((array) $needles as $needle) {
686
            if ($needle !== '' && substr($haystack, -strlen($needle)) === (string) $needle) {
687
                return true;
688
            }
689
        }
690
691
        return false;
692
    }
693
694
    /**
695
     * Cap a string with a single instance of a given value.
696
     *
697
     * @param  string $string String
698
     * @param  string $cap    Cap
699
     */
700
    public static function finish(string $string, string $cap): string
701
    {
702
        $quoted = preg_quote($cap, '/');
703
704
        return preg_replace('/(?:' . $quoted . ')+$/u', '', $string) . $cap;
705
    }
706
707
    /**
708
     * Generate a hash string from the input string.
709
     *
710
     * @param  string $string     String
711
     * @param  string $algorithm  Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..).
712
     *                            For a list of supported algorithms see hash_algos(). Default is md5.
713
     * @param  string $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Default is FALSE
714
     */
715
    public static function hash(string $string, string $algorithm = 'md5', bool $raw_output = false): string
716
    {
717
        if (in_array($algorithm, hash_algos())) {
718
            return hash($algorithm, $string, $raw_output);
719
        }
720
721
        return $string;
722
    }
723
}
724