Completed
Push — master ( 40b0f0...ce1cf8 )
by Lars
01:30
created

Stringy::replaceBeginning()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 10
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 3605
    public function __construct($str = '', string $encoding = null)
62
    {
63 3605
        if (\is_array($str)) {
64 3
            throw new \InvalidArgumentException(
65 3
                'Passed value cannot be an array'
66
            );
67
        }
68
69
        if (
70 3602
            \is_object($str)
71
            &&
72 3602
            !\method_exists($str, '__toString')
73
        ) {
74 3
            throw new \InvalidArgumentException(
75 3
                'Passed object must have a __toString method'
76
            );
77
        }
78
79 3599
        $this->str = (string) $str;
80
81 3599
        static $ASCII = null;
82 3599
        if ($ASCII === null) {
83
            $ASCII = new ASCII();
84
        }
85 3599
        $this->ascii = $ASCII;
86
87 3599
        static $UTF8 = null;
88 3599
        if ($UTF8 === null) {
89
            $UTF8 = new UTF8();
90
        }
91 3599
        $this->utf8 = $UTF8;
92
93 3599
        if ($encoding !== 'UTF-8') {
94 2429
            $this->encoding = $this->utf8::normalize_encoding($encoding, 'UTF-8');
95
        } else {
96 2682
            $this->encoding = $encoding;
97
        }
98 3599
    }
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
     * Determine if the string is composed of numeric characters.
1798
     *
1799
     * @return bool
1800
     */
1801 4
    public function isNumeric(): bool
1802
    {
1803 4
        return \is_numeric($this->str);
1804
    }
1805
1806
    /**
1807
     * Returns true if the string contains only lower case chars, false otherwise.
1808
     *
1809
     * @psalm-mutation-free
1810
     *
1811
     * @return bool
1812
     *              <p>Whether or not $str contains only lower case characters.</p>
1813
     */
1814 24
    public function isLowerCase(): bool
1815
    {
1816 24
        return $this->utf8::is_lowercase($this->str);
1817
    }
1818
1819
    /**
1820
     * Determine whether the string is considered to be NOT empty.
1821
     *
1822
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
1823
     *
1824
     * @psalm-mutation-free
1825
     *
1826
     * @return bool
1827
     *              <p>Whether or not $str is empty().</p>
1828
     */
1829 10
    public function isNotEmpty(): bool
1830
    {
1831 10
        return !$this->utf8::is_empty($this->str);
1832
    }
1833
1834
    /**
1835
     * Returns true if the string is serialized, false otherwise.
1836
     *
1837
     * @psalm-mutation-free
1838
     *
1839
     * @return bool
1840
     *              <p>Whether or not $str is serialized.</p>
1841
     */
1842 21
    public function isSerialized(): bool
1843
    {
1844 21
        return $this->utf8::is_serialized($this->str);
1845
    }
1846
1847
    /**
1848
     * Check if two strings are similar.
1849
     *
1850
     * @param string $str                     <p>The string to compare against.</p>
1851
     * @param float  $minPercentForSimilarity [optional] <p>The percentage of needed similarity. | Default: 80%</p>
1852
     *
1853
     * @psalm-mutation-free
1854
     *
1855
     * @return bool
1856
     */
1857 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
1858
    {
1859 2
        return $this->similarity($str) >= $minPercentForSimilarity;
1860
    }
1861
1862
    /**
1863
     * Returns true if the string contains only lower case chars, false
1864
     * otherwise.
1865
     *
1866
     * @psalm-mutation-free
1867
     *
1868
     * @return bool
1869
     *              <p>Whether or not $str contains only lower case characters.</p>
1870
     */
1871 24
    public function isUpperCase(): bool
1872
    {
1873 24
        return $this->utf8::is_uppercase($this->str);
1874
    }
1875
1876
    /**
1877
     * Returns true if the string contains only whitespace chars, false otherwise.
1878
     *
1879
     * @psalm-mutation-free
1880
     *
1881
     * @return bool
1882
     *              <p>Whether or not $str contains only whitespace characters.</p>
1883
     */
1884 30
    public function isWhitespace(): bool
1885
    {
1886 30
        return $this->isBlank();
1887
    }
1888
1889
    /**
1890
     * Returns value which can be serialized by json_encode().
1891
     *
1892
     * @noinspection ReturnTypeCanBeDeclaredInspection
1893
     *
1894
     * @psalm-mutation-free
1895
     *
1896
     * @return string The current value of the $str property
1897
     */
1898 2
    public function jsonSerialize()
1899
    {
1900 2
        return (string) $this;
1901
    }
1902
1903
    /**
1904
     * Returns the last $n characters of the string.
1905
     *
1906
     * @param int $n <p>Number of characters to retrieve from the end.</p>
1907
     *
1908
     * @psalm-mutation-free
1909
     *
1910
     * @return static
1911
     *                <p>Object with its $str being the last $n chars.</p>
1912
     */
1913 36
    public function last(int $n): self
1914
    {
1915 36
        return static::create(
1916 36
            $this->utf8::str_last_char(
1917 36
                $this->str,
1918 36
                $n,
1919 36
                $this->encoding
1920
            ),
1921 36
            $this->encoding
1922
        );
1923
    }
1924
1925
    /**
1926
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1927
     * If no match is found returns new empty Stringy object.
1928
     *
1929
     * @param string $needle       <p>The string to look for.</p>
1930
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1931
     *
1932
     * @psalm-mutation-free
1933
     *
1934
     * @return static
1935
     */
1936 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...
1937
    {
1938 4
        return static::create(
1939 4
            $this->utf8::str_substr_last(
1940 4
                $this->str,
1941 4
                $needle,
1942 4
                $beforeNeedle,
1943 4
                $this->encoding
1944
            ),
1945 4
            $this->encoding
1946
        );
1947
    }
1948
1949
    /**
1950
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1951
     * If no match is found returns new empty Stringy object.
1952
     *
1953
     * @param string $needle       <p>The string to look for.</p>
1954
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1955
     *
1956
     * @psalm-mutation-free
1957
     *
1958
     * @return static
1959
     */
1960 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...
1961
    {
1962 2
        return static::create(
1963 2
            $this->utf8::str_isubstr_last(
1964 2
                $this->str,
1965 2
                $needle,
1966 2
                $beforeNeedle,
1967 2
                $this->encoding
1968
            ),
1969 2
            $this->encoding
1970
        );
1971
    }
1972
1973
    /**
1974
     * Returns the length of the string.
1975
     *
1976
     * @psalm-mutation-free
1977
     *
1978
     * @return int
1979
     *             <p>The number of characters in $str given the encoding.</p>
1980
     */
1981 17
    public function length(): int
1982
    {
1983 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
1984
    }
1985
1986
    /**
1987
     * Line-Wrap the string after $limit, but also after the next word.
1988
     *
1989
     * @param int         $limit           [optional] <p>The column width.</p>
1990
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
1991
     * @param bool        $add_final_break [optional] <p>
1992
     *                                     If this flag is true, then the method will add a $break at the end
1993
     *                                     of the result string.
1994
     *                                     </p>
1995
     * @param string|null $delimiter       [optional] <p>
1996
     *                                     You can change the default behavior, where we split the string by newline.
1997
     *                                     </p>
1998
     *
1999
     * @psalm-mutation-free
2000
     *
2001
     * @return static
2002
     */
2003 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...
2004
        int $limit,
2005
        string $break = "\n",
2006
        bool $add_final_break = true,
2007
        string $delimiter = null
2008
    ): self {
2009 3
        return static::create(
2010 3
            $this->utf8::wordwrap_per_line(
2011 3
                $this->str,
2012 3
                $limit,
2013 3
                $break,
2014 3
                true,
2015 3
                $add_final_break,
2016 3
                $delimiter
2017
            ),
2018 3
            $this->encoding
2019
        );
2020
    }
