Completed
Push — master ( d219c5...40b0f0 )
by Lars
01:53
created

Stringy::substringOf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 7
Ratio 58.33 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 7
loc 12
ccs 8
cts 8
cp 1
crap 1
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stringy;
6
7
use Defuse\Crypto\Crypto;
8
use voku\helper\AntiXSS;
9
use voku\helper\ASCII;
10
use voku\helper\EmailCheck;
11
use voku\helper\URLify;
12
use voku\helper\UTF8;
13
14
/**
15
 * @template-implements \IteratorAggregate<string>
16
 * @template-implements \ArrayAccess<array-key,string>
17
 */
18
class Stringy implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
19
{
20
    /**
21
     * An instance's string.
22
     *
23
     * @var string
24
     */
25
    protected $str;
26
27
    /**
28
     * The string's encoding, which should be one of the mbstring module's
29
     * supported encodings.
30
     *
31
     * @var string
32
     */
33
    protected $encoding;
34
35
    /**
36
     * @var UTF8
37
     */
38
    private $utf8;
39
40
    /**
41
     * @var ASCII
42
     */
43
    private $ascii;
44
45
    /**
46
     * Initializes a Stringy object and assigns both str and encoding properties
47
     * the supplied values. $str is cast to a string prior to assignment, and if
48
     * $encoding is not specified, it defaults to mb_internal_encoding(). Throws
49
     * an InvalidArgumentException if the first argument is an array or object
50
     * without a __toString method.
51
     *
52
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
53
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
54
     *
55
     * @throws \InvalidArgumentException
56
     *                                   <p>if an array or object without a
57
     *                                   __toString method is passed as the first argument</p>
58
     *
59
     * @psalm-mutation-free
60
     */
61 3601
    public function __construct($str = '', string $encoding = null)
62
    {
63 3601
        if (\is_array($str)) {
64 3
            throw new \InvalidArgumentException(
65 3
                'Passed value cannot be an array'
66
            );
67
        }
68
69
        if (
70 3598
            \is_object($str)
71
            &&
72 3598
            !\method_exists($str, '__toString')
73
        ) {
74 3
            throw new \InvalidArgumentException(
75 3
                'Passed object must have a __toString method'
76
            );
77
        }
78
79 3595
        $this->str = (string) $str;
80
81 3595
        static $ASCII = null;
82 3595
        if ($ASCII === null) {
83
            $ASCII = new ASCII();
84
        }
85 3595
        $this->ascii = $ASCII;
86
87 3595
        static $UTF8 = null;
88 3595
        if ($UTF8 === null) {
89
            $UTF8 = new UTF8();
90
        }
91 3595
        $this->utf8 = $UTF8;
92
93 3595
        if ($encoding !== 'UTF-8') {
94 2425
            $this->encoding = $this->utf8::normalize_encoding($encoding, 'UTF-8');
95
        } else {
96 2682
            $this->encoding = $encoding;
97
        }
98 3595
    }
99
100
    /**
101
     * Returns the value in $str.
102
     *
103
     * @psalm-mutation-free
104
     *
105
     * @return string
106
     *                <p>The current value of the $str property.</p>
107
     */
108 1127
    public function __toString()
109
    {
110 1127
        return (string) $this->str;
111
    }
112
113
    /**
114
     * Return part of the string occurring after a specific string.
115
     *
116
     * @param string $string <p>The delimiting string.</p>
117
     *
118
     * @psalm-mutation-free
119
     *
120
     * @return static
121
     */
122 4
    public function after(string $string): self
123
    {
124 4
        $strArray = UTF8::str_split_pattern(
125 4
            $this->str,
126 4
            $string
127
        );
128
129 4
        unset($strArray[0]);
130
131 4
        return new static(
132 4
            \implode(' ', $strArray),
133 4
            $this->encoding
134
        );
135
    }
136
137
    /**
138
     * Gets the substring after the first occurrence of a separator.
139
     * If no match is found returns new empty Stringy object.
140
     *
141
     * @param string $separator
142
     *
143
     * @psalm-mutation-free
144
     *
145
     * @return static
146
     */
147 3
    public function afterFirst(string $separator): self
148
    {
149 3
        return static::create(
150 3
            $this->utf8::str_substr_after_first_separator(
151 3
                $this->str,
152 3
                $separator,
153 3
                $this->encoding
154
            )
155
        );
156
    }
157
158
    /**
159
     * Gets the substring after the first occurrence of a separator.
160
     * If no match is found returns new empty Stringy object.
161
     *
162
     * @param string $separator
163
     *
164
     * @psalm-mutation-free
165
     *
166
     * @return static
167
     */
168 2
    public function afterFirstIgnoreCase(string $separator): self
169
    {
170 2
        return static::create(
171 2
            $this->utf8::str_isubstr_after_first_separator(
172 2
                $this->str,
173 2
                $separator,
174 2
                $this->encoding
175
            )
176
        );
177
    }
178
179
    /**
180
     * Gets the substring after the last occurrence of a separator.
181
     * If no match is found returns new empty Stringy object.
182
     *
183
     * @param string $separator
184
     *
185
     * @psalm-mutation-free
186
     *
187
     * @return static
188
     */
189 2
    public function afterLast(string $separator): self
190
    {
191 2
        return static::create(
192 2
            $this->utf8::str_substr_after_last_separator(
193 2
                $this->str,
194 2
                $separator,
195 2
                $this->encoding
196
            )
197
        );
198
    }
199
200
    /**
201
     * Gets the substring after the last occurrence of a separator.
202
     * If no match is found returns new empty Stringy object.
203
     *
204
     * @param string $separator
205
     *
206
     * @psalm-mutation-free
207
     *
208
     * @return static
209
     */
210 2
    public function afterLastIgnoreCase(string $separator): self
211
    {
212 2
        return static::create(
213 2
            $this->utf8::str_isubstr_after_last_separator(
214 2
                $this->str,
215 2
                $separator,
216 2
                $this->encoding
217
            )
218
        );
219
    }
220
221
    /**
222
     * Returns a new string with $suffix appended.
223
     *
224
     * @param string ...$suffix <p>The string to append.</p>
225
     *
226
     * @psalm-mutation-free
227
     *
228
     * @return static
229
     *                <p>Object with appended $suffix.</p>
230
     *
231
     * @noinspection PhpDocSignatureInspection
232
     */
233 14 View Code Duplication
    public function append(string ...$suffix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
    {
235 14
        if (\count($suffix) <= 1) {
236
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
237 13
            $suffix = $suffix[0];
238
        } else {
239
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
240 1
            $suffix = \implode('', $suffix);
241
        }
242
243 14
        return static::create($this->str . $suffix, $this->encoding);
244
    }
245
246
    /**
247
     * Append an password (limited to chars that are good readable).
248
     *
249
     * @param int $length <p>Length of the random string.</p>
250
     *
251
     * @return static
252
     *                <p>Object with appended password.</p>
253
     */
254 2
    public function appendPassword(int $length): self
255
    {
256 2
        return $this->appendRandomString(
257 2
            $length,
258 2
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
259
        );
260
    }
261
262
    /**
263
     * Append an random string.
264
     *
265
     * @param int    $length        <p>Length of the random string.</p>
266
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
267
     *
268
     * @return static
269
     *                <p>Object with appended random string.</p>
270
     */
271 4
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
272
    {
273 4
        $str = $this->utf8::get_random_string($length, $possibleChars);
274
275 4
        return $this->append($str);
276
    }
277
278
    /**
279
     * Append an unique identifier.
280
     *
281
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
282
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
283
     *
284
     * @return static
285
     *                <p>Object with appended unique identifier as md5-hash.</p>
286
     */
287 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
288
    {
289 2
        return $this->append(
290 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
291
        );
292
    }
293
294
    /**
295
     * Returns the character at $index, with indexes starting at 0.
296
     *
297
     * @param int $index <p>Position of the character.</p>
298
     *
299
     * @psalm-mutation-free
300
     *
301
     * @return static
302
     *                <p>The character at $index.</p>
303
     */
304 24
    public function at(int $index): self
305
    {
306 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
307
    }
308
309
    /**
310
     * Decode the base64 encoded string.
311
     *
312
     * @psalm-mutation-free
313
     *
314
     * @return self
315
     */
316 2
    public function base64Decode(): self
317
    {
318 2
        return static::create(
319 2
            \base64_decode($this->str, true),
320 2
            $this->encoding
321
        );
322
    }
323
324
    /**
325
     * Encode the string to base64.
326
     *
327
     * @psalm-mutation-free
328
     *
329
     * @return self
330
     */
331 2
    public function base64Encode(): self
332
    {
333 2
        return static::create(
334 2
            \base64_encode($this->str),
335 2
            $this->encoding
336
        );
337
    }
338
339
    /**
340
     * Creates a hash from the string using the CRYPT_BLOWFISH algorithm.
341
     *
342
     * WARNING: Using this algorithm, will result in the ```$this->str```
343
     *          being truncated to a maximum length of 72 characters.
344
     *
345
     * @param array<array-key, int|string> $options [optional] <p>An array of bcrypt hasing options.</p>
346
     *
347
     * @return static
348
     */
349 3
    public function bcrypt(array $options = []): self
350
    {
351 3
        return new static(
352 3
            \password_hash(
353 3
                $this->str,
354 3
                \PASSWORD_BCRYPT,
355 3
                $options
356
            ),
357 3
            $this->encoding
358
        );
359
    }
360
361
    /**
362
     * Return part of the string occurring before a specific string.
363
     *
364
     * @param string $string <p>The delimiting string.</p>
365
     *
366
     * @psalm-mutation-free
367
     *
368
     * @return static
369
     */
370 4
    public function before(string $string): self
371
    {
372 4
        $strArray = UTF8::str_split_pattern(
373 4
            $this->str,
374 4
            $string,
375 4
            1
376
        );
377
378 4
        return new static(
379 4
            $strArray[0] ?? '',
380 4
            $this->encoding
381
        );
382
    }
383
384
    /**
385
     * Gets the substring before the first occurrence of a separator.
386
     * If no match is found returns new empty Stringy object.
387
     *
388
     * @param string $separator
389
     *
390
     * @psalm-mutation-free
391
     *
392
     * @return static
393
     */
394 2
    public function beforeFirst(string $separator): self
395
    {
396 2
        return static::create(
397 2
            $this->utf8::str_substr_before_first_separator(
398 2
                $this->str,
399 2
                $separator,
400 2
                $this->encoding
401
            )
402
        );
403
    }
404
405
    /**
406
     * Gets the substring before the first occurrence of a separator.
407
     * If no match is found returns new empty Stringy object.
408
     *
409
     * @param string $separator
410
     *
411
     * @psalm-mutation-free
412
     *
413
     * @return static
414
     */
415 2
    public function beforeFirstIgnoreCase(string $separator): self
416
    {
417 2
        return static::create(
418 2
            $this->utf8::str_isubstr_before_first_separator(
419 2
                $this->str,
420 2
                $separator,
421 2
                $this->encoding
422
            )
423
        );
424
    }
425
426
    /**
427
     * Gets the substring before the last occurrence of a separator.
428
     * If no match is found returns new empty Stringy object.
429
     *
430
     * @param string $separator
431
     *
432
     * @psalm-mutation-free
433
     *
434
     * @return static
435
     */
436 2
    public function beforeLast(string $separator): self
437
    {
438 2
        return static::create(
439 2
            $this->utf8::str_substr_before_last_separator(
440 2
                $this->str,
441 2
                $separator,
442 2
                $this->encoding
443
            )
444
        );
445
    }
446
447
    /**
448
     * Gets the substring before the last occurrence of a separator.
449
     * If no match is found returns new empty Stringy object.
450
     *
451
     * @param string $separator
452
     *
453
     * @psalm-mutation-free
454
     *
455
     * @return static
456
     */
457 2
    public function beforeLastIgnoreCase(string $separator): self
458
    {
459 2
        return static::create(
460 2
            $this->utf8::str_isubstr_before_last_separator(
461 2
                $this->str,
462 2
                $separator,
463 2
                $this->encoding
464
            )
465
        );
466
    }
467
468
    /**
469
     * Returns the substring between $start and $end, if found, or an empty
470
     * string. An optional offset may be supplied from which to begin the
471
     * search for the start string.
472
     *
473
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
474
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
475
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
476
     *
477
     * @psalm-mutation-free
478
     *
479
     * @return static
480
     *                <p>Object whose $str is a substring between $start and $end.</p>
481
     */
482 48
    public function between(string $start, string $end, int $offset = null): self
483
    {
484
        /** @noinspection UnnecessaryCastingInspection */
485 48
        $str = $this->utf8::between(
486 48
            $this->str,
487 48
            $start,
488 48
            $end,
489 48
            (int) $offset,
490 48
            $this->encoding
491
        );
492
493 48
        return static::create($str, $this->encoding);
494
    }
495
496
    /**
497
     * Returns a camelCase version of the string. Trims surrounding spaces,
498
     * capitalizes letters following digits, spaces, dashes and underscores,
499
     * and removes spaces, dashes, as well as underscores.
500
     *
501
     * @psalm-mutation-free
502
     *
503
     * @return static
504
     *                <p>Object with $str in camelCase.</p>
505
     */
506 57
    public function camelize(): self
507
    {
508 57
        return static::create(
509 57
            $this->utf8::str_camelize($this->str, $this->encoding),
510 57
            $this->encoding
511
        );
512
    }
513
514
    /**
515
     * Returns the string with the first letter of each word capitalized,
516
     * except for when the word is a name which shouldn't be capitalized.
517
     *
518
     * @psalm-mutation-free
519
     *
520
     * @return static
521
     *                <p>Object with $str capitalized.</p>
522
     */
523 78
    public function capitalizePersonalName(): self
524
    {
525 78
        return static::create(
526 78
            $this->utf8::str_capitalize_name($this->str),
527 78
            $this->encoding
528
        );
529
    }
530
531
    /**
532
     * Returns an array consisting of the characters in the string.
533
     *
534
     * @psalm-mutation-free
535
     *
536
     * @return string[]
537
     *                  <p>An array of string chars.</p>
538
     */
539 14
    public function chars(): array
540
    {
541 14
        return $this->utf8::str_split($this->str);
542
    }
543
544
    /**
545
     * Splits the string into chunks of Stringy objects.
546
     *
547
     * @param int  $length                   [optional] <p>Max character length of each array element.</p>
548
     * @param bool $return_stingy_collection [optional] <p>Return a collection object.</p>
549
     *
550
     * @psalm-mutation-free
551
     *
552
     * @return CollectionStringy|static[]
553
     *                                    <p>An collection of Stringy objects.</p>
554
     *
555
     * @psalm-return CollectionStringy<int,static>|array<int,static>
556
     */
557 13
    public function chunk(int $length = 1, bool $return_stingy_collection = false)
558
    {
559 13
        if ($length < 1) {
560
            throw new \InvalidArgumentException('The chunk length must be greater than zero.');
561
        }
562
563 13
        if ($this->str === '') {
564 2
            if ($return_stingy_collection) {
565
                /**
566
                 * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
567
                 */
568 1
                return CollectionStringy::create([]);
569
            }
570
571 1
            return [];
572
        }
573
574 11
        $chunks = $this->utf8::str_split($this->str, $length);
575
        /** @noinspection AlterInForeachInspection */
576 11
        foreach ($chunks as $i => &$value) {
577 11
            $value = static::create($value, $this->encoding);
578
        }
579
580 11
        if ($return_stingy_collection) {
581
            /**
582
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
583
             */
584 6
            return CollectionStringy::create($chunks);
585
        }
586
587 5
        return $chunks;
588
    }
589
590
    /**
591
     * Trims the string and replaces consecutive whitespace characters with a
592
     * single space. This includes tabs and newline characters, as well as
593
     * multibyte whitespace such as the thin space and ideographic space.
594
     *
595
     * @psalm-mutation-free
596
     *
597
     * @return static
598
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
599
     */
600 39
    public function collapseWhitespace(): self
601
    {
602 39
        return static::create(
603 39
            $this->utf8::collapse_whitespace($this->str),
604 39
            $this->encoding
605
        );
606
    }
607
608
    /**
609
     * Returns true if the string contains $needle, false otherwise. By default
610
     * the comparison is case-sensitive, but can be made insensitive by setting
611
     * $caseSensitive to false.
612
     *
613
     * @param string $needle        <p>Substring to look for.</p>
614
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
615
     *
616
     * @psalm-mutation-free
617
     *
618
     * @return bool
619
     *              <p>Whether or not $str contains $needle.</p>
620
     */
621 63
    public function contains(string $needle, bool $caseSensitive = true): bool
622
    {
623 63
        return $this->utf8::str_contains(
624 63
            $this->str,
625 63
            $needle,
626 63
            $caseSensitive
627
        );
628
    }
629
630
    /**
631
     * Returns true if the string contains all $needles, false otherwise. By
632
     * default the comparison is case-sensitive, but can be made insensitive by
633
     * setting $caseSensitive to false.
634
     *
635
     * @param string[] $needles       <p>SubStrings to look for.</p>
636
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
637
     *
638
     * @psalm-mutation-free
639
     *
640
     * @return bool
641
     *              <p>Whether or not $str contains $needle.</p>
642
     */
643 131
    public function containsAll(array $needles, bool $caseSensitive = true): bool
644
    {
645 131
        return $this->utf8::str_contains_all(
646 131
            $this->str,
647 131
            $needles,
648 131
            $caseSensitive
649
        );
650
    }
651
652
    /**
653
     * Returns true if the string contains any $needles, false otherwise. By
654
     * default the comparison is case-sensitive, but can be made insensitive by
655
     * setting $caseSensitive to false.
656
     *
657
     * @param string[] $needles       <p>SubStrings to look for.</p>
658
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
659
     *
660
     * @psalm-mutation-free
661
     *
662
     * @return bool
663
     *              <p>Whether or not $str contains $needle.</p>
664
     */
665 129
    public function containsAny(array $needles, bool $caseSensitive = true): bool
666
    {
667 129
        return $this->utf8::str_contains_any(
668 129
            $this->str,
669 129
            $needles,
670 129
            $caseSensitive
671
        );
672
    }
673
674
    /**
675
     * Returns the length of the string, implementing the countable interface.
676
     *
677
     * @psalm-mutation-free
678
     *
679
     * @return int
680
     *             <p>The number of characters in the string, given the encoding.</p>
681
     */
682 3
    public function count(): int
683
    {
684 3
        return $this->length();
685
    }
686
687
    /**
688
     * Returns the number of occurrences of $substring in the given string.
689
     * By default, the comparison is case-sensitive, but can be made insensitive
690
     * by setting $caseSensitive to false.
691
     *
692
     * @param string $substring     <p>The substring to search for.</p>
693
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
694
     *
695
     * @psalm-mutation-free
696
     *
697
     * @return int
698
     */
699 45
    public function countSubstr(string $substring, bool $caseSensitive = true): int
700
    {
701 45
        return $this->utf8::substr_count_simple(
702 45
            $this->str,
703 45
            $substring,
704 45
            $caseSensitive,
705 45
            $this->encoding
706
        );
707
    }
708
709
    /**
710
     * Calculates the crc32 polynomial of a string.
711
     *
712
     * @psalm-mutation-free
713
     *
714
     * @return int
715
     */
716 2
    public function crc32(): int
717
    {
718 2
        return \crc32($this->str);
719
    }
720
721
    /**
722
     * Creates a Stringy object and assigns both str and encoding properties
723
     * the supplied values. $str is cast to a string prior to assignment, and if
724
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
725
     * then returns the initialized object. Throws an InvalidArgumentException
726
     * if the first argument is an array or object without a __toString method.
727
     *
728
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
729
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
730
     *
731
     * @throws \InvalidArgumentException
732
     *                                   <p>if an array or object without a
733
     *                                   __toString method is passed as the first argument</p>
734
     *
735
     * @return static
736
     *                <p>A Stringy object.</p>
737
     * @psalm-pure
738
     */
739 3541
    public static function create($str = '', string $encoding = null): self
740
    {
741 3541
        return new static($str, $encoding);
742
    }
743
744
    /**
745
     * One-way string encryption (hashing).
746
     *
747
     * Hash the string using the standard Unix DES-based algorithm or an
748
     * alternative algorithm that may be available on the system.
749
     *
750
     * PS: if you need encrypt / decrypt, please use use ```static::encrypt($password)```
751
     *     and ```static::decrypt($password)```
752
     *
753
     * @param string $salt <p>A salt string to base the hashing on.</p>
754
     *
755
     * @return static
756
     */
757 3
    public function crypt(string $salt): self
758
    {
759 3
        return new static(
760 3
            \crypt(
761 3
                $this->str,
762 3
                $salt
763
            ),
764 3
            $this->encoding
765
        );
766
    }
767
768
    /**
769
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
770
     * inserted before uppercase characters (with the exception of the first
771
     * character of the string), and in place of spaces as well as underscores.
772
     *
773
     * @psalm-mutation-free
774
     *
775
     * @return static
776
     *                <p>Object with a dasherized $str</p>
777
     */
778 57
    public function dasherize(): self
779
    {
780 57
        return static::create(
781 57
            $this->utf8::str_dasherize($this->str),
782 57
            $this->encoding
783
        );
784
    }
785
786
    /**
787
     * Decrypt the string.
788
     *
789
     * @param string $password The key for decrypting
790
     *
791
     * @return static
792
     */
793 5
    public function decrypt(string $password): self
794
    {
795 5
        return new static(
796 5
            Crypto::decryptWithPassword($this->str, $password),
797 3
            $this->encoding
798
        );
799
    }
800
801
    /**
802
     * Returns a lowercase and trimmed string separated by the given delimiter.
803
     * Delimiters are inserted before uppercase characters (with the exception
804
     * of the first character of the string), and in place of spaces, dashes,
805
     * and underscores. Alpha delimiters are not converted to lowercase.
806
     *
807
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
808
     *
809
     * @psalm-mutation-free
810
     *
811
     * @return static
812
     *                <p>Object with a delimited $str.</p>
813
     */
814 90
    public function delimit(string $delimiter): self
815
    {
816 90
        return static::create(
817 90
            $this->utf8::str_delimit($this->str, $delimiter),
818 90
            $this->encoding
819
        );
820
    }
821
822
    /**
823
     * Set the internal character encoding.
824
     *
825
     * @param string $encoding The desired character encoding
826
     *
827
     * @psalm-mutation-free
828
     *
829
     * @return static
830
     */
831 1
    public function encoding(string $encoding): self
832
    {
833 1
        return new static($this->str, $encoding);
834
    }
835
836
    /**
837
     * Encrypt the string.
838
     *
839
     * @param string $password <p>The key for encrypting</p>
840
     *
841
     * @return static
842
     */
843 4
    public function encrypt(string $password): self
844
    {
845 4
        return new static(
846 4
            Crypto::encryptWithPassword($this->str, $password),
847 4
            $this->encoding
848
        );
849
    }
850
851
    /**
852
     * Returns true if the string ends with $substring, false otherwise. By
853
     * default, the comparison is case-sensitive, but can be made insensitive
854
     * by setting $caseSensitive to false.
855
     *
856
     * @param string $substring     <p>The substring to look for.</p>
857
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
858
     *
859
     * @psalm-mutation-free
860
     *
861
     * @return bool
862
     *              <p>Whether or not $str ends with $substring.</p>
863
     */
864 97
    public function endsWith(string $substring, bool $caseSensitive = true): bool
865
    {
866 97
        if ($caseSensitive) {
867 53
            return $this->utf8::str_ends_with($this->str, $substring);
868
        }
869
870 44
        return $this->utf8::str_iends_with($this->str, $substring);
871
    }
872
873
    /**
874
     * Returns true if the string ends with any of $substrings, false otherwise.
875
     * By default, the comparison is case-sensitive, but can be made insensitive
876
     * by setting $caseSensitive to false.
877
     *
878
     * @param string[] $substrings    <p>Substrings to look for.</p>
879
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
880
     *
881
     * @psalm-mutation-free
882
     *
883
     * @return bool
884
     *              <p>Whether or not $str ends with $substring.</p>
885
     */
886 33
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
887
    {
888 33
        if ($caseSensitive) {
889 21
            return $this->utf8::str_ends_with_any($this->str, $substrings);
890
        }
891
892 12
        return $this->utf8::str_iends_with_any($this->str, $substrings);
893
    }
894
895
    /**
896
     * Ensures that the string begins with $substring. If it doesn't, it's
897
     * prepended.
898
     *
899
     * @param string $substring <p>The substring to add if not present.</p>
900
     *
901
     * @psalm-mutation-free
902
     *
903
     * @return static
904
     *                <p>Object with its $str prefixed by the $substring.</p>
905
     */
906 30
    public function ensureLeft(string $substring): self
907
    {
908 30
        return static::create(
909 30
            $this->utf8::str_ensure_left($this->str, $substring),
910 30
            $this->encoding
911
        );
912
    }
913
914
    /**
915
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
916
     *
917
     * @param string $substring <p>The substring to add if not present.</p>
918
     *
919
     * @psalm-mutation-free
920
     *
921
     * @return static
922
     *                <p>Object with its $str suffixed by the $substring.</p>
923
     */
924 30
    public function ensureRight(string $substring): self
925
    {
926 30
        return static::create(
927 30
            $this->utf8::str_ensure_right($this->str, $substring),
928 30
            $this->encoding
929
        );
930
    }
931
932
    /**
933
     * Create a escape html version of the string via "htmlspecialchars()".
934
     *
935
     * @psalm-mutation-free
936
     *
937
     * @return static
938
     */
939 12
    public function escape(): self
940
    {
941 12
        return static::create(
942 12
            $this->utf8::htmlspecialchars(
943 12
                $this->str,
944 12
                \ENT_QUOTES | \ENT_SUBSTITUTE,
945 12
                $this->encoding
946
            ),
947 12
            $this->encoding
948
        );
949
    }
950
951
    /**
952
     * Split a string by a string.
953
     *
954
     * @param string $delimiter                <p>The boundary string</p>
955
     * @param int    $limit                    [optional] <p>The maximum number of elements in the exploded
956
     *                                         collection.</p>
957
     * @param bool   $return_stingy_collection [optional] <p>Return a collection object.</p>
958
     *
959
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
960
     *   element containing the rest of string.
961
     *   - If the limit parameter is negative, all components except the last -limit are returned.
962
     *   - If the limit parameter is zero, then this is treated as 1
963
     *
964
     * @psalm-mutation-free
965
     *
966
     * @return array<int,static>|CollectionStringy<int,static>
0 ignored issues
show
Documentation introduced by
The doc-type array<int,static>|CollectionStringy<int,static> could not be parsed: Expected "|" or "end of type", but got "<" at position 35. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
967
     */
968 3
    public function explode(
969
        string $delimiter,
970
        int $limit = \PHP_INT_MAX,
971
        bool $return_stingy_collection = false
972
    ) {
973 3
        if ($this->str === '') {
974
            if ($return_stingy_collection) {
975
                /**
976
                 * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
977
                 */
978
                return CollectionStringy::create([]);
979
            }
980
981
            return [];
982
        }
983
984 3
        $data = \explode($delimiter, $this->str, $limit);
985 3
        if ($data === false) {
986
            $data = [];
987
        }
988
989 3
        $data = \array_map(
990
            function ($str) {
991 3
                return new static($str, $this->encoding);
992 3
            },
993 3
            $data
994
        );
995
996 3
        if ($return_stingy_collection) {
997
            /**
998
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
999
             */
1000 1
            return CollectionStringy::create($data);
1001
        }
1002
1003 2
        return $data;
1004
    }
1005
1006
    /**
1007
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
1008
     *
1009
     * @param string   $search
1010
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
1011
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
1012
     *
1013
     * @psalm-mutation-free
1014
     *
1015
     * @return static
1016
     */
1017 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
1018
    {
1019 2
        return static::create(
1020 2
            $this->utf8::extract_text(
1021 2
                $this->str,
1022 2
                $search,
1023 2
                $length,
1024 2
                $replacerForSkippedText,
1025 2
                $this->encoding
1026
            ),
1027 2
            $this->encoding
1028
        );
1029
    }
1030
1031
    /**
1032
     * Returns the first $n characters of the string.
1033
     *
1034
     * @param int $n <p>Number of characters to retrieve from the start.</p>
1035
     *
1036
     * @psalm-mutation-free
1037
     *
1038
     * @return static
1039
     *                <p>Object with its $str being the first $n chars.</p>
1040
     */
1041 37
    public function first(int $n): self
1042
    {
1043 37
        return static::create(
1044 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
1045 37
            $this->encoding
1046
        );
1047
    }
1048
1049
    /**
1050
     * Return a formatted string via sprintf + named parameters via array syntax.
1051
     *
1052
     * <p>
1053
     * <br>
1054
     * It will use "sprintf()" so you can use e.g.:
1055
     * <br>
1056
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
1057
     * <br>
1058
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
1059
     * <br>
1060
     * <br>
1061
     * But you can also use named parameter via array syntax e.g.:
1062
     * <br>
1063
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
1064
     * </p>
1065
     *
1066
     * @param mixed ...$args [optional]
1067
     *
1068
     * @psalm-mutation-free
1069
     *
1070
     * @return static
1071
     *                <p>A Stringy object produced according to the formatting string
1072
     *                format.</p>
1073
     */
1074 10
    public function format(...$args): self
1075
    {
1076
        // init
1077 10
        $str = $this->str;
1078
1079 10
        if (\strpos($this->str, '%:') !== false) {
1080 8
            $offset = null;
1081 8
            $replacement = null;
1082
            /** @noinspection AlterInForeachInspection */
1083 8
            foreach ($args as $key => &$arg) {
1084 8
                if (!\is_array($arg)) {
1085 4
                    continue;
1086
                }
1087
1088 8
                foreach ($arg as $name => $param) {
1089 8
                    $name = (string) $name;
1090
1091 8
                    if (\strpos($name, '%:') !== 0) {
1092 8
                        $nameTmp = '%:' . $name;
1093
                    } else {
1094
                        $nameTmp = $name;
1095
                    }
1096
1097 8
                    if ($offset === null) {
1098 8
                        $offset = \strpos($str, $nameTmp);
1099
                    } else {
1100 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
1101
                    }
1102 8
                    if ($offset === false) {
1103 4
                        continue;
1104
                    }
1105
1106 8
                    unset($arg[$name]);
1107
1108 8
                    $str = \substr_replace($str, $param, (int) $offset, \strlen($nameTmp));
1109
                }
1110
1111 8
                unset($args[$key]);
1112
            }
1113
        }
1114
1115 10
        $str = \str_replace('%:', '%%:', $str);
1116
1117 10
        return static::create(
1118 10
            \sprintf($str, ...$args),
1119 10
            $this->encoding
1120
        );
1121
    }
1122
1123
    /**
1124
     * Returns the encoding used by the Stringy object.
1125
     *
1126
     * @psalm-mutation-free
1127
     *
1128
     * @return string
1129
     *                <p>The current value of the $encoding property.</p>
1130
     */
1131 7
    public function getEncoding(): string
1132
    {
1133 7
        return $this->encoding;
1134
    }
1135
1136
    /**
1137
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
1138
     * interface. The ArrayIterator's constructor is passed an array of chars
1139
     * in the multibyte string. This enables the use of foreach with instances
1140
     * of Stringy\Stringy.
1141
     *
1142
     * @psalm-mutation-free
1143
     *
1144
     * @return \ArrayIterator
1145
     *                        <p>An iterator for the characters in the string.</p>
1146
     *
1147
     * @psalm-return \ArrayIterator<array-key,string>
1148
     */
1149 3
    public function getIterator(): \ArrayIterator
1150
    {
1151 3
        return new \ArrayIterator($this->chars());
1152
    }
1153
1154
    /**
1155
     * Wrap the string after an exact number of characters.
1156
     *
1157
     * @param int    $width <p>Number of characters at which to wrap.</p>
1158
     * @param string $break [optional] <p>Character used to break the string. | Default: "\n"</p>
1159
     *
1160
     * @psalm-mutation-free
1161
     *
1162
     * @return static
1163
     */
1164 2
    public function hardWrap($width, $break = "\n"): self
1165
    {
1166 2
        return $this->lineWrap($width, $break, false);
1167
    }
1168
1169
    /**
1170
     * Returns true if the string contains a lower case char, false otherwise.
1171
     *
1172
     * @psalm-mutation-free
1173
     *
1174
     * @return bool
1175
     *              <p>Whether or not the string contains a lower case character.</p>
1176
     */
1177 36
    public function hasLowerCase(): bool
1178
    {
1179 36
        return $this->utf8::has_lowercase($this->str);
1180
    }
1181
1182
    /**
1183
     * Returns true if the string contains an upper case char, false otherwise.
1184
     *
1185
     * @psalm-mutation-free
1186
     *
1187
     * @return bool
1188
     *              <p>Whether or not the string contains an upper case character.</p>
1189
     */
1190 36
    public function hasUpperCase(): bool
1191
    {
1192 36
        return $this->utf8::has_uppercase($this->str);
1193
    }
1194
1195
    /**
1196
     * Generate a hash value (message digest)
1197
     *
1198
     * @see https://php.net/manual/en/function.hash.php
1199
     *
1200
     * @param string $algorithm
1201
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
1202
     *
1203
     * @psalm-mutation-free
1204
     *
1205
     * @return static
1206
     */
1207 8
    public function hash($algorithm): self
1208
    {
1209 8
        return static::create(\hash($algorithm, $this->str), $this->encoding);
1210
    }
1211
1212
    /**
1213
     * Decode the string from hex.
1214
     *
1215
     * @psalm-mutation-free
1216
     *
1217
     * @return static
1218
     */
1219 2
    public function hexDecode(): self
1220
    {
1221 2
        $string = \preg_replace_callback(
1222 2
            '/\\\\x([0-9A-Fa-f]+)/',
1223
            function (array $matched) {
1224 2
                return (string) $this->utf8::hex_to_chr($matched[1]);
1225 2
            },
1226 2
            $this->str
1227
        );
1228
1229 2
        return static::create(
1230 2
            $string,
1231 2
            $this->encoding
1232
        );
1233
    }
1234
1235
    /**
1236
     * Encode string to hex.
1237
     *
1238
     * @psalm-mutation-free
1239
     *
1240
     * @return static
1241
     */
1242 2
    public function hexEncode(): self
1243
    {
1244 2
        $string = \array_reduce(
1245 2
            $this->chars(),
1246
            function (string $str, string $char) {
1247 2
                return $str . $this->utf8::chr_to_hex($char);
1248 2
            },
1249 2
            ''
1250
        );
1251
1252 2
        return static::create(
1253 2
            $string,
1254 2
            $this->encoding
1255
        );
1256
    }
1257
1258
    /**
1259
     * Convert all HTML entities to their applicable characters.
1260
     *
1261
     * @param int $flags [optional] <p>
1262
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1263
     *                   which document type to use. The default is ENT_COMPAT.
1264
     *                   <table>
1265
     *                   Available <i>flags</i> constants
1266
     *                   <tr valign="top">
1267
     *                   <td>Constant Name</td>
1268
     *                   <td>Description</td>
1269
     *                   </tr>
1270
     *                   <tr valign="top">
1271
     *                   <td><b>ENT_COMPAT</b></td>
1272
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1273
     *                   </tr>
1274
     *                   <tr valign="top">
1275
     *                   <td><b>ENT_QUOTES</b></td>
1276
     *                   <td>Will convert both double and single quotes.</td>
1277
     *                   </tr>
1278
     *                   <tr valign="top">
1279
     *                   <td><b>ENT_NOQUOTES</b></td>
1280
     *                   <td>Will leave both double and single quotes unconverted.</td>
1281
     *                   </tr>
1282
     *                   <tr valign="top">
1283
     *                   <td><b>ENT_HTML401</b></td>
1284
     *                   <td>
1285
     *                   Handle code as HTML 4.01.
1286
     *                   </td>
1287
     *                   </tr>
1288
     *                   <tr valign="top">
1289
     *                   <td><b>ENT_XML1</b></td>
1290
     *                   <td>
1291
     *                   Handle code as XML 1.
1292
     *                   </td>
1293
     *                   </tr>
1294
     *                   <tr valign="top">
1295
     *                   <td><b>ENT_XHTML</b></td>
1296
     *                   <td>
1297
     *                   Handle code as XHTML.
1298
     *                   </td>
1299
     *                   </tr>
1300
     *                   <tr valign="top">
1301
     *                   <td><b>ENT_HTML5</b></td>
1302
     *                   <td>
1303
     *                   Handle code as HTML 5.
1304
     *                   </td>
1305
     *                   </tr>
1306
     *                   </table>
1307
     *                   </p>
1308
     *
1309
     * @psalm-mutation-free
1310
     *
1311
     * @return static
1312
     *                <p>Object with the resulting $str after being html decoded.</p>
1313
     */
1314 15 View Code Duplication
    public function htmlDecode(int $flags = \ENT_COMPAT): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1315
    {
1316 15
        return static::create(
1317 15
            $this->utf8::html_entity_decode(
1318 15
                $this->str,
1319 15
                $flags,
1320 15
                $this->encoding
1321
            ),
1322 15
            $this->encoding
1323
        );
1324
    }
1325
1326
    /**
1327
     * Convert all applicable characters to HTML entities.
1328
     *
1329
     * @param int $flags [optional] <p>
1330
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1331
     *                   which document type to use. The default is ENT_COMPAT.
1332
     *                   <table>
1333
     *                   Available <i>flags</i> constants
1334
     *                   <tr valign="top">
1335
     *                   <td>Constant Name</td>
1336
     *                   <td>Description</td>
1337
     *                   </tr>
1338
     *                   <tr valign="top">
1339
     *                   <td><b>ENT_COMPAT</b></td>
1340
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1341
     *                   </tr>
1342
     *                   <tr valign="top">
1343
     *                   <td><b>ENT_QUOTES</b></td>
1344
     *                   <td>Will convert both double and single quotes.</td>
1345
     *                   </tr>
1346
     *                   <tr valign="top">
1347
     *                   <td><b>ENT_NOQUOTES</b></td>
1348
     *                   <td>Will leave both double and single quotes unconverted.</td>
1349
     *                   </tr>
1350
     *                   <tr valign="top">
1351
     *                   <td><b>ENT_HTML401</b></td>
1352
     *                   <td>
1353
     *                   Handle code as HTML 4.01.
1354
     *                   </td>
1355
     *                   </tr>
1356
     *                   <tr valign="top">
1357
     *                   <td><b>ENT_XML1</b></td>
1358
     *                   <td>
1359
     *                   Handle code as XML 1.
1360
     *                   </td>
1361
     *                   </tr>
1362
     *                   <tr valign="top">
1363
     *                   <td><b>ENT_XHTML</b></td>
1364
     *                   <td>
1365
     *                   Handle code as XHTML.
1366
     *                   </td>
1367
     *                   </tr>
1368
     *                   <tr valign="top">
1369
     *                   <td><b>ENT_HTML5</b></td>
1370
     *                   <td>
1371
     *                   Handle code as HTML 5.
1372
     *                   </td>
1373
     *                   </tr>
1374
     *                   </table>
1375
     *                   </p>
1376
     *
1377
     * @psalm-mutation-free
1378
     *
1379
     * @return static
1380
     *                <p>Object with the resulting $str after being html encoded.</p>
1381
     */
1382 15 View Code Duplication
    public function htmlEncode(int $flags = \ENT_COMPAT): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1383
    {
1384 15
        return static::create(
1385 15
            $this->utf8::htmlentities(
1386 15
                $this->str,
1387 15
                $flags,
1388 15
                $this->encoding
1389
            ),
1390 15
            $this->encoding
1391
        );
1392
    }
1393
1394
    /**
1395
     * Capitalizes the first word of the string, replaces underscores with
1396
     * spaces, and strips '_id'.
1397
     *
1398
     * @psalm-mutation-free
1399
     *
1400
     * @return static
1401
     *                <p>Object with a humanized $str.</p>
1402
     */
1403 9
    public function humanize(): self
1404
    {
1405 9
        return static::create(
1406 9
            $this->utf8::str_humanize($this->str),
1407 9
            $this->encoding
1408
        );
1409
    }
1410
1411
    /**
1412
     * Determine if the current string exists in another string. By
1413
     * default, the comparison is case-sensitive, but can be made insensitive
1414
     * by setting $caseSensitive to false.
1415
     *
1416
     * @param string $str           <p>The string to compare against.</p>
1417
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1418
     *
1419
     * @psalm-mutation-free
1420
     *
1421
     * @return bool
1422
     */
1423 3
    public function in(string $str, bool $caseSensitive = true): bool
1424
    {
1425 3
        if ($caseSensitive) {
1426 2
            return \strpos($str, $this->str) !== false;
1427
        }
1428
1429 1
        return \stripos($str, $this->str) !== false;
1430
    }
1431
1432
    /**
1433
     * Returns the index of the first occurrence of $needle in the string,
1434
     * and false if not found. Accepts an optional offset from which to begin
1435
     * the search.
1436
     *
1437
     * @param string $needle <p>Substring to look for.</p>
1438
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1439
     *
1440
     * @psalm-mutation-free
1441
     *
1442
     * @return false|int
1443
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1444
     */
1445 31
    public function indexOf(string $needle, int $offset = 0)
1446
    {
1447 31
        return $this->utf8::strpos(
1448 31
            $this->str,
1449 31
            $needle,
1450 31
            $offset,
1451 31
            $this->encoding
1452
        );
1453
    }
1454
1455
    /**
1456
     * Returns the index of the first occurrence of $needle in the string,
1457
     * and false if not found. Accepts an optional offset from which to begin
1458
     * the search.
1459
     *
1460
     * @param string $needle <p>Substring to look for.</p>
1461
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1462
     *
1463
     * @psalm-mutation-free
1464
     *
1465
     * @return false|int
1466
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1467
     */
1468 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1469
    {
1470 20
        return $this->utf8::stripos(
1471 20
            $this->str,
1472 20
            $needle,
1473 20
            $offset,
1474 20
            $this->encoding
1475
        );
1476
    }
1477
1478
    /**
1479
     * Returns the index of the last occurrence of $needle in the string,
1480
     * and false if not found. Accepts an optional offset from which to begin
1481
     * the search. Offsets may be negative to count from the last character
1482
     * in the string.
1483
     *
1484
     * @param string $needle <p>Substring to look for.</p>
1485
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1486
     *
1487
     * @psalm-mutation-free
1488
     *
1489
     * @return false|int
1490
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1491
     */
1492 31
    public function indexOfLast(string $needle, int $offset = 0)
1493
    {
1494 31
        return $this->utf8::strrpos(
1495 31
            $this->str,
1496 31
            $needle,
1497 31
            $offset,
1498 31
            $this->encoding
1499
        );
1500
    }
1501
1502
    /**
1503
     * Returns the index of the last occurrence of $needle in the string,
1504
     * and false if not found. Accepts an optional offset from which to begin
1505
     * the search. Offsets may be negative to count from the last character
1506
     * in the string.
1507
     *
1508
     * @param string $needle <p>Substring to look for.</p>
1509
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1510
     *
1511
     * @psalm-mutation-free
1512
     *
1513
     * @return false|int
1514
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1515
     */
1516 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1517
    {
1518 20
        return $this->utf8::strripos(
1519 20
            $this->str,
1520 20
            $needle,
1521 20
            $offset,
1522 20
            $this->encoding
1523
        );
1524
    }
1525
1526
    /**
1527
     * Inserts $substring into the string at the $index provided.
1528
     *
1529
     * @param string $substring <p>String to be inserted.</p>
1530
     * @param int    $index     <p>The index at which to insert the substring.</p>
1531
     *
1532
     * @psalm-mutation-free
1533
     *
1534
     * @return static
1535
     *                <p>Object with the resulting $str after the insertion.</p>
1536
     */
1537 24
    public function insert(string $substring, int $index): self
1538
    {
1539 24
        return static::create(
1540 24
            $this->utf8::str_insert(
1541 24
                $this->str,
1542 24
                $substring,
1543 24
                $index,
1544 24
                $this->encoding
1545
            ),
1546 24
            $this->encoding
1547
        );
1548
    }
1549
1550
    /**
1551
     * Returns true if the string contains the $pattern, otherwise false.
1552
     *
1553
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1554
     * expression wildcards.
1555
     *
1556
     * @credit Originally from Laravel, thanks Taylor.
1557
     *
1558
     * @param string $pattern <p>The string or pattern to match against.</p>
1559
     *
1560
     * @psalm-mutation-free
1561
     *
1562
     * @return bool
1563
     *              <p>Whether or not we match the provided pattern.</p>
1564
     */
1565 26
    public function is(string $pattern): bool
1566
    {
1567 26
        if ($this->toString() === $pattern) {
1568 2
            return true;
1569
        }
1570
1571 24
        $quotedPattern = \preg_quote($pattern, '/');
1572 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1573
1574 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1575
    }
1576
1577
    /**
1578
     * Returns true if the string contains only alphabetic chars, false otherwise.
1579
     *
1580
     * @psalm-mutation-free
1581
     *
1582
     * @return bool
1583
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1584
     */
1585 30
    public function isAlpha(): bool
1586
    {
1587 30
        return $this->utf8::is_alpha($this->str);
1588
    }
1589
1590
    /**
1591
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1592
     *
1593
     * @psalm-mutation-free
1594
     *
1595
     * @return bool
1596
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1597
     */
1598 39
    public function isAlphanumeric(): bool
1599
    {
1600 39
        return $this->utf8::is_alphanumeric($this->str);
1601
    }
1602
1603
    /**
1604
     * Returns true if the string is base64 encoded, false otherwise.
1605
     *
1606
     * @param bool $emptyStringIsValid
1607
     *
1608
     * @psalm-mutation-free
1609
     *
1610
     * @return bool
1611
     *              <p>Whether or not $str is base64 encoded.</p>
1612
     */
1613 21
    public function isBase64($emptyStringIsValid = true): bool
1614
    {
1615 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
1616
    }
1617
1618
    /**
1619
     * Returns true if the string contains only whitespace chars, false otherwise.
1620
     *
1621
     * @psalm-mutation-free
1622
     *
1623
     * @return bool
1624
     *              <p>Whether or not $str contains only whitespace characters.</p>
1625
     */
1626 45
    public function isBlank(): bool
1627
    {
1628 45
        return $this->utf8::is_blank($this->str);
1629
    }
1630
1631
    /**
1632
     * Returns true if the string contains a valid E-Mail address, false otherwise.
1633
     *
1634
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
1635
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
1636
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
1637
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
1638
     *
1639
     * @psalm-mutation-free
1640
     *
1641
     * @return bool
1642
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
1643
     */
1644 2
    public function isEmail(
1645
        bool $useExampleDomainCheck = false,
1646
        bool $useTypoInDomainCheck = false,
1647
        bool $useTemporaryDomainCheck = false,
1648
        bool $useDnsCheck = false
1649
    ): bool {
1650
        /**
1651
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
1652
         */
1653 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
1654
    }
1655
1656
    /**
1657
     * Determine whether the string is considered to be empty.
1658
     *
1659
     * A variable is considered empty if it does not exist or if its value equals FALSE.
1660
     *
1661
     * @psalm-mutation-free
1662
     *
1663
     * @return bool
1664
     *              <p>Whether or not $str is empty().</p>
1665
     */
1666 10
    public function isEmpty(): bool
1667
    {
1668 10
        return $this->utf8::is_empty($this->str);
1669
    }
1670
1671
    /**
1672
     * Determine whether the string is equals to $str.
1673
     * Alias for isEqualsCaseSensitive()
1674
     *
1675
     * @param string|Stringy ...$str
1676
     *
1677
     * @psalm-mutation-free
1678
     *
1679
     * @return bool
1680
     */
1681 13
    public function isEquals(...$str): bool
1682
    {
1683 13
        return $this->isEqualsCaseSensitive(...$str);
1684
    }
1685
1686
    /**
1687
     * Determine whether the string is equals to $str.
1688
     *
1689
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1690
     *
1691
     * @psalm-mutation-free
1692
     *
1693
     * @return bool
1694
     *              <p>Whether or not $str is equals.</p>
1695
     */
1696 3
    public function isEqualsCaseInsensitive(...$str): bool
1697
    {
1698 3
        $strUpper = $this->toUpperCase()->str;
1699
1700 3 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1701
            /**
1702
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1703
             */
1704 3
            if ($strTmp instanceof self) {
1705
                if ($strUpper !== $strTmp->toUpperCase()) {
1706
                    return false;
1707
                }
1708 3
            } elseif (\is_scalar($strTmp)) {
1709 3
                if ($strUpper !== $this->utf8::strtoupper((string) $strTmp, $this->encoding)) {
1710 3
                    return false;
1711
                }
1712
            } else {
1713 3
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1714
            }
1715
        }
1716
1717 3
        return true;
1718
    }
1719
1720
    /**
1721
     * Determine whether the string is equals to $str.
1722
     *
1723
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1724
     *
1725
     * @psalm-mutation-free
1726
     *
1727
     * @return bool
1728
     *              <p>Whether or not $str is equals.</p>
1729
     */
1730 14
    public function isEqualsCaseSensitive(...$str): bool
1731
    {
1732 14 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1733
            /**
1734
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1735
             */
1736 14
            if ($strTmp instanceof self) {
1737 2
                if ($this->str !== $strTmp->str) {
1738 2
                    return false;
1739
                }
1740 12
            } elseif (\is_scalar($strTmp)) {
1741 12
                if ($this->str !== (string) $strTmp) {
1742 12
                    return false;
1743
                }
1744
            } else {
1745 3
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1746
            }
1747
        }
1748
1749 3
        return true;
1750
    }
