Completed
Push — master ( 5c2d6c...5ef457 )
by Lars
01:39
created

Stringy::similarity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 6
ccs 3
cts 3
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 voku\helper\AntiXSS;
8
use voku\helper\ASCII;
9
use voku\helper\EmailCheck;
10
use voku\helper\URLify;
11
use voku\helper\UTF8;
12
13
/**
14
 * @template-implements \IteratorAggregate<string>
15
 * @template-implements \ArrayAccess<array-key,string>
16
 */
17
class Stringy implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
18
{
19
    /**
20
     * An instance's string.
21
     *
22
     * @var string
23
     */
24
    protected $str;
25
26
    /**
27
     * The string's encoding, which should be one of the mbstring module's
28
     * supported encodings.
29
     *
30
     * @var string
31
     */
32
    protected $encoding;
33
34
    /**
35
     * @var UTF8
36
     */
37
    private $utf8;
38
39
    /**
40
     * @var ASCII
41
     */
42
    private $ascii;
43
44
    /**
45
     * Initializes a Stringy object and assigns both str and encoding properties
46
     * the supplied values. $str is cast to a string prior to assignment, and if
47
     * $encoding is not specified, it defaults to mb_internal_encoding(). Throws
48
     * an InvalidArgumentException if the first argument is an array or object
49
     * without a __toString method.
50
     *
51
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
52
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
53
     *
54
     * @throws \InvalidArgumentException
55
     *                                   <p>if an array or object without a
56
     *                                   __toString method is passed as the first argument</p>
57
     *
58
     * @psalm-mutation-free
59
     */
60 3556
    public function __construct($str = '', string $encoding = null)
61
    {
62 3556
        if (\is_array($str)) {
63 3
            throw new \InvalidArgumentException(
64 3
                'Passed value cannot be an array'
65
            );
66
        }
67
68
        if (
69 3553
            \is_object($str)
70
            &&
71 3553
            !\method_exists($str, '__toString')
72
        ) {
73 3
            throw new \InvalidArgumentException(
74 3
                'Passed object must have a __toString method'
75
            );
76
        }
77
78 3550
        $this->str = (string) $str;
79
80 3550
        static $ASCII = null;
81 3550
        if ($ASCII === null) {
82
            $ASCII = new ASCII();
83
        }
84 3550
        $this->ascii = $ASCII;
85
86 3550
        static $UTF8 = null;
87 3550
        if ($UTF8 === null) {
88
            $UTF8 = new UTF8();
89
        }
90 3550
        $this->utf8 = $UTF8;
91
92 3550
        if ($encoding !== 'UTF-8') {
93 2380
            $this->encoding = $this->utf8::normalize_encoding($encoding, 'UTF-8');
94
        } else {
95 2650
            $this->encoding = $encoding;
96
        }
97 3550
    }
98
99
    /**
100
     * Returns the value in $str.
101
     *
102
     * @psalm-mutation-free
103
     *
104
     * @return string
105
     *                <p>The current value of the $str property.</p>
106
     */
107 1103
    public function __toString()
108
    {
109 1103
        return (string) $this->str;
110
    }
111
112
    /**
113
     * Gets the substring after the first occurrence of a separator.
114
     * If no match is found returns new empty Stringy object.
115
     *
116
     * @param string $separator
117
     *
118
     * @psalm-mutation-free
119
     *
120
     * @return static
121
     */
122 3
    public function afterFirst(string $separator): self
123
    {
124 3
        return static::create(
125 3
            $this->utf8::str_substr_after_first_separator(
126 3
                $this->str,
127 3
                $separator,
128 3
                $this->encoding
129
            )
130
        );
131
    }
132
133
    /**
134
     * Gets the substring after the first occurrence of a separator.
135
     * If no match is found returns new empty Stringy object.
136
     *
137
     * @param string $separator
138
     *
139
     * @psalm-mutation-free
140
     *
141
     * @return static
142
     */
143 2
    public function afterFirstIgnoreCase(string $separator): self
144
    {
145 2
        return static::create(
146 2
            $this->utf8::str_isubstr_after_first_separator(
147 2
                $this->str,
148 2
                $separator,
149 2
                $this->encoding
150
            )
151
        );
152
    }
153
154
    /**
155
     * Gets the substring after the last occurrence of a separator.
156
     * If no match is found returns new empty Stringy object.
157
     *
158
     * @param string $separator
159
     *
160
     * @psalm-mutation-free
161
     *
162
     * @return static
163
     */
164 2
    public function afterLast(string $separator): self
165
    {
166 2
        return static::create(
167 2
            $this->utf8::str_substr_after_last_separator(
168 2
                $this->str,
169 2
                $separator,
170 2
                $this->encoding
171
            )
172
        );
173
    }
174
175
    /**
176
     * Gets the substring after the last occurrence of a separator.
177
     * If no match is found returns new empty Stringy object.
178
     *
179
     * @param string $separator
180
     *
181
     * @psalm-mutation-free
182
     *
183
     * @return static
184
     */
185 2
    public function afterLastIgnoreCase(string $separator): self
186
    {
187 2
        return static::create(
188 2
            $this->utf8::str_isubstr_after_last_separator(
189 2
                $this->str,
190 2
                $separator,
191 2
                $this->encoding
192
            )
193
        );
194
    }
195
196
    /**
197
     * Returns a new string with $string appended.
198
     *
199
     * @param string ...$suffix <p>The string to append.</p>
200
     *
201
     * @psalm-mutation-free
202
     *
203
     * @return static
204
     *                <p>Object with appended $string.</p>
205
     *
206
     * @noinspection PhpDocSignatureInspection
207
     */
208 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...
209
    {
210 14
        if (\count($suffix) <= 1) {
211
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
212 13
            $suffix = $suffix[0];
213
        } else {
214
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
215 1
            $suffix = \implode('', $suffix);
216
        }
217
218 14
        return static::create($this->str . $suffix, $this->encoding);
219
    }
220
221
    /**
222
     * Append an password (limited to chars that are good readable).
223
     *
224
     * @param int $length <p>Length of the random string.</p>
225
     *
226
     * @return static
227
     *                <p>Object with appended password.</p>
228
     */
229 2
    public function appendPassword(int $length): self
230
    {
231 2
        return $this->appendRandomString(
232 2
            $length,
233 2
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
234
        );
235
    }
236
237
    /**
238
     * Append an random string.
239
     *
240
     * @param int    $length        <p>Length of the random string.</p>
241
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
242
     *
243
     * @return static
244
     *                <p>Object with appended random string.</p>
245
     */
246 4
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
247
    {
248 4
        $str = $this->utf8::get_random_string($length, $possibleChars);
249
250 4
        return $this->append($str);
251
    }
252
253
    /**
254
     * Append an unique identifier.
255
     *
256
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
257
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
258
     *
259
     * @return static
260
     *                <p>Object with appended unique identifier as md5-hash.</p>
261
     */
262 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
263
    {
264 2
        return $this->append(
265 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
266
        );
267
    }
268
269
    /**
270
     * @psalm-mutation-free
271
     *
272
     * @return static
273
     */
274 2
    public function md5(): self {
275 2
        return static::create($this->hash('md5'), $this->encoding);
276
    }
277
278
    /**
279
     * @psalm-mutation-free
280
     *
281
     * @return static
282
     */
283 2
    public function sha1(): self {
284 2
        return static::create($this->hash('sha1'), $this->encoding);
285
    }
286
287
    /**
288
     * @psalm-mutation-free
289
     *
290
     * @return static
291
     */
292 2
    public function sha256(): self {
293 2
        return static::create($this->hash('sha256'), $this->encoding);
294
    }
295
296
    /**
297
     * @psalm-mutation-free
298
     *
299
     * @return static
300
     */
301 2
    public function sha512(): self {
302 2
        return static::create($this->hash('sha512'), $this->encoding);
303
    }
304
305
    /**
306
     * @psalm-mutation-free
307
     *
308
     * @return int
309
     */
310 2
    public function crc32(): int {
311 2
        return crc32($this->str);
312
    }
313
314
    /**
315
     * Generate a hash value (message digest)
316
     *
317
     * @link https://php.net/manual/en/function.hash.php
318
     *
319
     * @param string $algorithm
320
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
321
     *
322
     * @psalm-mutation-free
323
     *
324
     * @return static
325
     */
326 8
    public function hash($algorithm): self {
327 8
        return static::create(hash($algorithm, $this->str), $this->encoding);
328
    }
329
330
    /**
331
     * Returns the character at $index, with indexes starting at 0.
332
     *
333
     * @param int $index <p>Position of the character.</p>
334
     *
335
     * @psalm-mutation-free
336
     *
337
     * @return static
338
     *                <p>The character at $index.</p>
339
     */
340 24
    public function at(int $index): self
341
    {
342 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
343
    }
344
345
    /**
346
     * Gets the substring before the first occurrence of a separator.
347
     * If no match is found returns new empty Stringy object.
348
     *
349
     * @param string $separator
350
     *
351
     * @psalm-mutation-free
352
     *
353
     * @return static
354
     */
355 2
    public function beforeFirst(string $separator): self
356
    {
357 2
        return static::create(
358 2
            $this->utf8::str_substr_before_first_separator(
359 2
                $this->str,
360 2
                $separator,
361 2
                $this->encoding
362
            )
363
        );
364
    }
365
366
    /**
367
     * Gets the substring before the first occurrence of a separator.
368
     * If no match is found returns new empty Stringy object.
369
     *
370
     * @param string $separator
371
     *
372
     * @psalm-mutation-free
373
     *
374
     * @return static
375
     */
376 2
    public function beforeFirstIgnoreCase(string $separator): self
377
    {
378 2
        return static::create(
379 2
            $this->utf8::str_isubstr_before_first_separator(
380 2
                $this->str,
381 2
                $separator,
382 2
                $this->encoding
383
            )
384
        );
385
    }
386
387
    /**
388
     * Gets the substring before the last occurrence of a separator.
389
     * If no match is found returns new empty Stringy object.
390
     *
391
     * @param string $separator
392
     *
393
     * @psalm-mutation-free
394
     *
395
     * @return static
396
     */
397 2
    public function beforeLast(string $separator): self
398
    {
399 2
        return static::create(
400 2
            $this->utf8::str_substr_before_last_separator(
401 2
                $this->str,
402 2
                $separator,
403 2
                $this->encoding
404
            )
405
        );
406
    }
407
408
    /**
409
     * Gets the substring before the last occurrence of a separator.
410
     * If no match is found returns new empty Stringy object.
411
     *
412
     * @param string $separator
413
     *
414
     * @psalm-mutation-free
415
     *
416
     * @return static
417
     */
418 2
    public function beforeLastIgnoreCase(string $separator): self
419
    {
420 2
        return static::create(
421 2
            $this->utf8::str_isubstr_before_last_separator(
422 2
                $this->str,
423 2
                $separator,
424 2
                $this->encoding
425
            )
426
        );
427
    }
428
429
    /**
430
     * Returns the substring between $start and $end, if found, or an empty
431
     * string. An optional offset may be supplied from which to begin the
432
     * search for the start string.
433
     *
434
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
435
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
436
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
437
     *
438
     * @psalm-mutation-free
439
     *
440
     * @return static
441
     *                <p>Object whose $str is a substring between $start and $end.</p>
442
     */
443 48
    public function between(string $start, string $end, int $offset = null): self
444
    {
445
        /** @noinspection UnnecessaryCastingInspection */
446 48
        $str = $this->utf8::between(
447 48
            $this->str,
448 48
            $start,
449 48
            $end,
450 48
            (int) $offset,
451 48
            $this->encoding
452
        );
453
454 48
        return static::create($str, $this->encoding);
455
    }
456
457
    /**
458
     * Returns a camelCase version of the string. Trims surrounding spaces,
459
     * capitalizes letters following digits, spaces, dashes and underscores,
460
     * and removes spaces, dashes, as well as underscores.
461
     *
462
     * @psalm-mutation-free
463
     *
464
     * @return static
465
     *                <p>Object with $str in camelCase.</p>
466
     */
467 57
    public function camelize(): self
468
    {
469 57
        return static::create(
470 57
            $this->utf8::str_camelize($this->str, $this->encoding),
471 57
            $this->encoding
472
        );
473
    }
474
475
    /**
476
     * Returns the string with the first letter of each word capitalized,
477
     * except for when the word is a name which shouldn't be capitalized.
478
     *
479
     * @psalm-mutation-free
480
     *
481
     * @return static
482
     *                <p>Object with $str capitalized.</p>
483
     */
484 78
    public function capitalizePersonalName(): self
485
    {
486 78
        return static::create(
487 78
            $this->utf8::str_capitalize_name($this->str),
488 78
            $this->encoding
489
        );
490
    }
491
492
    /**
493
     * Returns an array consisting of the characters in the string.
494
     *
495
     * @psalm-mutation-free
496
     *
497
     * @return string[]
498
     *                  <p>An array of string chars.</p>
499
     */
500 12
    public function chars(): array
501
    {
502 12
        return $this->utf8::str_split($this->str);
503
    }
504
505
    /**
506
     * Splits the string into chunks of Stringy objects.
507
     *
508
     * @param int $length
509
     *
510
     * @return CollectionStringy|static[]
511
     *                                    <p>An collection of Stringy objects.</p>
512
     *
513
     * @psalm-return CollectionStringy<int,static>
514
     */
515 10
    public function chunk(int $length = 1): CollectionStringy
516
    {
517 10
        if ($length < 1) {
518
            throw new \InvalidArgumentException('The chunk length must be greater than zero.');
519
        }
520
521 10
        if ($this->str === '') {
522
            /**
523
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
524
             */
525 2
            return CollectionStringy::create([]);
526
        }
527
528 8
        $chunks = $this->utf8::str_split($this->str, $length);
529 8
        foreach ($chunks as $i => &$value) {
530 8
            $value = static::create($value, $this->encoding);
531
        }
532
533
        /**
534
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
535
         */
536 8
        return CollectionStringy::create($chunks);
537
    }
538
539
    /**
540
     * Trims the string and replaces consecutive whitespace characters with a
541
     * single space. This includes tabs and newline characters, as well as
542
     * multibyte whitespace such as the thin space and ideographic space.
543
     *
544
     * @psalm-mutation-free
545
     *
546
     * @return static
547
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
548
     */
549 39
    public function collapseWhitespace(): self
550
    {
551 39
        return static::create(
552 39
            $this->utf8::collapse_whitespace($this->str),
553 39
            $this->encoding
554
        );
555
    }
556
557
    /**
558
     * Returns true if the string contains $needle, false otherwise. By default
559
     * the comparison is case-sensitive, but can be made insensitive by setting
560
     * $caseSensitive to false.
561
     *
562
     * @param string $needle        <p>Substring to look for.</p>
563
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
564
     *
565
     * @return bool
566
     *              <p>Whether or not $str contains $needle.</p>
567
     */
568 63
    public function contains(string $needle, bool $caseSensitive = true): bool
569
    {
570 63
        return $this->utf8::str_contains(
571 63
            $this->str,
572 63
            $needle,
573 63
            $caseSensitive
574
        );
575
    }
576
577
    /**
578
     * Returns true if the string contains all $needles, false otherwise. By
579
     * default the comparison is case-sensitive, but can be made insensitive by
580
     * setting $caseSensitive to false.
581
     *
582
     * @param string[] $needles       <p>SubStrings to look for.</p>
583
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
584
     *
585
     * @return bool
586
     *              <p>Whether or not $str contains $needle.</p>
587
     */
588 131
    public function containsAll(array $needles, bool $caseSensitive = true): bool
589
    {
590 131
        return $this->utf8::str_contains_all(
591 131
            $this->str,
592 131
            $needles,
593 131
            $caseSensitive
594
        );
595
    }
596
597
    /**
598
     * Get every nth character of the string.
599
     *
600
     * @param int $step   The number of characters to step
601
     * @param int $offset The string offset to start at
602
     *
603
     * @psalm-mutation-free
604
     *
605
     * @return static
606
     */
607 4
    public function nth(int $step, int $offset = 0): self
608
    {
609 4
        $length = $step - 1;
610 4
        $substring = $this->substr($offset)->toString();
611
612 4
        if ($substring === '') {
613
            return new static('', $this->encoding);
614
        }
615
616 4
        \preg_match_all(
617 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
618 4
            $substring,
619 4
            $matches
620
        );
621
622 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
623
    }
624
625
    /**
626
     * Returns true if the string contains any $needles, false otherwise. By
627
     * default the comparison is case-sensitive, but can be made insensitive by
628
     * setting $caseSensitive to false.
629
     *
630
     * @param string[] $needles       <p>SubStrings to look for.</p>
631
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
632
     *
633
     * @psalm-mutation-free
634
     *
635
     * @return bool
636
     *              <p>Whether or not $str contains $needle.</p>
637
     */
638 129
    public function containsAny(array $needles, bool $caseSensitive = true): bool
639
    {
640 129
        return $this->utf8::str_contains_any(
641 129
            $this->str,
642 129
            $needles,
643 129
            $caseSensitive
644
        );
645
    }
646
647
    /**
648
     * Returns the length of the string, implementing the countable interface.
649
     *
650
     * @psalm-mutation-free
651
     *
652
     * @return int
653
     *             <p>The number of characters in the string, given the encoding.</p>
654
     */
655 3
    public function count(): int
656
    {
657 3
        return $this->length();
658
    }
659
660
    /**
661
     * Returns the number of occurrences of $substring in the given string.
662
     * By default, the comparison is case-sensitive, but can be made insensitive
663
     * by setting $caseSensitive to false.
664
     *
665
     * @param string $substring     <p>The substring to search for.</p>
666
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
667
     *
668
     * @psalm-mutation-free
669
     *
670
     * @return int
671
     */
672 45
    public function countSubstr(string $substring, bool $caseSensitive = true): int
673
    {
674 45
        return $this->utf8::substr_count_simple(
675 45
            $this->str,
676 45
            $substring,
677 45
            $caseSensitive,
678 45
            $this->encoding
679
        );
680
    }
681
682
    /**
683
     * Creates a Stringy object and assigns both str and encoding properties
684
     * the supplied values. $str is cast to a string prior to assignment, and if
685
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
686
     * then returns the initialized object. Throws an InvalidArgumentException
687
     * if the first argument is an array or object without a __toString method.
688
     *
689
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
690
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
691
     *
692
     * @throws \InvalidArgumentException
693
     *                                   <p>if an array or object without a
694
     *                                   __toString method is passed as the first argument</p>
695
     *
696
     * @return static
697
     *                <p>A Stringy object.</p>
698
     *
699
     * @psalm-pure
700
     */
701 3522
    public static function create($str = '', string $encoding = null): self
702
    {
703 3522
        return new static($str, $encoding);
704
    }
705
706
    /**
707
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
708
     * inserted before uppercase characters (with the exception of the first
709
     * character of the string), and in place of spaces as well as underscores.
710
     *
711
     * @psalm-mutation-free
712
     *
713
     * @return static
714
     *                <p>Object with a dasherized $str</p>
715
     */
716 57
    public function dasherize(): self
717
    {
718 57
        return static::create(
719 57
            $this->utf8::str_dasherize($this->str),
720 57
            $this->encoding
721
        );
722
    }
723
724
    /**
725
     * Returns a lowercase and trimmed string separated by the given delimiter.
726
     * Delimiters are inserted before uppercase characters (with the exception
727
     * of the first character of the string), and in place of spaces, dashes,
728
     * and underscores. Alpha delimiters are not converted to lowercase.
729
     *
730
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
731
     *
732
     * @psalm-mutation-free
733
     *
734
     * @return static
735
     *                <p>Object with a delimited $str.</p>
736
     */
737 90
    public function delimit(string $delimiter): self
738
    {
739 90
        return static::create(
740 90
            $this->utf8::str_delimit($this->str, $delimiter),
741 90
            $this->encoding
742
        );
743
    }
744
745
    /**
746
     * Returns true if the string ends with $substring, false otherwise. By
747
     * default, the comparison is case-sensitive, but can be made insensitive
748
     * by setting $caseSensitive to false.
749
     *
750
     * @param string $substring     <p>The substring to look for.</p>
751
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
752
     *
753
     * @psalm-mutation-free
754
     *
755
     * @return bool
756
     *              <p>Whether or not $str ends with $substring.</p>
757
     */
758 97
    public function endsWith(string $substring, bool $caseSensitive = true): bool
759
    {
760 97
        if ($caseSensitive) {
761 53
            return $this->utf8::str_ends_with($this->str, $substring);
762
        }
763
764 44
        return $this->utf8::str_iends_with($this->str, $substring);
765
    }
766
767
    /**
768
     * Returns true if the string ends with any of $substrings, false otherwise.
769
     * By default, the comparison is case-sensitive, but can be made insensitive
770
     * by setting $caseSensitive to false.
771
     *
772
     * @param string[] $substrings    <p>Substrings to look for.</p>
773
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
774
     *
775
     * @psalm-mutation-free
776
     *
777
     * @return bool
778
     *              <p>Whether or not $str ends with $substring.</p>
779
     */
780 33
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
781
    {
782 33
        if ($caseSensitive) {
783 21
            return $this->utf8::str_ends_with_any($this->str, $substrings);
784
        }
785
786 12
        return $this->utf8::str_iends_with_any($this->str, $substrings);
787
    }
788
789
    /**
790
     * Ensures that the string begins with $substring. If it doesn't, it's
791
     * prepended.
792
     *
793
     * @param string $substring <p>The substring to add if not present.</p>
794
     *
795
     * @psalm-mutation-free
796
     *
797
     * @return static
798
     *                <p>Object with its $str prefixed by the $substring.</p>
799
     */
800 30
    public function ensureLeft(string $substring): self
801
    {
802 30
        return static::create(
803 30
            $this->utf8::str_ensure_left($this->str, $substring),
804 30
            $this->encoding
805
        );
806
    }
807
808
    /**
809
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
810
     *
811
     * @param string $substring <p>The substring to add if not present.</p>
812
     *
813
     * @psalm-mutation-free
814
     *
815
     * @return static
816
     *                <p>Object with its $str suffixed by the $substring.</p>
817
     */
818 30
    public function ensureRight(string $substring): self
819
    {
820 30
        return static::create(
821 30
            $this->utf8::str_ensure_right($this->str, $substring),
822 30
            $this->encoding
823
        );
824
    }
825
826
    /**
827
     * Create a escape html version of the string via "htmlspecialchars()".
828
     *
829
     * @psalm-mutation-free
830
     *
831
     * @return static
832
     */
833 12
    public function escape(): self
834
    {
835 12
        return static::create(
836 12
            $this->utf8::htmlspecialchars(
837 12
                $this->str,
838 12
                \ENT_QUOTES | \ENT_SUBSTITUTE,
839 12
                $this->encoding
840
            ),
841 12
            $this->encoding
842
        );
843
    }
844
845
    /**
846
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
847
     *
848
     * @param string   $search
849
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
850
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
851
     *
852
     * @psalm-mutation-free
853
     *
854
     * @return static
855
     */
856 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
857
    {
858 2
        return static::create(
859 2
            $this->utf8::extract_text(
860 2
                $this->str,
861 2
                $search,
862 2
                $length,
863 2
                $replacerForSkippedText,
864 2
                $this->encoding
865
            ),
866 2
            $this->encoding
867
        );
868
    }
869
870
    /**
871
     * Returns the first $n characters of the string.
872
     *
873
     * @param int $n <p>Number of characters to retrieve from the start.</p>
874
     *
875
     * @psalm-mutation-free
876
     *
877
     * @return static
878
     *                <p>Object with its $str being the first $n chars.</p>
879
     */
880 37
    public function first(int $n): self
881
    {
882 37
        return static::create(
883 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
884 37
            $this->encoding
885
        );
886
    }
887
888
    /**
889
     * Return a formatted string via sprintf + named parameters via array syntax.
890
     *
891
     * <p>
892
     * <br>
893
     * It will use "sprintf()" so you can use e.g.:
894
     * <br>
895
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
896
     * <br>
897
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
898
     * <br>
899
     * <br>
900
     * But you can also use named parameter via array syntax e.g.:
901
     * <br>
902
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
903
     * </p>
904
     *
905
     * @param mixed ...$args [optional]
906
     *
907
     * @psalm-mutation-free
908
     *
909
     * @return static
910
     *                <p>A Stringy object produced according to the formatting string
911
     *                format.</p>
912
     */
913 10
    public function format(...$args): self
914
    {
915
        // init
916 10
        $str = $this->str;
917
918 10
        if (\strpos($this->str, '%:') !== false) {
919 8
            $offset = null;
920 8
            $replacement = null;
921
            /** @noinspection AlterInForeachInspection */
922 8
            foreach ($args as $key => &$arg) {
923 8
                if (!\is_array($arg)) {
924 4
                    continue;
925
                }
926
927 8
                foreach ($arg as $name => $param) {
928 8
                    $name = (string) $name;
929
930 8
                    if (\strpos($name, '%:') !== 0) {
931 8
                        $nameTmp = '%:' . $name;
932
                    } else {
933
                        $nameTmp = $name;
934
                    }
935
936 8
                    if ($offset === null) {
937 8
                        $offset = \strpos($str, $nameTmp);
938
                    } else {
939 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
940
                    }
941 8
                    if ($offset === false) {
942 4
                        continue;
943
                    }
944
945 8
                    unset($arg[$name]);
946
947 8
                    $str = \substr_replace($str, $param, (int) $offset, \strlen($nameTmp));
948
                }
949
950 8
                unset($args[$key]);
951
            }
952
        }
953
954 10
        $str = \str_replace('%:', '%%:', $str);
955
956 10
        return static::create(
957 10
            \sprintf($str, ...$args),
958 10
            $this->encoding
959
        );
960
    }
961
962
    /**
963
     * Returns the encoding used by the Stringy object.
964
     *
965
     * @psalm-mutation-free
966
     *
967
     * @return string
968
     *                <p>The current value of the $encoding property.</p>
969
     */
970 7
    public function getEncoding(): string
971
    {
972 7
        return $this->encoding;
973
    }
974
975
    /**
976
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
977
     * interface. The ArrayIterator's constructor is passed an array of chars
978
     * in the multibyte string. This enables the use of foreach with instances
979
     * of Stringy\Stringy.
980
     *
981
     * @psalm-mutation-free
982
     *
983
     * @return \ArrayIterator
984
     *                        <p>An iterator for the characters in the string.</p>
985
     *
986
     * @psalm-return \ArrayIterator<array-key,string>
987
     */
988 3
    public function getIterator(): \ArrayIterator
989
    {
990 3
        return new \ArrayIterator($this->chars());
991
    }
992
993
    /**
994
     * Returns true if the string contains a lower case char, false otherwise.
995
     *
996
     * @psalm-mutation-free
997
     *
998
     * @return bool
999
     *              <p>Whether or not the string contains a lower case character.</p>
1000
     */
1001 36
    public function hasLowerCase(): bool
1002
    {
1003 36
        return $this->utf8::has_lowercase($this->str);
1004
    }
1005
1006
    /**
1007
     * Returns true if the string contains an upper case char, false otherwise.
1008
     *
1009
     * @psalm-mutation-free
1010
     *
1011
     * @return bool
1012
     *              <p>Whether or not the string contains an upper case character.</p>
1013
     */
1014 36
    public function hasUpperCase(): bool
1015
    {
1016 36
        return $this->utf8::has_uppercase($this->str);
1017
    }
1018
1019
    /**
1020
     * Convert all HTML entities to their applicable characters.
1021
     *
1022
     * @param int $flags [optional] <p>
1023
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1024
     *                   which document type to use. The default is ENT_COMPAT.
1025
     *                   <table>
1026
     *                   Available <i>flags</i> constants
1027
     *                   <tr valign="top">
1028
     *                   <td>Constant Name</td>
1029
     *                   <td>Description</td>
1030
     *                   </tr>
1031
     *                   <tr valign="top">
1032
     *                   <td><b>ENT_COMPAT</b></td>
1033
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1034
     *                   </tr>
1035
     *                   <tr valign="top">
1036
     *                   <td><b>ENT_QUOTES</b></td>
1037
     *                   <td>Will convert both double and single quotes.</td>
1038
     *                   </tr>
1039
     *                   <tr valign="top">
1040
     *                   <td><b>ENT_NOQUOTES</b></td>
1041
     *                   <td>Will leave both double and single quotes unconverted.</td>
1042
     *                   </tr>
1043
     *                   <tr valign="top">
1044
     *                   <td><b>ENT_HTML401</b></td>
1045
     *                   <td>
1046
     *                   Handle code as HTML 4.01.
1047
     *                   </td>
1048
     *                   </tr>
1049
     *                   <tr valign="top">
1050
     *                   <td><b>ENT_XML1</b></td>
1051
     *                   <td>
1052
     *                   Handle code as XML 1.
1053
     *                   </td>
1054
     *                   </tr>
1055
     *                   <tr valign="top">
1056
     *                   <td><b>ENT_XHTML</b></td>
1057
     *                   <td>
1058
     *                   Handle code as XHTML.
1059
     *                   </td>
1060
     *                   </tr>
1061
     *                   <tr valign="top">
1062
     *                   <td><b>ENT_HTML5</b></td>
1063
     *                   <td>
1064
     *                   Handle code as HTML 5.
1065
     *                   </td>
1066
     *                   </tr>
1067
     *                   </table>
1068
     *                   </p>
1069
     *
1070
     * @psalm-mutation-free
1071
     *
1072
     * @return static
1073
     *                <p>Object with the resulting $str after being html decoded.</p>
1074
     */
1075 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...
1076
    {
1077 15
        return static::create(
1078 15
            $this->utf8::html_entity_decode(
1079 15
                $this->str,
1080 15
                $flags,
1081 15
                $this->encoding
1082
            ),
1083 15
            $this->encoding
1084
        );
1085
    }
1086
1087
    /**
1088
     * Convert all applicable characters to HTML entities.
1089
     *
1090
     * @param int $flags [optional] <p>
1091
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1092
     *                   which document type to use. The default is ENT_COMPAT.
1093
     *                   <table>
1094
     *                   Available <i>flags</i> constants
1095
     *                   <tr valign="top">
1096
     *                   <td>Constant Name</td>
1097
     *                   <td>Description</td>
1098
     *                   </tr>
1099
     *                   <tr valign="top">
1100
     *                   <td><b>ENT_COMPAT</b></td>
1101
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1102
     *                   </tr>
1103
     *                   <tr valign="top">
1104
     *                   <td><b>ENT_QUOTES</b></td>
1105
     *                   <td>Will convert both double and single quotes.</td>
1106
     *                   </tr>
1107
     *                   <tr valign="top">
1108
     *                   <td><b>ENT_NOQUOTES</b></td>
1109
     *                   <td>Will leave both double and single quotes unconverted.</td>
1110
     *                   </tr>
1111
     *                   <tr valign="top">
1112
     *                   <td><b>ENT_HTML401</b></td>
1113
     *                   <td>
1114
     *                   Handle code as HTML 4.01.
1115
     *                   </td>
1116
     *                   </tr>
1117
     *                   <tr valign="top">
1118
     *                   <td><b>ENT_XML1</b></td>
1119
     *                   <td>
1120
     *                   Handle code as XML 1.
1121
     *                   </td>
1122
     *                   </tr>
1123
     *                   <tr valign="top">
1124
     *                   <td><b>ENT_XHTML</b></td>
1125
     *                   <td>
1126
     *                   Handle code as XHTML.
1127
     *                   </td>
1128
     *                   </tr>
1129
     *                   <tr valign="top">
1130
     *                   <td><b>ENT_HTML5</b></td>
1131
     *                   <td>
1132
     *                   Handle code as HTML 5.
1133
     *                   </td>
1134
     *                   </tr>
1135
     *                   </table>
1136
     *                   </p>
1137
     *
1138
     * @psalm-mutation-free
1139
     *
1140
     * @return static
1141
     *                <p>Object with the resulting $str after being html encoded.</p>
1142
     */
1143 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...
1144
    {
1145 15
        return static::create(
1146 15
            $this->utf8::htmlentities(
1147 15
                $this->str,
1148 15
                $flags,
1149 15
                $this->encoding
1150
            ),
1151 15
            $this->encoding
1152
        );
1153
    }
1154
1155
    /**
1156
     * Capitalizes the first word of the string, replaces underscores with
1157
     * spaces, and strips '_id'.
1158
     *
1159
     * @psalm-mutation-free
1160
     *
1161
     * @return static
1162
     *                <p>Object with a humanized $str.</p>
1163
     */
1164 9
    public function humanize(): self
1165
    {
1166 9
        return static::create(
1167 9
            $this->utf8::str_humanize($this->str),
1168 9
            $this->encoding
1169
        );
1170
    }
1171
1172
    /**
1173
     * Returns the index of the first occurrence of $needle in the string,
1174
     * and false if not found. Accepts an optional offset from which to begin
1175
     * the search.
1176
     *
1177
     * @param string $needle <p>Substring to look for.</p>
1178
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1179
     *
1180
     * @psalm-mutation-free
1181
     *
1182
     * @return false|int
1183
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1184
     */
1185 31
    public function indexOf(string $needle, int $offset = 0)
1186
    {
1187 31
        return $this->utf8::strpos(
1188 31
            $this->str,
1189 31
            $needle,
1190 31
            $offset,
1191 31
            $this->encoding
1192
        );
1193
    }
1194
1195
    /**
1196
     * Returns the index of the first occurrence of $needle in the string,
1197
     * and false if not found. Accepts an optional offset from which to begin
1198
     * the search.
1199
     *
1200
     * @param string $needle <p>Substring to look for.</p>
1201
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1202
     *
1203
     * @psalm-mutation-free
1204
     *
1205
     * @return false|int
1206
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1207
     */
1208 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1209
    {
1210 20
        return $this->utf8::stripos(
1211 20
            $this->str,
1212 20
            $needle,
1213 20
            $offset,
1214 20
            $this->encoding
1215
        );
1216
    }
1217
1218
    /**
1219
     * Returns the index of the last occurrence of $needle in the string,
1220
     * and false if not found. Accepts an optional offset from which to begin
1221
     * the search. Offsets may be negative to count from the last character
1222
     * in the string.
1223
     *
1224
     * @param string $needle <p>Substring to look for.</p>
1225
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1226
     *
1227
     * @psalm-mutation-free
1228
     *
1229
     * @return false|int
1230
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1231
     */
1232 31
    public function indexOfLast(string $needle, int $offset = 0)
1233
    {
1234 31
        return $this->utf8::strrpos(
1235 31
            $this->str,
1236 31
            $needle,
1237 31
            $offset,
1238 31
            $this->encoding
1239
        );
1240
    }
1241
1242
    /**
1243
     * Returns the index of the last occurrence of $needle in the string,
1244
     * and false if not found. Accepts an optional offset from which to begin
1245
     * the search. Offsets may be negative to count from the last character
1246
     * in the string.
1247
     *
1248
     * @param string $needle <p>Substring to look for.</p>
1249
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1250
     *
1251
     * @psalm-mutation-free
1252
     *
1253
     * @return false|int
1254
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1255
     */
1256 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1257
    {
1258 20
        return $this->utf8::strripos(
1259 20
            $this->str,
1260 20
            $needle,
1261 20
            $offset,
1262 20
            $this->encoding
1263
        );
1264
    }
1265
1266
    /**
1267
     * Inserts $substring into the string at the $index provided.
1268
     *
1269
     * @param string $substring <p>String to be inserted.</p>
1270
     * @param int    $index     <p>The index at which to insert the substring.</p>
1271
     *
1272
     * @psalm-mutation-free
1273
     *
1274
     * @return static
1275
     *                <p>Object with the resulting $str after the insertion.</p>
1276
     */
1277 24
    public function insert(string $substring, int $index): self
1278
    {
1279 24
        return static::create(
1280 24
            $this->utf8::str_insert(
1281 24
                $this->str,
1282 24
                $substring,
1283 24
                $index,
1284 24
                $this->encoding
1285
            ),
1286 24
            $this->encoding
1287
        );
1288
    }
1289
1290
    /**
1291
     * Returns true if the string contains the $pattern, otherwise false.
1292
     *
1293
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1294
     * expression wildcards.
1295
     *
1296
     * @credit Originally from Laravel, thanks Taylor.
1297
     *
1298
     * @param string $pattern <p>The string or pattern to match against.</p>
1299
     *
1300
     * @psalm-mutation-free
1301
     *
1302
     * @return bool
1303
     *              <p>Whether or not we match the provided pattern.</p>
1304
     */
1305 26
    public function is(string $pattern): bool
1306
    {
1307 26
        if ($this->toString() === $pattern) {
1308 2
            return true;
1309
        }
1310
1311 24
        $quotedPattern = \preg_quote($pattern, '/');
1312 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1313
1314 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1315
    }
1316
1317
    /**
1318
     * Returns true if the string contains only alphabetic chars, false otherwise.
1319
     *
1320
     * @psalm-mutation-free
1321
     *
1322
     * @return bool
1323
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1324
     */
1325 30
    public function isAlpha(): bool
1326
    {
1327 30
        return $this->utf8::is_alpha($this->str);
1328
    }
1329
1330
    /**
1331
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1332
     *
1333
     * @psalm-mutation-free
1334
     *
1335
     * @return bool
1336
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1337
     */
1338 39
    public function isAlphanumeric(): bool
1339
    {
1340 39
        return $this->utf8::is_alphanumeric($this->str);
1341
    }
1342
1343
    /**
1344
     * Returns true if the string is base64 encoded, false otherwise.
1345
     *
1346
     * @param bool $emptyStringIsValid
1347
     *
1348
     * @psalm-mutation-free
1349
     *
1350
     * @return bool
1351
     *              <p>Whether or not $str is base64 encoded.</p>
1352
     */
1353 21
    public function isBase64($emptyStringIsValid = true): bool
1354
    {
1355 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
1356
    }
1357
1358
    /**
1359
     * Returns true if the string contains only whitespace chars, false otherwise.
1360
     *
1361
     * @psalm-mutation-free
1362
     *
1363
     * @return bool
1364
     *              <p>Whether or not $str contains only whitespace characters.</p>
1365
     */
1366 45
    public function isBlank(): bool
1367
    {
1368 45
        return $this->utf8::is_blank($this->str);
1369
    }
1370
1371
    /**
1372
     * Returns true if the string contains a valid E-Mail address, false otherwise.
1373
     *
1374
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
1375
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
1376
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
1377
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
1378
     *
1379
     * @psalm-mutation-free
1380
     *
1381
     * @return bool
1382
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
1383
     */
1384 2
    public function isEmail(bool $useExampleDomainCheck = false, bool $useTypoInDomainCheck = false, bool $useTemporaryDomainCheck = false, bool $useDnsCheck = false): bool
1385
    {
1386
        /**
1387
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
1388
         */
1389 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
1390
    }
1391
1392
    /**
1393
     * Determine whether the string is considered to be empty.
1394
     *
1395
     * A variable is considered empty if it does not exist or if its value equals FALSE.
1396
     *
1397
     * @psalm-mutation-free
1398
     *
1399
     * @return bool
1400
     *              <p>Whether or not $str is empty().</p>
1401
     */
1402 10
    public function isEmpty(): bool
1403
    {
1404 10
        return $this->utf8::is_empty($this->str);
1405
    }
1406
1407
    /**
1408
     * Determine whether the string is equals to $str.
1409
     *
1410
     * @param string|Stringy ...$str <p>The string to compare.</p>
1411
     *
1412
     * @psalm-mutation-free
1413
     *
1414
     * @return bool
1415
     *              <p>Whether or not $str is equals.</p>
1416
     */
1417 16
    public function isEquals(...$str): bool
1418
    {
1419 16
        foreach ($str as $strTmp) {
1420
            /**
1421
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1422
             */
1423 16
            if ($strTmp instanceof self) {
1424 2
                if ($this->str !== $strTmp->str) {
1425 2
                    return false;
1426
                }
1427 14
            } elseif (\is_string($strTmp)) {
1428 8
                if ($this->str !== $strTmp) {
1429 8
                    return false;
1430
                }
1431
            } else {
1432 6
                return false;
1433
            }
1434
        }
1435
1436 3
        return true;
1437
    }
1438
1439
    /**
1440
     * Returns true if the string contains only hexadecimal chars, false otherwise.
1441
     *
1442
     * @psalm-mutation-free
1443
     *
1444
     * @return bool
1445
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
1446
     */
1447 39
    public function isHexadecimal(): bool
1448
    {
1449 39
        return $this->utf8::is_hexadecimal($this->str);
1450
    }
1451
1452
    /**
1453
     * Returns true if the string contains HTML-Tags, false otherwise.
1454
     *
1455
     * @psalm-mutation-free
1456
     *
1457
     * @return bool
1458
     *              <p>Whether or not $str contains HTML-Tags.</p>
1459
     */
1460 2
    public function isHtml(): bool
1461
    {
1462 2
        return $this->utf8::is_html($this->str);
1463
    }
1464
1465
    /**
1466
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
1467
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
1468
     * in that an empty string is not considered valid JSON.
1469
     *
1470
     * @param bool $onlyArrayOrObjectResultsAreValid
1471
     *
1472
     * @return bool
1473
     *              <p>Whether or not $str is JSON.</p>
1474
     */
1475 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
1476
    {
1477 60
        return $this->utf8::is_json(
1478 60
            $this->str,
1479 60
            $onlyArrayOrObjectResultsAreValid
1480
        );
1481
    }
1482
1483
    /**
1484
     * Returns true if the string contains only lower case chars, false otherwise.
1485
     *
1486
     * @psalm-mutation-free
1487
     *
1488
     * @return bool
1489
     *              <p>Whether or not $str contains only lower case characters.</p>
1490
     */
1491 24
    public function isLowerCase(): bool
1492
    {
1493 24
        return $this->utf8::is_lowercase($this->str);
1494
    }
1495
1496
    /**
1497
     * Determine whether the string is considered to be NOT empty.
1498
     *
1499
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
1500
     *
1501
     * @psalm-mutation-free
1502
     *
1503
     * @return bool
1504
     *              <p>Whether or not $str is empty().</p>
1505
     */
1506 10
    public function isNotEmpty(): bool
1507
    {
1508 10
        return !$this->utf8::is_empty($this->str);
1509
    }
1510
1511
    /**
1512
     * Returns true if the string is serialized, false otherwise.
1513
     *
1514
     * @psalm-mutation-free
1515
     *
1516
     * @return bool
1517
     *              <p>Whether or not $str is serialized.</p>
1518
     */
1519 21
    public function isSerialized(): bool
1520
    {
1521 21
        return $this->utf8::is_serialized($this->str);
1522
    }
1523
1524
    /**
1525
     * Returns true if the string contains only lower case chars, false
1526
     * otherwise.
1527
     *
1528
     * @psalm-mutation-free
1529
     *
1530
     * @return bool
1531
     *              <p>Whether or not $str contains only lower case characters.</p>
1532
     */
1533 24
    public function isUpperCase(): bool
1534
    {
1535 24
        return $this->utf8::is_uppercase($this->str);
1536
    }
1537
1538
    /**
1539
     * Returns true if the string contains only whitespace chars, false otherwise.
1540
     *
1541
     * @psalm-mutation-free
1542
     *
1543
     * @return bool
1544
     *              <p>Whether or not $str contains only whitespace characters.</p>
1545
     */
1546 30
    public function isWhitespace(): bool
1547
    {
1548 30
        return $this->isBlank();
1549
    }
1550
1551
    /**
1552
     * Calculate the similarity between two strings.
1553
     *
1554
     * @param string $str
1555
     *
1556
     * @psalm-mutation-free
1557
     *
1558
     * @return float
1559
     */
1560 2
    public function similarity(string $str): float
1561
    {
1562 2
        \similar_text($this->str, $str, $percent);
1563
1564 2
        return $percent;
1565
    }
1566
1567
    /**
1568
     * Check if two strings are similar.
1569
     *
1570
     * @param string $str
1571
     * @param float  $minPercentForSimilarity
1572
     *
1573
     * @psalm-mutation-free
1574
     *
1575
     * @return bool
1576
     */
1577 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
1578
    {
1579 2
        return $this->similarity($str) >= $minPercentForSimilarity;
1580
    }
1581
1582
    /**
1583
     * Returns value which can be serialized by json_encode().
1584
     *
1585
     * @noinspection ReturnTypeCanBeDeclaredInspection
1586
     *
1587
     * @psalm-mutation-free
1588
     *
1589
     * @return string The current value of the $str property
1590
     */
1591 2
    public function jsonSerialize()
1592
    {
1593 2
        return (string) $this;
1594
    }
1595
1596
    /**
1597
     * Returns the last $n characters of the string.
1598
     *
1599
     * @param int $n <p>Number of characters to retrieve from the end.</p>
1600
     *
1601
     * @psalm-mutation-free
1602
     *
1603
     * @return static
1604
     *                <p>Object with its $str being the last $n chars.</p>
1605
     */
1606 36
    public function last(int $n): self
1607
    {
1608 36
        return static::create(
1609 36
            $this->utf8::str_last_char(
1610 36
                $this->str,
1611 36
                $n,
1612 36
                $this->encoding
1613
            ),
1614 36
            $this->encoding
1615
        );
1616
    }
1617
1618
    /**
1619
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1620
     * If no match is found returns new empty Stringy object.
1621
     *
1622
     * @param string $needle       <p>The string to look for.</p>
1623
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1624
     *
1625
     * @psalm-mutation-free
1626
     *
1627
     * @return static
1628
     */
1629 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...
1630
    {
1631 4
        return static::create(
1632 4
            $this->utf8::str_substr_last(
1633 4
                $this->str,
1634 4
                $needle,
1635 4
                $beforeNeedle,
1636 4
                $this->encoding
1637
            ),
1638 4
            $this->encoding
1639
        );
1640
    }
1641
1642
    /**
1643
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1644
     * If no match is found returns new empty Stringy object.
1645
     *
1646
     * @param string $needle       <p>The string to look for.</p>
1647
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1648
     *
1649
     * @psalm-mutation-free
1650
     *
1651
     * @return static
1652
     */
1653 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...
1654
    {
1655 2
        return static::create(
1656 2
            $this->utf8::str_isubstr_last(
1657 2
                $this->str,
1658 2
                $needle,
1659 2
                $beforeNeedle,
1660 2
                $this->encoding
1661
            ),
1662 2
            $this->encoding
1663
        );
1664
    }
1665
1666
    /**
1667
     * Returns the length of the string.
1668
     *
1669
     * @psalm-mutation-free
1670
     *
1671
     * @return int
1672
     *             <p>The number of characters in $str given the encoding.</p>
1673
     */
1674 17
    public function length(): int
1675
    {
1676 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
1677
    }
1678
1679
    /**
1680
     * Line-Wrap the string after $limit, but also after the next word.
1681
     *
1682
     * @param int $limit
1683
     *
1684
     * @psalm-mutation-free
1685
     *
1686
     * @return static
1687
     */
1688 2
    public function lineWrapAfterWord(int $limit): self
1689
    {
1690 2
        return static::create(
1691 2
            $this->utf8::wordwrap_per_line($this->str, $limit),
1692 2
            $this->encoding
1693
        );
1694
    }
1695
1696
    /**
1697
     * Splits on newlines and carriage returns, returning an array of Stringy
1698
     * objects corresponding to the lines in the string.
1699
     *
1700
     * @psalm-mutation-free
1701
     *
1702
     * @return CollectionStringy|static[]
1703
     *                                    <p>An collection of Stringy objects.</p>
1704
     *
1705
     * @psalm-return CollectionStringy<int,static>
1706
     */
1707 51
    public function lines(): CollectionStringy
1708
    {
1709 51
        $array = $this->utf8::str_to_lines($this->str);
1710
        /** @noinspection AlterInForeachInspection */
1711 51
        foreach ($array as $i => &$value) {
1712 51
            $value = static::create($value, $this->encoding);
1713
        }
1714
1715
        /** @noinspection PhpSillyAssignmentInspection */
1716
        /** @var static[] $array */
1717 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...
1718
1719
        /**
1720
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
1721
         */
1722 51
        return CollectionStringy::create($array);
1723
    }
1724
1725
    /**
1726
     * Returns the longest common prefix between the string and $otherStr.
1727
     *
1728
     * @param string $otherStr <p>Second string for comparison.</p>
1729
     *
1730
     * @psalm-mutation-free
1731
     *
1732
     * @return static
1733
     *                <p>Object with its $str being the longest common prefix.</p>
1734
     */
1735 30
    public function longestCommonPrefix(string $otherStr): self
1736
    {
1737 30
        return static::create(
1738 30
            $this->utf8::str_longest_common_prefix(
1739 30
                $this->str,
1740 30
                $otherStr,
1741 30
                $this->encoding
1742
            ),
1743 30
            $this->encoding
1744
        );
1745
    }
1746
1747
    /**
1748
     * Returns the longest common substring between the string and $otherStr.
1749
     * In the case of ties, it returns that which occurs first.
1750
     *
1751
     * @param string $otherStr <p>Second string for comparison.</p>
1752
     *
1753
     * @psalm-mutation-free
1754
     *
1755
     * @return static
1756
     *                <p>Object with its $str being the longest common substring.</p>
1757
     */
1758 30
    public function longestCommonSubstring(string $otherStr): self
1759
    {
1760 30
        return static::create(
1761 30
            $this->utf8::str_longest_common_substring(
1762 30
                $this->str,
1763 30
                $otherStr,
1764 30
                $this->encoding
1765
            ),
1766 30
            $this->encoding
1767
        );
1768
    }
1769
1770
    /**
1771
     * Returns the longest common suffix between the string and $otherStr.
1772
     *
1773
     * @param string $otherStr <p>Second string for comparison.</p>
1774
     *
1775
     * @psalm-mutation-free
1776
     *
1777
     * @return static
1778
     *                <p>Object with its $str being the longest common suffix.</p>
1779
     */
1780 30
    public function longestCommonSuffix(string $otherStr): self
1781
    {
1782 30
        return static::create(
1783 30
            $this->utf8::str_longest_common_suffix(
1784 30
                $this->str,
1785 30
                $otherStr,
1786 30
                $this->encoding
1787
            ),
1788 30
            $this->encoding
1789
        );
1790
    }
1791
1792
    /**
1793
     * Converts the first character of the string to lower case.
1794
     *
1795
     * @psalm-mutation-free
1796
     *
1797
     * @return static
1798
     *                <p>Object with the first character of $str being lower case.</p>
1799
     */
1800 15
    public function lowerCaseFirst(): self
1801
    {
1802 15
        return static::create(
1803 15
            $this->utf8::lcfirst($this->str, $this->encoding),
1804 15
            $this->encoding
1805
        );
1806
    }
1807
1808
    /**
1809
     * Returns whether or not a character exists at an index. Offsets may be
1810
     * negative to count from the last character in the string. Implements
1811
     * part of the ArrayAccess interface.
1812
     *
1813
     * @param int $offset <p>The index to check.</p>
1814
     *
1815
     * @psalm-mutation-free
1816
     *
1817
     * @return bool
1818
     *              <p>Whether or not the index exists.</p>
1819
     */
1820 18
    public function offsetExists($offset): bool
1821
    {
1822 18
        return $this->utf8::str_offset_exists(
1823 18
            $this->str,
1824 18
            $offset,
1825 18
            $this->encoding
1826
        );
1827
    }
1828
1829
    /**
1830
     * Returns the character at the given index. Offsets may be negative to
1831
     * count from the last character in the string. Implements part of the
1832
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
1833
     * does not exist.
1834
     *
1835
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
1836
     *
1837
     * @throws \OutOfBoundsException
1838
     *                               <p>If the positive or negative offset does not exist.</p>
1839
     *
1840
     * @psalm-mutation-free
1841
     *
1842
     * @return string
1843
     *                <p>The character at the specified index.</p>
1844
     */
1845 6
    public function offsetGet($offset): string
1846
    {
1847 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
1848
    }
1849
1850
    /**
1851
     * Implements part of the ArrayAccess interface, but throws an exception
1852
     * when called. This maintains the immutability of Stringy objects.
1853
     *
1854
     * @param int   $offset <p>The index of the character.</p>
1855
     * @param mixed $value  <p>Value to set.</p>
1856
     *
1857
     * @throws \Exception
1858
     *                    <p>When called.</p>
1859
     *
1860
     * @return void
1861
     */
1862 3
    public function offsetSet($offset, $value)
1863
    {
1864
        // Stringy is immutable, cannot directly set char
1865
        /** @noinspection ThrowRawExceptionInspection */
1866 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
1867
    }
1868
1869
    /**
1870
     * Implements part of the ArrayAccess interface, but throws an exception
1871
     * when called. This maintains the immutability of Stringy objects.
1872
     *
1873
     * @param int $offset <p>The index of the character.</p>
1874
     *
1875
     * @throws \Exception
1876
     *                    <p>When called.</p>
1877
     *
1878
     * @return void
1879
     */
1880 3
    public function offsetUnset($offset)
1881
    {
1882
        // Don't allow directly modifying the string
1883
        /** @noinspection ThrowRawExceptionInspection */
1884 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
1885
    }
1886
1887
    /**
1888
     * Pads the string to a given length with $padStr. If length is less than
1889
     * or equal to the length of the string, no padding takes places. The
1890
     * default string used for padding is a space, and the default type (one of
1891
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
1892
     * if $padType isn't one of those 3 values.
1893
     *
1894
     * @param int    $length  <p>Desired string length after padding.</p>
1895
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1896
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
1897
     *
1898
     * @throws \InvalidArgumentException
1899
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
1900
     *
1901
     * @psalm-mutation-free
1902
     *
1903
     * @return static
1904
     *                <p>Object with a padded $str.</p>
1905
     *
1906
     * @psalm-mutation-free
1907
     */
1908 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
1909
    {
1910 39
        return static::create(
1911 39
            $this->utf8::str_pad(
1912 39
                $this->str,
1913 39
                $length,
1914 39
                $padStr,
1915 39
                $padType,
1916 39
                $this->encoding
1917
            )
1918
        );
1919
    }
1920
1921
    /**
1922
     * Returns a new string of a given length such that both sides of the
1923
     * string are padded. Alias for pad() with a $padType of 'both'.
1924
     *
1925
     * @param int    $length <p>Desired string length after padding.</p>
1926
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1927
     *
1928
     * @psalm-mutation-free
1929
     *
1930
     * @return static
1931
     *                <p>String with padding applied.</p>
1932
     */
1933 33
    public function padBoth(int $length, string $padStr = ' '): self
1934
    {
1935 33
        return static::create(
1936 33
            $this->utf8::str_pad_both(
1937 33
                $this->str,
1938 33
                $length,
1939 33
                $padStr,
1940 33
                $this->encoding
1941
            )
1942
        );
1943
    }
1944
1945
    /**
1946
     * Returns a new string of a given length such that the beginning of the
1947
     * string is padded. Alias for pad() with a $padType of 'left'.
1948
     *
1949
     * @param int    $length <p>Desired string length after padding.</p>
1950
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1951
     *
1952
     * @psalm-mutation-free
1953
     *
1954
     * @return static
1955
     *                <p>String with left padding.</p>
1956
     */
1957 21
    public function padLeft(int $length, string $padStr = ' '): self
1958
    {
1959 21
        return static::create(
1960 21
            $this->utf8::str_pad_left(
1961 21
                $this->str,
1962 21
                $length,
1963 21
                $padStr,
1964 21
                $this->encoding
1965
            )
1966
        );
1967
    }
1968
1969
    /**
1970
     * Returns a new string of a given length such that the end of the string
1971
     * is padded. Alias for pad() with a $padType of 'right'.
1972
     *
1973
     * @param int    $length <p>Desired string length after padding.</p>
1974
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1975
     *
1976
     * @psalm-mutation-free
1977
     *
1978
     * @return static
1979
     *                <p>String with right padding.</p>
1980
     */
1981 21
    public function padRight(int $length, string $padStr = ' '): self
1982
    {
1983 21
        return static::create(
1984 21
            $this->utf8::str_pad_right(
1985 21
                $this->str,
1986 21
                $length,
1987 21
                $padStr,
1988 21
                $this->encoding
1989
            )
1990
        );
1991
    }
1992
1993
    /**
1994
     * Returns a new string starting with $string.
1995
     *
1996
     * @param string ...$prefix <p>The string to append.</p>
1997
     *
1998
     * @psalm-mutation-free
1999
     *
2000
     * @return static
2001
     *                <p>Object with appended $string.</p>
2002
     *
2003
     * @noinspection PhpDocSignatureInspection
2004
     */
2005 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...
2006
    {
2007 7
        if (\count($prefix) <= 1) {
2008
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2009 6
            $prefix = $prefix[0];
2010
        } else {
2011
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2012 1
            $prefix = \implode('', $prefix);
2013
        }
2014
2015 7
        return static::create($prefix . $this->str, $this->encoding);
2016
    }
2017
2018
    /**
2019
     * Replaces all occurrences of $pattern in $str by $replacement.
2020
     *
2021
     * @param string $pattern     <p>The regular expression pattern.</p>
2022
     * @param string $replacement <p>The string to replace with.</p>
2023
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2024
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2025
     *
2026
     * @psalm-mutation-free
2027
     *
2028
     * @return static
2029
     *                <p>Object with the result2ing $str after the replacements.</p>
2030
     */
2031 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2032
    {
2033 29
        return static::create(
2034 29
            $this->utf8::regex_replace(
2035 29
                $this->str,
2036 29
                $pattern,
2037 29
                $replacement,
2038 29
                $options,
2039 29
                $delimiter
2040
            ),
2041 29
            $this->encoding
2042
        );
2043
    }
2044
2045
    /**
2046
     * Remove html via "strip_tags()" from the string.
2047
     *
2048
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2049
     *                              not be stripped. Default: null
2050
     *                              </p>
2051
     *
2052
     * @psalm-mutation-free
2053
     *
2054
     * @return static
2055
     */
2056 12
    public function removeHtml(string $allowableTags = ''): self
2057
    {
2058 12
        return static::create(
2059 12
            $this->utf8::remove_html($this->str, $allowableTags),
2060 12
            $this->encoding
2061
        );
2062
    }
2063
2064
    /**
2065
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2066
     *
2067
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2068
     *
2069
     * @psalm-mutation-free
2070
     *
2071
     * @return static
2072
     */
2073 12
    public function removeHtmlBreak(string $replacement = ''): self
2074
    {
2075 12
        return static::create(
2076 12
            $this->utf8::remove_html_breaks($this->str, $replacement),
2077 12
            $this->encoding
2078
        );
2079
    }
2080
2081
    /**
2082
     * Returns a new string with the prefix $substring removed, if present.
2083
     *
2084
     * @param string $substring <p>The prefix to remove.</p>
2085
     *
2086
     * @psalm-mutation-free
2087
     *
2088
     * @return static
2089
     *                <p>Object having a $str without the prefix $substring.</p>
2090
     */
2091 36
    public function removeLeft(string $substring): self
2092
    {
2093 36
        return static::create(
2094 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2095 36
            $this->encoding
2096
        );
2097
    }
2098
2099
    /**
2100
     * Returns a new string with the suffix $substring removed, if present.
2101
     *
2102
     * @param string $substring <p>The suffix to remove.</p>
2103
     *
2104
     * @psalm-mutation-free
2105
     *
2106
     * @return static
2107
     *                <p>Object having a $str without the suffix $substring.</p>
2108
     */
2109 36
    public function removeRight(string $substring): self
2110
    {
2111 36
        return static::create(
2112 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2113 36
            $this->encoding
2114
        );
2115
    }
2116
2117
    /**
2118
     * Try to remove all XSS-attacks from the string.
2119
     *
2120
     * @psalm-mutation-free
2121
     *
2122
     * @return static
2123
     */
2124 12
    public function removeXss(): self
2125
    {
2126
        /**
2127
         * @var AntiXSS|null
2128
         *
2129
         * @psalm-suppress ImpureStaticVariable
2130
         */
2131 12
        static $antiXss = null;
2132
2133 12
        if ($antiXss === null) {
2134 1
            $antiXss = new AntiXSS();
2135
        }
2136
2137
        /**
2138
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2139
         */
2140 12
        $str = $antiXss->xss_clean($this->str);
2141
2142 12
        return static::create($str, $this->encoding);
2143
    }
2144
2145
    /**
2146
     * Returns a repeated string given a multiplier.
2147
     *
2148
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2149
     *
2150
     * @psalm-mutation-free
2151
     *
2152
     * @return static
2153
     *                <p>Object with a repeated str.</p>
2154
     */
2155 21
    public function repeat(int $multiplier): self
2156
    {
2157 21
        return static::create(
2158 21
            \str_repeat($this->str, $multiplier),
2159 21
            $this->encoding
2160
        );
2161
    }
2162
2163
    /**
2164
     * Replaces all occurrences of $search in $str by $replacement.
2165
     *
2166
     * @param string $search        <p>The needle to search for.</p>
2167
     * @param string $replacement   <p>The string to replace with.</p>
2168
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2169
     *
2170
     * @psalm-mutation-free
2171
     *
2172
     * @return static
2173
     *                <p>Object with the resulting $str after the replacements.</p>
2174
     */
2175 74
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2176
    {
2177 74
        if ($search === '' && $replacement === '') {
2178 16
            return static::create($this->str, $this->encoding);
2179
        }
2180
2181 58
        if ($this->str === '' && $search === '') {
2182 2
            return static::create($replacement, $this->encoding);
2183
        }
2184
2185 56
        if ($caseSensitive) {
2186 46
            return static::create(
2187 46
                $this->utf8::str_replace($search, $replacement, $this->str),
2188 46
                $this->encoding
2189
            );
2190
        }
2191
2192 10
        return static::create(
2193 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2194 10
            $this->encoding
2195
        );
2196
    }
2197
2198
    /**
2199
     * Replaces all occurrences of $search in $str by $replacement.
2200
     *
2201
     * @param string[]        $search        <p>The elements to search for.</p>
2202
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2203
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2204
     *
2205
     * @psalm-mutation-free
2206
     *
2207
     * @return static
2208
     *                <p>Object with the resulting $str after the replacements.</p>
2209
     */
2210 60
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2211
    {
2212 60
        if ($caseSensitive) {
2213 46
            return static::create(
2214 46
                $this->utf8::str_replace($search, $replacement, $this->str),
2215 46
                $this->encoding
2216
            );
2217
        }
2218
2219 14
        return static::create(
2220 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2221 14
            $this->encoding
2222
        );
2223
    }
2224
2225
    /**
2226
     * Replaces all occurrences of $search from the beginning of string with $replacement.
2227
     *
2228
     * @param string $search      <p>The string to search for.</p>
2229
     * @param string $replacement <p>The replacement.</p>
2230
     *
2231
     * @psalm-mutation-free
2232
     *
2233
     * @return static
2234
     *                <p>Object with the resulting $str after the replacements.</p>
2235
     */
2236 32
    public function replaceBeginning(string $search, string $replacement): self
2237
    {
2238 32
        return static::create(
2239 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
2240 32
            $this->encoding
2241
        );
2242
    }
2243
2244
    /**
2245
     * Replaces all occurrences of $search from the ending of string with $replacement.
2246
     *
2247
     * @param string $search      <p>The string to search for.</p>
2248
     * @param string $replacement <p>The replacement.</p>
2249
     *
2250
     * @psalm-mutation-free
2251
     *
2252
     * @return static
2253
     *                <p>Object with the resulting $str after the replacements.</p>
2254
     */
2255 32
    public function replaceEnding(string $search, string $replacement): self
2256
    {
2257 32
        return static::create(
2258 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
2259 32
            $this->encoding
2260
        );
2261
    }
2262
2263
    /**
2264
     * Replaces first occurrences of $search from the beginning of string with $replacement.
2265
     *
2266
     * @param string $search      <p>The string to search for.</p>
2267
     * @param string $replacement <p>The replacement.</p>
2268
     *
2269
     * @psalm-mutation-free
2270
     *
2271
     * @return static
2272
     *                <p>Object with the resulting $str after the replacements.</p>
2273
     */
2274 32
    public function replaceFirst(string $search, string $replacement): self
2275
    {
2276 32
        return static::create(
2277 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
2278 32
            $this->encoding
2279
        );
2280
    }
2281
2282
    /**
2283
     * Replaces last occurrences of $search from the ending of string with $replacement.
2284
     *
2285
     * @param string $search      <p>The string to search for.</p>
2286
     * @param string $replacement <p>The replacement.</p>
2287
     *
2288
     * @psalm-mutation-free
2289
     *
2290
     * @return static
2291
     *                <p>Object with the resulting $str after the replacements.</p>
2292
     */
2293 30
    public function replaceLast(string $search, string $replacement): self
2294
    {
2295 30
        return static::create(
2296 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
2297 30
            $this->encoding
2298
        );
2299
    }
2300
2301
    /**
2302
     * Returns a reversed string. A multibyte version of strrev().
2303
     *
2304
     * @psalm-mutation-free
2305
     *
2306
     * @return static
2307
     *                <p>Object with a reversed $str.</p>
2308
     */
2309 15
    public function reverse(): self
2310
    {
2311 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
2312
    }
2313
2314
    /**
2315
     * Truncates the string to a given length, while ensuring that it does not
2316
     * split words. If $substring is provided, and truncating occurs, the
2317
     * string is further truncated so that the substring may be appended without
2318
     * exceeding the desired length.
2319
     *
2320
     * @param int    $length                          <p>Desired length of the truncated string.</p>
2321
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
2322
     * @param bool   $ignoreDoNotSplitWordsForOneWord
2323
     *
2324
     * @psalm-mutation-free
2325
     *
2326
     * @return static
2327
     *                <p>Object with the resulting $str after truncating.</p>
2328
     */
2329 68
    public function safeTruncate(
2330
        int $length,
2331
        string $substring = '',
2332
        bool $ignoreDoNotSplitWordsForOneWord = true
2333
    ): self {
2334 68
        return static::create(
2335 68
            $this->utf8::str_truncate_safe(
2336 68
                $this->str,
2337 68
                $length,
2338 68
                $substring,
2339 68
                $this->encoding,
2340 68
                $ignoreDoNotSplitWordsForOneWord
2341
            ),
2342 68
            $this->encoding
2343
        );
2344
    }
2345
2346
    /**
2347
     * Shorten the string after $length, but also after the next word.
2348
     *
2349
     * @param int    $length
2350
     * @param string $strAddOn [optional] <p>Default: '…'</p>
2351
     *
2352
     * @psalm-mutation-free
2353
     *
2354
     * @return static
2355
     */
2356 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
2357
    {
2358 8
        return static::create(
2359 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
2360 8
            $this->encoding
2361
        );
2362
    }
2363
2364
    /**
2365
     * A multibyte string shuffle function. It returns a string with its
2366
     * characters in random order.
2367
     *
2368
     * @psalm-mutation-free
2369
     *
2370
     * @return static
2371
     *                <p>Object with a shuffled $str.</p>
2372
     */
2373 9
    public function shuffle(): self
2374
    {
2375 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
2376
    }
2377
2378
    /**
2379
     * Returns the substring beginning at $start, and up to, but not including
2380
     * the index specified by $end. If $end is omitted, the function extracts
2381
     * the remaining string. If $end is negative, it is computed from the end
2382
     * of the string.
2383
     *
2384
     * @param int $start <p>Initial index from which to begin extraction.</p>
2385
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
2386
     *
2387
     * @psalm-mutation-free
2388
     *
2389
     * @return static
2390
     *                <p>Object with its $str being the extracted substring.</p>
2391
     */
2392 50
    public function slice(int $start, int $end = null): self
2393
    {
2394 50
        return static::create(
2395 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
2396 50
            $this->encoding
2397
        );
2398
    }
2399
2400
    /**
2401
     * Converts the string into an URL slug. This includes replacing non-ASCII
2402
     * characters with their closest ASCII equivalents, removing remaining
2403
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
2404
     * $separator. The separator defaults to a single dash, and the string
2405
     * is also converted to lowercase. The language of the source string can
2406
     * also be supplied for language-specific transliteration.
2407
     *
2408
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
2409
     * @param string                $language              [optional] <p>Language of the source string.</p>
2410
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
2411
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
2412
     *                                                     pound ".</p>
2413
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
2414
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
2415
     *                                                     chars.</p>
2416
     *
2417
     * @psalm-mutation-free
2418
     *
2419
     * @return static
2420
     *                <p>Object whose $str has been converted to an URL slug.</p>
2421
     */
2422 17
    public function slugify(
2423
        string $separator = '-',
2424
        string $language = 'en',
2425
        array $replacements = [],
2426
        bool $replace_extra_symbols = true,
2427
        bool $use_str_to_lower = true,
2428
        bool $use_transliterate = false
2429
    ): self {
2430 17
        return static::create(
2431 17
            $this->ascii::to_slugify(
2432 17
                $this->str,
2433 17
                $separator,
2434 17
                $language,
2435 17
                $replacements,
2436 17
                $replace_extra_symbols,
2437 17
                $use_str_to_lower,
2438 17
                $use_transliterate
2439
            ),
2440 17
            $this->encoding
2441
        );
2442
    }
2443
2444
    /**
2445
     * Convert a string to e.g.: "snake_case"
2446
     *
2447
     * @psalm-mutation-free
2448
     *
2449
     * @return static
2450
     *                <p>Object with $str in snake_case.</p>
2451
     */
2452 40
    public function snakeize(): self
2453
    {
2454 40
        return static::create(
2455 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
2456 40
            $this->encoding
2457
        );
2458
    }
2459
2460
    /**
2461
     * Splits the string with the provided regular expression, returning an
2462
     * array of Stringy objects. An optional integer $limit will truncate the
2463
     * results.
2464
     *
2465
     * @param string $pattern <p>The regex with which to split the string.</p>
2466
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no limit</p>
2467
     *
2468
     * @psalm-mutation-free
2469
     *
2470
     * @return CollectionStringy|static[]
2471
     *                                    <p>An collection of Stringy objects.</p>
2472
     *
2473
     * @psalm-return CollectionStringy<int,static>
2474
     */
2475 51
    public function split(string $pattern, int $limit = null): CollectionStringy
2476
    {
2477 51
        if ($limit === null) {
2478 7
            $limit = -1;
2479
        }
2480
2481 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
2482
        /** @noinspection AlterInForeachInspection */
2483 51
        foreach ($array as $i => &$value) {
2484 45
            $value = static::create($value, $this->encoding);
2485
        }
2486
2487
        /** @noinspection PhpSillyAssignmentInspection */
2488
        /** @var static[] $array */
2489 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...
2490
2491
        /**
2492
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2493
         */
2494 51
        return CollectionStringy::create($array);
2495
    }
2496
2497
    /**
2498
     * Returns true if the string begins with $substring, false otherwise. By
2499
     * default, the comparison is case-sensitive, but can be made insensitive
2500
     * by setting $caseSensitive to false.
2501
     *
2502
     * @param string $substring     <p>The substring to look for.</p>
2503
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2504
     *
2505
     * @psalm-mutation-free
2506
     *
2507
     * @return bool
2508
     *              <p>Whether or not $str starts with $substring.</p>
2509
     */
2510 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
2511
    {
2512 99
        if ($caseSensitive) {
2513 53
            return $this->utf8::str_starts_with($this->str, $substring);
2514
        }
2515
2516 46
        return $this->utf8::str_istarts_with($this->str, $substring);
2517
    }
2518
2519
    /**
2520
     * Returns true if the string begins with any of $substrings, false otherwise.
2521
     * By default the comparison is case-sensitive, but can be made insensitive by
2522
     * setting $caseSensitive to false.
2523
     *
2524
     * @param string[] $substrings    <p>Substrings to look for.</p>
2525
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2526
     *
2527
     * @psalm-mutation-free
2528
     *
2529
     * @return bool
2530
     *              <p>Whether or not $str starts with $substring.</p>
2531
     */
2532 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
2533
    {
2534 35
        if ($caseSensitive) {
2535 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
2536
        }
2537
2538 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
2539
    }
2540
2541
    /**
2542
     * Strip all whitespace characters. This includes tabs and newline characters,
2543
     * as well as multibyte whitespace such as the thin space and ideographic space.
2544
     *
2545
     * @psalm-mutation-free
2546
     *
2547
     * @return static
2548
     */
2549 36
    public function stripWhitespace(): self
2550
    {
2551 36
        return static::create(
2552 36
            $this->utf8::strip_whitespace($this->str),
2553 36
            $this->encoding
2554
        );
2555
    }
2556
2557
    /**
2558
     * Remove css media-queries.
2559
     *
2560
     * @psalm-mutation-free
2561
     *
2562
     * @return static
2563
     */
2564 2
    public function stripeCssMediaQueries(): self
2565
    {
2566 2
        return static::create(
2567 2
            $this->utf8::css_stripe_media_queries($this->str),
2568 2
            $this->encoding
2569
        );
2570
    }
2571
2572
    /**
2573
     * Remove empty html-tag.
2574
     *
2575
     * e.g.: <tag></tag>
2576
     *
2577
     * @psalm-mutation-free
2578
     *
2579
     * @return static
2580
     */
2581 2
    public function stripeEmptyHtmlTags(): self
2582
    {
2583 2
        return static::create(
2584 2
            $this->utf8::html_stripe_empty_tags($this->str),
2585 2
            $this->encoding
2586
        );
2587
    }
2588
2589
    /**
2590
     * Returns the substring beginning at $start with the specified $length.
2591
     * It differs from the $this->utf8::substr() function in that providing a $length of
2592
     * null will return the rest of the string, rather than an empty string.
2593
     *
2594
     * @param int $start  <p>Position of the first character to use.</p>
2595
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
2596
     *
2597
     * @psalm-mutation-free
2598
     *
2599
     * @return static
2600
     *                <p>Object with its $str being the substring.</p>
2601
     */
2602 31
    public function substr(int $start, int $length = null): self
2603
    {
2604 31
        return static::create(
2605 31
            $this->utf8::substr(
2606 31
                $this->str,
2607 31
                $start,
2608 31
                $length,
2609 31
                $this->encoding
2610
            ),
2611 31
            $this->encoding
2612
        );
2613
    }
2614
2615
    /**
2616
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
2617
     * If no match is found returns new empty Stringy object.
2618
     *
2619
     * @param string $needle       <p>The string to look for.</p>
2620
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2621
     *
2622
     * @psalm-mutation-free
2623
     *
2624
     * @return static
2625
     */
2626 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...
2627
    {
2628 4
        return static::create(
2629 4
            $this->utf8::str_substr_first(
2630 4
                $this->str,
2631 4
                $needle,
2632 4
                $beforeNeedle,
2633 4
                $this->encoding
2634
            ),
2635 4
            $this->encoding
2636
        );
2637
    }
2638
2639
    /**
2640
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
2641
     * If no match is found returns new empty Stringy object.
2642
     *
2643
     * @param string $needle       <p>The string to look for.</p>
2644
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2645
     *
2646
     * @psalm-mutation-free
2647
     *
2648
     * @return static
2649
     */
2650 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...
2651
    {
2652 4
        return static::create(
2653 4
            $this->utf8::str_isubstr_first(
2654 4
                $this->str,
2655 4
                $needle,
2656 4
                $beforeNeedle,
2657 4
                $this->encoding
2658
            ),
2659 4
            $this->encoding
2660
        );
2661
    }
2662
2663
    /**
2664
     * Surrounds $str with the given substring.
2665
     *
2666
     * @param string $substring <p>The substring to add to both sides.</P>
2667
     *
2668
     * @psalm-mutation-free
2669
     *
2670
     * @return static
2671
     *                <p>Object whose $str had the substring both prepended and appended.</p>
2672
     */
2673 15
    public function surround(string $substring): self
2674
    {
2675 15
        return static::create(
2676 15
            $substring . $this->str . $substring,
2677 15
            $this->encoding
2678
        );
2679
    }
2680
2681
    /**
2682
     * Returns a case swapped version of the string.
2683
     *
2684
     * @psalm-mutation-free
2685
     *
2686
     * @return static
2687
     *                <p>Object whose $str has each character's case swapped.</P>
2688
     */
2689 15
    public function swapCase(): self
2690
    {
2691 15
        return static::create(
2692 15
            $this->utf8::swapCase($this->str, $this->encoding),
2693 15
            $this->encoding
2694
        );
2695
    }
2696
2697
    /**
2698
     * Returns a string with smart quotes, ellipsis characters, and dashes from
2699
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
2700
     * equivalents.
2701
     *
2702
     * @psalm-mutation-free
2703
     *
2704
     * @return static
2705
     *                <p>Object whose $str has those characters removed.</p>
2706
     */
2707 12
    public function tidy(): self
2708
    {
2709 12
        return static::create(
2710 12
            $this->ascii::normalize_msword($this->str),
2711 12
            $this->encoding
2712
        );
2713
    }
2714
2715
    /**
2716
     * Returns a trimmed string with the first letter of each word capitalized.
2717
     * Also accepts an array, $ignore, allowing you to list words not to be
2718
     * capitalized.
2719
     *
2720
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
2721
     *                                               Default: null</p>
2722
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
2723
     *                                               separator === words.</p>
2724
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
2725
     *
2726
     * @psalm-mutation-free
2727
     *
2728
     * @return static
2729
     *                <p>Object with a titleized $str.</p>
2730
     */
2731 23
    public function titleize(
2732
        array $ignore = null,
2733
        string $word_define_chars = null,
2734
        string $language = null
2735
    ): self {
2736 23
        return static::create(
2737 23
            $this->utf8::str_titleize(
2738 23
                $this->str,
2739 23
                $ignore,
2740 23
                $this->encoding,
2741 23
                false,
2742 23
                $language,
2743 23
                false,
2744 23
                true,
2745 23
                $word_define_chars
2746
            ),
2747 23
            $this->encoding
2748
        );
2749
    }
2750
2751
    /**
2752
     * Returns a trimmed string in proper title case.
2753
     *
2754
     * Also accepts an array, $ignore, allowing you to list words not to be
2755
     * capitalized.
2756
     *
2757
     * Adapted from John Gruber's script.
2758
     *
2759
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
2760
     *
2761
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
2762
     *
2763
     * @psalm-mutation-free
2764
     *
2765
     * @return static
2766
     *                <p>Object with a titleized $str</p>
2767
     */
2768 70
    public function titleizeForHumans(array $ignore = []): self
2769
    {
2770 70
        return static::create(
2771 70
            $this->utf8::str_titleize_for_humans(
2772 70
                $this->str,
2773 70
                $ignore,
2774 70
                $this->encoding
2775
            ),
2776 70
            $this->encoding
2777
        );
2778
    }
2779
2780
    /**
2781
     * Returns an ASCII version of the string. A set of non-ASCII characters are
2782
     * replaced with their closest ASCII counterparts, and the rest are removed
2783
     * by default. The language or locale of the source string can be supplied
2784
     * for language-specific transliteration in any of the following formats:
2785
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
2786
     * to "aeoeue" rather than "aou" as in other languages.
2787
     *
2788
     * @param string $language          [optional] <p>Language of the source string.</p>
2789
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
2790
     *                                  unsupported characters.</p>
2791
     *
2792
     * @psalm-mutation-free
2793
     *
2794
     * @return static
2795
     *                <p>Object whose $str contains only ASCII characters.</p>
2796
     */
2797 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
2798
    {
2799 23
        return static::create(
2800 23
            $this->ascii::to_ascii(
2801 23
                $this->str,
2802 23
                $language,
2803 23
                $removeUnsupported
2804
            ),
2805 23
            $this->encoding
2806
        );
2807
    }
2808
2809
    /**
2810
     * Returns a boolean representation of the given logical string value.
2811
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
2812
     * 'off', and 'no' will return false. In all instances, case is ignored.
2813
     * For other numeric strings, their sign will determine the return value.
2814
     * In addition, blank strings consisting of only whitespace will return
2815
     * false. For all other strings, the return value is a result of a
2816
     * boolean cast.
2817
     *
2818
     * @psalm-mutation-free
2819
     *
2820
     * @return bool
2821
     *              <p>A boolean value for the string.</p>
2822
     */
2823 45
    public function toBoolean(): bool
2824
    {
2825 45
        return $this->utf8::to_boolean($this->str);
2826
    }
2827
2828
    /**
2829
     * Converts all characters in the string to lowercase.
2830
     *
2831
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
2832
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
2833
     *
2834
     * @psalm-mutation-free
2835
     *
2836
     * @return static
2837
     *                <p>Object with all characters of $str being lowercase.</p>
2838
     */
2839 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...
2840
    {
2841 17
        return static::create(
2842 17
            $this->utf8::strtolower(
2843 17
                $this->str,
2844 17
                $this->encoding,
2845 17
                false,
2846 17
                $lang,
2847 17
                $tryToKeepStringLength
2848
            ),
2849 17
            $this->encoding
2850
        );
2851
    }
2852
2853
    /**
2854
     * Converts each tab in the string to some number of spaces, as defined by
2855
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
2856
     *
2857
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
2858
     *
2859
     * @psalm-mutation-free
2860
     *
2861
     * @return static
2862
     *                <p>Object whose $str has had tabs switched to spaces.</p>
2863
     */
2864 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...
2865
    {
2866 18
        if ($tabLength === 4) {
2867 9
            $tab = '    ';
2868 9
        } elseif ($tabLength === 2) {
2869 3
            $tab = '  ';
2870
        } else {
2871 6
            $tab = \str_repeat(' ', $tabLength);
2872
        }
2873
2874 18
        return static::create(
2875 18
            \str_replace("\t", $tab, $this->str),
2876 18
            $this->encoding
2877
        );
2878
    }
2879
2880
    /**
2881
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
2882
     * string.
2883
     *
2884
     * @psalm-mutation-free
2885
     *
2886
     * @return string
2887
     */
2888 2172
    public function toString(): string
2889
    {
2890 2172
        return (string) $this->str;
2891
    }
2892
2893
    /**
2894
     * Converts each occurrence of some consecutive number of spaces, as
2895
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
2896
     * are converted to a tab.
2897
     *
2898
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
2899
     *
2900
     * @psalm-mutation-free
2901
     *
2902
     * @return static
2903
     *                <p>Object whose $str has had spaces switched to tabs.</p>
2904
     */
2905 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...
2906
    {
2907 15
        if ($tabLength === 4) {
2908 9
            $tab = '    ';
2909 6
        } elseif ($tabLength === 2) {
2910 3
            $tab = '  ';
2911
        } else {
2912 3
            $tab = \str_repeat(' ', $tabLength);
2913
        }
2914
2915 15
        return static::create(
2916 15
            \str_replace($tab, "\t", $this->str),
2917 15
            $this->encoding
2918
        );
2919
    }
2920
2921
    /**
2922
     * Converts the first character of each word in the string to uppercase
2923
     * and all other chars to lowercase.
2924
     *
2925
     * @psalm-mutation-free
2926
     *
2927
     * @return static
2928
     *                <p>Object with all characters of $str being title-cased.</p>
2929
     */
2930 15
    public function toTitleCase(): self
2931
    {
2932 15
        return static::create(
2933 15
            $this->utf8::titlecase($this->str, $this->encoding),
2934 15
            $this->encoding
2935
        );
2936
    }
2937
2938
    /**
2939
     * Returns an ASCII version of the string. A set of non-ASCII characters are
2940
     * replaced with their closest ASCII counterparts, and the rest are removed
2941
     * unless instructed otherwise.
2942
     *
2943
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
2944
     *                        performance | Default: false</p>
2945
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
2946
     *
2947
     * @psalm-mutation-free
2948
     *
2949
     * @return static
2950
     *                <p>Object whose $str contains only ASCII characters.</p>
2951
     */
2952 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
2953
    {
2954 34
        return static::create(
2955 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
2956 34
            $this->encoding
2957
        );
2958
    }
2959
2960
    /**
2961
     * Converts all characters in the string to uppercase.
2962
     *
2963
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
2964
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
2965
     *
2966
     * @psalm-mutation-free
2967
     *
2968
     * @return static
2969
     *                <p>Object with all characters of $str being uppercase.</p>
2970
     */
2971 17 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...
2972
    {
2973 17
        return static::create(
2974 17
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
2975 17
            $this->encoding
2976
        );
2977
    }
2978
2979
    /**
2980
     * Returns a string with whitespace removed from the start and end of the
2981
     * string. Supports the removal of unicode whitespace. Accepts an optional
2982
     * string of characters to strip instead of the defaults.
2983
     *
2984
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
2985
     *
2986
     * @psalm-mutation-free
2987
     *
2988
     * @return static
2989
     *                <p>Object with a trimmed $str.</p>
2990
     */
2991 36
    public function trim(string $chars = null): self
2992
    {
2993 36
        return static::create(
2994 36
            $this->utf8::trim($this->str, $chars),
2995 36
            $this->encoding
2996
        );
2997
    }
2998
2999
    /**
3000
     * Returns a string with whitespace removed from the start of the string.
3001
     * Supports the removal of unicode whitespace. Accepts an optional
3002
     * string of characters to strip instead of the defaults.
3003
     *
3004
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3005
     *
3006
     * @psalm-mutation-free
3007
     *
3008
     * @return static
3009
     *                <p>Object with a trimmed $str.</p>
3010
     */
3011 39
    public function trimLeft(string $chars = null): self
3012
    {
3013 39
        return static::create(
3014 39
            $this->utf8::ltrim($this->str, $chars),
3015 39
            $this->encoding
3016
        );
3017
    }
3018
3019
    /**
3020
     * Returns a string with whitespace removed from the end of the string.
3021
     * Supports the removal of unicode whitespace. Accepts an optional
3022
     * string of characters to strip instead of the defaults.
3023
     *
3024
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3025
     *
3026
     * @psalm-mutation-free
3027
     *
3028
     * @return static
3029
     *                <p>Object with a trimmed $str.</p>
3030
     */
3031 39
    public function trimRight(string $chars = null): self
3032
    {
3033 39
        return static::create(
3034 39
            $this->utf8::rtrim($this->str, $chars),
3035 39
            $this->encoding
3036
        );
3037
    }
3038
3039
    /**
3040
     * Truncates the string to a given length. If $substring is provided, and
3041
     * truncating occurs, the string is further truncated so that the substring
3042
     * may be appended without exceeding the desired length.
3043
     *
3044
     * @param int    $length    <p>Desired length of the truncated string.</p>
3045
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
3046
     *
3047
     * @psalm-mutation-free
3048
     *
3049
     * @return static
3050
     *                <p>Object with the resulting $str after truncating.</p>
3051
     */
3052 66
    public function truncate(int $length, string $substring = ''): self
3053
    {
3054 66
        return static::create(
3055 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
3056 66
            $this->encoding
3057
        );
3058
    }
3059
3060
    /**
3061
     * Returns a lowercase and trimmed string separated by underscores.
3062
     * Underscores are inserted before uppercase characters (with the exception
3063
     * of the first character of the string), and in place of spaces as well as
3064
     * dashes.
3065
     *
3066
     * @psalm-mutation-free
3067
     *
3068
     * @return static
3069
     *                <p>Object with an underscored $str.</p>
3070
     */
3071 48
    public function underscored(): self
3072
    {
3073 48
        return $this->delimit('_');
3074
    }
3075
3076
    /**
3077
     * Returns an UpperCamelCase version of the supplied string. It trims
3078
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
3079
     * and underscores, and removes spaces, dashes, underscores.
3080
     *
3081
     * @psalm-mutation-free
3082
     *
3083
     * @return static
3084
     *                <p>Object with $str in UpperCamelCase.</p>
3085
     */
3086 39
    public function upperCamelize(): self
3087
    {
3088 39
        return static::create(
3089 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
3090 39
            $this->encoding
3091
        );
3092
    }
3093
3094
    /**
3095
     * Converts the first character of the supplied string to upper case.
3096
     *
3097
     * @psalm-mutation-free
3098
     *
3099
     * @return static
3100
     *                <p>Object with the first character of $str being upper case.</p>
3101
     */
3102 18
    public function upperCaseFirst(): self
3103
    {
3104 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
3105
    }
3106
3107
    /**
3108
     * Converts the string into an URL slug. This includes replacing non-ASCII
3109
     * characters with their closest ASCII equivalents, removing remaining
3110
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3111
     * $separator. The separator defaults to a single dash, and the string
3112
     * is also converted to lowercase.
3113
     *
3114
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
3115
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
3116
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
3117
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
3118
     *
3119
     * @psalm-mutation-free
3120
     *
3121
     * @return static
3122
     *                <p>Object whose $str has been converted to an URL slug.</p>
3123
     *
3124
     * @psalm-suppress ImpureMethodCall :/
3125
     */
3126 32
    public function urlify(
3127
        string $separator = '-',
3128
        string $language = 'en',
3129
        array $replacements = [],
3130
        bool $strToLower = true
3131
    ): self {
3132
        // init
3133 32
        $str = $this->str;
3134
3135 32
        foreach ($replacements as $from => $to) {
3136 32
            $str = \str_replace($from, $to, $str);
3137
        }
3138
3139 32
        return static::create(
3140 32
            URLify::slug(
3141 32
                $str,
3142 32
                $language,
3143 32
                $separator,
3144 32
                $strToLower
3145
            ),
3146 32
            $this->encoding
3147
        );
3148
    }
3149
3150
    /**
3151
     * Converts the string into an valid UTF-8 string.
3152
     *
3153
     * @psalm-mutation-free
3154
     *
3155
     * @return static
3156
     */
3157 2
    public function utf8ify(): self
3158
    {
3159 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
3160
    }
3161
3162
    /**
3163
     * Convert a string into an array of words.
3164
     *
3165
     * @param string   $char_list           <p>Additional chars for the definition of "words".</p>
3166
     * @param bool     $remove_empty_values <p>Remove empty values.</p>
3167
     * @param int|null $remove_short_values <p>The min. string length or null to disable</p>
3168
     *
3169
     * @psalm-mutation-free
3170
     *
3171
     * @return CollectionStringy|static[]
3172
     *
3173
     * @psalm-return CollectionStringy<int,static>
3174
     */
3175 2
    public function words(
3176
        string $char_list = '',
3177
        bool $remove_empty_values = false,
3178
        int $remove_short_values = null
3179
    ): CollectionStringy {
3180
        /**
3181
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3182
         */
3183 2
        return CollectionStringy::createFromStrings(
3184 2
            $this->utf8::str_to_words(
3185 2
                $this->str,
3186 2
                $char_list,
3187 2
                $remove_empty_values,
3188 2
                $remove_short_values
3189
            )
3190
        );
3191
    }
3192
3193
    /**
3194
     * Surrounds $str with the given substring.
3195
     *
3196
     * @param string $substring <p>The substring to add to both sides.</P>
3197
     *
3198
     * @psalm-mutation-free
3199
     *
3200
     * @return static
3201
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3202
     */
3203 10
    public function wrap(string $substring): self
3204
    {
3205 10
        return $this->surround($substring);
3206
    }
3207
3208
    /**
3209
     * Returns the replacements for the toAscii() method.
3210
     *
3211
     * @noinspection PhpUnused
3212
     *
3213
     * @psalm-mutation-free
3214
     *
3215
     * @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...
3216
     *                       <p>An array of replacements.</p>
3217
     *
3218
     * @deprecated   this is only here for backward-compatibly reasons
3219
     */
3220 1
    protected function charsArray(): array
3221
    {
3222 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
3223
    }
3224
3225
    /**
3226
     * Returns true if $str matches the supplied pattern, false otherwise.
3227
     *
3228
     * @param string $pattern <p>Regex pattern to match against.</p>
3229
     *
3230
     * @psalm-mutation-free
3231
     *
3232
     * @return bool
3233
     *              <p>Whether or not $str matches the pattern.</p>
3234
     */
3235 24
    protected function matchesPattern(string $pattern): bool
3236
    {
3237 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
3238
    }
3239
}
3240