2021
2022
    /**
2023
     * Line-Wrap the string after $limit, but also after the next word.
2024
     *
2025
     * @param int         $limit           [optional] <p>The column width.</p>
2026
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2027
     * @param bool        $add_final_break [optional] <p>
2028
     *                                     If this flag is true, then the method will add a $break at the end
2029
     *                                     of the result string.
2030
     *                                     </p>
2031
     * @param string|null $delimiter       [optional] <p>
2032
     *                                     You can change the default behavior, where we split the string by newline.
2033
     *                                     </p>
2034
     *
2035
     * @psalm-mutation-free
2036
     *
2037
     * @return static
2038
     */
2039 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...
2040
        int $limit,
2041
        string $break = "\n",
2042
        bool $add_final_break = true,
2043
        string $delimiter = null
2044
    ): self {
2045 4
        return static::create(
2046 4
            $this->utf8::wordwrap_per_line(
2047 4
                $this->str,
2048 4
                $limit,
2049 4
                $break,
2050 4
                false,
2051 4
                $add_final_break,
2052 4
                $delimiter
2053
            ),
2054 4
            $this->encoding
2055
        );
2056
    }
2057
2058
    /**
2059
     * Splits on newlines and carriage returns, returning an array of Stringy
2060
     * objects corresponding to the lines in the string.
2061
     *
2062
     * @param bool $return_stingy_collection [optional] <p>Return a collection object.</p>
2063
     *
2064
     * @psalm-mutation-free
2065
     *
2066
     * @return CollectionStringy|static[]
2067
     *                                    <p>An collection of Stringy objects.</p>
2068
     *
2069
     * @psalm-return CollectionStringy<int,static>|array<int,static>
2070
     */
2071 51
    public function lines(bool $return_stingy_collection = false)
2072
    {
2073 51
        if ($this->str === '') {
2074 3
            if ($return_stingy_collection) {
2075
                /**
2076
                 * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2077
                 */
2078 3
                return CollectionStringy::create([static::create('')]);
2079
            }
2080
2081
            return [static::create('')];
2082
        }
2083
2084 48
        $array = $this->utf8::str_to_lines($this->str);
2085
        /** @noinspection AlterInForeachInspection */
2086 48
        foreach ($array as $i => &$value) {
2087 48
            $value = static::create($value, $this->encoding);
2088
        }
2089
2090
        /** @noinspection PhpSillyAssignmentInspection */
2091
        /** @var static[] $array */
2092 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...
2093
2094 48
        if ($return_stingy_collection) {
2095
            /**
2096
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2097
             */
2098 48
            return CollectionStringy::create($array);
2099
        }
2100
2101
        return $array;
2102
    }
2103
2104
    /**
2105
     * Returns the longest common prefix between the string and $otherStr.
2106
     *
2107
     * @param string $otherStr <p>Second string for comparison.</p>
2108
     *
2109
     * @psalm-mutation-free
2110
     *
2111
     * @return static
2112
     *                <p>Object with its $str being the longest common prefix.</p>
2113
     */
2114 30
    public function longestCommonPrefix(string $otherStr): self
2115
    {
2116 30
        return static::create(
2117 30
            $this->utf8::str_longest_common_prefix(
2118 30
                $this->str,
2119 30
                $otherStr,
2120 30
                $this->encoding
2121
            ),
2122 30
            $this->encoding
2123
        );
2124
    }
2125
2126
    /**
2127
     * Returns the longest common substring between the string and $otherStr.
2128
     * In the case of ties, it returns that which occurs first.
2129
     *
2130
     * @param string $otherStr <p>Second string for comparison.</p>
2131
     *
2132
     * @psalm-mutation-free
2133
     *
2134
     * @return static
2135
     *                <p>Object with its $str being the longest common substring.</p>
2136
     */
2137 30
    public function longestCommonSubstring(string $otherStr): self
2138
    {
2139 30
        return static::create(
2140 30
            $this->utf8::str_longest_common_substring(
2141 30
                $this->str,
2142 30
                $otherStr,
2143 30
                $this->encoding
2144
            ),
2145 30
            $this->encoding
2146
        );
2147
    }
2148
2149
    /**
2150
     * Returns the longest common suffix between the string and $otherStr.
2151
     *
2152
     * @param string $otherStr <p>Second string for comparison.</p>
2153
     *
2154
     * @psalm-mutation-free
2155
     *
2156
     * @return static
2157
     *                <p>Object with its $str being the longest common suffix.</p>
2158
     */
2159 30
    public function longestCommonSuffix(string $otherStr): self
2160
    {
2161 30
        return static::create(
2162 30
            $this->utf8::str_longest_common_suffix(
2163 30
                $this->str,
2164 30
                $otherStr,
2165 30
                $this->encoding
2166
            ),
2167 30
            $this->encoding
2168
        );
2169
    }
2170
2171
    /**
2172
     * Converts the first character of the string to lower case.
2173
     *
2174
     * @psalm-mutation-free
2175
     *
2176
     * @return static
2177
     *                <p>Object with the first character of $str being lower case.</p>
2178
     */
2179 15
    public function lowerCaseFirst(): self
2180
    {
2181 15
        return static::create(
2182 15
            $this->utf8::lcfirst($this->str, $this->encoding),
2183 15
            $this->encoding
2184
        );
2185
    }
2186
2187
    /**
2188
     * Determine if the string matches another string regardless of case.
2189
     * Alias for isEqualsCaseInsensitive()
2190
     *
2191
     * @psalm-mutation-free
2192
     *
2193
     * @param string|Stringy ...$str
2194
     *                               <p>The string to compare against.</p>
2195
     *
2196
     * @psalm-mutation-free
2197
     *
2198
     * @return bool
2199
     */
2200 3
    public function matchCaseInsensitive(...$str): bool
2201
    {
2202 3
        return $this->isEqualsCaseInsensitive(...$str);
2203
    }
2204
2205
    /**
2206
     * Determine if the string matches another string.
2207
     * Alias for isEqualsCaseSensitive()
2208
     *
2209
     * @psalm-mutation-free
2210
     *
2211
     * @param string|Stringy ...$str
2212
     *                               <p>The string to compare against.</p>
2213
     *
2214
     * @psalm-mutation-free
2215
     *
2216
     * @return bool
2217
     */
2218 7
    public function matchCaseSensitive(...$str): bool
2219
    {
2220 7
        return $this->isEqualsCaseSensitive(...$str);
2221
    }
2222
2223
    /**
2224
     * Create a md5 hash from the current string.
2225
     *
2226
     * @psalm-mutation-free
2227
     *
2228
     * @return static
2229
     */
2230 2
    public function md5(): self
2231
    {
2232 2
        return static::create($this->hash('md5'), $this->encoding);
2233
    }
2234
2235
    /**
2236
     * Get every nth character of the string.
2237
     *
2238
     * @param int $step   <p>The number of characters to step.</p>
2239
     * @param int $offset [optional] <p>The string offset to start at.</p>
2240
     *
2241
     * @psalm-mutation-free
2242
     *
2243
     * @return static
2244
     */
2245 4
    public function nth(int $step, int $offset = 0): self
2246
    {
2247 4
        $length = $step - 1;
2248 4
        $substring = $this->substr($offset)->toString();
2249
2250 4
        if ($substring === '') {
2251
            return new static('', $this->encoding);
2252
        }
2253
2254 4
        \preg_match_all(
2255 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2256 4
            $substring,
2257 4
            $matches
2258
        );
2259
2260 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2261
    }