1751
1752
    /**
1753
     * Returns true if the string contains only hexadecimal chars, false otherwise.
1754
     *
1755
     * @psalm-mutation-free
1756
     *
1757
     * @return bool
1758
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
1759
     */
1760 39
    public function isHexadecimal(): bool
1761
    {
1762 39
        return $this->utf8::is_hexadecimal($this->str);
1763
    }
1764
1765
    /**
1766
     * Returns true if the string contains HTML-Tags, false otherwise.
1767
     *
1768
     * @psalm-mutation-free
1769
     *
1770
     * @return bool
1771
     *              <p>Whether or not $str contains HTML-Tags.</p>
1772
     */
1773 2
    public function isHtml(): bool
1774
    {
1775 2
        return $this->utf8::is_html($this->str);
1776
    }
1777
1778
    /**
1779
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
1780
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
1781
     * in that an empty string is not considered valid JSON.
1782
     *
1783
     * @param bool $onlyArrayOrObjectResultsAreValid
1784
     *
1785
     * @return bool
1786
     *              <p>Whether or not $str is JSON.</p>
1787
     */
1788 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
1789
    {
1790 60
        return $this->utf8::is_json(
1791 60
            $this->str,
1792 60
            $onlyArrayOrObjectResultsAreValid
1793
        );
1794
    }
