Completed
Push — master ( bf0dc0...d2111f )
by Lars
04:39
created

Stringy::isEquals()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

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