2262
2263
    /**
2264
     * Returns whether or not a character exists at an index. Offsets may be
2265
     * negative to count from the last character in the string. Implements
2266
     * part of the ArrayAccess interface.
2267
     *
2268
     * @param int $offset <p>The index to check.</p>
2269
     *
2270
     * @psalm-mutation-free
2271
     *
2272
     * @return bool
2273
     *              <p>Whether or not the index exists.</p>
2274
     */
2275 18
    public function offsetExists($offset): bool
2276
    {
2277 18
        return $this->utf8::str_offset_exists(
2278 18
            $this->str,
2279 18
            $offset,
2280 18
            $this->encoding
2281
        );
2282
    }
2283
2284
    /**
2285
     * Returns the character at the given index. Offsets may be negative to
2286
     * count from the last character in the string. Implements part of the
2287
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2288
     * does not exist.
2289
     *
2290
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2291
     *
2292
     * @throws \OutOfBoundsException
2293
     *                               <p>If the positive or negative offset does not exist.</p>
2294
     *
2295
     * @return string
2296
     *                <p>The character at the specified index.</p>
2297
     *
2298
     * @psalm-mutation-free
2299
     */
2300 6
    public function offsetGet($offset): string
2301
    {
2302 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2303
    }
2304
2305
    /**
2306
     * Implements part of the ArrayAccess interface, but throws an exception
2307
     * when called. This maintains the immutability of Stringy objects.
2308
     *
2309
     * @param int   $offset <p>The index of the character.</p>
2310
     * @param mixed $value  <p>Value to set.</p>
2311
     *
2312
     * @throws \Exception
2313
     *                    <p>When called.</p>
2314
     *
2315
     * @return void
2316
     */
2317 3
    public function offsetSet($offset, $value)
2318
    {
2319
        // Stringy is immutable, cannot directly set char
2320
        /** @noinspection ThrowRawExceptionInspection */
2321 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
2322
    }
2323
2324
    /**
2325
     * Implements part of the ArrayAccess interface, but throws an exception
2326
     * when called. This maintains the immutability of Stringy objects.
2327
     *
2328
     * @param int $offset <p>The index of the character.</p>
2329
     *
2330
     * @throws \Exception
2331
     *                    <p>When called.</p>
2332
     *
2333
     * @return void
2334
     */
2335 3
    public function offsetUnset($offset)
2336
    {
2337
        // Don't allow directly modifying the string
2338
        /** @noinspection ThrowRawExceptionInspection */
2339 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
2340
    }
2341
2342
    /**
2343
     * Pads the string to a given length with $padStr. If length is less than
2344
     * or equal to the length of the string, no padding takes places. The
2345
     * default string used for padding is a space, and the default type (one of
2346
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
2347
     * if $padType isn't one of those 3 values.
2348
     *
2349
     * @param int    $length  <p>Desired string length after padding.</p>
2350
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2351
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
2352
     *
2353
     * @throws \InvalidArgumentException
2354
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
2355
     *
2356
     * @return static
2357
     *                <p>Object with a padded $str.</p>
2358
     *
2359
     * @psalm-mutation-free
2360
     */
2361 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
2362
    {
2363 39
        return static::create(
2364 39
            $this->utf8::str_pad(
2365 39
                $this->str,
2366 39
                $length,
2367 39
                $padStr,
2368 39
                $padType,
2369 39
                $this->encoding
2370
            )
2371
        );
2372
    }
2373
2374
    /**
2375
     * Returns a new string of a given length such that both sides of the
2376
     * string are padded. Alias for pad() with a $padType of 'both'.
2377
     *
2378
     * @param int    $length <p>Desired string length after padding.</p>
2379
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2380
     *
2381
     * @psalm-mutation-free
2382
     *
2383
     * @return static
2384
     *                <p>String with padding applied.</p>
2385
     */
2386 33
    public function padBoth(int $length, string $padStr = ' '): self
2387
    {
2388 33
        return static::create(
2389 33
            $this->utf8::str_pad_both(
2390 33
                $this->str,
2391 33
                $length,
2392 33
                $padStr,
2393 33
                $this->encoding
2394
            )
2395
        );
2396
    }
2397
2398
    /**
2399
     * Returns a new string of a given length such that the beginning of the
2400
     * string is padded. Alias for pad() with a $padType of 'left'.
2401
     *
2402
     * @param int    $length <p>Desired string length after padding.</p>
2403
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2404
     *
2405
     * @psalm-mutation-free
2406
     *
2407
     * @return static
2408
     *                <p>String with left padding.</p>
2409
     */
2410 21
    public function padLeft(int $length, string $padStr = ' '): self
2411
    {
2412 21
        return static::create(
2413 21
            $this->utf8::str_pad_left(
2414 21
                $this->str,
2415 21
                $length,
2416 21
                $padStr,
2417 21
                $this->encoding
2418
            )
2419
        );
2420
    }
2421
2422
    /**
2423
     * Returns a new string of a given length such that the end of the string
2424
     * is padded. Alias for pad() with a $padType of 'right'.
2425
     *
2426
     * @param int    $length <p>Desired string length after padding.</p>
2427
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2428
     *
2429
     * @psalm-mutation-free
2430
     *
2431
     * @return static
2432
     *                <p>String with right padding.</p>
2433
     */
2434 21
    public function padRight(int $length, string $padStr = ' '): self
2435
    {
2436 21
        return static::create(
2437 21
            $this->utf8::str_pad_right(
2438 21
                $this->str,
2439 21
                $length,
2440 21
                $padStr,
2441 21
                $this->encoding
2442
            )
2443
        );
2444
    }
2445
2446
    /**
2447
     * Returns a new string starting with $prefix.
2448
     *
2449
     * @param string ...$prefix <p>The string to append.</p>
2450
     *
2451
     * @psalm-mutation-free
2452
     *
2453
     * @return static
2454
     *                <p>Object with appended $prefix.</p>
2455
     *
2456
     * @noinspection PhpDocSignatureInspection
2457
     */
2458 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...
2459
    {
2460 7
        if (\count($prefix) <= 1) {
2461
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2462 6
            $prefix = $prefix[0];
2463
        } else {
2464
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2465 1
            $prefix = \implode('', $prefix);
2466
        }
2467
2468 7
        return static::create($prefix . $this->str, $this->encoding);
2469
    }
2470
2471
    /**
2472
     * Replaces all occurrences of $pattern in $str by $replacement.
2473
     *
2474
     * @param string $pattern     <p>The regular expression pattern.</p>
2475
     * @param string $replacement <p>The string to replace with.</p>
2476
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2477
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2478
     *
2479
     * @psalm-mutation-free
2480
     *
2481
     * @return static
2482
     *                <p>Object with the result2ing $str after the replacements.</p>
2483
     */
2484 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2485
    {
2486 29
        return static::create(
2487 29
            $this->utf8::regex_replace(
2488 29
                $this->str,
2489 29
                $pattern,
2490 29
                $replacement,
2491 29
                $options,
2492 29
                $delimiter
2493
            ),
2494 29
            $this->encoding
2495
        );
2496
    }
2497
2498
    /**
2499
     * Remove html via "strip_tags()" from the string.
2500
     *
2501
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2502
     *                              not be stripped. Default: null
2503
     *                              </p>
2504
     *
2505
     * @psalm-mutation-free
2506
     *
2507
     * @return static
2508
     */
2509 12
    public function removeHtml(string $allowableTags = ''): self
2510
    {
2511 12
        return static::create(
2512 12
            $this->utf8::remove_html($this->str, $allowableTags),
2513 12
            $this->encoding
2514
        );
2515
    }
2516
2517
    /**
2518
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2519
     *
2520
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2521
     *
2522
     * @psalm-mutation-free
2523
     *
2524
     * @return static
2525
     */