1795
1796
    /**
1797
     * Returns true if the string contains only lower case chars, false otherwise.
1798
     *
1799
     * @psalm-mutation-free
1800
     *
1801
     * @return bool
1802
     *              <p>Whether or not $str contains only lower case characters.</p>
1803
     */
1804 24
    public function isLowerCase(): bool
1805
    {
1806 24
        return $this->utf8::is_lowercase($this->str);
1807
    }
1808
1809
    /**
1810
     * Determine whether the string is considered to be NOT empty.
1811
     *
1812
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
1813
     *
1814
     * @psalm-mutation-free
1815
     *
1816
     * @return bool
1817
     *              <p>Whether or not $str is empty().</p>
1818
     */
1819 10
    public function isNotEmpty(): bool
1820
    {
1821 10
        return !$this->utf8::is_empty($this->str);
1822
    }
1823
1824
    /**
1825
     * Returns true if the string is serialized, false otherwise.
1826
     *
1827
     * @psalm-mutation-free
1828
     *
1829
     * @return bool
1830
     *              <p>Whether or not $str is serialized.</p>
1831
     */
1832 21
    public function isSerialized(): bool
1833
    {
1834 21
        return $this->utf8::is_serialized($this->str);
1835
    }
1836
1837
    /**
1838
     * Check if two strings are similar.
1839
     *
1840
     * @param string $str                     <p>The string to compare against.</p>
1841
     * @param float  $minPercentForSimilarity [optional] <p>The percentage of needed similarity. | Default: 80%</p>
1842
     *
1843
     * @psalm-mutation-free
1844
     *
1845
     * @return bool
1846
     */