2526 12
    public function removeHtmlBreak(string $replacement = ''): self
2527
    {
2528 12
        return static::create(
2529 12
            $this->utf8::remove_html_breaks($this->str, $replacement),
2530 12
            $this->encoding
2531
        );
2532
    }
2533
2534
    /**
2535
     * Returns a new string with the prefix $substring removed, if present.
2536
     *
2537
     * @param string $substring <p>The prefix to remove.</p>
2538
     *
2539
     * @psalm-mutation-free
2540
     *
2541
     * @return static
2542
     *                <p>Object having a $str without the prefix $substring.</p>
2543
     */
2544 36
    public function removeLeft(string $substring): self
2545
    {
2546 36
        return static::create(
2547 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2548 36
            $this->encoding
2549
        );
2550
    }
2551
2552
    /**
2553
     * Returns a new string with the suffix $substring removed, if present.
2554
     *
2555
     * @param string $substring <p>The suffix to remove.</p>
2556
     *
2557
     * @psalm-mutation-free
2558
     *
2559
     * @return static
2560
     *                <p>Object having a $str without the suffix $substring.</p>
2561
     */
2562 36
    public function removeRight(string $substring): self
2563
    {
2564 36
        return static::create(
2565 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2566 36
            $this->encoding
2567
        );
2568
    }
2569
2570
    /**
2571
     * Try to remove all XSS-attacks from the string.
2572
     *
2573
     * @psalm-mutation-free
2574
     *
2575
     * @return static
2576
     */
2577 12
    public function removeXss(): self
2578
    {
2579
        /**
2580
         * @var AntiXSS|null
2581
         *
2582
         * @psalm-suppress ImpureStaticVariable
2583
         */
2584 12
        static $antiXss = null;
2585
2586 12
        if ($antiXss === null) {
2587 1
            $antiXss = new AntiXSS();
2588
        }
2589
2590
        /**
2591
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2592
         */
2593 12
        $str = $antiXss->xss_clean($this->str);
2594
2595 12
        return static::create($str, $this->encoding);
2596
    }
2597
2598
    /**
2599
     * Returns a repeated string given a multiplier.
2600
     *
2601
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2602
     *
2603
     * @psalm-mutation-free
2604
     *
2605
     * @return static
2606
     *                <p>Object with a repeated str.</p>
2607
     */
2608 21
    public function repeat(int $multiplier): self
2609
    {
2610 21
        return static::create(
2611 21
            \str_repeat($this->str, $multiplier),
2612 21
            $this->encoding
2613
        );
2614
    }
2615
2616
    /**
2617
     * Replaces all occurrences of $search in $str by $replacement.
2618
     *
2619
     * @param string $search        <p>The needle to search for.</p>
2620
     * @param string $replacement   <p>The string to replace with.</p>
2621
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2622
     *
2623
     * @psalm-mutation-free
2624
     *
2625
     * @return static
2626
     *                <p>Object with the resulting $str after the replacements.</p>
2627
     */
2628 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2629
    {
2630 76
        if ($search === '' && $replacement === '') {
2631 16
            return static::create($this->str, $this->encoding);
2632
        }
2633
2634 60
        if ($this->str === '' && $search === '') {
2635 2
            return static::create($replacement, $this->encoding);
2636
        }
2637
2638 58
        if ($caseSensitive) {
2639 48
            return static::create(
2640 48
                $this->utf8::str_replace($search, $replacement, $this->str),
2641 48
                $this->encoding
2642
            );
2643
        }
2644
2645 10
        return static::create(
2646 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2647 10
            $this->encoding
2648
        );
2649
    }
2650
2651
    /**
2652
     * Replaces all occurrences of $search in $str by $replacement.
2653
     *
2654
     * @param string[]        $search        <p>The elements to search for.</p>
2655
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2656
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2657
     *
2658
     * @psalm-mutation-free
2659
     *
2660
     * @return static
2661
     *                <p>Object with the resulting $str after the replacements.</p>
2662
     */
2663 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2664
    {
2665 61
        if ($caseSensitive) {
2666 47
            return static::create(
2667 47
                $this->utf8::str_replace($search, $replacement, $this->str),
2668 47
                $this->encoding
2669
            );
2670
        }
2671
2672 14
        return static::create(
2673 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2674 14
            $this->encoding
2675
        );
2676
    }
2677
2678
    /**
2679
     * Replaces all occurrences of $search from the beginning of string with $replacement.
2680
     *
2681
     * @param string $search      <p>The string to search for.</p>
2682
     * @param string $replacement <p>The replacement.</p>
2683
     *
2684
     * @psalm-mutation-free
2685
     *
2686
     * @return static
2687
     *                <p>Object with the resulting $str after the replacements.</p>
2688
     */
2689 32
    public function replaceBeginning(string $search, string $replacement): self
2690
    {
2691 32
        return static::create(
2692 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
2693 32
            $this->encoding
2694
        );
2695
    }
2696
2697
    /**
2698
     * Replaces all occurrences of $search from the ending of string with $replacement.
2699
     *
2700
     * @param string $search      <p>The string to search for.</p>
2701
     * @param string $replacement <p>The replacement.</p>
2702
     *
2703
     * @psalm-mutation-free
2704
     *
2705
     * @return static
2706
     *                <p>Object with the resulting $str after the replacements.</p>
2707
     */
2708 32
    public function replaceEnding(string $search, string $replacement): self
2709
    {
2710 32
        return static::create(
2711 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
2712 32
            $this->encoding
2713
        );
2714
    }
2715
2716
    /**
2717
     * Replaces first occurrences of $search from the beginning of string with $replacement.
2718
     *
2719
     * @param string $search      <p>The string to search for.</p>
2720
     * @param string $replacement <p>The replacement.</p>
2721
     *
2722
     * @psalm-mutation-free
2723
     *
2724
     * @return static
2725
     *                <p>Object with the resulting $str after the replacements.</p>
2726
     */
2727 32
    public function replaceFirst(string $search, string $replacement): self
2728
    {
2729 32
        return static::create(
2730 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
2731 32
            $this->encoding
2732
        );
2733
    }
2734
2735
    /**
2736
     * Replaces last occurrences of $search from the ending of string with $replacement.
2737
     *
2738
     * @param string $search      <p>The string to search for.</p>
2739
     * @param string $replacement <p>The replacement.</p>
2740
     *
2741
     * @psalm-mutation-free
2742
     *
2743
     * @return static
2744
     *                <p>Object with the resulting $str after the replacements.</p>
2745
     */
2746 30
    public function replaceLast(string $search, string $replacement): self
2747
    {
2748 30
        return static::create(
2749 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
2750 30
            $this->encoding
2751
        );
2752
    }
2753
2754
    /**
2755
     * Returns a reversed string. A multibyte version of strrev().
2756
     *
2757
     * @psalm-mutation-free
2758
     *
2759
     * @return static
2760
     *                <p>Object with a reversed $str.</p>
2761
     */
2762 15
    public function reverse(): self
2763
    {
2764 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
2765
    }
2766
2767
    /**
2768
     * Truncates the string to a given length, while ensuring that it does not
2769
     * split words. If $substring is provided, and truncating occurs, the
2770
     * string is further truncated so that the substring may be appended without
2771
     * exceeding the desired length.
2772
     *
2773
     * @param int    $length                          <p>Desired length of the truncated string.</p>
2774
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
2775
     * @param bool   $ignoreDoNotSplitWordsForOneWord
2776
     *
2777
     * @psalm-mutation-free
2778
     *
2779
     * @return static
2780
     *                <p>Object with the resulting $str after truncating.</p>
2781
     */