1847 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
1848
    {
1849 2
        return $this->similarity($str) >= $minPercentForSimilarity;
1850
    }
1851
1852
    /**
1853
     * Returns true if the string contains only lower case chars, false
1854
     * otherwise.
1855
     *
1856
     * @psalm-mutation-free
1857
     *
1858
     * @return bool
1859
     *              <p>Whether or not $str contains only lower case characters.</p>
1860
     */
1861 24
    public function isUpperCase(): bool
1862
    {
1863 24
        return $this->utf8::is_uppercase($this->str);
1864
    }
1865
1866
    /**
1867
     * Returns true if the string contains only whitespace chars, false otherwise.
1868
     *
1869
     * @psalm-mutation-free
1870
     *
1871
     * @return bool
1872
     *              <p>Whether or not $str contains only whitespace characters.</p>
1873
     */
1874 30
    public function isWhitespace(): bool
1875
    {
1876 30
        return $this->isBlank();
1877
    }
1878
1879
    /**
1880
     * Returns value which can be serialized by json_encode().
1881
     *
1882
     * @noinspection ReturnTypeCanBeDeclaredInspection
1883
     *
1884
     * @psalm-mutation-free
1885
     *
1886
     * @return string The current value of the $str property
1887
     */
1888 2
    public function jsonSerialize()
1889
    {
1890 2
        return (string) $this;
1891
    }
1892
1893
    /**
1894
     * Returns the last $n characters of the string.
1895
     *
1896
     * @param int $n <p>Number of characters to retrieve from the end.</p>
1897
     *
1898
     * @psalm-mutation-free
1899
     *
1900
     * @return static
1901
     *                <p>Object with its $str being the last $n chars.</p>
1902
     */
1903 36
    public function last(int $n): self
1904
    {
1905 36
        return static::create(
1906 36
            $this->utf8::str_last_char(
1907 36
                $this->str,
1908 36
                $n,
1909 36
                $this->encoding
1910
            ),
1911 36
            $this->encoding
1912
        );
1913
    }
1914
1915
    /**
1916
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1917
     * If no match is found returns new empty Stringy object.
1918
     *
1919
     * @param string $needle       <p>The string to look for.</p>
1920
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1921
     *
1922
     * @psalm-mutation-free
1923
     *
1924
     * @return static
1925
     */