2782 68
    public function safeTruncate(
2783
        int $length,
2784
        string $substring = '',
2785
        bool $ignoreDoNotSplitWordsForOneWord = true
2786
    ): self {
2787 68
        return static::create(
2788 68
            $this->utf8::str_truncate_safe(
2789 68
                $this->str,
2790 68
                $length,
2791 68
                $substring,
2792 68
                $this->encoding,
2793 68
                $ignoreDoNotSplitWordsForOneWord
2794
            ),
2795 68
            $this->encoding
2796
        );
2797
    }
2798
2799
    /**
2800
     * Create a sha1 hash from the current string.
2801
     *
2802
     * @psalm-mutation-free
2803
     *
2804
     * @return static
2805
     */
2806 2
    public function sha1(): self
2807
    {
2808 2
        return static::create($this->hash('sha1'), $this->encoding);
2809
    }
2810
2811
    /**
2812
     * Create a sha256 hash from the current string.
2813
     *
2814
     * @psalm-mutation-free
2815
     *
2816
     * @return static
2817
     */
2818 2
    public function sha256(): self
2819
    {
2820 2
        return static::create($this->hash('sha256'), $this->encoding);
2821
    }
2822
2823
    /**
2824
     * Create a sha512 hash from the current string.
2825
     *
2826
     * @psalm-mutation-free
2827
     *
2828
     * @return static
2829
     */
2830 2
    public function sha512(): self
2831
    {
2832 2
        return static::create($this->hash('sha512'), $this->encoding);
2833
    }
2834
2835
    /**
2836
     * Shorten the string after $length, but also after the next word.
2837
     *
2838
     * @param int    $length   <p>The given length.</p>
2839
     * @param string $strAddOn [optional] <p>Default: '…'</p>
2840
     *
2841
     * @psalm-mutation-free
2842
     *
2843
     * @return static
2844
     */
2845 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
2846
    {
2847 8
        return static::create(
2848 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
2849 8
            $this->encoding
2850
        );
2851
    }
2852
2853
    /**
2854
     * A multibyte string shuffle function. It returns a string with its
2855
     * characters in random order.
2856
     *
2857
     * @psalm-mutation-free
2858
     *
2859
     * @return static
2860
     *                <p>Object with a shuffled $str.</p>
2861
     */
2862 9
    public function shuffle(): self
2863
    {
2864 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
2865
    }
2866
2867
    /**
2868
     * Calculate the similarity between two strings.
2869
     *
2870
     * @param string $str <p>The delimiting string.</p>
2871
     *
2872
     * @psalm-mutation-free
2873
     *
2874
     * @return float
2875
     */
2876 2
    public function similarity(string $str): float
2877
    {
2878 2
        \similar_text($this->str, $str, $percent);
2879
2880 2
        return $percent;
2881
    }
2882
2883
    /**
2884
     * Returns the substring beginning at $start, and up to, but not including
2885
     * the index specified by $end. If $end is omitted, the function extracts
2886
     * the remaining string. If $end is negative, it is computed from the end
2887
     * of the string.
2888
     *
2889
     * @param int $start <p>Initial index from which to begin extraction.</p>
2890
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
2891
     *
2892
     * @psalm-mutation-free
2893
     *
2894
     * @return static
2895
     *                <p>Object with its $str being the extracted substring.</p>
2896
     */
2897 50
    public function slice(int $start, int $end = null): self
2898
    {
2899 50
        return static::create(
2900 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
2901 50
            $this->encoding
2902
        );
2903
    }
2904
2905
    /**
2906
     * Converts the string into an URL slug. This includes replacing non-ASCII
2907
     * characters with their closest ASCII equivalents, removing remaining
2908
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
2909
     * $separator. The separator defaults to a single dash, and the string
2910
     * is also converted to lowercase. The language of the source string can
2911
     * also be supplied for language-specific transliteration.
2912
     *
2913
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
2914
     * @param string                $language              [optional] <p>Language of the source string.</p>
2915
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
2916
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
2917
     *                                                     pound ".</p>
2918
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
2919
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
2920
     *                                                     chars.</p>
2921
     *
2922
     * @psalm-mutation-free
2923
     *
2924
     * @return static
2925
     *                <p>Object whose $str has been converted to an URL slug.</p>
2926
     *
2927
     * @noinspection PhpTooManyParametersInspection
2928
     */
2929 17
    public function slugify(
2930
        string $separator = '-',
2931
        string $language = 'en',
2932
        array $replacements = [],
2933
        bool $replace_extra_symbols = true,
2934
        bool $use_str_to_lower = true,
2935
        bool $use_transliterate = false
2936
    ): self {
2937 17
        return static::create(
2938 17
            $this->ascii::to_slugify(
2939 17
                $this->str,
2940 17
                $separator,
2941 17
                $language,
2942 17
                $replacements,
2943 17
                $replace_extra_symbols,
2944 17
                $use_str_to_lower,
2945 17
                $use_transliterate
2946
            ),
2947 17
            $this->encoding
2948
        );
2949
    }
2950
2951
    /**
2952
     * Convert a string to e.g.: "snake_case"
2953
     *
2954
     * @psalm-mutation-free
2955
     *
2956
     * @return static
2957
     *                <p>Object with $str in snake_case.</p>
2958
     */
2959 40
    public function snakeize(): self
2960
    {
2961 40
        return static::create(
2962 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
2963 40
            $this->encoding
2964
        );
2965
    }
2966
2967
    /**
2968
     * Wrap the string after the first whitespace character after a given number
2969
     * of characters.
2970
     *
2971
     * @param int    $width <p>Number of characters at which to wrap.</p>
2972
     * @param string $break [optional] <p>Character used to break the string. | Default "\n"</p>
2973
     *
2974
     * @psalm-mutation-free
2975
     *
2976
     * @return static
2977
     */
2978 2
    public function softWrap(int $width, string $break = "\n"): self
2979
    {
2980 2
        return $this->lineWrapAfterWord($width, $break, false);
2981
    }
2982
2983
    /**
2984
     * Splits the string with the provided regular expression, returning an
2985
     * array of Stringy objects. An optional integer $limit will truncate the
2986
     * results.
2987
     *
2988
     * @param string $pattern                  <p>The regex with which to split the string.</p>
2989
     * @param int    $limit                    [optional] <p>Maximum number of results to return. Default: -1 === no
2990
     *                                         limit</p>
2991
     * @param bool   $return_stingy_collection [optional] <p>Return a collection object.</p>
2992
     *
2993
     * @psalm-mutation-free
2994
     *
2995
     * @return CollectionStringy|static[]
2996
     *                                    <p>An collection of Stringy objects.</p>
2997
     *
2998
     * @psalm-return CollectionStringy<int,static>|array<int,static>
2999
     */
3000 51
    public function split(
3001
        string $pattern,
3002
        int $limit = null,
3003
        bool $return_stingy_collection = false
3004
    ) {
3005 51
        if ($this->str === '') {
3006
            if ($return_stingy_collection) {
3007
                /**
3008
                 * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3009
                 */
3010
                return CollectionStringy::create([]);
3011
            }
3012
3013
            return [];
3014
        }
3015
3016 51
        if ($limit === null) {
3017 7
            $limit = -1;
3018
        }
3019
3020 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
3021
        /** @noinspection AlterInForeachInspection */
3022 51
        foreach ($array as $i => &$value) {
3023 45
            $value = static::create($value, $this->encoding);
3024
        }
3025
3026
        /** @noinspection PhpSillyAssignmentInspection */
3027
        /** @var static[] $array */
3028 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...
3029
3030 51
        if ($return_stingy_collection) {
3031
            /**
3032
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3033
             */
3034 35
            return CollectionStringy::create($array);
3035
        }
3036
3037 16
        return $array;
3038
    }
3039
3040
    /**
3041
     * Returns true if the string begins with $substring, false otherwise. By
3042
     * default, the comparison is case-sensitive, but can be made insensitive
3043
     * by setting $caseSensitive to false.
3044
     *
3045
     * @param string $substring     <p>The substring to look for.</p>
3046
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3047
     *
3048
     * @psalm-mutation-free
3049
     *
3050
     * @return bool
3051
     *              <p>Whether or not $str starts with $substring.</p>
3052
     */
3053 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
3054
    {
3055 99
        if ($caseSensitive) {
3056 53
            return $this->utf8::str_starts_with($this->str, $substring);
3057
        }
3058
3059 46
        return $this->utf8::str_istarts_with($this->str, $substring);
3060
    }
3061
3062
    /**
3063
     * Returns true if the string begins with any of $substrings, false otherwise.
3064
     * By default the comparison is case-sensitive, but can be made insensitive by
3065
     * setting $caseSensitive to false.
3066
     *
3067
     * @param string[] $substrings    <p>Substrings to look for.</p>
3068
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3069
     *
3070
     * @psalm-mutation-free
3071
     *
3072
     * @return bool
3073
     *              <p>Whether or not $str starts with $substring.</p>
3074
     */
3075 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
3076
    {
3077 35
        if ($caseSensitive) {
3078 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
3079
        }
3080
3081 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
3082
    }
3083
3084
    /**
3085
     * Remove one or more strings from the string.
3086
     *
3087
     * @param string|string[] $search One or more strings to be removed
3088
     *
3089
     * @psalm-mutation-free
3090
     *
3091
     * @return static
3092
     */
3093 3
    public function strip($search): self
3094
    {
3095 3
        if (\is_array($search)) {
3096 1
            return $this->replaceAll($search, '');
3097
        }
3098
3099 2
        return $this->replace($search, '');
3100
    }
3101
3102
    /**
3103
     * Strip all whitespace characters. This includes tabs and newline characters,
3104
     * as well as multibyte whitespace such as the thin space and ideographic space.
3105
     *
3106
     * @psalm-mutation-free
3107
     *
3108
     * @return static
3109
     */
3110 36
    public function stripWhitespace(): self
3111
    {
3112 36
        return static::create(
3113 36
            $this->utf8::strip_whitespace($this->str),
3114 36
            $this->encoding
3115
        );
3116
    }
3117
3118
    /**
3119
     * Remove css media-queries.
3120
     *
3121
     * @psalm-mutation-free
3122
     *
3123
     * @return static
3124
     */
3125 2
    public function stripeCssMediaQueries(): self
3126
    {
3127 2
        return static::create(
3128 2
            $this->utf8::css_stripe_media_queries($this->str),
3129 2
            $this->encoding
3130
        );
3131
    }
3132
3133
    /**
3134
     * Remove empty html-tag.
3135
     *
3136
     * e.g.: <tag></tag>
3137
     *
3138
     * @psalm-mutation-free
3139
     *
3140
     * @return static
3141
     */
3142 2
    public function stripeEmptyHtmlTags(): self
3143
    {
3144 2
        return static::create(
3145 2
            $this->utf8::html_stripe_empty_tags($this->str),
3146 2
            $this->encoding
3147
        );
3148
    }
3149
3150
    /**
3151
     * Returns the substring beginning at $start with the specified $length.
3152
     * It differs from the $this->utf8::substr() function in that providing a $length of
3153
     * null will return the rest of the string, rather than an empty string.
3154
     *
3155
     * @param int $start  <p>Position of the first character to use.</p>
3156
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
3157
     *
3158
     * @psalm-mutation-free
3159
     *
3160
     * @return static
3161
     *                <p>Object with its $str being the substring.</p>
3162
     */
3163 31
    public function substr(int $start, int $length = null): self
3164
    {
3165 31
        return static::create(
3166 31
            $this->utf8::substr(
3167 31
                $this->str,
3168 31
                $start,
3169 31
                $length,
3170 31
                $this->encoding
3171
            ),
3172 31
            $this->encoding
3173
        );
3174
    }
3175
3176
    /**
3177
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3178
     * If no match is found returns new empty Stringy object.
3179
     *
3180
     * @param string $needle       <p>The string to look for.</p>
3181
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3182
     *
3183
     * @psalm-mutation-free
3184
     *
3185
     * @return static
3186
     */
3187 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...
3188
    {
3189 4
        return static::create(
3190 4
            $this->utf8::str_substr_first(
3191 4
                $this->str,
3192 4
                $needle,
3193 4
                $beforeNeedle,
3194 4
                $this->encoding
3195
            ),
3196 4
            $this->encoding
3197
        );
3198
    }
3199
3200
    /**
3201
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3202
     * If no match is found returns new empty Stringy object.
3203
     *
3204
     * @param string $needle       <p>The string to look for.</p>
3205
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3206
     *
3207
     * @psalm-mutation-free
3208
     *
3209
     * @return static
3210
     */
3211 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...
3212
    {
3213 4
        return static::create(
3214 4
            $this->utf8::str_isubstr_first(
3215 4
                $this->str,
3216 4
                $needle,
3217 4
                $beforeNeedle,
3218 4
                $this->encoding
3219
            ),
3220 4
            $this->encoding
3221
        );
3222
    }
3223
3224
    /**
3225
     * Surrounds $str with the given substring.
3226
     *
3227
     * @param string $substring <p>The substring to add to both sides.</P>
3228
     *
3229
     * @psalm-mutation-free
3230
     *
3231
     * @return static
3232
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3233
     */
3234 15
    public function surround(string $substring): self
3235
    {
3236 15
        return static::create(
3237 15
            $substring . $this->str . $substring,
3238 15
            $this->encoding
3239
        );
3240
    }
3241
3242
    /**
3243
     * Returns a case swapped version of the string.
3244
     *
3245
     * @psalm-mutation-free
3246
     *
3247
     * @return static
3248
     *                <p>Object whose $str has each character's case swapped.</P>
3249
     */
3250 15
    public function swapCase(): self
3251
    {
3252 15
        return static::create(
3253 15
            $this->utf8::swapCase($this->str, $this->encoding),
3254 15
            $this->encoding
3255
        );
3256
    }
3257
3258
    /**
3259
     * Returns a string with smart quotes, ellipsis characters, and dashes from
3260
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
3261
     * equivalents.
3262
     *
3263
     * @psalm-mutation-free
3264
     *
3265
     * @return static
3266
     *                <p>Object whose $str has those characters removed.</p>
3267
     */
3268 12
    public function tidy(): self
3269
    {
3270 12
        return static::create(
3271 12
            $this->ascii::normalize_msword($this->str),
3272 12
            $this->encoding
3273
        );
3274
    }
3275
3276
    /**
3277
     * Returns a trimmed string with the first letter of each word capitalized.
3278
     * Also accepts an array, $ignore, allowing you to list words not to be
3279
     * capitalized.
3280
     *
3281
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
3282
     *                                               Default: null</p>
3283
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
3284
     *                                               separator === words.</p>
3285
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
3286
     *
3287
     * @psalm-mutation-free
3288
     *
3289
     * @return static
3290
     *                <p>Object with a titleized $str.</p>
3291
     */
3292 23
    public function titleize(
3293
        array $ignore = null,
3294
        string $word_define_chars = null,
3295
        string $language = null
3296
    ): self {
3297 23
        return static::create(
3298 23
            $this->utf8::str_titleize(
3299 23
                $this->str,
3300 23
                $ignore,
3301 23
                $this->encoding,
3302 23
                false,
3303 23
                $language,
3304 23
                false,
3305 23
                true,
3306 23
                $word_define_chars
3307
            ),
3308 23
            $this->encoding
3309
        );
3310
    }