1926 4 View Code Duplication
    public function lastSubstringOf(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1927
    {
1928 4
        return static::create(
1929 4
            $this->utf8::str_substr_last(
1930 4
                $this->str,
1931 4
                $needle,
1932 4
                $beforeNeedle,
1933 4
                $this->encoding
1934
            ),
1935 4
            $this->encoding
1936
        );
1937
    }
1938
1939
    /**
1940
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1941
     * If no match is found returns new empty Stringy object.
1942
     *
1943
     * @param string $needle       <p>The string to look for.</p>
1944
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1945
     *
1946
     * @psalm-mutation-free
1947
     *
1948
     * @return static
1949
     */
1950 2 View Code Duplication
    public function lastSubstringOfIgnoreCase(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1951
    {
1952 2
        return static::create(
1953 2
            $this->utf8::str_isubstr_last(
1954 2
                $this->str,
1955 2
                $needle,
1956 2
                $beforeNeedle,
1957 2
                $this->encoding
1958
            ),
1959 2
            $this->encoding
1960
        );
1961
    }
1962
1963
    /**
1964
     * Returns the length of the string.
1965
     *
1966
     * @psalm-mutation-free
1967
     *
1968
     * @return int
1969
     *             <p>The number of characters in $str given the encoding.</p>
1970
     */
1971 17
    public function length(): int
1972
    {
1973 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
1974
    }
1975
1976
    /**
1977
     * Line-Wrap the string after $limit, but also after the next word.
1978
     *
1979
     * @param int         $limit           [optional] <p>The column width.</p>
1980
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
1981
     * @param bool        $add_final_break [optional] <p>
1982
     *                                     If this flag is true, then the method will add a $break at the end
1983
     *                                     of the result string.
1984
     *                                     </p>
1985
     * @param string|null $delimiter       [optional] <p>
1986
     *                                     You can change the default behavior, where we split the string by newline.
1987
     *                                     </p>
1988
     *
1989
     * @psalm-mutation-free
1990
     *
1991
     * @return static
1992
     */
1993 3 View Code Duplication
    public function lineWrap(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1994
        int $limit,
1995
        string $break = "\n",
1996
        bool $add_final_break = true,
1997
        string $delimiter = null
1998
    ): self {
1999 3
        return static::create(
2000 3
            $this->utf8::wordwrap_per_line(
2001 3
                $this->str,
2002 3
                $limit,
2003 3
                $break,
2004 3
                true,
2005 3
                $add_final_break,
2006 3
                $delimiter
2007
            ),
2008 3
            $this->encoding
2009
        );
2010
    }
2011
2012
    /**
2013
     * Line-Wrap the string after $limit, but also after the next word.
2014
     *
2015
     * @param int         $limit           [optional] <p>The column width.</p>
2016
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2017
     * @param bool        $add_final_break [optional] <p>
2018
     *                                     If this flag is true, then the method will add a $break at the end
2019
     *                                     of the result string.
2020
     *                                     </p>
2021
     * @param string|null $delimiter       [optional] <p>
2022
     *                                     You can change the default behavior, where we split the string by newline.
2023
     *                                     </p>
2024
     *
2025
     * @psalm-mutation-free
2026
     *
2027
     * @return static
2028
     */
2029 4 View Code Duplication
    public function lineWrapAfterWord(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2030
        int $limit,
2031
        string $break = "\n",
2032
        bool $add_final_break = true,
2033
        string $delimiter = null
2034
    ): self {
2035 4
        return static::create(
2036 4
            $this->utf8::wordwrap_per_line(
2037 4
                $this->str,
2038 4
                $limit,
2039 4
                $break,
2040 4
                false,
2041 4
                $add_final_break,
2042 4
                $delimiter
2043
            ),
2044 4
            $this->encoding
2045
        );
2046
    }
2047
2048
    /**
2049
     * Splits on newlines and carriage returns, returning an array of Stringy
2050
     * objects corresponding to the lines in the string.
2051
     *
2052
     * @param bool $return_stingy_collection [optional] <p>Return a collection object.</p>
2053
     *
2054
     * @psalm-mutation-free
2055
     *
2056
     * @return CollectionStringy|static[]
2057
     *                                    <p>An collection of Stringy objects.</p>
2058
     *
2059
     * @psalm-return CollectionStringy<int,static>|array<int,static>
2060
     */
2061 51
    public function lines(bool $return_stingy_collection = false)
2062
    {
2063 51
        if ($this->str === '') {
2064 3
            if ($return_stingy_collection) {
2065
                /**
2066
                 * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2067
                 */
2068 3
                return CollectionStringy::create([static::create('')]);
2069
            }
2070
2071
            return [static::create('')];
2072
        }
2073
2074 48
        $array = $this->utf8::str_to_lines($this->str);
2075
        /** @noinspection AlterInForeachInspection */
2076 48
        foreach ($array as $i => &$value) {
2077 48
            $value = static::create($value, $this->encoding);
2078
        }
2079
2080
        /** @noinspection PhpSillyAssignmentInspection */
2081
        /** @var static[] $array */
2082 48
        $array = $array;
0 ignored issues
show
Bug introduced by
Why assign $array to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
2083
2084 48
        if ($return_stingy_collection) {
2085
            /**
2086
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2087
             */
2088 48
            return CollectionStringy::create($array);
2089
        }
2090
2091
        return $array;
2092
    }
2093
2094
    /**
2095
     * Returns the longest common prefix between the string and $otherStr.
2096
     *
2097
     * @param string $otherStr <p>Second string for comparison.</p>
2098
     *
2099
     * @psalm-mutation-free
2100
     *
2101
     * @return static
2102
     *                <p>Object with its $str being the longest common prefix.</p>
2103
     */
2104 30
    public function longestCommonPrefix(string $otherStr): self
2105
    {
2106 30
        return static::create(
2107 30
            $this->utf8::str_longest_common_prefix(
2108 30
                $this->str,
2109 30
                $otherStr,
2110 30
                $this->encoding
2111
            ),
2112 30
            $this->encoding
2113
        );
2114
    }
2115
2116
    /**
2117
     * Returns the longest common substring between the string and $otherStr.
2118
     * In the case of ties, it returns that which occurs first.
2119
     *
2120
     * @param string $otherStr <p>Second string for comparison.</p>
2121
     *
2122
     * @psalm-mutation-free
2123
     *
2124
     * @return static
2125
     *                <p>Object with its $str being the longest common substring.</p>
2126
     */
2127 30
    public function longestCommonSubstring(string $otherStr): self
2128
    {
2129 30
        return static::create(
2130 30
            $this->utf8::str_longest_common_substring(
2131 30
                $this->str,
2132 30
                $otherStr,
2133 30
                $this->encoding
2134
            ),
2135 30
            $this->encoding
2136
        );
2137
    }
2138
2139
    /**
2140
     * Returns the longest common suffix between the string and $otherStr.
2141
     *
2142
     * @param string $otherStr <p>Second string for comparison.</p>
2143
     *
2144
     * @psalm-mutation-free
2145
     *
2146
     * @return static
2147
     *                <p>Object with its $str being the longest common suffix.</p>
2148
     */
2149 30
    public function longestCommonSuffix(string $otherStr): self
2150
    {
2151 30
        return static::create(
2152 30
            $this->utf8::str_longest_common_suffix(
2153 30
                $this->str,
2154 30
                $otherStr,
2155 30
                $this->encoding
2156
            ),
2157 30
            $this->encoding
2158
        );
2159
    }
2160
2161
    /**
2162
     * Converts the first character of the string to lower case.
2163
     *
2164
     * @psalm-mutation-free
2165
     *
2166
     * @return static
2167
     *                <p>Object with the first character of $str being lower case.</p>
2168
     */
2169 15
    public function lowerCaseFirst(): self
2170
    {
2171 15
        return static::create(
2172 15
            $this->utf8::lcfirst($this->str, $this->encoding),
2173 15
            $this->encoding
2174
        );
2175
    }
2176
2177
    /**
2178
     * Determine if the string matches another string regardless of case.
2179
     * Alias for isEqualsCaseInsensitive()
2180
     *
2181
     * @psalm-mutation-free
2182
     *
2183
     * @param string|Stringy ...$str
2184
     *                               <p>The string to compare against.</p>
2185
     *
2186
     * @psalm-mutation-free
2187
     *
2188
     * @return bool
2189
     */
2190 3
    public function matchCaseInsensitive(...$str): bool
2191
    {
2192 3
        return $this->isEqualsCaseInsensitive(...$str);
2193
    }
2194
2195
    /**
2196
     * Determine if the string matches another string.
2197
     * Alias for isEqualsCaseSensitive()
2198
     *
2199
     * @psalm-mutation-free
2200
     *
2201
     * @param string|Stringy ...$str
2202
     *                               <p>The string to compare against.</p>
2203
     *
2204
     * @psalm-mutation-free
2205
     *
2206
     * @return bool
2207
     */
2208 7
    public function matchCaseSensitive(...$str): bool
2209
    {
2210 7
        return $this->isEqualsCaseSensitive(...$str);
2211
    }
2212
2213
    /**
2214
     * Create a md5 hash from the current string.
2215
     *
2216
     * @psalm-mutation-free
2217
     *
2218
     * @return static
2219
     */
2220 2
    public function md5(): self
2221
    {
2222 2
        return static::create($this->hash('md5'), $this->encoding);
2223
    }
2224
2225
    /**
2226
     * Get every nth character of the string.
2227
     *
2228
     * @param int $step   <p>The number of characters to step.</p>
2229
     * @param int $offset [optional] <p>The string offset to start at.</p>
2230
     *
2231
     * @psalm-mutation-free
2232
     *
2233
     * @return static
2234
     */
2235 4
    public function nth(int $step, int $offset = 0): self
2236
    {
2237 4
        $length = $step - 1;
2238 4
        $substring = $this->substr($offset)->toString();
2239
2240 4
        if ($substring === '') {
2241
            return new static('', $this->encoding);
2242
        }
2243
2244 4
        \preg_match_all(
2245 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2246 4
            $substring,
2247 4
            $matches
2248
        );
2249
2250 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2251
    }
2252
2253
    /**
2254
     * Returns whether or not a character exists at an index. Offsets may be
2255
     * negative to count from the last character in the string. Implements
2256
     * part of the ArrayAccess interface.
2257
     *
2258
     * @param int $offset <p>The index to check.</p>
2259
     *
2260
     * @psalm-mutation-free
2261
     *
2262
     * @return bool
2263
     *              <p>Whether or not the index exists.</p>
2264
     */
2265 18
    public function offsetExists($offset): bool
2266
    {
2267 18
        return $this->utf8::str_offset_exists(
2268 18
            $this->str,
2269 18
            $offset,
2270 18
            $this->encoding
2271
        );
2272
    }
2273
2274
    /**
2275
     * Returns the character at the given index. Offsets may be negative to
2276
     * count from the last character in the string. Implements part of the
2277
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2278
     * does not exist.
2279
     *
2280
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2281
     *
2282
     * @throws \OutOfBoundsException
2283
     *                               <p>If the positive or negative offset does not exist.</p>
2284
     *
2285
     * @return string
2286
     *                <p>The character at the specified index.</p>
2287
     *
2288
     * @psalm-mutation-free
2289
     */
2290 6
    public function offsetGet($offset): string
2291
    {
2292 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2293
    }
2294
2295
    /**
2296
     * Implements part of the ArrayAccess interface, but throws an exception
2297
     * when called. This maintains the immutability of Stringy objects.
2298
     *
2299
     * @param int   $offset <p>The index of the character.</p>
2300
     * @param mixed $value  <p>Value to set.</p>
2301
     *
2302
     * @throws \Exception
2303
     *                    <p>When called.</p>
2304
     *
2305
     * @return void
2306
     */
2307 3
    public function offsetSet($offset, $value)
2308
    {
2309
        // Stringy is immutable, cannot directly set char
2310
        /** @noinspection ThrowRawExceptionInspection */
2311 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
2312
    }
2313
2314
    /**
2315
     * Implements part of the ArrayAccess interface, but throws an exception
2316
     * when called. This maintains the immutability of Stringy objects.
2317
     *
2318
     * @param int $offset <p>The index of the character.</p>
2319
     *
2320
     * @throws \Exception
2321
     *                    <p>When called.</p>
2322
     *
2323
     * @return void
2324
     */
2325 3
    public function offsetUnset($offset)
2326
    {
2327
        // Don't allow directly modifying the string
2328
        /** @noinspection ThrowRawExceptionInspection */
2329 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
2330
    }
2331
2332
    /**
2333
     * Pads the string to a given length with $padStr. If length is less than
2334
     * or equal to the length of the string, no padding takes places. The
2335
     * default string used for padding is a space, and the default type (one of
2336
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
2337
     * if $padType isn't one of those 3 values.
2338
     *
2339
     * @param int    $length  <p>Desired string length after padding.</p>
2340
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2341
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
2342
     *
2343
     * @throws \InvalidArgumentException
2344
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
2345
     *
2346
     * @return static
2347
     *                <p>Object with a padded $str.</p>
2348
     *
2349
     * @psalm-mutation-free
2350
     */
2351 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
2352
    {
2353 39
        return static::create(
2354 39
            $this->utf8::str_pad(
2355 39
                $this->str,
2356 39
                $length,
2357 39
                $padStr,
2358 39
                $padType,
2359 39
                $this->encoding
2360
            )
2361
        );
2362
    }
2363
2364
    /**
2365
     * Returns a new string of a given length such that both sides of the
2366
     * string are padded. Alias for pad() with a $padType of 'both'.
2367
     *
2368
     * @param int    $length <p>Desired string length after padding.</p>
2369
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2370
     *
2371
     * @psalm-mutation-free
2372
     *
2373
     * @return static
2374
     *                <p>String with padding applied.</p>
2375
     */
2376 33
    public function padBoth(int $length, string $padStr = ' '): self
2377
    {
2378 33
        return static::create(
2379 33
            $this->utf8::str_pad_both(
2380 33
                $this->str,
2381 33
                $length,
2382 33
                $padStr,
2383 33
                $this->encoding
2384
            )
2385
        );
2386
    }
2387
2388
    /**
2389
     * Returns a new string of a given length such that the beginning of the
2390
     * string is padded. Alias for pad() with a $padType of 'left'.
2391
     *
2392
     * @param int    $length <p>Desired string length after padding.</p>
2393
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2394
     *
2395
     * @psalm-mutation-free
2396
     *
2397
     * @return static
2398
     *                <p>String with left padding.</p>
2399
     */
2400 21
    public function padLeft(int $length, string $padStr = ' '): self
2401
    {
2402 21
        return static::create(
2403 21
            $this->utf8::str_pad_left(
2404 21
                $this->str,
2405 21
                $length,
2406 21
                $padStr,
2407 21
                $this->encoding
2408
            )
2409
        );
2410
    }
2411
2412
    /**
2413
     * Returns a new string of a given length such that the end of the string
2414
     * is padded. Alias for pad() with a $padType of 'right'.
2415
     *
2416
     * @param int    $length <p>Desired string length after padding.</p>
2417
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2418
     *
2419
     * @psalm-mutation-free
2420
     *
2421
     * @return static
2422
     *                <p>String with right padding.</p>
2423
     */
2424 21
    public function padRight(int $length, string $padStr = ' '): self
2425
    {
2426 21
        return static::create(
2427 21
            $this->utf8::str_pad_right(
2428 21
                $this->str,
2429 21
                $length,
2430 21
                $padStr,
2431 21
                $this->encoding
2432
            )
2433
        );
2434
    }
2435
2436
    /**
2437
     * Returns a new string starting with $prefix.
2438
     *
2439
     * @param string ...$prefix <p>The string to append.</p>
2440
     *
2441
     * @psalm-mutation-free
2442
     *
2443
     * @return static
2444
     *                <p>Object with appended $prefix.</p>
2445
     *
2446
     * @noinspection PhpDocSignatureInspection
2447
     */
2448 7 View Code Duplication
    public function prepend(string ...$prefix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2449
    {
2450 7
        if (\count($prefix) <= 1) {
2451
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2452 6
            $prefix = $prefix[0];
2453
        } else {
2454
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2455 1
            $prefix = \implode('', $prefix);
2456
        }
2457
2458 7
        return static::create($prefix . $this->str, $this->encoding);
2459
    }
2460
2461
    /**
2462
     * Replaces all occurrences of $pattern in $str by $replacement.
2463
     *
2464
     * @param string $pattern     <p>The regular expression pattern.</p>
2465
     * @param string $replacement <p>The string to replace with.</p>
2466
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2467
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2468
     *
2469
     * @psalm-mutation-free
2470
     *
2471
     * @return static
2472
     *                <p>Object with the result2ing $str after the replacements.</p>
2473
     */
2474 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2475
    {
2476 29
        return static::create(
2477 29
            $this->utf8::regex_replace(
2478 29
                $this->str,
2479 29
                $pattern,
2480 29
                $replacement,
2481 29
                $options,
2482 29
                $delimiter
2483
            ),
2484 29
            $this->encoding
2485
        );
2486
    }
2487
2488
    /**
2489
     * Remove html via "strip_tags()" from the string.
2490
     *
2491
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2492
     *                              not be stripped. Default: null
2493
     *                              </p>
2494
     *
2495
     * @psalm-mutation-free
2496
     *
2497
     * @return static
2498
     */
2499 12
    public function removeHtml(string $allowableTags = ''): self
2500
    {
2501 12
        return static::create(
2502 12
            $this->utf8::remove_html($this->str, $allowableTags),
2503 12
            $this->encoding
2504
        );
2505
    }
2506
2507
    /**
2508
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2509
     *
2510
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2511
     *
2512
     * @psalm-mutation-free
2513
     *
2514
     * @return static
2515
     */
2516 12
    public function removeHtmlBreak(string $replacement = ''): self
2517
    {
2518 12
        return static::create(
2519 12
            $this->utf8::remove_html_breaks($this->str, $replacement),
2520 12
            $this->encoding
2521
        );
2522
    }
2523
2524
    /**
2525
     * Returns a new string with the prefix $substring removed, if present.
2526
     *
2527
     * @param string $substring <p>The prefix to remove.</p>
2528
     *
2529
     * @psalm-mutation-free
2530
     *
2531
     * @return static
2532
     *                <p>Object having a $str without the prefix $substring.</p>
2533
     */
2534 36
    public function removeLeft(string $substring): self
2535
    {
2536 36
        return static::create(
2537 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2538 36
            $this->encoding
2539
        );
2540
    }
2541
2542
    /**
2543
     * Returns a new string with the suffix $substring removed, if present.
2544
     *
2545
     * @param string $substring <p>The suffix to remove.</p>
2546
     *
2547
     * @psalm-mutation-free
2548
     *
2549
     * @return static
2550
     *                <p>Object having a $str without the suffix $substring.</p>
2551
     */
2552 36
    public function removeRight(string $substring): self
2553
    {
2554 36
        return static::create(
2555 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2556 36
            $this->encoding
2557
        );
2558
    }
2559
2560
    /**
2561
     * Try to remove all XSS-attacks from the string.
2562
     *
2563
     * @psalm-mutation-free
2564
     *
2565
     * @return static
2566
     */
2567 12
    public function removeXss(): self
2568
    {
2569
        /**
2570
         * @var AntiXSS|null
2571
         *
2572
         * @psalm-suppress ImpureStaticVariable
2573
         */
2574 12
        static $antiXss = null;
2575
2576 12
        if ($antiXss === null) {
2577 1
            $antiXss = new AntiXSS();
2578
        }
2579
2580
        /**
2581
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2582
         */
2583 12
        $str = $antiXss->xss_clean($this->str);
2584
2585 12
        return static::create($str, $this->encoding);
2586
    }
2587
2588
    /**
2589
     * Returns a repeated string given a multiplier.
2590
     *
2591
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2592
     *
2593
     * @psalm-mutation-free
2594
     *
2595
     * @return static
2596
     *                <p>Object with a repeated str.</p>
2597
     */
2598 21
    public function repeat(int $multiplier): self
2599
    {
2600 21
        return static::create(
2601 21
            \str_repeat($this->str, $multiplier),
2602 21
            $this->encoding
2603
        );
2604
    }
2605
2606
    /**
2607
     * Replaces all occurrences of $search in $str by $replacement.
2608
     *
2609
     * @param string $search        <p>The needle to search for.</p>
2610
     * @param string $replacement   <p>The string to replace with.</p>
2611
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2612
     *
2613
     * @psalm-mutation-free
2614
     *
2615
     * @return static
2616
     *                <p>Object with the resulting $str after the replacements.</p>
2617
     */
2618 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2619
    {
2620 76
        if ($search === '' && $replacement === '') {
2621 16
            return static::create($this->str, $this->encoding);
2622
        }
2623
2624 60
        if ($this->str === '' && $search === '') {
2625 2
            return static::create($replacement, $this->encoding);
2626
        }
2627
2628 58
        if ($caseSensitive) {
2629 48
            return static::create(
2630 48
                $this->utf8::str_replace($search, $replacement, $this->str),
2631 48
                $this->encoding
2632
            );
2633
        }
2634
2635 10
        return static::create(
2636 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2637 10
            $this->encoding
2638
        );
2639
    }
2640
2641
    /**
2642
     * Replaces all occurrences of $search in $str by $replacement.
2643
     *
2644
     * @param string[]        $search        <p>The elements to search for.</p>
2645
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2646
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2647
     *
2648
     * @psalm-mutation-free
2649
     *
2650
     * @return static
2651
     *                <p>Object with the resulting $str after the replacements.</p>
2652
     */
2653 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2654
    {
2655 61
        if ($caseSensitive) {
2656 47
            return static::create(
2657 47
                $this->utf8::str_replace($search, $replacement, $this->str),
2658 47
                $this->encoding
2659
            );
2660
        }
2661
2662 14
        return static::create(
2663 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2664 14
            $this->encoding
2665
        );
2666
    }
2667
2668
    /**
2669
     * Replaces all occurrences of $search from the beginning of string with $replacement.
2670
     *
2671
     * @param string $search      <p>The string to search for.</p>
2672
     * @param string $replacement <p>The replacement.</p>
2673
     *
2674
     * @psalm-mutation-free
2675
     *
2676
     * @return static
2677
     *                <p>Object with the resulting $str after the replacements.</p>
2678
     */
2679 32
    public function replaceBeginning(string $search, string $replacement): self
2680
    {
2681 32
        return static::create(
2682 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
2683 32
            $this->encoding
2684
        );
2685
    }
2686
2687
    /**
2688
     * Replaces all occurrences of $search from the ending of string with $replacement.
2689
     *
2690
     * @param string $search      <p>The string to search for.</p>
2691
     * @param string $replacement <p>The replacement.</p>
2692
     *
2693
     * @psalm-mutation-free
2694
     *
2695
     * @return static
2696
     *                <p>Object with the resulting $str after the replacements.</p>
2697
     */
2698 32
    public function replaceEnding(string $search, string $replacement): self
2699
    {
2700 32
        return static::create(
2701 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
2702 32
            $this->encoding
2703
        );
2704
    }
2705
2706
    /**
2707
     * Replaces first occurrences of $search from the beginning of string with $replacement.
2708
     *
2709
     * @param string $search      <p>The string to search for.</p>
2710
     * @param string $replacement <p>The replacement.</p>
2711
     *
2712
     * @psalm-mutation-free
2713
     *
2714
     * @return static
2715
     *                <p>Object with the resulting $str after the replacements.</p>
2716
     */
2717 32
    public function replaceFirst(string $search, string $replacement): self
2718
    {
2719 32
        return static::create(
2720 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
2721 32
            $this->encoding
2722
        );
2723
    }
2724
2725
    /**
2726
     * Replaces last occurrences of $search from the ending of string with $replacement.
2727
     *
2728
     * @param string $search      <p>The string to search for.</p>
2729
     * @param string $replacement <p>The replacement.</p>
2730
     *
2731
     * @psalm-mutation-free
2732
     *
2733
     * @return static
2734
     *                <p>Object with the resulting $str after the replacements.</p>
2735
     */
2736 30
    public function replaceLast(string $search, string $replacement): self
2737
    {
2738 30
        return static::create(
2739 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
2740 30
            $this->encoding
2741
        );
2742
    }
2743
2744
    /**
2745
     * Returns a reversed string. A multibyte version of strrev().
2746
     *
2747
     * @psalm-mutation-free
2748
     *
2749
     * @return static
2750
     *                <p>Object with a reversed $str.</p>
2751
     */
2752 15
    public function reverse(): self
2753
    {
2754 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
2755
    }
2756
2757
    /**
2758
     * Truncates the string to a given length, while ensuring that it does not
2759
     * split words. If $substring is provided, and truncating occurs, the
2760
     * string is further truncated so that the substring may be appended without
2761
     * exceeding the desired length.
2762
     *
2763
     * @param int    $length                          <p>Desired length of the truncated string.</p>
2764
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
2765
     * @param bool   $ignoreDoNotSplitWordsForOneWord
2766
     *
2767
     * @psalm-mutation-free
2768
     *
2769
     * @return static
2770
     *                <p>Object with the resulting $str after truncating.</p>
2771
     */
2772 68
    public function safeTruncate(
2773
        int $length,
2774
        string $substring = '',
2775
        bool $ignoreDoNotSplitWordsForOneWord = true
2776
    ): self {
2777 68
        return static::create(
2778 68
            $this->utf8::str_truncate_safe(
2779 68
                $this->str,
2780 68
                $length,
2781 68
                $substring,
2782 68
                $this->encoding,
2783 68
                $ignoreDoNotSplitWordsForOneWord
2784
            ),
2785 68
            $this->encoding
2786
        );
2787
    }
2788
2789
    /**
2790
     * Create a sha1 hash from the current string.
2791
     *
2792
     * @psalm-mutation-free
2793
     *
2794
     * @return static
2795
     */
2796 2
    public function sha1(): self
2797
    {
2798 2
        return static::create($this->hash('sha1'), $this->encoding);
2799
    }
2800
2801
    /**
2802
     * Create a sha256 hash from the current string.
2803
     *
2804
     * @psalm-mutation-free
2805
     *
2806
     * @return static
2807
     */
2808 2
    public function sha256(): self
2809
    {
2810 2
        return static::create($this->hash('sha256'), $this->encoding);
2811
    }
2812
2813
    /**
2814
     * Create a sha512 hash from the current string.
2815
     *
2816
     * @psalm-mutation-free
2817
     *
2818
     * @return static
2819
     */
2820 2
    public function sha512(): self
2821
    {
2822 2
        return static::create($this->hash('sha512'), $this->encoding);
2823
    }
2824
2825
    /**
2826
     * Shorten the string after $length, but also after the next word.
2827
     *
2828
     * @param int    $length   <p>The given length.</p>
2829
     * @param string $strAddOn [optional] <p>Default: '…'</p>
2830
     *
2831
     * @psalm-mutation-free
2832
     *
2833
     * @return static
2834
     */
2835 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
2836
    {
2837 8
        return static::create(
2838 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
2839 8
            $this->encoding
2840
        );
2841
    }
2842
2843
    /**
2844
     * A multibyte string shuffle function. It returns a string with its
2845
     * characters in random order.
2846
     *
2847
     * @psalm-mutation-free
2848
     *
2849
     * @return static
2850
     *                <p>Object with a shuffled $str.</p>
2851
     */
2852 9
    public function shuffle(): self
2853
    {
2854 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
2855
    }
2856
2857
    /**
2858
     * Calculate the similarity between two strings.
2859
     *
2860
     * @param string $str <p>The delimiting string.</p>
2861
     *
2862
     * @psalm-mutation-free
2863
     *
2864
     * @return float
2865
     */
2866 2
    public function similarity(string $str): float
2867
    {
2868 2
        \similar_text($this->str, $str, $percent);
2869
2870 2
        return $percent;
2871
    }
2872
2873
    /**
2874
     * Returns the substring beginning at $start, and up to, but not including
2875
     * the index specified by $end. If $end is omitted, the function extracts
2876
     * the remaining string. If $end is negative, it is computed from the end
2877
     * of the string.
2878
     *
2879
     * @param int $start <p>Initial index from which to begin extraction.</p>
2880
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
2881
     *
2882
     * @psalm-mutation-free
2883
     *
2884
     * @return static
2885
     *                <p>Object with its $str being the extracted substring.</p>
2886
     */
2887 50
    public function slice(int $start, int $end = null): self
2888
    {
2889 50
        return static::create(
2890 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
2891 50
            $this->encoding
2892
        );
2893
    }
2894
2895
    /**
2896
     * Converts the string into an URL slug. This includes replacing non-ASCII
2897
     * characters with their closest ASCII equivalents, removing remaining
2898
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
2899
     * $separator. The separator defaults to a single dash, and the string
2900
     * is also converted to lowercase. The language of the source string can
2901
     * also be supplied for language-specific transliteration.
2902
     *
2903
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
2904
     * @param string                $language              [optional] <p>Language of the source string.</p>
2905
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
2906
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
2907
     *                                                     pound ".</p>
2908
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
2909
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
2910
     *                                                     chars.</p>
2911
     *
2912
     * @psalm-mutation-free
2913
     *
2914
     * @return static
2915
     *                <p>Object whose $str has been converted to an URL slug.</p>
2916
     *
2917
     * @noinspection PhpTooManyParametersInspection
2918
     */
2919 17
    public function slugify(
2920
        string $separator = '-',
2921
        string $language = 'en',
2922
        array $replacements = [],
2923
        bool $replace_extra_symbols = true,
2924
        bool $use_str_to_lower = true,
2925
        bool $use_transliterate = false
2926
    ): self {
2927 17
        return static::create(
2928 17
            $this->ascii::to_slugify(
2929 17
                $this->str,
2930 17
                $separator,
2931 17
                $language,
2932 17
                $replacements,
2933 17
                $replace_extra_symbols,
2934 17
                $use_str_to_lower,
2935 17
                $use_transliterate
2936
            ),
2937 17
            $this->encoding
2938
        );
2939
    }
2940
2941
    /**
2942
     * Convert a string to e.g.: "snake_case"
2943
     *
2944
     * @psalm-mutation-free
2945
     *
2946
     * @return static
2947
     *                <p>Object with $str in snake_case.</p>
2948
     */
2949 40
    public function snakeize(): self
2950
    {
2951 40
        return static::create(
2952 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
2953 40
            $this->encoding
2954
        );
2955
    }
2956
2957
    /**
2958
     * Wrap the string after the first whitespace character after a given number
2959
     * of characters.
2960
     *
2961
     * @param int    $width <p>Number of characters at which to wrap.</p>
2962
     * @param string $break [optional] <p>Character used to break the string. | Default "\n"</p>
2963
     *
2964
     * @psalm-mutation-free
2965
     *
2966
     * @return static
2967
     */
2968 2
    public function softWrap(int $width, string $break = "\n"): self
2969
    {
2970 2
        return $this->lineWrapAfterWord($width, $break, false);
2971
    }
2972
2973
    /**
2974
     * Splits the string with the provided regular expression, returning an
2975
     * array of Stringy objects. An optional integer $limit will truncate the
2976
     * results.
2977
     *
2978
     * @param string $pattern                  <p>The regex with which to split the string.</p>
2979
     * @param int    $limit                    [optional] <p>Maximum number of results to return. Default: -1 === no
2980
     *                                         limit</p>
2981
     * @param bool   $return_stingy_collection [optional] <p>Return a collection object.</p>
2982
     *
2983
     * @psalm-mutation-free
2984
     *
2985
     * @return CollectionStringy|static[]
2986
     *                                    <p>An collection of Stringy objects.</p>
2987
     *
2988
     * @psalm-return CollectionStringy<int,static>|array<int,static>
2989
     */
2990 51
    public function split(
2991
        string $pattern,
2992
        int $limit = null,
2993
        bool $return_stingy_collection = false
2994
    ) {
2995 51
        if ($this->str === '') {
2996
            if ($return_stingy_collection) {
2997
                /**
2998
                 * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2999
                 */
3000
                return CollectionStringy::create([]);
3001
            }
3002
3003
            return [];
3004
        }
3005
3006 51
        if ($limit === null) {
3007 7
            $limit = -1;
3008
        }
3009
3010 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
3011
        /** @noinspection AlterInForeachInspection */
3012 51
        foreach ($array as $i => &$value) {
3013 45
            $value = static::create($value, $this->encoding);
3014
        }
3015
3016
        /** @noinspection PhpSillyAssignmentInspection */
3017
        /** @var static[] $array */
3018 51
        $array = $array;
0 ignored issues
show
Bug introduced by
Why assign $array to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
3019
3020 51
        if ($return_stingy_collection) {
3021
            /**
3022
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3023
             */
3024 35
            return CollectionStringy::create($array);
3025
        }
3026
3027 16
        return $array;
3028
    }
3029
3030
    /**
3031
     * Returns true if the string begins with $substring, false otherwise. By
3032
     * default, the comparison is case-sensitive, but can be made insensitive
3033
     * by setting $caseSensitive to false.
3034
     *
3035
     * @param string $substring     <p>The substring to look for.</p>
3036
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3037
     *
3038
     * @psalm-mutation-free
3039
     *
3040
     * @return bool
3041
     *              <p>Whether or not $str starts with $substring.</p>
3042
     */
3043 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
3044
    {
3045 99
        if ($caseSensitive) {
3046 53
            return $this->utf8::str_starts_with($this->str, $substring);
3047
        }
3048
3049 46
        return $this->utf8::str_istarts_with($this->str, $substring);
3050
    }
3051
3052
    /**
3053
     * Returns true if the string begins with any of $substrings, false otherwise.
3054
     * By default the comparison is case-sensitive, but can be made insensitive by
3055
     * setting $caseSensitive to false.
3056
     *
3057
     * @param string[] $substrings    <p>Substrings to look for.</p>
3058
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3059
     *
3060
     * @psalm-mutation-free
3061
     *
3062
     * @return bool
3063
     *              <p>Whether or not $str starts with $substring.</p>
3064
     */
3065 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
3066
    {
3067 35
        if ($caseSensitive) {
3068 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
3069
        }
3070
3071 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
3072
    }
3073
3074
    /**
3075
     * Remove one or more strings from the string.
3076
     *
3077
     * @param string|string[] $search One or more strings to be removed
3078
     *
3079
     * @psalm-mutation-free
3080
     *
3081
     * @return static
3082
     */
3083 3
    public function strip($search): self
3084
    {
3085 3
        if (\is_array($search)) {
3086 1
            return $this->replaceAll($search, '');
3087
        }
3088
3089 2
        return $this->replace($search, '');
3090
    }
3091
3092
    /**
3093
     * Strip all whitespace characters. This includes tabs and newline characters,
3094
     * as well as multibyte whitespace such as the thin space and ideographic space.
3095
     *
3096
     * @psalm-mutation-free
3097
     *
3098
     * @return static
3099
     */
3100 36
    public function stripWhitespace(): self
3101
    {
3102 36
        return static::create(
3103 36
            $this->utf8::strip_whitespace($this->str),
3104 36
            $this->encoding
3105
        );
3106
    }
3107
3108
    /**
3109
     * Remove css media-queries.
3110
     *
3111
     * @psalm-mutation-free
3112
     *
3113
     * @return static
3114
     */
3115 2
    public function stripeCssMediaQueries(): self
3116
    {
3117 2
        return static::create(
3118 2
            $this->utf8::css_stripe_media_queries($this->str),
3119 2
            $this->encoding
3120
        );
3121
    }
3122
3123
    /**
3124
     * Remove empty html-tag.
3125
     *
3126
     * e.g.: <tag></tag>
3127
     *
3128
     * @psalm-mutation-free
3129
     *
3130
     * @return static
3131
     */
3132 2
    public function stripeEmptyHtmlTags(): self
3133
    {
3134 2
        return static::create(
3135 2
            $this->utf8::html_stripe_empty_tags($this->str),
3136 2
            $this->encoding
3137
        );
3138
    }
3139
3140
    /**
3141
     * Returns the substring beginning at $start with the specified $length.
3142
     * It differs from the $this->utf8::substr() function in that providing a $length of
3143
     * null will return the rest of the string, rather than an empty string.
3144
     *
3145
     * @param int $start  <p>Position of the first character to use.</p>
3146
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
3147
     *
3148
     * @psalm-mutation-free
3149
     *
3150
     * @return static
3151
     *                <p>Object with its $str being the substring.</p>
3152
     */
3153 31
    public function substr(int $start, int $length = null): self
3154
    {
3155 31
        return static::create(
3156 31
            $this->utf8::substr(
3157 31
                $this->str,
3158 31
                $start,
3159 31
                $length,
3160 31
                $this->encoding
3161
            ),
3162 31
            $this->encoding
3163
        );
3164
    }
3165
3166
    /**
3167
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3168
     * If no match is found returns new empty Stringy object.
3169
     *
3170
     * @param string $needle       <p>The string to look for.</p>
3171
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3172
     *
3173
     * @psalm-mutation-free
3174
     *
3175
     * @return static
3176
     */
3177 4 View Code Duplication
    public function substringOf(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3178
    {
3179 4
        return static::create(
3180 4
            $this->utf8::str_substr_first(
3181 4
                $this->str,
3182 4
                $needle,
3183 4
                $beforeNeedle,
3184 4
                $this->encoding
3185
            ),
3186 4
            $this->encoding
3187
        );
3188
    }
3189
3190
    /**
3191
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3192
     * If no match is found returns new empty Stringy object.
3193
     *
3194
     * @param string $needle       <p>The string to look for.</p>
3195
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3196
     *
3197
     * @psalm-mutation-free
3198
     *
3199
     * @return static
3200
     */
3201 4 View Code Duplication
    public function substringOfIgnoreCase(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3202
    {
3203 4
        return static::create(
3204 4
            $this->utf8::str_isubstr_first(
3205 4
                $this->str,
3206 4
                $needle,
3207 4
                $beforeNeedle,
3208 4
                $this->encoding
3209
            ),
3210 4
            $this->encoding
3211
        );
3212
    }
3213
3214
    /**
3215
     * Surrounds $str with the given substring.
3216
     *
3217
     * @param string $substring <p>The substring to add to both sides.</P>
3218
     *
3219
     * @psalm-mutation-free
3220
     *
3221
     * @return static
3222
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3223
     */
3224 15
    public function surround(string $substring): self
3225
    {
3226 15
        return static::create(
3227 15
            $substring . $this->str . $substring,
3228 15
            $this->encoding
3229
        );
3230
    }
3231
3232
    /**
3233
     * Returns a case swapped version of the string.
3234
     *
3235
     * @psalm-mutation-free
3236
     *
3237
     * @return static
3238
     *                <p>Object whose $str has each character's case swapped.</P>
3239
     */
3240 15
    public function swapCase(): self
3241
    {
3242 15
        return static::create(
3243 15
            $this->utf8::swapCase($this->str, $this->encoding),
3244 15
            $this->encoding
3245
        );
3246
    }
3247
3248
    /**
3249
     * Returns a string with smart quotes, ellipsis characters, and dashes from
3250
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
3251
     * equivalents.
3252
     *
3253
     * @psalm-mutation-free
3254
     *
3255
     * @return static
3256
     *                <p>Object whose $str has those characters removed.</p>
3257
     */
3258 12
    public function tidy(): self
3259
    {
3260 12
        return static::create(
3261 12
            $this->ascii::normalize_msword($this->str),
3262 12
            $this->encoding
3263
        );
3264
    }
3265
3266
    /**
3267
     * Returns a trimmed string with the first letter of each word capitalized.
3268
     * Also accepts an array, $ignore, allowing you to list words not to be
3269
     * capitalized.
3270
     *
3271
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
3272
     *                                               Default: null</p>
3273
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
3274
     *                                               separator === words.</p>
3275
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
3276
     *
3277
     * @psalm-mutation-free
3278
     *
3279
     * @return static
3280
     *                <p>Object with a titleized $str.</p>
3281
     */
3282 23
    public function titleize(
3283
        array $ignore = null,
3284
        string $word_define_chars = null,
3285
        string $language = null
3286
    ): self {
3287 23
        return static::create(
3288 23
            $this->utf8::str_titleize(
3289 23
                $this->str,
3290 23
                $ignore,
3291 23
                $this->encoding,
3292 23
                false,
3293 23
                $language,
3294 23
                false,
3295 23
                true,
3296 23
                $word_define_chars
3297
            ),
3298 23
            $this->encoding
3299
        );
3300
    }
3301
3302
    /**
3303
     * Returns a trimmed string in proper title case.
3304
     *
3305
     * Also accepts an array, $ignore, allowing you to list words not to be
3306
     * capitalized.
3307
     *
3308
     * Adapted from John Gruber's script.
3309
     *
3310
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
3311
     *
3312
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
3313
     *
3314
     * @psalm-mutation-free
3315
     *
3316
     * @return static
3317
     *                <p>Object with a titleized $str</p>
3318
     */
3319 70
    public function titleizeForHumans(array $ignore = []): self
3320
    {
3321 70
        return static::create(
3322 70
            $this->utf8::str_titleize_for_humans(
3323 70
                $this->str,
3324 70
                $ignore,
3325 70
                $this->encoding
3326
            ),
3327 70
            $this->encoding
3328
        );
3329
    }
3330
3331
    /**
3332
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3333
     * replaced with their closest ASCII counterparts, and the rest are removed
3334
     * by default. The language or locale of the source string can be supplied
3335
     * for language-specific transliteration in any of the following formats:
3336
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
3337
     * to "aeoeue" rather than "aou" as in other languages.
3338
     *
3339
     * @param string $language          [optional] <p>Language of the source string.</p>
3340
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
3341
     *                                  unsupported characters.</p>
3342
     *
3343
     * @psalm-mutation-free
3344
     *
3345
     * @return static
3346
     *                <p>Object whose $str contains only ASCII characters.</p>
3347
     */
3348 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
3349
    {
3350 23
        return static::create(
3351 23
            $this->ascii::to_ascii(
3352 23
                $this->str,
3353 23
                $language,
3354 23
                $removeUnsupported
3355
            ),
3356 23
            $this->encoding
3357
        );
3358
    }
3359
3360
    /**
3361
     * Returns a boolean representation of the given logical string value.
3362
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
3363
     * 'off', and 'no' will return false. In all instances, case is ignored.
3364
     * For other numeric strings, their sign will determine the return value.
3365
     * In addition, blank strings consisting of only whitespace will return
3366
     * false. For all other strings, the return value is a result of a
3367
     * boolean cast.
3368
     *
3369
     * @psalm-mutation-free
3370
     *
3371
     * @return bool
3372
     *              <p>A boolean value for the string.</p>
3373
     */
3374 45
    public function toBoolean(): bool
3375
    {
3376 45
        return $this->utf8::to_boolean($this->str);
3377
    }
3378
3379
    /**
3380
     * Converts all characters in the string to lowercase.
3381
     *
3382
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3383
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3384
     *
3385
     * @psalm-mutation-free
3386
     *
3387
     * @return static
3388
     *                <p>Object with all characters of $str being lowercase.</p>
3389
     */
3390 17 View Code Duplication
    public function toLowerCase($tryToKeepStringLength = false, $lang = null): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3391
    {
3392 17
        return static::create(
3393 17
            $this->utf8::strtolower(
3394 17
                $this->str,
3395 17
                $this->encoding,
3396 17
                false,
3397 17
                $lang,
3398 17
                $tryToKeepStringLength
3399
            ),
3400 17
            $this->encoding
3401
        );
3402
    }
3403
3404
    /**
3405
     * Converts each tab in the string to some number of spaces, as defined by
3406
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
3407
     *
3408
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
3409
     *
3410
     * @psalm-mutation-free
3411
     *
3412
     * @return static
3413
     *                <p>Object whose $str has had tabs switched to spaces.</p>
3414
     */
3415 18 View Code Duplication
    public function toSpaces(int $tabLength = 4): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3416
    {
3417 18
        if ($tabLength === 4) {
3418 9
            $tab = '    ';
3419 9
        } elseif ($tabLength === 2) {
3420 3
            $tab = '  ';
3421
        } else {
3422 6
            $tab = \str_repeat(' ', $tabLength);
3423
        }
3424
3425 18
        return static::create(
3426 18
            \str_replace("\t", $tab, $this->str),
3427 18
            $this->encoding
3428
        );
3429
    }
3430
3431
    /**
3432
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
3433
     * string.
3434
     *
3435
     * @psalm-mutation-free
3436
     *
3437
     * @return string
3438
     */
3439 2180
    public function toString(): string
3440
    {
3441 2180
        return (string) $this->str;
3442
    }
3443
3444
    /**
3445
     * Converts each occurrence of some consecutive number of spaces, as
3446
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
3447
     * are converted to a tab.
3448
     *
3449
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
3450
     *
3451
     * @psalm-mutation-free
3452
     *
3453
     * @return static
3454
     *                <p>Object whose $str has had spaces switched to tabs.</p>
3455
     */
3456 15 View Code Duplication
    public function toTabs(int $tabLength = 4): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3457
    {
3458 15
        if ($tabLength === 4) {
3459 9
            $tab = '    ';
3460 6
        } elseif ($tabLength === 2) {
3461 3
            $tab = '  ';
3462
        } else {
3463 3
            $tab = \str_repeat(' ', $tabLength);
3464
        }
3465
3466 15
        return static::create(
3467 15
            \str_replace($tab, "\t", $this->str),
3468 15
            $this->encoding
3469
        );
3470
    }
3471
3472
    /**
3473
     * Converts the first character of each word in the string to uppercase
3474
     * and all other chars to lowercase.
3475
     *
3476
     * @psalm-mutation-free
3477
     *
3478
     * @return static
3479
     *                <p>Object with all characters of $str being title-cased.</p>
3480
     */
3481 15
    public function toTitleCase(): self
3482
    {
3483 15
        return static::create(
3484 15
            $this->utf8::titlecase($this->str, $this->encoding),
3485 15
            $this->encoding
3486
        );
3487
    }
3488
3489
    /**
3490
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3491
     * replaced with their closest ASCII counterparts, and the rest are removed
3492
     * unless instructed otherwise.
3493
     *
3494
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
3495
     *                        performance | Default: false</p>
3496
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
3497
     *
3498
     * @psalm-mutation-free
3499
     *
3500
     * @return static
3501
     *                <p>Object whose $str contains only ASCII characters.</p>
3502
     */
3503 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
3504
    {
3505 34
        return static::create(
3506 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
3507 34
            $this->encoding
3508
        );
3509
    }
3510
3511
    /**
3512
     * Converts all characters in the string to uppercase.
3513
     *
3514
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3515
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3516
     *
3517
     * @psalm-mutation-free
3518
     *
3519
     * @return static
3520
     *                <p>Object with all characters of $str being uppercase.</p>
3521
     */
3522 20 View Code Duplication
    public function toUpperCase($tryToKeepStringLength = false, $lang = null): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3523
    {
3524 20
        return static::create(
3525 20
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
3526 20
            $this->encoding
3527
        );
3528
    }
3529
3530
    /**
3531
     * Returns a string with whitespace removed from the start and end of the
3532
     * string. Supports the removal of unicode whitespace. Accepts an optional
3533
     * string of characters to strip instead of the defaults.
3534
     *
3535
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
3536
     *
3537
     * @psalm-mutation-free
3538
     *
3539
     * @return static
3540
     *                <p>Object with a trimmed $str.</p>
3541
     */
3542 36
    public function trim(string $chars = null): self
3543
    {
3544 36
        return static::create(
3545 36
            $this->utf8::trim($this->str, $chars),
3546 36
            $this->encoding
3547
        );
3548
    }
3549
3550
    /**
3551
     * Returns a string with whitespace removed from the start of the string.
3552
     * Supports the removal of unicode whitespace. Accepts an optional
3553
     * string of characters to strip instead of the defaults.
3554
     *
3555
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3556
     *
3557
     * @psalm-mutation-free
3558
     *
3559
     * @return static
3560
     *                <p>Object with a trimmed $str.</p>
3561
     */
3562 39
    public function trimLeft(string $chars = null): self
3563
    {
3564 39
        return static::create(
3565 39
            $this->utf8::ltrim($this->str, $chars),
3566 39
            $this->encoding
3567
        );
3568
    }
3569
3570
    /**
3571
     * Returns a string with whitespace removed from the end of the string.
3572
     * Supports the removal of unicode whitespace. Accepts an optional
3573
     * string of characters to strip instead of the defaults.
3574
     *
3575
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3576
     *
3577
     * @psalm-mutation-free
3578
     *
3579
     * @return static
3580
     *                <p>Object with a trimmed $str.</p>
3581
     */
3582 39
    public function trimRight(string $chars = null): self
3583
    {
3584 39
        return static::create(
3585 39
            $this->utf8::rtrim($this->str, $chars),
3586 39
            $this->encoding
3587
        );
3588
    }
3589
3590
    /**
3591
     * Truncates the string to a given length. If $substring is provided, and
3592
     * truncating occurs, the string is further truncated so that the substring
3593
     * may be appended without exceeding the desired length.
3594
     *
3595
     * @param int    $length    <p>Desired length of the truncated string.</p>
3596
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
3597
     *
3598
     * @psalm-mutation-free
3599
     *
3600
     * @return static
3601
     *                <p>Object with the resulting $str after truncating.</p>
3602
     */
3603 66
    public function truncate(int $length, string $substring = ''): self
3604
    {
3605 66
        return static::create(
3606 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
3607 66
            $this->encoding
3608
        );
3609
    }
3610
3611
    /**
3612
     * Returns a lowercase and trimmed string separated by underscores.
3613
     * Underscores are inserted before uppercase characters (with the exception
3614
     * of the first character of the string), and in place of spaces as well as
3615
     * dashes.
3616
     *
3617
     * @psalm-mutation-free
3618
     *
3619
     * @return static
3620
     *                <p>Object with an underscored $str.</p>
3621
     */
3622 48
    public function underscored(): self
3623
    {
3624 48
        return $this->delimit('_');
3625
    }
3626
3627
    /**
3628
     * Returns an UpperCamelCase version of the supplied string. It trims
3629
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
3630
     * and underscores, and removes spaces, dashes, underscores.
3631
     *
3632
     * @psalm-mutation-free
3633
     *
3634
     * @return static
3635
     *                <p>Object with $str in UpperCamelCase.</p>
3636
     */
3637 39
    public function upperCamelize(): self
3638
    {
3639 39
        return static::create(
3640 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
3641 39
            $this->encoding
3642
        );
3643
    }
3644
3645
    /**
3646
     * Converts the first character of the supplied string to upper case.
3647
     *
3648
     * @psalm-mutation-free
3649
     *
3650
     * @return static
3651
     *                <p>Object with the first character of $str being upper case.</p>
3652
     */
3653 18
    public function upperCaseFirst(): self
3654
    {
3655 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
3656
    }
3657
3658
    /**
3659
     * Converts the string into an URL slug. This includes replacing non-ASCII
3660
     * characters with their closest ASCII equivalents, removing remaining
3661
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3662
     * $separator. The separator defaults to a single dash, and the string
3663
     * is also converted to lowercase.
3664
     *
3665
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
3666
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
3667
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
3668
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
3669
     *
3670
     * @psalm-mutation-free
3671
     *
3672
     * @return static
3673
     *                <p>Object whose $str has been converted to an URL slug.</p>
3674
     *
3675
     * @psalm-suppress ImpureMethodCall :/
3676
     */
3677 32
    public function urlify(
3678
        string $separator = '-',
3679
        string $language = 'en',
3680
        array $replacements = [],
3681
        bool $strToLower = true
3682
    ): self {
3683
        // init
3684 32
        $str = $this->str;
3685
3686 32
        foreach ($replacements as $from => $to) {
3687 32
            $str = \str_replace($from, $to, $str);
3688
        }
3689
3690 32
        return static::create(
3691 32
            URLify::slug(
3692 32
                $str,
3693 32
                $language,
3694 32
                $separator,
3695 32
                $strToLower
3696
            ),
3697 32
            $this->encoding
3698
        );
3699
    }
3700
3701
    /**
3702
     * Converts the string into an valid UTF-8 string.
3703
     *
3704
     * @psalm-mutation-free
3705
     *
3706
     * @return static
3707
     */
3708 2
    public function utf8ify(): self
3709
    {
3710 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
3711
    }
3712
3713
    /**
3714
     * Convert a string into an array of words.
3715
     *
3716
     * @param string   $char_list                [optional] <p>Additional chars for the definition of "words".</p>
3717
     * @param bool     $remove_empty_values      [optional] <p>Remove empty values.</p>
3718
     * @param int|null $remove_short_values      [optional] <p>The min. string length or null to disable</p>
3719
     * @param bool     $return_stingy_collection [optional] <p>Return a collection object.</p>
3720
     *
3721
     * @psalm-mutation-free
3722
     *
3723
     * @return CollectionStringy|static[]
3724
     *
3725
     * @psalm-return CollectionStringy<int,static>|array<int,static>
3726
     */
3727 2
    public function words(
3728
        string $char_list = '',
3729
        bool $remove_empty_values = false,
3730
        $remove_short_values = null,
3731
        bool $return_stingy_collection = false
3732
    ) {
3733
        /**
3734
         * @psalm-suppress DocblockTypeContradiction
3735
         */
3736 2
        if ($remove_short_values !== null && !\is_int($remove_short_values)) {
3737
            throw new \InvalidArgumentException(
3738
                'Passed value must be a null or int'
3739
            );
3740
        }
3741
3742 2
        if ($remove_short_values === null) {
3743 2
            $strings = $this->utf8::str_to_words(
3744 2
                $this->str,
3745 2
                $char_list,
3746 2
                $remove_empty_values
3747
            );
3748
        } else {
3749 2
            $strings = $this->utf8::str_to_words(
3750 2
                $this->str,
3751 2
                $char_list,
3752 2
                $remove_empty_values,
3753 2
                $remove_short_values
3754
            );
3755
        }
3756
3757
        /** @noinspection AlterInForeachInspection */
3758 2
        foreach ($strings as &$string) {
3759 2
            $string = static::create($string);
3760
        }
3761
3762
        /** @noinspection PhpSillyAssignmentInspection */
3763
        /** @var static[] $strings */
3764 2
        $strings = $strings;
0 ignored issues
show
Bug introduced by
Why assign $strings to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
3765
3766 2
        if ($return_stingy_collection) {
3767
            /**
3768
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3769
             */
3770 2
            return CollectionStringy::create($strings);
3771
        }
3772
3773
        return $strings;
3774
    }
3775
3776
    /**
3777
     * Surrounds $str with the given substring.
3778
     *
3779
     * @param string $substring <p>The substring to add to both sides.</P>
3780
     *
3781
     * @psalm-mutation-free
3782
     *
3783
     * @return static
3784
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3785
     */
3786 10
    public function wrap(string $substring): self
3787
    {
3788 10
        return $this->surround($substring);
3789
    }
3790
3791
    /**
3792
     * Returns the replacements for the toAscii() method.
3793
     *
3794
     * @noinspection PhpUnused
3795
     *
3796
     * @psalm-mutation-free
3797
     *
3798
     * @return array<string, array<int, string>>
0 ignored issues
show
Documentation introduced by
The doc-type array<string, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
3799
     *                       <p>An array of replacements.</p>
3800
     *
3801
     * @deprecated   this is only here for backward-compatibly reasons
3802
     */
3803 1
    protected function charsArray(): array
3804
    {
3805 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
3806
    }
3807
3808
    /**
3809
     * Returns true if $str matches the supplied pattern, false otherwise.
3810
     *
3811
     * @param string $pattern <p>Regex pattern to match against.</p>
3812
     *
3813
     * @psalm-mutation-free
3814
     *
3815
     * @return bool
3816
     *              <p>Whether or not $str matches the pattern.</p>
3817
     */
3818 24
    protected function matchesPattern(string $pattern): bool
3819
    {
3820 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
3821
    }
3822
}
3823