3311
3312
    /**
3313
     * Returns a trimmed string in proper title case.
3314
     *
3315
     * Also accepts an array, $ignore, allowing you to list words not to be
3316
     * capitalized.
3317
     *
3318
     * Adapted from John Gruber's script.
3319
     *
3320
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
3321
     *
3322
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
3323
     *
3324
     * @psalm-mutation-free
3325
     *
3326
     * @return static
3327
     *                <p>Object with a titleized $str</p>
3328
     */
3329 70
    public function titleizeForHumans(array $ignore = []): self
3330
    {
3331 70
        return static::create(
3332 70
            $this->utf8::str_titleize_for_humans(
3333 70
                $this->str,
3334 70
                $ignore,
3335 70
                $this->encoding
3336
            ),
3337 70
            $this->encoding
3338
        );
3339
    }
3340
3341
    /**
3342
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3343
     * replaced with their closest ASCII counterparts, and the rest are removed
3344
     * by default. The language or locale of the source string can be supplied
3345
     * for language-specific transliteration in any of the following formats:
3346
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
3347
     * to "aeoeue" rather than "aou" as in other languages.
3348
     *
3349
     * @param string $language          [optional] <p>Language of the source string.</p>
3350
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
3351
     *                                  unsupported characters.</p>
3352
     *
3353
     * @psalm-mutation-free
3354
     *
3355
     * @return static
3356
     *                <p>Object whose $str contains only ASCII characters.</p>
3357
     */
3358 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
3359
    {
3360 23
        return static::create(
3361 23
            $this->ascii::to_ascii(
3362 23
                $this->str,
3363 23
                $language,
3364 23
                $removeUnsupported
3365
            ),
3366 23
            $this->encoding
3367
        );
3368
    }
3369
3370
    /**
3371
     * Returns a boolean representation of the given logical string value.
3372
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
3373
     * 'off', and 'no' will return false. In all instances, case is ignored.
3374
     * For other numeric strings, their sign will determine the return value.
3375
     * In addition, blank strings consisting of only whitespace will return
3376
     * false. For all other strings, the return value is a result of a
3377
     * boolean cast.
3378
     *
3379
     * @psalm-mutation-free
3380
     *
3381
     * @return bool
3382
     *              <p>A boolean value for the string.</p>
3383
     */
3384 45
    public function toBoolean(): bool
3385
    {
3386 45
        return $this->utf8::to_boolean($this->str);
3387
    }
3388
3389
    /**
3390
     * Converts all characters in the string to lowercase.
3391
     *
3392
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3393
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3394
     *
3395
     * @psalm-mutation-free
3396
     *
3397
     * @return static
3398
     *                <p>Object with all characters of $str being lowercase.</p>
3399
     */
3400 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...
3401
    {
3402 17
        return static::create(
3403 17
            $this->utf8::strtolower(
3404 17
                $this->str,
3405 17
                $this->encoding,
3406 17
                false,
3407 17
                $lang,
3408 17
                $tryToKeepStringLength
3409
            ),
3410 17
            $this->encoding
3411
        );
3412
    }
3413
3414
    /**
3415
     * Converts each tab in the string to some number of spaces, as defined by
3416
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
3417
     *
3418
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
3419
     *
3420
     * @psalm-mutation-free
3421
     *
3422
     * @return static
3423
     *                <p>Object whose $str has had tabs switched to spaces.</p>
3424
     */
3425 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...
3426
    {
3427 18
        if ($tabLength === 4) {
3428 9
            $tab = '    ';
3429 9
        } elseif ($tabLength === 2) {
3430 3
            $tab = '  ';
3431
        } else {
3432 6
            $tab = \str_repeat(' ', $tabLength);
3433
        }
3434
3435 18
        return static::create(
3436 18
            \str_replace("\t", $tab, $this->str),
3437 18
            $this->encoding
3438
        );
3439
    }
3440
3441
    /**
3442
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
3443
     * string.
3444
     *
3445
     * @psalm-mutation-free
3446
     *
3447
     * @return string
3448
     */
3449 2180
    public function toString(): string
3450
    {
3451 2180
        return (string) $this->str;
3452
    }
3453
3454
    /**
3455
     * Converts each occurrence of some consecutive number of spaces, as
3456
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
3457
     * are converted to a tab.
3458
     *
3459
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
3460
     *
3461
     * @psalm-mutation-free
3462
     *
3463
     * @return static
3464
     *                <p>Object whose $str has had spaces switched to tabs.</p>
3465
     */
3466 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...
3467
    {
3468 15
        if ($tabLength === 4) {
3469 9
            $tab = '    ';
3470 6
        } elseif ($tabLength === 2) {
3471 3
            $tab = '  ';
3472
        } else {
3473 3
            $tab = \str_repeat(' ', $tabLength);
3474
        }
3475
3476 15
        return static::create(
3477 15
            \str_replace($tab, "\t", $this->str),
3478 15
            $this->encoding
3479
        );
3480
    }
3481
3482
    /**
3483
     * Converts the first character of each word in the string to uppercase
3484
     * and all other chars to lowercase.
3485
     *
3486
     * @psalm-mutation-free
3487
     *
3488
     * @return static
3489
     *                <p>Object with all characters of $str being title-cased.</p>
3490
     */
3491 15
    public function toTitleCase(): self
3492
    {
3493 15
        return static::create(
3494 15
            $this->utf8::titlecase($this->str, $this->encoding),
3495 15
            $this->encoding
3496
        );
3497
    }
3498
3499
    /**
3500
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3501
     * replaced with their closest ASCII counterparts, and the rest are removed
3502
     * unless instructed otherwise.
3503
     *
3504
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
3505
     *                        performance | Default: false</p>
3506
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
3507
     *
3508
     * @psalm-mutation-free
3509
     *
3510
     * @return static
3511
     *                <p>Object whose $str contains only ASCII characters.</p>
3512
     */
3513 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
3514
    {
3515 34
        return static::create(
3516 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
3517 34
            $this->encoding
3518
        );
3519
    }
3520
3521
    /**
3522
     * Converts all characters in the string to uppercase.
3523
     *
3524
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3525
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3526
     *
3527
     * @psalm-mutation-free
3528
     *
3529
     * @return static
3530
     *                <p>Object with all characters of $str being uppercase.</p>
3531
     */
3532 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...
3533
    {
3534 20
        return static::create(
3535 20
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
3536 20
            $this->encoding
3537
        );
3538
    }
3539
3540
    /**
3541
     * Returns a string with whitespace removed from the start and end of the
3542
     * string. Supports the removal of unicode whitespace. Accepts an optional
3543
     * string of characters to strip instead of the defaults.
3544
     *
3545
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
3546
     *
3547
     * @psalm-mutation-free
3548
     *
3549
     * @return static
3550
     *                <p>Object with a trimmed $str.</p>
3551
     */
3552 36
    public function trim(string $chars = null): self
3553
    {
3554 36
        return static::create(
3555 36
            $this->utf8::trim($this->str, $chars),
3556 36
            $this->encoding
3557
        );
3558
    }
3559
3560
    /**
3561
     * Returns a string with whitespace removed from the start of the string.
3562
     * Supports the removal of unicode whitespace. Accepts an optional
3563
     * string of characters to strip instead of the defaults.
3564
     *
3565
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3566
     *
3567
     * @psalm-mutation-free
3568
     *
3569
     * @return static
3570
     *                <p>Object with a trimmed $str.</p>
3571
     */
3572 39
    public function trimLeft(string $chars = null): self
3573
    {
3574 39
        return static::create(
3575 39
            $this->utf8::ltrim($this->str, $chars),
3576 39
            $this->encoding
3577
        );
3578
    }
3579
3580
    /**
3581
     * Returns a string with whitespace removed from the end of the string.
3582
     * Supports the removal of unicode whitespace. Accepts an optional
3583
     * string of characters to strip instead of the defaults.
3584
     *
3585
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3586
     *
3587
     * @psalm-mutation-free
3588
     *
3589
     * @return static
3590
     *                <p>Object with a trimmed $str.</p>
3591
     */
3592 39
    public function trimRight(string $chars = null): self
3593
    {
3594 39
        return static::create(
3595 39
            $this->utf8::rtrim($this->str, $chars),
3596 39
            $this->encoding
3597
        );
3598
    }
3599
3600
    /**
3601
     * Truncates the string to a given length. If $substring is provided, and
3602
     * truncating occurs, the string is further truncated so that the substring
3603
     * may be appended without exceeding the desired length.
3604
     *
3605
     * @param int    $length    <p>Desired length of the truncated string.</p>
3606
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
3607
     *
3608
     * @psalm-mutation-free
3609
     *
3610
     * @return static
3611
     *                <p>Object with the resulting $str after truncating.</p>
3612
     */
3613 66
    public function truncate(int $length, string $substring = ''): self
3614
    {
3615 66
        return static::create(
3616 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
3617 66
            $this->encoding
3618
        );
3619
    }
3620
3621
    /**
3622
     * Returns a lowercase and trimmed string separated by underscores.
3623
     * Underscores are inserted before uppercase characters (with the exception
3624
     * of the first character of the string), and in place of spaces as well as
3625
     * dashes.
3626
     *
3627
     * @psalm-mutation-free
3628
     *
3629
     * @return static
3630
     *                <p>Object with an underscored $str.</p>
3631
     */
3632 48
    public function underscored(): self
3633
    {
3634 48
        return $this->delimit('_');
3635
    }
3636
3637
    /**
3638
     * Returns an UpperCamelCase version of the supplied string. It trims
3639
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
3640
     * and underscores, and removes spaces, dashes, underscores.
3641
     *
3642
     * @psalm-mutation-free
3643
     *
3644
     * @return static
3645
     *                <p>Object with $str in UpperCamelCase.</p>
3646
     */
3647 39
    public function upperCamelize(): self
3648
    {
3649 39
        return static::create(
3650 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
3651 39
            $this->encoding
3652
        );
3653
    }
3654
3655
    /**
3656
     * Converts the first character of the supplied string to upper case.
3657
     *
3658
     * @psalm-mutation-free
3659
     *
3660
     * @return static
3661
     *                <p>Object with the first character of $str being upper case.</p>
3662
     */
3663 18
    public function upperCaseFirst(): self
3664
    {
3665 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
3666
    }
3667
3668
    /**
3669
     * Converts the string into an URL slug. This includes replacing non-ASCII
3670
     * characters with their closest ASCII equivalents, removing remaining
3671
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3672
     * $separator. The separator defaults to a single dash, and the string
3673
     * is also converted to lowercase.
3674
     *
3675
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
3676
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
3677
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
3678
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
3679
     *
3680
     * @psalm-mutation-free
3681
     *
3682
     * @return static
3683
     *                <p>Object whose $str has been converted to an URL slug.</p>
3684
     *
3685
     * @psalm-suppress ImpureMethodCall :/
3686
     */
3687 32
    public function urlify(
3688
        string $separator = '-',
3689
        string $language = 'en',
3690
        array $replacements = [],
3691
        bool $strToLower = true
3692
    ): self {
3693
        // init
3694 32
        $str = $this->str;
3695
3696 32
        foreach ($replacements as $from => $to) {
3697 32
            $str = \str_replace($from, $to, $str);
3698
        }
3699
3700 32
        return static::create(
3701 32
            URLify::slug(
3702 32
                $str,
3703 32
                $language,
3704 32
                $separator,
3705 32
                $strToLower
3706
            ),
3707 32
            $this->encoding
3708
        );
3709
    }
3710
3711
    /**
3712
     * Converts the string into an valid UTF-8 string.
3713
     *
3714
     * @psalm-mutation-free
3715
     *
3716
     * @return static
3717
     */
3718 2
    public function utf8ify(): self
3719
    {
3720 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
3721
    }
3722
3723
    /**
3724
     * Convert a string into an array of words.
3725
     *
3726
     * @param string   $char_list                [optional] <p>Additional chars for the definition of "words".</p>
3727
     * @param bool     $remove_empty_values      [optional] <p>Remove empty values.</p>
3728
     * @param int|null $remove_short_values      [optional] <p>The min. string length or null to disable</p>
3729
     * @param bool     $return_stingy_collection [optional] <p>Return a collection object.</p>
3730
     *
3731
     * @psalm-mutation-free
3732
     *
3733
     * @return CollectionStringy|static[]
3734
     *
3735
     * @psalm-return CollectionStringy<int,static>|array<int,static>
3736
     */
3737 2
    public function words(
3738
        string $char_list = '',
3739
        bool $remove_empty_values = false,
3740
        $remove_short_values = null,
3741
        bool $return_stingy_collection = false
3742
    ) {
3743
        /**
3744
         * @psalm-suppress DocblockTypeContradiction
3745
         */
3746 2
        if ($remove_short_values !== null && !\is_int($remove_short_values)) {
3747
            throw new \InvalidArgumentException(
3748
                'Passed value must be a null or int'
3749
            );
3750
        }
3751
3752 2
        if ($remove_short_values === null) {
3753 2
            $strings = $this->utf8::str_to_words(
3754 2
                $this->str,
3755 2
                $char_list,
3756 2
                $remove_empty_values
3757
            );
3758
        } else {
3759 2
            $strings = $this->utf8::str_to_words(
3760 2
                $this->str,
3761 2
                $char_list,
3762 2
                $remove_empty_values,
3763 2
                $remove_short_values
3764
            );
3765
        }
3766
3767
        /** @noinspection AlterInForeachInspection */
3768 2
        foreach ($strings as &$string) {
3769 2
            $string = static::create($string);
3770
        }
3771
3772
        /** @noinspection PhpSillyAssignmentInspection */
3773
        /** @var static[] $strings */
3774 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...
3775
3776 2
        if ($return_stingy_collection) {
3777
            /**
3778
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3779
             */
3780 2
            return CollectionStringy::create($strings);
3781
        }
3782
3783
        return $strings;
3784
    }
3785
3786
    /**
3787
     * Surrounds $str with the given substring.
3788
     *
3789
     * @param string $substring <p>The substring to add to both sides.</P>
3790
     *
3791
     * @psalm-mutation-free
3792
     *
3793
     * @return static
3794
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3795
     */
3796 10
    public function wrap(string $substring): self
3797
    {
3798 10
        return $this->surround($substring);
3799
    }
3800
3801
    /**
3802
     * Returns the replacements for the toAscii() method.
3803
     *
3804
     * @noinspection PhpUnused
3805
     *
3806
     * @psalm-mutation-free
3807
     *
3808
     * @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...
3809
     *                       <p>An array of replacements.</p>
3810
     *
3811
     * @deprecated   this is only here for backward-compatibly reasons
3812
     */
3813 1
    protected function charsArray(): array
3814
    {
3815 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
3816
    }
3817
3818
    /**
3819
     * Returns true if $str matches the supplied pattern, false otherwise.
3820
     *
3821
     * @param string $pattern <p>Regex pattern to match against.</p>
3822
     *
3823
     * @psalm-mutation-free
3824
     *
3825
     * @return bool
3826
     *              <p>Whether or not $str matches the pattern.</p>
3827
     */
3828 24
    protected function matchesPattern(string $pattern): bool
3829
    {
3830 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
3831
    }
3832
}
3833