Completed
Push — master ( 2136ea...292a08 )
by Lars
04:54
created

Stringy::matchCaseSensitive()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stringy;
6
7
use Defuse\Crypto\Crypto;
8
use voku\helper\AntiXSS;
9
use voku\helper\ASCII;
10
use voku\helper\EmailCheck;
11
use voku\helper\URLify;
12
use voku\helper\UTF8;
13
14
/**
15
 * @template-implements \IteratorAggregate<string>
16
 * @template-implements \ArrayAccess<array-key,string>
17
 */
18
class Stringy implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
19
{
20
    /**
21
     * An instance's string.
22
     *
23
     * @var string
24
     */
25
    protected $str;
26
27
    /**
28
     * The string's encoding, which should be one of the mbstring module's
29
     * supported encodings.
30
     *
31
     * @var string
32
     */
33
    protected $encoding;
34
35
    /**
36
     * @var UTF8
37
     */
38
    private $utf8;
39
40
    /**
41
     * @var ASCII
42
     */
43
    private $ascii;
44
45
    /**
46
     * Initializes a Stringy object and assigns both str and encoding properties
47
     * the supplied values. $str is cast to a string prior to assignment, and if
48
     * $encoding is not specified, it defaults to mb_internal_encoding(). Throws
49
     * an InvalidArgumentException if the first argument is an array or object
50
     * without a __toString method.
51
     *
52
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
53
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
54
     *
55
     * @throws \InvalidArgumentException
56
     *                                   <p>if an array or object without a
57
     *                                   __toString method is passed as the first argument</p>
58
     *
59
     * @psalm-mutation-free
60
     */
61 3640
    public function __construct($str = '', string $encoding = null)
62
    {
63 3640
        if (\is_array($str)) {
64 3
            throw new \InvalidArgumentException(
65 3
                'Passed value cannot be an array'
66
            );
67
        }
68
69
        if (
70 3637
            \is_object($str)
71
            &&
72 3637
            !\method_exists($str, '__toString')
73
        ) {
74 4
            throw new \InvalidArgumentException(
75 4
                'Passed object must have a __toString method'
76
            );
77
        }
78
79 3634
        $this->str = (string) $str;
80
81 3634
        static $ASCII = null;
82 3634
        if ($ASCII === null) {
83
            $ASCII = new ASCII();
84
        }
85 3634
        $this->ascii = $ASCII;
86
87 3634
        static $UTF8 = null;
88 3634
        if ($UTF8 === null) {
89
            $UTF8 = new UTF8();
90
        }
91 3634
        $this->utf8 = $UTF8;
92
93 3634
        if ($encoding !== 'UTF-8') {
94 2463
            $this->encoding = $this->utf8::normalize_encoding($encoding, 'UTF-8');
95
        } else {
96 2703
            $this->encoding = $encoding;
97
        }
98 3634
    }
99
100
    /**
101
     * Returns the value in $str.
102
     *
103
     * EXAMPLE: <code>
104
     * </code>
105
     *
106
     * @psalm-mutation-free
107
     *
108
     * @return string
109
     *                <p>The current value of the $str property.</p>
110
     */
111 1143
    public function __toString()
112
    {
113 1143
        return (string) $this->str;
114
    }
115
116
    /**
117
     * Return part of the string occurring after a specific string.
118
     *
119
     * EXAMPLE: <code>
120
     * s('宮本 茂')->after('本'); // ' 茂'
121
     * </code>
122
     *
123
     * @param string $string <p>The delimiting string.</p>
124
     *
125
     * @psalm-mutation-free
126
     *
127
     * @return static
128
     */
129 4
    public function after(string $string): self
130
    {
131 4
        $strArray = UTF8::str_split_pattern(
132 4
            $this->str,
133 4
            $string
134
        );
135
136 4
        unset($strArray[0]);
137
138 4
        return new static(
139 4
            \implode(' ', $strArray),
140 4
            $this->encoding
141
        );
142
    }
143
144
    /**
145
     * Gets the substring after the first occurrence of a separator.
146
     * If no match is found returns new empty Stringy object.
147
     *
148
     * EXAMPLE: <code>
149
     * s('</b></b>')->afterFirst('b'); // '></b>'
150
     * </code>
151
     *
152
     * @param string $separator
153
     *
154
     * @psalm-mutation-free
155
     *
156
     * @return static
157
     */
158 3
    public function afterFirst(string $separator): self
159
    {
160 3
        return static::create(
161 3
            $this->utf8::str_substr_after_first_separator(
162 3
                $this->str,
163
                $separator,
164 3
                $this->encoding
165
            )
166
        );
167
    }
168
169
    /**
170
     * Gets the substring after the first occurrence of a separator.
171
     * If no match is found returns new empty Stringy object.
172
     *
173
     * EXAMPLE: <code>
174
     * s('</B></B>')->afterFirstIgnoreCase('b'); // '></B>'
175
     * </code>
176
     *
177
     * @param string $separator
178
     *
179
     * @psalm-mutation-free
180
     *
181
     * @return static
182
     */
183 2
    public function afterFirstIgnoreCase(string $separator): self
184
    {
185 2
        return static::create(
186 2
            $this->utf8::str_isubstr_after_first_separator(
187 2
                $this->str,
188
                $separator,
189 2
                $this->encoding
190
            )
191
        );
192
    }
193
194
    /**
195
     * Gets the substring after the last occurrence of a separator.
196
     * If no match is found returns new empty Stringy object.
197
     *
198
     * EXAMPLE: <code>
199
     * s('</b></b>')->afterLast('b'); // '>'
200
     * </code>
201
     *
202
     * @param string $separator
203
     *
204
     * @psalm-mutation-free
205
     *
206
     * @return static
207
     */
208 2
    public function afterLast(string $separator): self
209
    {
210 2
        return static::create(
211 2
            $this->utf8::str_substr_after_last_separator(
212 2
                $this->str,
213
                $separator,
214 2
                $this->encoding
215
            )
216
        );
217
    }
218
219
    /**
220
     * Gets the substring after the last occurrence of a separator.
221
     * If no match is found returns new empty Stringy object.
222
     *
223
     * EXAMPLE: <code>
224
     * s('</B></B>')->afterLastIgnoreCase('b'); // '>'
225
     * </code>
226
     *
227
     * @param string $separator
228
     *
229
     * @psalm-mutation-free
230
     *
231
     * @return static
232
     */
233 2
    public function afterLastIgnoreCase(string $separator): self
234
    {
235 2
        return static::create(
236 2
            $this->utf8::str_isubstr_after_last_separator(
237 2
                $this->str,
238
                $separator,
239 2
                $this->encoding
240
            )
241
        );
242
    }
243
244
    /**
245
     * Returns a new string with $suffix appended.
246
     *
247
     * EXAMPLE: <code>
248
     * s('fòô')->append('bàř'); // 'fòôbàř'
249
     * </code>
250
     *
251
     * @param string ...$suffix <p>The string to append.</p>
252
     *
253
     * @psalm-mutation-free
254
     *
255
     * @return static
256
     *                <p>Object with appended $suffix.</p>
257
     */
258 15 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...
259
    {
260 15
        if (\count($suffix) <= 1) {
261
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
262 13
            $suffix = $suffix[0];
263
        } else {
264
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
265 2
            $suffix = \implode('', $suffix);
266
        }
267
268 15
        return static::create($this->str . $suffix, $this->encoding);
269
    }
270
271
    /**
272
     * Append an password (limited to chars that are good readable).
273
     *
274
     * EXAMPLE: <code>
275
     * s('')->appendPassword(8); // e.g.: '89bcdfgh'
276
     * </code>
277
     *
278
     * @param int $length <p>Length of the random string.</p>
279
     *
280
     * @return static
281
     *                <p>Object with appended password.</p>
282
     */
283 2
    public function appendPassword(int $length): self
284
    {
285 2
        return $this->appendRandomString(
286 2
            $length,
287 2
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
288
        );
289
    }
290
291
    /**
292
     * Append an random string.
293
     *
294
     * EXAMPLE: <code>
295
     * s('')->appendUniqueIdentifier(5, 'ABCDEFGHI'); // e.g.: 'CDEHI'
296
     * </code>
297
     *
298
     * @param int    $length        <p>Length of the random string.</p>
299
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
300
     *
301
     * @return static
302
     *                <p>Object with appended random string.</p>
303
     */
304 4
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
305
    {
306 4
        $str = $this->utf8::get_random_string($length, $possibleChars);
307
308 4
        return $this->append($str);
309
    }
310
311
    /**
312
     * Returns a new string with $suffix appended.
313
     *
314
     * EXAMPLE: <code>
315
     * </code>
316
     *
317
     * @param CollectionStringy|static ...$suffix <p>The Stringy objects to append.</p>
318
     *
319
     * @psalm-param CollectionStringy<int,static>|static ...$suffix
320
     *
321
     * @psalm-mutation-free
322
     *
323
     * @return static
324
     *                <p>Object with appended $suffix.</p>
325
     */
326 7 View Code Duplication
    public function appendStringy(...$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...
327
    {
328 7
        $suffixStr = '';
329 7
        foreach ($suffix as $suffixTmp) {
330 7
            if ($suffixTmp instanceof CollectionStringy) {
331 1
                $suffixStr .= $suffixTmp->implode('');
332
            } else {
333 7
                $suffixStr .= $suffixTmp->toString();
334
            }
335
        }
336
337 7
        return static::create($this->str . $suffixStr, $this->encoding);
338
    }
339
340
    /**
341
     * Append an unique identifier.
342
     *
343
     * EXAMPLE: <code>
344
     * s('')->appendUniqueIdentifier(); // e.g.: '1f3870be274f6c49b3e31a0c6728957f'
345
     * </code>
346
     *
347
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
348
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
349
     *
350
     * @return static
351
     *                <p>Object with appended unique identifier as md5-hash.</p>
352
     */
353 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
354
    {
355 2
        return $this->append(
356 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
357
        );
358
    }
359
360
    /**
361
     * Returns the character at $index, with indexes starting at 0.
362
     *
363
     * EXAMPLE: <code>
364
     * s('fòôbàř')->at(3); // 'b'
365
     * </code>
366
     *
367
     * @param int $index <p>Position of the character.</p>
368
     *
369
     * @psalm-mutation-free
370
     *
371
     * @return static
372
     *                <p>The character at $index.</p>
373
     */
374 24
    public function at(int $index): self
375
    {
376 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
377
    }
378
379
    /**
380
     * Decode the base64 encoded string.
381
     *
382
     * EXAMPLE: <code>
383
     * </code>
384
     *
385
     * @psalm-mutation-free
386
     *
387
     * @return self
388
     */
389 2
    public function base64Decode(): self
390
    {
391 2
        return static::create(
392 2
            \base64_decode($this->str, true),
393 2
            $this->encoding
394
        );
395
    }
396
397
    /**
398
     * Encode the string to base64.
399
     *
400
     * EXAMPLE: <code>
401
     * </code>
402
     *
403
     * @psalm-mutation-free
404
     *
405
     * @return self
406
     */
407 2
    public function base64Encode(): self
408
    {
409 2
        return static::create(
410 2
            \base64_encode($this->str),
411 2
            $this->encoding
412
        );
413
    }
414
415
    /**
416
     * Creates a hash from the string using the CRYPT_BLOWFISH algorithm.
417
     *
418
     * WARNING: Using this algorithm, will result in the ```$this->str```
419
     *          being truncated to a maximum length of 72 characters.
420
     *
421
     * EXAMPLE: <code>
422
     * </code>
423
     *
424
     * @param array<array-key, int|string> $options [optional] <p>An array of bcrypt hasing options.</p>
425
     *
426
     * @psalm-mutation-free
427
     *
428
     * @return static
429
     */
430 3
    public function bcrypt(array $options = []): self
431
    {
432 3
        return new static(
433 3
            \password_hash(
434 3
                $this->str,
435 3
                \PASSWORD_BCRYPT,
436 3
                $options
437
            ),
438 3
            $this->encoding
439
        );
440
    }
441
442
    /**
443
     * Return part of the string occurring before a specific string.
444
     *
445
     * EXAMPLE: <code>
446
     * </code>
447
     *
448
     * @param string $string <p>The delimiting string.</p>
449
     *
450
     * @psalm-mutation-free
451
     *
452
     * @return static
453
     */
454 4
    public function before(string $string): self
455
    {
456 4
        $strArray = UTF8::str_split_pattern(
457 4
            $this->str,
458 4
            $string,
459 4
            1
460
        );
461
462 4
        return new static(
463 4
            $strArray[0] ?? '',
464 4
            $this->encoding
465
        );
466
    }
467
468
    /**
469
     * Gets the substring before the first occurrence of a separator.
470
     * If no match is found returns new empty Stringy object.
471
     *
472
     * EXAMPLE: <code>
473
     * s('</b></b>')->beforeFirst('b'); // '</'
474
     * </code>
475
     *
476
     * @param string $separator
477
     *
478
     * @psalm-mutation-free
479
     *
480
     * @return static
481
     */
482 2
    public function beforeFirst(string $separator): self
483
    {
484 2
        return static::create(
485 2
            $this->utf8::str_substr_before_first_separator(
486 2
                $this->str,
487
                $separator,
488 2
                $this->encoding
489
            )
490
        );
491
    }
492
493
    /**
494
     * Gets the substring before the first occurrence of a separator.
495
     * If no match is found returns new empty Stringy object.
496
     *
497
     * EXAMPLE: <code>
498
     * s('</B></B>')->beforeFirstIgnoreCase('b'); // '</'
499
     * </code>
500
     *
501
     * @param string $separator
502
     *
503
     * @psalm-mutation-free
504
     *
505
     * @return static
506
     */
507 2
    public function beforeFirstIgnoreCase(string $separator): self
508
    {
509 2
        return static::create(
510 2
            $this->utf8::str_isubstr_before_first_separator(
511 2
                $this->str,
512
                $separator,
513 2
                $this->encoding
514
            )
515
        );
516
    }
517
518
    /**
519
     * Gets the substring before the last occurrence of a separator.
520
     * If no match is found returns new empty Stringy object.
521
     *
522
     * EXAMPLE: <code>
523
     * s('</b></b>')->beforeLast('b'); // '</b></'
524
     * </code>
525
     *
526
     * @param string $separator
527
     *
528
     * @psalm-mutation-free
529
     *
530
     * @return static
531
     */
532 2
    public function beforeLast(string $separator): self
533
    {
534 2
        return static::create(
535 2
            $this->utf8::str_substr_before_last_separator(
536 2
                $this->str,
537
                $separator,
538 2
                $this->encoding
539
            )
540
        );
541
    }
542
543
    /**
544
     * Gets the substring before the last occurrence of a separator.
545
     * If no match is found returns new empty Stringy object.
546
     *
547
     * EXAMPLE: <code>
548
     * s('</B></B>')->beforeLastIgnoreCase('b'); // '</B></'
549
     * </code>
550
     *
551
     * @param string $separator
552
     *
553
     * @psalm-mutation-free
554
     *
555
     * @return static
556
     */
557 2
    public function beforeLastIgnoreCase(string $separator): self
558
    {
559 2
        return static::create(
560 2
            $this->utf8::str_isubstr_before_last_separator(
561 2
                $this->str,
562
                $separator,
563 2
                $this->encoding
564
            )
565
        );
566
    }
567
568
    /**
569
     * Returns the substring between $start and $end, if found, or an empty
570
     * string. An optional offset may be supplied from which to begin the
571
     * search for the start string.
572
     *
573
     * EXAMPLE: <code>
574
     * s('{foo} and {bar}')->between('{', '}'); // 'foo'
575
     * </code>
576
     *
577
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
578
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
579
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
580
     *
581
     * @psalm-mutation-free
582
     *
583
     * @return static
584
     *                <p>Object whose $str is a substring between $start and $end.</p>
585
     */
586 48
    public function between(string $start, string $end, int $offset = null): self
587
    {
588 48
        $str = $this->utf8::between(
589 48
            $this->str,
590
            $start,
591
            $end,
592 48
            (int) $offset,
593 48
            $this->encoding
594
        );
595
596 48
        return static::create($str, $this->encoding);
597
    }
598
599
    /**
600
     * Call a user function.
601
     *
602
     * EXAMPLE: <code>
603
     * S::create('foo bar lall')->callUserFunction(static function ($str) {
604
     *     return UTF8::str_limit($str, 8);
605
     * })->toString(); // "foo bar…"
606
     * </code>
607
     *
608
     * @param callable $function
609
     * @param mixed    ...$parameter
610
     *
611
     * @psalm-mutation-free
612
     *
613
     * @return static
614
     *                <p>Object having a $str changed via $function.</p>
615
     */
616 2
    public function callUserFunction(callable $function, ...$parameter): self
617
    {
618 2
        $str = $function($this->str, ...$parameter);
619
620 2
        return static::create(
621 2
            $str,
622 2
            $this->encoding
623
        );
624
    }
625
626
    /**
627
     * Returns a camelCase version of the string. Trims surrounding spaces,
628
     * capitalizes letters following digits, spaces, dashes and underscores,
629
     * and removes spaces, dashes, as well as underscores.
630
     *
631
     * EXAMPLE: <code>
632
     * s('Camel-Case')->camelize(); // 'camelCase'
633
     * </code>
634
     *
635
     * @psalm-mutation-free
636
     *
637
     * @return static
638
     *                <p>Object with $str in camelCase.</p>
639
     */
640 57
    public function camelize(): self
641
    {
642 57
        return static::create(
643 57
            $this->utf8::str_camelize($this->str, $this->encoding),
644 57
            $this->encoding
645
        );
646
    }
647
648
    /**
649
     * Returns the string with the first letter of each word capitalized,
650
     * except for when the word is a name which shouldn't be capitalized.
651
     *
652
     * EXAMPLE: <code>
653
     * s('jaap de hoop scheffer')->capitalizePersonName(); // 'Jaap de Hoop Scheffer'
654
     * </code>
655
     *
656
     * @psalm-mutation-free
657
     *
658
     * @return static
659
     *                <p>Object with $str capitalized.</p>
660
     */
661 78
    public function capitalizePersonalName(): self
662
    {
663 78
        return static::create(
664 78
            $this->utf8::str_capitalize_name($this->str),
665 78
            $this->encoding
666
        );
667
    }
668
669
    /**
670
     * Returns an array consisting of the characters in the string.
671
     *
672
     * EXAMPLE: <code>
673
     * s('fòôbàř')->chars(); // ['f', 'ò', 'ô', 'b', 'à', 'ř']
674
     * </code>
675
     *
676
     * @psalm-mutation-free
677
     *
678
     * @return string[]
679
     *                  <p>An array of string chars.</p>
680
     */
681 14
    public function chars(): array
682
    {
683
        /** @var string[] */
684 14
        return $this->utf8::str_split($this->str);
685
    }
686
687
    /**
688
     * Splits the string into chunks of Stringy objects.
689
     *
690
     * EXAMPLE: <code>
691
     * s('foobar')->chunk(3); // ['foo', 'bar']
692
     * </code>
693
     *
694
     * @param int $length [optional] <p>Max character length of each array element.</p>
695
     *
696
     * @psalm-mutation-free
697
     *
698
     * @return static[]
699
     *                  <p>An array of Stringy objects.</p>
700
     *
701
     * @psalm-return array<int,static>
702
     */
703 13
    public function chunk(int $length = 1): array
704
    {
705 13
        if ($length < 1) {
706
            throw new \InvalidArgumentException('The chunk length must be greater than zero.');
707
        }
708
709 13
        if ($this->str === '') {
710 2
            return [];
711
        }
712
713 11
        $chunks = $this->utf8::str_split($this->str, $length);
714
715
        /** @noinspection AlterInForeachInspection */
716 11
        foreach ($chunks as $i => &$value) {
717 11
            $value = static::create($value, $this->encoding);
718
        }
719
720
        /** @noinspection PhpSillyAssignmentInspection */
721
        /** @var static[] $chunks */
722 11
        $chunks = $chunks;
0 ignored issues
show
Bug introduced by
Why assign $chunks to itself?

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

This assignement can be removed without consequences.

Loading history...
723
724 11
        return $chunks;
725
    }
726
727
    /**
728
     * Splits the string into chunks of Stringy objects collection.
729
     *
730
     * EXAMPLE: <code>
731
     * </code>
732
     *
733
     * @param int $length [optional] <p>Max character length of each array element.</p>
734
     *
735
     * @psalm-mutation-free
736
     *
737
     * @return CollectionStringy|static[]
738
     *                                    <p>An collection of Stringy objects.</p>
739
     *
740
     * @psalm-return CollectionStringy<int,static>
741
     */
742 7
    public function chunkCollection(int $length = 1): CollectionStringy
743
    {
744
        /**
745
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
746
         */
747 7
        return CollectionStringy::create(
748 7
            $this->chunk($length)
749
        );
750
    }
751
752
    /**
753
     * Trims the string and replaces consecutive whitespace characters with a
754
     * single space. This includes tabs and newline characters, as well as
755
     * multibyte whitespace such as the thin space and ideographic space.
756
     *
757
     * EXAMPLE: <code>
758
     * s('   Ο     συγγραφέας  ')->collapseWhitespace(); // 'Ο συγγραφέας'
759
     * </code>
760
     *
761
     * @psalm-mutation-free
762
     *
763
     * @return static
764
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
765
     */
766 39
    public function collapseWhitespace(): self
767
    {
768 39
        return static::create(
769 39
            $this->utf8::collapse_whitespace($this->str),
770 39
            $this->encoding
771
        );
772
    }
773
774
    /**
775
     * Returns true if the string contains $needle, false otherwise. By default
776
     * the comparison is case-sensitive, but can be made insensitive by setting
777
     * $caseSensitive to false.
778
     *
779
     * EXAMPLE: <code>
780
     * s('Ο συγγραφέας είπε')->contains('συγγραφέας'); // true
781
     * </code>
782
     *
783
     * @param string $needle        <p>Substring to look for.</p>
784
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
785
     *
786
     * @psalm-mutation-free
787
     *
788
     * @return bool
789
     *              <p>Whether or not $str contains $needle.</p>
790
     */
791 63
    public function contains(string $needle, bool $caseSensitive = true): bool
792
    {
793 63
        return $this->utf8::str_contains(
794 63
            $this->str,
795
            $needle,
796
            $caseSensitive
797
        );
798
    }
799
800
    /**
801
     * Returns true if the string contains all $needles, false otherwise. By
802
     * default the comparison is case-sensitive, but can be made insensitive by
803
     * setting $caseSensitive to false.
804
     *
805
     * EXAMPLE: <code>
806
     * s('foo & bar')->containsAll(['foo', 'bar']); // true
807
     * </code>
808
     *
809
     * @param string[] $needles       <p>SubStrings to look for.</p>
810
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
811
     *
812
     * @psalm-mutation-free
813
     *
814
     * @return bool
815
     *              <p>Whether or not $str contains $needle.</p>
816
     */
817 131
    public function containsAll(array $needles, bool $caseSensitive = true): bool
818
    {
819 131
        return $this->utf8::str_contains_all(
820 131
            $this->str,
821
            $needles,
822
            $caseSensitive
823
        );
824
    }
825
826
    /**
827
     * Returns true if the string contains any $needles, false otherwise. By
828
     * default the comparison is case-sensitive, but can be made insensitive by
829
     * setting $caseSensitive to false.
830
     *
831
     * EXAMPLE: <code>
832
     * s('str contains foo')->containsAny(['foo', 'bar']); // true
833
     * </code>
834
     *
835
     * @param string[] $needles       <p>SubStrings to look for.</p>
836
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
837
     *
838
     * @psalm-mutation-free
839
     *
840
     * @return bool
841
     *              <p>Whether or not $str contains $needle.</p>
842
     */
843 129
    public function containsAny(array $needles, bool $caseSensitive = true): bool
844
    {
845 129
        return $this->utf8::str_contains_any(
846 129
            $this->str,
847
            $needles,
848
            $caseSensitive
849
        );
850
    }
851
852
    /**
853
     * Checks if string starts with "BOM" (Byte Order Mark Character) character.
854
     *
855
     * EXAMPLE: <code>s("\xef\xbb\xbf foobar")->containsBom(); // true</code>
856
     *
857
     * @psalm-mutation-free
858
     *
859
     * @return bool
860
     *              <strong>true</strong> if the string has BOM at the start,<br>
861
     *              <strong>false</strong> otherwise
862
     */
863
    public function containsBom(): bool
864
    {
865
        return $this->utf8::string_has_bom($this->str);
866
    }
867
868
    /**
869
     * Returns the length of the string, implementing the countable interface.
870
     *
871
     * EXAMPLE: <code>
872
     * </code>
873
     *
874
     * @psalm-mutation-free
875
     *
876
     * @return int
877
     *             <p>The number of characters in the string, given the encoding.</p>
878
     */
879 3
    public function count(): int
880
    {
881 3
        return $this->length();
882
    }
883
884
    /**
885
     * Returns the number of occurrences of $substring in the given string.
886
     * By default, the comparison is case-sensitive, but can be made insensitive
887
     * by setting $caseSensitive to false.
888
     *
889
     * EXAMPLE: <code>
890
     * s('Ο συγγραφέας είπε')->countSubstr('α'); // 2
891
     * </code>
892
     *
893
     * @param string $substring     <p>The substring to search for.</p>
894
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
895
     *
896
     * @psalm-mutation-free
897
     *
898
     * @return int
899
     */
900 45
    public function countSubstr(string $substring, bool $caseSensitive = true): int
901
    {
902 45
        return $this->utf8::substr_count_simple(
903 45
            $this->str,
904
            $substring,
905
            $caseSensitive,
906 45
            $this->encoding
907
        );
908
    }
909
910
    /**
911
     * Calculates the crc32 polynomial of a string.
912
     *
913
     * EXAMPLE: <code>
914
     * </code>
915
     *
916
     * @psalm-mutation-free
917
     *
918
     * @return int
919
     */
920 2
    public function crc32(): int
921
    {
922 2
        return \crc32($this->str);
923
    }
924
925
    /**
926
     * Creates a Stringy object and assigns both str and encoding properties
927
     * the supplied values. $str is cast to a string prior to assignment, and if
928
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
929
     * then returns the initialized object. Throws an InvalidArgumentException
930
     * if the first argument is an array or object without a __toString method.
931
     *
932
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
933
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
934
     *
935
     * @throws \InvalidArgumentException
936
     *                                   <p>if an array or object without a
937
     *                                   __toString method is passed as the first argument</p>
938
     *
939
     * @return static
940
     *                <p>A Stringy object.</p>
941
     * @psalm-pure
942
     */
943 3568
    public static function create($str = '', string $encoding = null): self
944
    {
945 3568
        return new static($str, $encoding);
946
    }
947
948
    /**
949
     * One-way string encryption (hashing).
950
     *
951
     * Hash the string using the standard Unix DES-based algorithm or an
952
     * alternative algorithm that may be available on the system.
953
     *
954
     * PS: if you need encrypt / decrypt, please use ```static::encrypt($password)```
955
     *     and ```static::decrypt($password)```
956
     *
957
     * EXAMPLE: <code>
958
     * </code>
959
     *
960
     * @param string $salt <p>A salt string to base the hashing on.</p>
961
     *
962
     * @psalm-mutation-free
963
     *
964
     * @return static
965
     */
966 3
    public function crypt(string $salt): self
967
    {
968 3
        return new static(
969 3
            \crypt(
970 3
                $this->str,
971 3
                $salt
972
            ),
973 3
            $this->encoding
974
        );
975
    }
976
977
    /**
978
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
979
     * inserted before uppercase characters (with the exception of the first
980
     * character of the string), and in place of spaces as well as underscores.
981
     *
982
     * EXAMPLE: <code>
983
     * s('fooBar')->dasherize(); // 'foo-bar'
984
     * </code>
985
     *
986
     * @psalm-mutation-free
987
     *
988
     * @return static
989
     *                <p>Object with a dasherized $str</p>
990
     */
991 57
    public function dasherize(): self
992
    {
993 57
        return static::create(
994 57
            $this->utf8::str_dasherize($this->str),
995 57
            $this->encoding
996
        );
997
    }
998
999
    /**
1000
     * Decrypt the string.
1001
     *
1002
     * EXAMPLE: <code>
1003
     * </code>
1004
     *
1005
     * @param string $password The key for decrypting
1006
     *
1007
     * @psalm-mutation-free
1008
     *
1009
     * @return static
1010
     */
1011 5
    public function decrypt(string $password): self
1012
    {
1013
        /**
1014
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff
1015
         */
1016 5
        return new static(
1017 5
            Crypto::decryptWithPassword($this->str, $password),
1018 3
            $this->encoding
1019
        );
1020
    }
1021
1022
    /**
1023
     * Returns a lowercase and trimmed string separated by the given delimiter.
1024
     * Delimiters are inserted before uppercase characters (with the exception
1025
     * of the first character of the string), and in place of spaces, dashes,
1026
     * and underscores. Alpha delimiters are not converted to lowercase.
1027
     *
1028
     * EXAMPLE: <code>
1029
     * s('fooBar')->delimit('::'); // 'foo::bar'
1030
     * </code>
1031
     *
1032
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
1033
     *
1034
     * @psalm-mutation-free
1035
     *
1036
     * @return static
1037
     *                <p>Object with a delimited $str.</p>
1038
     */
1039 90
    public function delimit(string $delimiter): self
1040
    {
1041 90
        return static::create(
1042 90
            $this->utf8::str_delimit($this->str, $delimiter),
1043 90
            $this->encoding
1044
        );
1045
    }
1046
1047
    /**
1048
     * Encode the given string into the given $encoding + set the internal character encoding.
1049
     *
1050
     * EXAMPLE: <code>
1051
     * </code>
1052
     *
1053
     * @param string $new_encoding         <p>The desired character encoding.</p>
1054
     * @param bool   $auto_detect_encoding [optional] <p>Auto-detect the current string-encoding</p>
1055
     *
1056
     * @psalm-mutation-free
1057
     *
1058
     * @return static
1059
     */
1060 2
    public function encode(string $new_encoding, bool $auto_detect_encoding = false): self
1061
    {
1062 2
        if ($auto_detect_encoding) {
1063 1
            $str = $this->utf8::encode(
1064 1
                $new_encoding,
1065 1
                $this->str
1066
            );
1067
        } else {
1068 1
            $str = $this->utf8::encode(
1069 1
                $new_encoding,
1070 1
                $this->str,
1071 1
                false,
1072 1
                $this->encoding
1073
            );
1074
        }
1075
1076 2
        return new static($str, $new_encoding);
1077
    }
1078
1079
    /**
1080
     * Encrypt the string.
1081
     *
1082
     * EXAMPLE: <code>
1083
     * </code>
1084
     *
1085
     * @param string $password <p>The key for encrypting</p>
1086
     *
1087
     * @psalm-mutation-free
1088
     *
1089
     * @return static
1090
     */
1091 4
    public function encrypt(string $password): self
1092
    {
1093
        /**
1094
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff
1095
         */
1096 4
        return new static(
1097 4
            Crypto::encryptWithPassword($this->str, $password),
1098 4
            $this->encoding
1099
        );
1100
    }
1101
1102
    /**
1103
     * Returns true if the string ends with $substring, false otherwise. By
1104
     * default, the comparison is case-sensitive, but can be made insensitive
1105
     * by setting $caseSensitive to false.
1106
     *
1107
     * EXAMPLE: <code>
1108
     * s('fòôbàř')->endsWith('bàř', true); // true
1109
     * </code>
1110
     *
1111
     * @param string $substring     <p>The substring to look for.</p>
1112
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1113
     *
1114
     * @psalm-mutation-free
1115
     *
1116
     * @return bool
1117
     *              <p>Whether or not $str ends with $substring.</p>
1118
     */
1119 97
    public function endsWith(string $substring, bool $caseSensitive = true): bool
1120
    {
1121 97
        if ($caseSensitive) {
1122 53
            return $this->utf8::str_ends_with($this->str, $substring);
1123
        }
1124
1125 44
        return $this->utf8::str_iends_with($this->str, $substring);
1126
    }
1127
1128
    /**
1129
     * Returns true if the string ends with any of $substrings, false otherwise.
1130
     * By default, the comparison is case-sensitive, but can be made insensitive
1131
     * by setting $caseSensitive to false.
1132
     *
1133
     * EXAMPLE: <code>
1134
     * s('fòôbàř')->endsWithAny(['bàř', 'baz'], true); // true
1135
     * </code>
1136
     *
1137
     * @param string[] $substrings    <p>Substrings to look for.</p>
1138
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1139
     *
1140
     * @psalm-mutation-free
1141
     *
1142
     * @return bool
1143
     *              <p>Whether or not $str ends with $substring.</p>
1144
     */
1145 33
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
1146
    {
1147 33
        if ($caseSensitive) {
1148 21
            return $this->utf8::str_ends_with_any($this->str, $substrings);
1149
        }
1150
1151 12
        return $this->utf8::str_iends_with_any($this->str, $substrings);
1152
    }
1153
1154
    /**
1155
     * Ensures that the string begins with $substring. If it doesn't, it's
1156
     * prepended.
1157
     *
1158
     * EXAMPLE: <code>
1159
     * s('foobar')->ensureLeft('http://'); // 'http://foobar'
1160
     * </code>
1161
     *
1162
     * @param string $substring <p>The substring to add if not present.</p>
1163
     *
1164
     * @psalm-mutation-free
1165
     *
1166
     * @return static
1167
     *                <p>Object with its $str prefixed by the $substring.</p>
1168
     */
1169 30
    public function ensureLeft(string $substring): self
1170
    {
1171 30
        return static::create(
1172 30
            $this->utf8::str_ensure_left($this->str, $substring),
1173 30
            $this->encoding
1174
        );
1175
    }
1176
1177
    /**
1178
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
1179
     *
1180
     * EXAMPLE: <code>
1181
     * s('foobar')->ensureRight('.com'); // 'foobar.com'
1182
     * </code>
1183
     *
1184
     * @param string $substring <p>The substring to add if not present.</p>
1185
     *
1186
     * @psalm-mutation-free
1187
     *
1188
     * @return static
1189
     *                <p>Object with its $str suffixed by the $substring.</p>
1190
     */
1191 30
    public function ensureRight(string $substring): self
1192
    {
1193 30
        return static::create(
1194 30
            $this->utf8::str_ensure_right($this->str, $substring),
1195 30
            $this->encoding
1196
        );
1197
    }
1198
1199
    /**
1200
     * Create a escape html version of the string via "htmlspecialchars()".
1201
     *
1202
     * EXAMPLE: <code>
1203
     * s('<∂∆ onerror="alert(xss)">')->escape(); // '&lt;∂∆ onerror=&quot;alert(xss)&quot;&gt;'
1204
     * </code>
1205
     *
1206
     * @psalm-mutation-free
1207
     *
1208
     * @return static
1209
     */
1210 12
    public function escape(): self
1211
    {
1212 12
        return static::create(
1213 12
            $this->utf8::htmlspecialchars(
1214 12
                $this->str,
1215 12
                \ENT_QUOTES | \ENT_SUBSTITUTE,
1216 12
                $this->encoding
1217
            ),
1218 12
            $this->encoding
1219
        );
1220
    }
1221
1222
    /**
1223
     * Split a string by a string.
1224
     *
1225
     * EXAMPLE: <code>
1226
     * </code>
1227
     *
1228
     * @param string $delimiter <p>The boundary string</p>
1229
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1230
     *                          collection.</p>
1231
     *
1232
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1233
     *   element containing the rest of string.
1234
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1235
     *   - If the limit parameter is zero, then this is treated as 1
1236
     *
1237
     * @psalm-mutation-free
1238
     *
1239
     * @return array<int,static>
1240
     */
1241 3
    public function explode(string $delimiter, int $limit = \PHP_INT_MAX): array
1242
    {
1243 3
        if ($this->str === '') {
1244
            return [];
1245
        }
1246
1247 3
        $strings = \explode($delimiter, $this->str, $limit);
1248
        /** @phpstan-ignore-next-line - if "$delimiter" is an empty string, then "explode()" will return "false" */
1249 3
        if ($strings === false) {
1250
            $strings = [];
1251
        }
1252
1253 3
        return \array_map(
1254 3
            function ($str) {
1255 3
                return new static($str, $this->encoding);
1256 3
            },
1257 3
            $strings
1258
        );
1259
    }
1260
1261
    /**
1262
     * Split a string by a string.
1263
     *
1264
     * EXAMPLE: <code>
1265
     * </code>
1266
     *
1267
     * @param string $delimiter <p>The boundary string</p>
1268
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1269
     *                          collection.</p>
1270
     *
1271
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1272
     *   element containing the rest of string.
1273
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1274
     *   - If the limit parameter is zero, then this is treated as 1
1275
     *
1276
     * @psalm-mutation-free
1277
     *
1278
     * @return CollectionStringy|static[]
1279
     *                                    <p>An collection of Stringy objects.</p>
1280
     *
1281
     * @psalm-return CollectionStringy<int,static>
1282
     */
1283 1
    public function explodeCollection(string $delimiter, int $limit = \PHP_INT_MAX): CollectionStringy
1284
    {
1285
        /**
1286
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
1287
         */
1288 1
        return CollectionStringy::create(
1289 1
            $this->explode($delimiter, $limit)
1290
        );
1291
    }
1292
1293
    /**
1294
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
1295
     *
1296
     * EXAMPLE: <code>
1297
     * $sentence = 'This is only a Fork of Stringy, take a look at the new features.';
1298
     * s($sentence)->extractText('Stringy'); // '...Fork of Stringy...'
1299
     * </code>
1300
     *
1301
     * @param string   $search
1302
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
1303
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
1304
     *
1305
     * @psalm-mutation-free
1306
     *
1307
     * @return static
1308
     */
1309 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
1310
    {
1311 2
        return static::create(
1312 2
            $this->utf8::extract_text(
1313 2
                $this->str,
1314
                $search,
1315
                $length,
1316
                $replacerForSkippedText,
1317 2
                $this->encoding
1318
            ),
1319 2
            $this->encoding
1320
        );
1321
    }
1322
1323
    /**
1324
     * Returns the first $n characters of the string.
1325
     *
1326
     * EXAMPLE: <code>
1327
     * s('fòôbàř')->first(3); // 'fòô'
1328
     * </code>
1329
     *
1330
     * @param int $n <p>Number of characters to retrieve from the start.</p>
1331
     *
1332
     * @psalm-mutation-free
1333
     *
1334
     * @return static
1335
     *                <p>Object with its $str being the first $n chars.</p>
1336
     */
1337 37
    public function first(int $n): self
1338
    {
1339 37
        return static::create(
1340 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
1341 37
            $this->encoding
1342
        );
1343
    }
1344
1345
    /**
1346
     * Return a formatted string via sprintf + named parameters via array syntax.
1347
     *
1348
     * <p>
1349
     * <br>
1350
     * It will use "sprintf()" so you can use e.g.:
1351
     * <br>
1352
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
1353
     * <br>
1354
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
1355
     * <br>
1356
     * <br>
1357
     * But you can also use named parameter via array syntax e.g.:
1358
     * <br>
1359
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
1360
     * </p>
1361
     *
1362
     * EXAMPLE: <code>
1363
     * $input = 'one: %2$d, %1$s: 2, %:text_three: %3$d';
1364
     * s($input)->format(['text_three' => '%4$s'], 'two', 1, 3, 'three'); // 'One: 1, two: 2, three: 3'
1365
     * </code>
1366
     *
1367
     * @param mixed ...$args [optional]
1368
     *
1369
     * @psalm-mutation-free
1370
     *
1371
     * @return static
1372
     *                <p>A Stringy object produced according to the formatting string
1373
     *                format.</p>
1374
     */
1375 10
    public function format(...$args): self
1376
    {
1377
        // init
1378 10
        $str = $this->str;
1379
1380 10
        if (\strpos($this->str, '%:') !== false) {
1381 8
            $offset = null;
1382 8
            $replacement = null;
1383
            /** @noinspection AlterInForeachInspection */
1384 8
            foreach ($args as $key => &$arg) {
1385 8
                if (!\is_array($arg)) {
1386 4
                    continue;
1387
                }
1388
1389 8
                foreach ($arg as $name => $param) {
1390 8
                    $name = (string) $name;
1391
1392 8
                    if (\strpos($name, '%:') !== 0) {
1393 8
                        $nameTmp = '%:' . $name;
1394
                    } else {
1395
                        $nameTmp = $name;
1396
                    }
1397
1398 8
                    if ($offset === null) {
1399 8
                        $offset = \strpos($str, $nameTmp);
1400
                    } else {
1401 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
1402
                    }
1403 8
                    if ($offset === false) {
1404 4
                        continue;
1405
                    }
1406
1407 8
                    unset($arg[$name]);
1408
1409 8
                    $str = \substr_replace($str, (string) $param, (int) $offset, \strlen($nameTmp));
1410
                }
1411
1412 8
                unset($args[$key]);
1413
            }
1414
        }
1415
1416 10
        $str = \str_replace('%:', '%%:', $str);
1417
1418 10
        return static::create(
1419 10
            \sprintf($str, ...$args),
1420 10
            $this->encoding
1421
        );
1422
    }
1423
1424
    /**
1425
     * Returns the encoding used by the Stringy object.
1426
     *
1427
     * EXAMPLE: <code>
1428
     * s('fòôbàř', 'UTF-8')->getEncoding(); // 'UTF-8'
1429
     * </code>
1430
     *
1431
     * @psalm-mutation-free
1432
     *
1433
     * @return string
1434
     *                <p>The current value of the $encoding property.</p>
1435
     */
1436 25
    public function getEncoding(): string
1437
    {
1438 25
        return $this->encoding;
1439
    }
1440
1441
    /**
1442
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
1443
     * interface. The ArrayIterator's constructor is passed an array of chars
1444
     * in the multibyte string. This enables the use of foreach with instances
1445
     * of Stringy\Stringy.
1446
     *
1447
     * EXAMPLE: <code>
1448
     * </code>
1449
     *
1450
     * @psalm-mutation-free
1451
     *
1452
     * @return \ArrayIterator
1453
     *                        <p>An iterator for the characters in the string.</p>
1454
     *
1455
     * @psalm-return \ArrayIterator<array-key,string>
1456
     */
1457 3
    public function getIterator(): \ArrayIterator
1458
    {
1459 3
        return new \ArrayIterator($this->chars());
1460
    }
1461
1462
    /**
1463
     * Wrap the string after an exact number of characters.
1464
     *
1465
     * EXAMPLE: <code>
1466
     * </code>
1467
     *
1468
     * @param int    $width <p>Number of characters at which to wrap.</p>
1469
     * @param string $break [optional] <p>Character used to break the string. | Default: "\n"</p>
1470
     *
1471
     * @psalm-mutation-free
1472
     *
1473
     * @return static
1474
     */
1475 2
    public function hardWrap($width, $break = "\n"): self
1476
    {
1477 2
        return $this->lineWrap($width, $break, false);
1478
    }
1479
1480
    /**
1481
     * Returns true if the string contains a lower case char, false otherwise
1482
     *
1483
     * EXAMPLE: <code>
1484
     * s('fòôbàř')->hasLowerCase(); // true
1485
     * </code>
1486
     *
1487
     * @psalm-mutation-free
1488
     *
1489
     * @return bool
1490
     *              <p>Whether or not the string contains a lower case character.</p>
1491
     */
1492 36
    public function hasLowerCase(): bool
1493
    {
1494 36
        return $this->utf8::has_lowercase($this->str);
1495
    }
1496
1497
    /**
1498
     * Returns true if the string contains an upper case char, false otherwise.
1499
     *
1500
     * EXAMPLE: <code>
1501
     * s('fòôbàř')->hasUpperCase(); // false
1502
     * </code>
1503
     *
1504
     * @psalm-mutation-free
1505
     *
1506
     * @return bool
1507
     *              <p>Whether or not the string contains an upper case character.</p>
1508
     */
1509 36
    public function hasUpperCase(): bool
1510
    {
1511 36
        return $this->utf8::has_uppercase($this->str);
1512
    }
1513
1514
    /**
1515
     * Generate a hash value (message digest).
1516
     *
1517
     * EXAMPLE: <code>
1518
     * </code>
1519
     *
1520
     * @see https://php.net/manual/en/function.hash.php
1521
     *
1522
     * @param string $algorithm
1523
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
1524
     *
1525
     * @psalm-mutation-free
1526
     *
1527
     * @return static
1528
     */
1529 8
    public function hash($algorithm): self
1530
    {
1531 8
        return static::create(\hash($algorithm, $this->str), $this->encoding);
1532
    }
1533
1534
    /**
1535
     * Decode the string from hex.
1536
     *
1537
     * EXAMPLE: <code>
1538
     * </code>
1539
     *
1540
     * @psalm-mutation-free
1541
     *
1542
     * @return static
1543
     */
1544 2
    public function hexDecode(): self
1545
    {
1546 2
        $string = \preg_replace_callback(
1547 2
            '/\\\\x([0-9A-Fa-f]+)/',
1548 2
            function (array $matched) {
1549 2
                return (string) $this->utf8::hex_to_chr($matched[1]);
1550 2
            },
1551 2
            $this->str
1552
        );
1553
1554 2
        return static::create(
1555 2
            $string,
1556 2
            $this->encoding
1557
        );
1558
    }
1559
1560
    /**
1561
     * Encode string to hex.
1562
     *
1563
     * EXAMPLE: <code>
1564
     * </code>
1565
     *
1566
     * @psalm-mutation-free
1567
     *
1568
     * @return static
1569
     */
1570 2
    public function hexEncode(): self
1571
    {
1572 2
        $string = \array_reduce(
1573 2
            $this->chars(),
1574 2
            function (string $str, string $char) {
1575 2
                return $str . $this->utf8::chr_to_hex($char);
1576 2
            },
1577 2
            ''
1578
        );
1579
1580 2
        return static::create(
1581 2
            $string,
1582 2
            $this->encoding
1583
        );
1584
    }
1585
1586
    /**
1587
     * Convert all HTML entities to their applicable characters.
1588
     *
1589
     * EXAMPLE: <code>
1590
     * s('&amp;')->htmlDecode(); // '&'
1591
     * </code>
1592
     *
1593
     * @param int $flags [optional] <p>
1594
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1595
     *                   which document type to use. The default is ENT_COMPAT.
1596
     *                   <table>
1597
     *                   Available <i>flags</i> constants
1598
     *                   <tr valign="top">
1599
     *                   <td>Constant Name</td>
1600
     *                   <td>Description</td>
1601
     *                   </tr>
1602
     *                   <tr valign="top">
1603
     *                   <td><b>ENT_COMPAT</b></td>
1604
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1605
     *                   </tr>
1606
     *                   <tr valign="top">
1607
     *                   <td><b>ENT_QUOTES</b></td>
1608
     *                   <td>Will convert both double and single quotes.</td>
1609
     *                   </tr>
1610
     *                   <tr valign="top">
1611
     *                   <td><b>ENT_NOQUOTES</b></td>
1612
     *                   <td>Will leave both double and single quotes unconverted.</td>
1613
     *                   </tr>
1614
     *                   <tr valign="top">
1615
     *                   <td><b>ENT_HTML401</b></td>
1616
     *                   <td>
1617
     *                   Handle code as HTML 4.01.
1618
     *                   </td>
1619
     *                   </tr>
1620
     *                   <tr valign="top">
1621
     *                   <td><b>ENT_XML1</b></td>
1622
     *                   <td>
1623
     *                   Handle code as XML 1.
1624
     *                   </td>
1625
     *                   </tr>
1626
     *                   <tr valign="top">
1627
     *                   <td><b>ENT_XHTML</b></td>
1628
     *                   <td>
1629
     *                   Handle code as XHTML.
1630
     *                   </td>
1631
     *                   </tr>
1632
     *                   <tr valign="top">
1633
     *                   <td><b>ENT_HTML5</b></td>
1634
     *                   <td>
1635
     *                   Handle code as HTML 5.
1636
     *                   </td>
1637
     *                   </tr>
1638
     *                   </table>
1639
     *                   </p>
1640
     *
1641
     * @psalm-mutation-free
1642
     *
1643
     * @return static
1644
     *                <p>Object with the resulting $str after being html decoded.</p>
1645
     */
1646 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...
1647
    {
1648 15
        return static::create(
1649 15
            $this->utf8::html_entity_decode(
1650 15
                $this->str,
1651
                $flags,
1652 15
                $this->encoding
1653
            ),
1654 15
            $this->encoding
1655
        );
1656
    }
1657
1658
    /**
1659
     * Convert all applicable characters to HTML entities.
1660
     *
1661
     * EXAMPLE: <code>
1662
     * s('&')->htmlEncode(); // '&amp;'
1663
     * </code>
1664
     *
1665
     * @param int $flags [optional] <p>
1666
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1667
     *                   which document type to use. The default is ENT_COMPAT.
1668
     *                   <table>
1669
     *                   Available <i>flags</i> constants
1670
     *                   <tr valign="top">
1671
     *                   <td>Constant Name</td>
1672
     *                   <td>Description</td>
1673
     *                   </tr>
1674
     *                   <tr valign="top">
1675
     *                   <td><b>ENT_COMPAT</b></td>
1676
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1677
     *                   </tr>
1678
     *                   <tr valign="top">
1679
     *                   <td><b>ENT_QUOTES</b></td>
1680
     *                   <td>Will convert both double and single quotes.</td>
1681
     *                   </tr>
1682
     *                   <tr valign="top">
1683
     *                   <td><b>ENT_NOQUOTES</b></td>
1684
     *                   <td>Will leave both double and single quotes unconverted.</td>
1685
     *                   </tr>
1686
     *                   <tr valign="top">
1687
     *                   <td><b>ENT_HTML401</b></td>
1688
     *                   <td>
1689
     *                   Handle code as HTML 4.01.
1690
     *                   </td>
1691
     *                   </tr>
1692
     *                   <tr valign="top">
1693
     *                   <td><b>ENT_XML1</b></td>
1694
     *                   <td>
1695
     *                   Handle code as XML 1.
1696
     *                   </td>
1697
     *                   </tr>
1698
     *                   <tr valign="top">
1699
     *                   <td><b>ENT_XHTML</b></td>
1700
     *                   <td>
1701
     *                   Handle code as XHTML.
1702
     *                   </td>
1703
     *                   </tr>
1704
     *                   <tr valign="top">
1705
     *                   <td><b>ENT_HTML5</b></td>
1706
     *                   <td>
1707
     *                   Handle code as HTML 5.
1708
     *                   </td>
1709
     *                   </tr>
1710
     *                   </table>
1711
     *                   </p>
1712
     *
1713
     * @psalm-mutation-free
1714
     *
1715
     * @return static
1716
     *                <p>Object with the resulting $str after being html encoded.</p>
1717
     */
1718 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...
1719
    {
1720 15
        return static::create(
1721 15
            $this->utf8::htmlentities(
1722 15
                $this->str,
1723
                $flags,
1724 15
                $this->encoding
1725
            ),
1726 15
            $this->encoding
1727
        );
1728
    }
1729
1730
    /**
1731
     * Capitalizes the first word of the string, replaces underscores with
1732
     * spaces, and strips '_id'.
1733
     *
1734
     * EXAMPLE: <code>
1735
     * s('author_id')->humanize(); // 'Author'
1736
     * </code>
1737
     *
1738
     * @psalm-mutation-free
1739
     *
1740
     * @return static
1741
     *                <p>Object with a humanized $str.</p>
1742
     */
1743 9
    public function humanize(): self
1744
    {
1745 9
        return static::create(
1746 9
            $this->utf8::str_humanize($this->str),
1747 9
            $this->encoding
1748
        );
1749
    }
1750
1751
    /**
1752
     * Determine if the current string exists in another string. By
1753
     * default, the comparison is case-sensitive, but can be made insensitive
1754
     * by setting $caseSensitive to false.
1755
     *
1756
     * EXAMPLE: <code>
1757
     * </code>
1758
     *
1759
     * @param string $str           <p>The string to compare against.</p>
1760
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1761
     *
1762
     * @psalm-mutation-free
1763
     *
1764
     * @return bool
1765
     */
1766 3
    public function in(string $str, bool $caseSensitive = true): bool
1767
    {
1768 3
        if ($caseSensitive) {
1769 2
            return \strpos($str, $this->str) !== false;
1770
        }
1771
1772 1
        return \stripos($str, $this->str) !== false;
1773
    }
1774
1775
    /**
1776
     * Returns the index of the first occurrence of $needle in the string,
1777
     * and false if not found. Accepts an optional offset from which to begin
1778
     * the search.
1779
     *
1780
     * EXAMPLE: <code>
1781
     * s('string')->indexOf('ing'); // 3
1782
     * </code>
1783
     *
1784
     * @param string $needle <p>Substring to look for.</p>
1785
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1786
     *
1787
     * @psalm-mutation-free
1788
     *
1789
     * @return false|int
1790
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1791
     */
1792 31
    public function indexOf(string $needle, int $offset = 0)
1793
    {
1794 31
        return $this->utf8::strpos(
1795 31
            $this->str,
1796
            $needle,
1797
            $offset,
1798 31
            $this->encoding
1799
        );
1800
    }
1801
1802
    /**
1803
     * Returns the index of the first occurrence of $needle in the string,
1804
     * and false if not found. Accepts an optional offset from which to begin
1805
     * the search.
1806
     *
1807
     * EXAMPLE: <code>
1808
     * s('string')->indexOfIgnoreCase('ING'); // 3
1809
     * </code>
1810
     *
1811
     * @param string $needle <p>Substring to look for.</p>
1812
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1813
     *
1814
     * @psalm-mutation-free
1815
     *
1816
     * @return false|int
1817
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1818
     */
1819 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1820
    {
1821 20
        return $this->utf8::stripos(
1822 20
            $this->str,
1823
            $needle,
1824
            $offset,
1825 20
            $this->encoding
1826
        );
1827
    }
1828
1829
    /**
1830
     * Returns the index of the last occurrence of $needle in the string,
1831
     * and false if not found. Accepts an optional offset from which to begin
1832
     * the search. Offsets may be negative to count from the last character
1833
     * in the string.
1834
     *
1835
     * EXAMPLE: <code>
1836
     * s('foobarfoo')->indexOfLast('foo'); // 10
1837
     * </code>
1838
     *
1839
     * @param string $needle <p>Substring to look for.</p>
1840
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1841
     *
1842
     * @psalm-mutation-free
1843
     *
1844
     * @return false|int
1845
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1846
     */
1847 31
    public function indexOfLast(string $needle, int $offset = 0)
1848
    {
1849 31
        return $this->utf8::strrpos(
1850 31
            $this->str,
1851
            $needle,
1852
            $offset,
1853 31
            $this->encoding
1854
        );
1855
    }
1856
1857
    /**
1858
     * Returns the index of the last occurrence of $needle in the string,
1859
     * and false if not found. Accepts an optional offset from which to begin
1860
     * the search. Offsets may be negative to count from the last character
1861
     * in the string.
1862
     *
1863
     * EXAMPLE: <code>
1864
     * s('fooBarFoo')->indexOfLastIgnoreCase('foo'); // 10
1865
     * </code>
1866
     *
1867
     * @param string $needle <p>Substring to look for.</p>
1868
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1869
     *
1870
     * @psalm-mutation-free
1871
     *
1872
     * @return false|int
1873
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1874
     */
1875 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1876
    {
1877 20
        return $this->utf8::strripos(
1878 20
            $this->str,
1879
            $needle,
1880
            $offset,
1881 20
            $this->encoding
1882
        );
1883
    }
1884
1885
    /**
1886
     * Inserts $substring into the string at the $index provided.
1887
     *
1888
     * EXAMPLE: <code>
1889
     * s('fòôbř')->insert('à', 4); // 'fòôbàř'
1890
     * </code>
1891
     *
1892
     * @param string $substring <p>String to be inserted.</p>
1893
     * @param int    $index     <p>The index at which to insert the substring.</p>
1894
     *
1895
     * @psalm-mutation-free
1896
     *
1897
     * @return static
1898
     *                <p>Object with the resulting $str after the insertion.</p>
1899
     */
1900 24
    public function insert(string $substring, int $index): self
1901
    {
1902 24
        return static::create(
1903 24
            $this->utf8::str_insert(
1904 24
                $this->str,
1905
                $substring,
1906
                $index,
1907 24
                $this->encoding
1908
            ),
1909 24
            $this->encoding
1910
        );
1911
    }
1912
1913
    /**
1914
     * Returns true if the string contains the $pattern, otherwise false.
1915
     *
1916
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1917
     * expression wildcards.
1918
     *
1919
     * EXAMPLE: <code>
1920
     * s('Foo\\Bar\\Lall')->is('*\\Bar\\*'); // true
1921
     * </code>
1922
     *
1923
     * @credit Originally from Laravel, thanks Taylor.
1924
     *
1925
     * @param string $pattern <p>The string or pattern to match against.</p>
1926
     *
1927
     * @psalm-mutation-free
1928
     *
1929
     * @return bool
1930
     *              <p>Whether or not we match the provided pattern.</p>
1931
     */
1932 26
    public function is(string $pattern): bool
1933
    {
1934 26
        if ($this->toString() === $pattern) {
1935 2
            return true;
1936
        }
1937
1938 24
        $quotedPattern = \preg_quote($pattern, '/');
1939 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1940
1941 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1942
    }
1943
1944
    /**
1945
     * Returns true if the string contains only alphabetic chars, false otherwise.
1946
     *
1947
     * EXAMPLE: <code>
1948
     * s('丹尼爾')->isAlpha(); // true
1949
     * </code>
1950
     *
1951
     * @psalm-mutation-free
1952
     *
1953
     * @return bool
1954
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1955
     */
1956 30
    public function isAlpha(): bool
1957
    {
1958 30
        return $this->utf8::is_alpha($this->str);
1959
    }
1960
1961
    /**
1962
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1963
     *
1964
     * EXAMPLE: <code>
1965
     * s('دانيال1')->isAlphanumeric(); // true
1966
     * </code>
1967
     *
1968
     * @psalm-mutation-free
1969
     *
1970
     * @return bool
1971
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1972
     */
1973 39
    public function isAlphanumeric(): bool
1974
    {
1975 39
        return $this->utf8::is_alphanumeric($this->str);
1976
    }
1977
1978
    /**
1979
     * Checks if a string is 7 bit ASCII.
1980
     *
1981
     * EXAMPLE: <code>s('白')->isAscii; // false</code>
1982
     *
1983
     * @psalm-mutation-free
1984
     *
1985
     * @return bool
1986
     *              <p>
1987
     *              <strong>true</strong> if it is ASCII<br>
1988
     *              <strong>false</strong> otherwise
1989
     *              </p>
1990
     *
1991
     * @noinspection GetSetMethodCorrectnessInspection
1992
     */
1993
    public function isAscii(): bool
1994
    {
1995
        return $this->utf8::is_ascii($this->str);
1996
    }
1997
1998
    /**
1999
     * Returns true if the string is base64 encoded, false otherwise.
2000
     *
2001
     * EXAMPLE: <code>
2002
     * s('Zm9vYmFy')->isBase64(); // true
2003
     * </code>
2004
     *
2005
     * @param bool $emptyStringIsValid
2006
     *
2007
     * @psalm-mutation-free
2008
     *
2009
     * @return bool
2010
     *              <p>Whether or not $str is base64 encoded.</p>
2011
     */
2012 21
    public function isBase64($emptyStringIsValid = true): bool
2013
    {
2014 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
2015
    }
2016
2017
    /**
2018
     * Check if the input is binary... (is look like a hack).
2019
     *
2020
     * EXAMPLE: <code>s(01)->isBinary(); // true</code>
2021
     *
2022
     * @psalm-mutation-free
2023
     *
2024
     * @return bool
2025
     */
2026
    public function isBinary(): bool
2027
    {
2028
        return $this->utf8::is_binary($this->str);
2029
    }
2030
2031
    /**
2032
     * Returns true if the string contains only whitespace chars, false otherwise.
2033
     *
2034
     * EXAMPLE: <code>
2035
     * s("\n\t  \v\f")->isBlank(); // true
2036
     * </code>
2037
     *
2038
     * @psalm-mutation-free
2039
     *
2040
     * @return bool
2041
     *              <p>Whether or not $str contains only whitespace characters.</p>
2042
     */
2043 45
    public function isBlank(): bool
2044
    {
2045 45
        return $this->utf8::is_blank($this->str);
2046
    }
2047
2048
    /**
2049
     * Checks if the given string is equal to any "Byte Order Mark".
2050
     *
2051
     * WARNING: Use "s::string_has_bom()" if you will check BOM in a string.
2052
     *
2053
     * EXAMPLE: <code>s->("\xef\xbb\xbf")->isBom(); // true</code>
2054
     *
2055
     * @psalm-mutation-free
2056
     *
2057
     * @return bool
2058
     *              <p><strong>true</strong> if the $utf8_chr is Byte Order Mark, <strong>false</strong> otherwise.</p>
2059
     */
2060
    public function isBom(): bool
2061
    {
2062
        return $this->utf8::is_bom($this->str);
2063
    }
2064
2065
    /**
2066
     * Returns true if the string contains a valid E-Mail address, false otherwise.
2067
     *
2068
     * EXAMPLE: <code>
2069
     * s('[email protected]')->isEmail(); // true
2070
     * </code>
2071
     *
2072
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
2073
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
2074
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
2075
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
2076
     *
2077
     * @psalm-mutation-free
2078
     *
2079
     * @return bool
2080
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
2081
     */
2082 2
    public function isEmail(
2083
        bool $useExampleDomainCheck = false,
2084
        bool $useTypoInDomainCheck = false,
2085
        bool $useTemporaryDomainCheck = false,
2086
        bool $useDnsCheck = false
2087
    ): bool {
2088
        /**
2089
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
2090
         */
2091 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
2092
    }
2093
2094
    /**
2095
     * Determine whether the string is considered to be empty.
2096
     *
2097
     * A variable is considered empty if it does not exist or if its value equals FALSE.
2098
     *
2099
     * EXAMPLE: <code>
2100
     * s('')->isEmpty(); // true
2101
     * </code>
2102
     *
2103
     * @psalm-mutation-free
2104
     *
2105
     * @return bool
2106
     *              <p>Whether or not $str is empty().</p>
2107
     */
2108 10
    public function isEmpty(): bool
2109
    {
2110 10
        return $this->utf8::is_empty($this->str);
2111
    }
2112
2113
    /**
2114
     * Determine whether the string is equals to $str.
2115
     * Alias for isEqualsCaseSensitive()
2116
     *
2117
     * EXAMPLE: <code>
2118
     * s('foo')->isEquals('foo'); // true
2119
     * </code>
2120
     *
2121
     * @param string|Stringy ...$str
2122
     *
2123
     * @psalm-mutation-free
2124
     *
2125
     * @return bool
2126
     */
2127 13
    public function isEquals(...$str): bool
2128
    {
2129 13
        return $this->isEqualsCaseSensitive(...$str);
2130
    }
2131
2132
    /**
2133
     * Determine whether the string is equals to $str.
2134
     *
2135
     * EXAMPLE: <code>
2136
     * </code>
2137
     *
2138
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
2139
     *
2140
     * @psalm-mutation-free
2141
     *
2142
     * @return bool
2143
     *              <p>Whether or not $str is equals.</p>
2144
     */
2145 3
    public function isEqualsCaseInsensitive(...$str): bool
2146
    {
2147 3
        $strUpper = $this->toUpperCase()->str;
2148
2149 3 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2150
            /**
2151
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
2152
             */
2153 3
            if ($strTmp instanceof self) {
2154
                if ($strUpper !== $strTmp->toUpperCase()->str) {
2155
                    return false;
2156
                }
2157 3
            } elseif (\is_scalar($strTmp)) {
2158 3
                if ($strUpper !== $this->utf8::strtoupper((string) $strTmp, $this->encoding)) {
2159 3
                    return false;
2160
                }
2161
            } else {
2162
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
2163
            }
2164
        }
2165
2166 3
        return true;
2167
    }
2168
2169
    /**
2170
     * Determine whether the string is equals to $str.
2171
     *
2172
     * EXAMPLE: <code>
2173
     * </code>
2174
     *
2175
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
2176
     *
2177
     * @psalm-mutation-free
2178
     *
2179
     * @return bool
2180
     *              <p>Whether or not $str is equals.</p>
2181
     */
2182 14
    public function isEqualsCaseSensitive(...$str): bool
2183
    {
2184 14 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2185
            /**
2186
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
2187
             */
2188 14
            if ($strTmp instanceof self) {
2189 2
                if ($this->str !== $strTmp->str) {
2190 2
                    return false;
2191
                }
2192 12
            } elseif (\is_scalar($strTmp)) {
2193 12
                if ($this->str !== (string) $strTmp) {
2194 12
                    return false;
2195
                }
2196
            } else {
2197
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
2198
            }
2199
        }
2200
2201 3
        return true;
2202
    }
2203
2204
    /**
2205
     * Returns true if the string contains only hexadecimal chars, false otherwise.
2206
     *
2207
     * EXAMPLE: <code>
2208
     * s('A102F')->isHexadecimal(); // true
2209
     * </code>
2210
     *
2211
     * @psalm-mutation-free
2212
     *
2213
     * @return bool
2214
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
2215
     */
2216 39
    public function isHexadecimal(): bool
2217
    {
2218 39
        return $this->utf8::is_hexadecimal($this->str);
2219
    }
2220
2221
    /**
2222
     * Returns true if the string contains HTML-Tags, false otherwise.
2223
     *
2224
     * EXAMPLE: <code>
2225
     * s('<h1>foo</h1>')->isHtml(); // true
2226
     * </code>
2227
     *
2228
     * @psalm-mutation-free
2229
     *
2230
     * @return bool
2231
     *              <p>Whether or not $str contains HTML-Tags.</p>
2232
     */
2233 2
    public function isHtml(): bool
2234
    {
2235 2
        return $this->utf8::is_html($this->str);
2236
    }
2237
2238
    /**
2239
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
2240
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
2241
     * in that an empty string is not considered valid JSON.
2242
     *
2243
     * EXAMPLE: <code>
2244
     * s('{"foo":"bar"}')->isJson(); // true
2245
     * </code>
2246
     *
2247
     * @param bool $onlyArrayOrObjectResultsAreValid
2248
     *
2249
     * @psalm-mutation-free
2250
     *
2251
     * @return bool
2252
     *              <p>Whether or not $str is JSON.</p>
2253
     */
2254 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
2255
    {
2256
        /**
2257
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff?
2258
         */
2259 60
        return $this->utf8::is_json(
2260 60
            $this->str,
2261
            $onlyArrayOrObjectResultsAreValid
2262
        );
2263
    }
2264
2265
    /**
2266
     * Returns true if the string contains only lower case chars, false otherwise.
2267
     *
2268
     * EXAMPLE: <code>
2269
     * s('fòôbàř')->isLowerCase(); // true
2270
     * </code>
2271
     *
2272
     * @psalm-mutation-free
2273
     *
2274
     * @return bool
2275
     *              <p>Whether or not $str contains only lower case characters.</p>
2276
     */
2277 24
    public function isLowerCase(): bool
2278
    {
2279 24
        return $this->utf8::is_lowercase($this->str);
2280
    }
2281
2282
    /**
2283
     * Determine whether the string is considered to be NOT empty.
2284
     *
2285
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
2286
     *
2287
     * EXAMPLE: <code>
2288
     * s('')->isNotEmpty(); // false
2289
     * </code>
2290
     *
2291
     * @psalm-mutation-free
2292
     *
2293
     * @return bool
2294
     *              <p>Whether or not $str is empty().</p>
2295
     */
2296 10
    public function isNotEmpty(): bool
2297
    {
2298 10
        return !$this->utf8::is_empty($this->str);
2299
    }
2300
2301
    /**
2302
     * Determine if the string is composed of numeric characters.
2303
     *
2304
     * EXAMPLE: <code>
2305
     * </code>
2306
     *
2307
     * @psalm-mutation-free
2308
     *
2309
     * @return bool
2310
     */
2311 4
    public function isNumeric(): bool
2312
    {
2313 4
        return \is_numeric($this->str);
2314
    }
2315
2316
    /**
2317
     * Determine if the string is composed of printable (non-invisible) characters.
2318
     *
2319
     * EXAMPLE: <code>
2320
     * </code>
2321
     *
2322
     * @psalm-mutation-free
2323
     *
2324
     * @return bool
2325
     */
2326 3
    public function isPrintable(): bool
2327
    {
2328 3
        return $this->utf8::is_printable($this->str);
2329
    }
2330
2331
    /**
2332
     * Determine if the string is composed of punctuation characters.
2333
     *
2334
     * EXAMPLE: <code>
2335
     * </code>
2336
     *
2337
     * @psalm-mutation-free
2338
     *
2339
     * @return bool
2340
     */
2341 3
    public function isPunctuation(): bool
2342
    {
2343 3
        return $this->utf8::is_punctuation($this->str);
2344
    }
2345
2346
    /**
2347
     * Returns true if the string is serialized, false otherwise.
2348
     *
2349
     * EXAMPLE: <code>
2350
     * s('a:1:{s:3:"foo";s:3:"bar";}')->isSerialized(); // true
2351
     * </code>
2352
     *
2353
     * @psalm-mutation-free
2354
     *
2355
     * @return bool
2356
     *              <p>Whether or not $str is serialized.</p>
2357
     */
2358 21
    public function isSerialized(): bool
2359
    {
2360 21
        return $this->utf8::is_serialized($this->str);
2361
    }
2362
2363
    /**
2364
     * Check if two strings are similar.
2365
     *
2366
     * EXAMPLE: <code>
2367
     * </code>
2368
     *
2369
     * @param string $str                     <p>The string to compare against.</p>
2370
     * @param float  $minPercentForSimilarity [optional] <p>The percentage of needed similarity. | Default: 80%</p>
2371
     *
2372
     * @psalm-mutation-free
2373
     *
2374
     * @return bool
2375
     */
2376 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
2377
    {
2378 2
        return $this->similarity($str) >= $minPercentForSimilarity;
2379
    }
2380
2381
    /**
2382
     * Returns true if the string contains only lower case chars, false
2383
     * otherwise.
2384
     *
2385
     * EXAMPLE: <code>
2386
     * s('FÒÔBÀŘ')->isUpperCase(); // true
2387
     * </code>
2388
     *
2389
     * @psalm-mutation-free
2390
     *
2391
     * @return bool
2392
     *              <p>Whether or not $str contains only lower case characters.</p>
2393
     */
2394 24
    public function isUpperCase(): bool
2395
    {
2396 24
        return $this->utf8::is_uppercase($this->str);
2397
    }
2398
2399
    /**
2400
     * /**
2401
     * Check if $url is an correct url.
2402
     *
2403
     * @param bool $disallow_localhost
2404
     *
2405
     * @psalm-mutation-free
2406
     *
2407
     * @return bool
2408
     */
2409
    public function isUrl(bool $disallow_localhost = false): bool
2410
    {
2411
        return $this->utf8::is_url($this->str, $disallow_localhost);
2412
    }
2413
2414
    /**
2415
     * Check if the string is UTF-16.
2416
     *
2417
     * @psalm-mutation-free
2418
     *
2419
     * @return false|int
2420
     *                   <strong>false</strong> if is't not UTF-16,<br>
2421
     *                   <strong>1</strong> for UTF-16LE,<br>
2422
     *                   <strong>2</strong> for UTF-16BE
2423
     */
2424
    public function isUtf16()
2425
    {
2426
        return $this->utf8::is_utf16($this->str);
2427
    }
2428
2429
    /**
2430
     * Check if the string is UTF-32.
2431
     *
2432
     * @psalm-mutation-free
2433
     *
2434
     * @return false|int
2435
     *                   <strong>false</strong> if is't not UTF-32,<br>
2436
     *                   <strong>1</strong> for UTF-32LE,<br>
2437
     *                   <strong>2</strong> for UTF-32BE
2438
     */
2439
    public function isUtf32()
2440
    {
2441
        return $this->utf8::is_utf32($this->str);
2442
    }
2443
2444
    /**
2445
     * Checks whether the passed input contains only byte sequences that appear valid UTF-8.
2446
     *
2447
     * EXAMPLE: <code>
2448
     * s('Iñtërnâtiônàlizætiøn')->isUtf8(); // true
2449
     * //
2450
     * s("Iñtërnâtiônàlizætiøn\xA0\xA1")->isUtf8(); // false
2451
     * </code>
2452
     *
2453
     * @param bool $strict <p>Check also if the string is not UTF-16 or UTF-32.</p>
2454
     *
2455
     * @psalm-mutation-free
2456
     *
2457
     * @return bool
2458
     */
2459
    public function isUtf8(bool $strict = false): bool
2460
    {
2461
        return $this->utf8::is_utf8($this->str, $strict);
2462
    }
2463
2464
    /**
2465
     * Returns true if the string contains only whitespace chars, false otherwise.
2466
     *
2467
     * EXAMPLE: <code>
2468
     * </code>
2469
     *
2470
     * @psalm-mutation-free
2471
     *
2472
     * @return bool
2473
     *              <p>Whether or not $str contains only whitespace characters.</p>
2474
     */
2475 30
    public function isWhitespace(): bool
2476
    {
2477 30
        return $this->isBlank();
2478
    }
2479
2480
    /**
2481
     * Returns value which can be serialized by json_encode().
2482
     *
2483
     * EXAMPLE: <code>
2484
     * </code>
2485
     *
2486
     * @noinspection ReturnTypeCanBeDeclaredInspection
2487
     *
2488
     * @psalm-mutation-free
2489
     *
2490
     * @return string The current value of the $str property
2491
     */
2492 2
    public function jsonSerialize()
2493
    {
2494 2
        return (string) $this;
2495
    }
2496
2497
    /**
2498
     * Convert the string to kebab-case.
2499
     *
2500
     * EXAMPLE: <code>
2501
     * </code>
2502
     *
2503
     * @psalm-mutation-free
2504
     *
2505
     * @return static
2506
     */
2507 3 View Code Duplication
    public function kebabCase(): 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...
2508
    {
2509 3
        $words = \array_map(
2510 3
            static function (self $word) {
2511 3
                return $word->toLowerCase();
2512 3
            },
2513 3
            $this->words('', true)
2514
        );
2515
2516 3
        return new static(\implode('-', $words), $this->encoding);
2517
    }
2518
2519
    /**
2520
     * Returns the last $n characters of the string.
2521
     *
2522
     * EXAMPLE: <code>
2523
     * s('fòôbàř')->last(3); // 'bàř'
2524
     * </code>
2525
     *
2526
     * @param int $n <p>Number of characters to retrieve from the end.</p>
2527
     *
2528
     * @psalm-mutation-free
2529
     *
2530
     * @return static
2531
     *                <p>Object with its $str being the last $n chars.</p>
2532
     */
2533 36
    public function last(int $n): self
2534
    {
2535 36
        return static::create(
2536 36
            $this->utf8::str_last_char(
2537 36
                $this->str,
2538
                $n,
2539 36
                $this->encoding
2540
            ),
2541 36
            $this->encoding
2542
        );
2543
    }
2544
2545
    /**
2546
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2547
     * If no match is found returns new empty Stringy object.
2548
     *
2549
     * EXAMPLE: <code>
2550
     * </code>
2551
     *
2552
     * @param string $needle       <p>The string to look for.</p>
2553
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2554
     *
2555
     * @psalm-mutation-free
2556
     *
2557
     * @return static
2558
     */
2559 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...
2560
    {
2561 4
        return static::create(
2562 4
            $this->utf8::str_substr_last(
2563 4
                $this->str,
2564
                $needle,
2565
                $beforeNeedle,
2566 4
                $this->encoding
2567
            ),
2568 4
            $this->encoding
2569
        );
2570
    }
2571
2572
    /**
2573
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2574
     * If no match is found returns new empty Stringy object.
2575
     *
2576
     * EXAMPLE: <code>
2577
     * </code>
2578
     *
2579
     * @param string $needle       <p>The string to look for.</p>
2580
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2581
     *
2582
     * @psalm-mutation-free
2583
     *
2584
     * @return static
2585
     */
2586 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...
2587
    {
2588 2
        return static::create(
2589 2
            $this->utf8::str_isubstr_last(
2590 2
                $this->str,
2591
                $needle,
2592
                $beforeNeedle,
2593 2
                $this->encoding
2594
            ),
2595 2
            $this->encoding
2596
        );
2597
    }
2598
2599
    /**
2600
     * Returns the length of the string.
2601
     *
2602
     * EXAMPLE: <code>
2603
     * s('fòôbàř')->length(); // 6
2604
     * </code>
2605
     *
2606
     * @psalm-mutation-free
2607
     *
2608
     * @return int
2609
     *             <p>The number of characters in $str given the encoding.</p>
2610
     */
2611 17
    public function length(): int
2612
    {
2613 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
2614
    }
2615
2616
    /**
2617
     * Line-Wrap the string after $limit, but also after the next word.
2618
     *
2619
     * EXAMPLE: <code>
2620
     * </code>
2621
     *
2622
     * @param int         $limit           [optional] <p>The column width.</p>
2623
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2624
     * @param bool        $add_final_break [optional] <p>
2625
     *                                     If this flag is true, then the method will add a $break at the end
2626
     *                                     of the result string.
2627
     *                                     </p>
2628
     * @param string|null $delimiter       [optional] <p>
2629
     *                                     You can change the default behavior, where we split the string by newline.
2630
     *                                     </p>
2631
     *
2632
     * @psalm-mutation-free
2633
     *
2634
     * @return static
2635
     */
2636 3 View Code Duplication
    public function lineWrap(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2637
        int $limit,
2638
        string $break = "\n",
2639
        bool $add_final_break = true,
2640
        string $delimiter = null
2641
    ): self {
2642 3
        return static::create(
2643 3
            $this->utf8::wordwrap_per_line(
2644 3
                $this->str,
2645
                $limit,
2646
                $break,
2647 3
                true,
2648
                $add_final_break,
2649
                $delimiter
2650
            ),
2651 3
            $this->encoding
2652
        );
2653
    }
2654
2655
    /**
2656
     * Line-Wrap the string after $limit, but also after the next word.
2657
     *
2658
     * EXAMPLE: <code>
2659
     * </code>
2660
     *
2661
     * @param int         $limit           [optional] <p>The column width.</p>
2662
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2663
     * @param bool        $add_final_break [optional] <p>
2664
     *                                     If this flag is true, then the method will add a $break at the end
2665
     *                                     of the result string.
2666
     *                                     </p>
2667
     * @param string|null $delimiter       [optional] <p>
2668
     *                                     You can change the default behavior, where we split the string by newline.
2669
     *                                     </p>
2670
     *
2671
     * @psalm-mutation-free
2672
     *
2673
     * @return static
2674
     */
2675 4 View Code Duplication
    public function lineWrapAfterWord(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2676
        int $limit,
2677
        string $break = "\n",
2678
        bool $add_final_break = true,
2679
        string $delimiter = null
2680
    ): self {
2681 4
        return static::create(
2682 4
            $this->utf8::wordwrap_per_line(
2683 4
                $this->str,
2684
                $limit,
2685
                $break,
2686 4
                false,
2687
                $add_final_break,
2688
                $delimiter
2689
            ),
2690 4
            $this->encoding
2691
        );
2692
    }
2693
2694
    /**
2695
     * Splits on newlines and carriage returns, returning an array of Stringy
2696
     * objects corresponding to the lines in the string.
2697
     *
2698
     * EXAMPLE: <code>
2699
     * s("fòô\r\nbàř\n")->lines(); // ['fòô', 'bàř', '']
2700
     * </code>
2701
     *
2702
     * @psalm-mutation-free
2703
     *
2704
     * @return static[]
2705
     *                  <p>An array of Stringy objects.</p>
2706
     *
2707
     * @psalm-return array<int,static>
2708
     */
2709 51
    public function lines(): array
2710
    {
2711 51
        if ($this->str === '') {
2712 3
            return [static::create('')];
2713
        }
2714
2715 48
        $strings = $this->utf8::str_to_lines($this->str);
2716
        /** @noinspection AlterInForeachInspection */
2717 48
        foreach ($strings as &$str) {
2718 48
            $str = static::create($str, $this->encoding);
2719
        }
2720
2721
        /** @noinspection PhpSillyAssignmentInspection */
2722
        /** @var static[] $strings */
2723 48
        $strings = $strings;
0 ignored issues
show
Bug introduced by
Why assign $strings to itself?

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

This assignement can be removed without consequences.

Loading history...
2724
2725 48
        return $strings;
2726
    }
2727
2728
    /**
2729
     * Splits on newlines and carriage returns, returning an array of Stringy
2730
     * objects corresponding to the lines in the string.
2731
     *
2732
     * EXAMPLE: <code>
2733
     * </code>
2734
     *
2735
     * @psalm-mutation-free
2736
     *
2737
     * @return CollectionStringy|static[]
2738
     *                                    <p>An collection of Stringy objects.</p>
2739
     *
2740
     * @psalm-return CollectionStringy<int,static>
2741
     */
2742 34
    public function linesCollection(): CollectionStringy
2743
    {
2744
        /**
2745
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2746
         */
2747 34
        return CollectionStringy::create(
2748 34
            $this->lines()
2749
        );
2750
    }
2751
2752
    /**
2753
     * Returns the longest common prefix between the string and $otherStr.
2754
     *
2755
     * EXAMPLE: <code>
2756
     * s('foobar')->longestCommonPrefix('foobaz'); // 'fooba'
2757
     * </code>
2758
     *
2759
     * @param string $otherStr <p>Second string for comparison.</p>
2760
     *
2761
     * @psalm-mutation-free
2762
     *
2763
     * @return static
2764
     *                <p>Object with its $str being the longest common prefix.</p>
2765
     */
2766 30
    public function longestCommonPrefix(string $otherStr): self
2767
    {
2768 30
        return static::create(
2769 30
            $this->utf8::str_longest_common_prefix(
2770 30
                $this->str,
2771
                $otherStr,
2772 30
                $this->encoding
2773
            ),
2774 30
            $this->encoding
2775
        );
2776
    }
2777
2778
    /**
2779
     * Returns the longest common substring between the string and $otherStr.
2780
     * In the case of ties, it returns that which occurs first.
2781
     *
2782
     * EXAMPLE: <code>
2783
     * s('foobar')->longestCommonSubstring('boofar'); // 'oo'
2784
     * </code>
2785
     *
2786
     * @param string $otherStr <p>Second string for comparison.</p>
2787
     *
2788
     * @psalm-mutation-free
2789
     *
2790
     * @return static
2791
     *                <p>Object with its $str being the longest common substring.</p>
2792
     */
2793 30
    public function longestCommonSubstring(string $otherStr): self
2794
    {
2795 30
        return static::create(
2796 30
            $this->utf8::str_longest_common_substring(
2797 30
                $this->str,
2798
                $otherStr,
2799 30
                $this->encoding
2800
            ),
2801 30
            $this->encoding
2802
        );
2803
    }
2804
2805
    /**
2806
     * Returns the longest common suffix between the string and $otherStr.
2807
     *
2808
     * EXAMPLE: <code>
2809
     * s('fòôbàř')->longestCommonSuffix('fòrbàř'); // 'bàř'
2810
     * </code>
2811
     *
2812
     * @param string $otherStr <p>Second string for comparison.</p>
2813
     *
2814
     * @psalm-mutation-free
2815
     *
2816
     * @return static
2817
     *                <p>Object with its $str being the longest common suffix.</p>
2818
     */
2819 30
    public function longestCommonSuffix(string $otherStr): self
2820
    {
2821 30
        return static::create(
2822 30
            $this->utf8::str_longest_common_suffix(
2823 30
                $this->str,
2824
                $otherStr,
2825 30
                $this->encoding
2826
            ),
2827 30
            $this->encoding
2828
        );
2829
    }
2830
2831
    /**
2832
     * Converts the first character of the string to lower case.
2833
     *
2834
     * EXAMPLE: <code>
2835
     * s('Σ Foo')->lowerCaseFirst(); // 'σ Foo'
2836
     * </code>
2837
     *
2838
     * @psalm-mutation-free
2839
     *
2840
     * @return static
2841
     *                <p>Object with the first character of $str being lower case.</p>
2842
     */
2843 16
    public function lowerCaseFirst(): self
2844
    {
2845 16
        return static::create(
2846 16
            $this->utf8::lcfirst($this->str, $this->encoding),
2847 16
            $this->encoding
2848
        );
2849
    }
2850
2851
    /**
2852
     * Determine if the string matches another string regardless of case.
2853
     * Alias for isEqualsCaseInsensitive()
2854
     *
2855
     * EXAMPLE: <code>
2856
     * </code>
2857
     *
2858
     * @psalm-mutation-free
2859
     *
2860
     * @param string|Stringy ...$str
2861
     *                               <p>The string to compare against.</p>
2862
     *
2863
     * @psalm-mutation-free
2864
     *
2865
     * @return bool
2866
     */
2867 3
    public function matchCaseInsensitive(...$str): bool
2868
    {
2869 3
        return $this->isEqualsCaseInsensitive(...$str);
2870
    }
2871
2872
    /**
2873
     * Determine if the string matches another string.
2874
     * Alias for isEqualsCaseSensitive()
2875
     *
2876
     * EXAMPLE: <code>
2877
     * </code>
2878
     *
2879
     * @psalm-mutation-free
2880
     *
2881
     * @param string|Stringy ...$str
2882
     *                               <p>The string to compare against.</p>
2883
     *
2884
     * @psalm-mutation-free
2885
     *
2886
     * @return bool
2887
     */
2888 7
    public function matchCaseSensitive(...$str): bool
2889
    {
2890 7
        return $this->isEqualsCaseSensitive(...$str);
2891
    }
2892
2893
    /**
2894
     * Create a md5 hash from the current string.
2895
     *
2896
     * @psalm-mutation-free
2897
     *
2898
     * @return static
2899
     */
2900 2
    public function md5(): self
2901
    {
2902 2
        return static::create($this->hash('md5'), $this->encoding);
2903
    }
2904
2905
    /**
2906
     * Replace all breaks [<br> | \r\n | \r | \n | ...] into "<br>".
2907
     *
2908
     * EXAMPLE: <code>
2909
     * </code>
2910
     *
2911
     * @return static
2912
     */
2913 1
    public function newLineToHtmlBreak(): self
2914
    {
2915 1
        return $this->removeHtmlBreak('<br>');
2916
    }
2917
2918
    /**
2919
     * Get every nth character of the string.
2920
     *
2921
     * EXAMPLE: <code>
2922
     * </code>
2923
     *
2924
     * @param int $step   <p>The number of characters to step.</p>
2925
     * @param int $offset [optional] <p>The string offset to start at.</p>
2926
     *
2927
     * @psalm-mutation-free
2928
     *
2929
     * @return static
2930
     */
2931 4
    public function nth(int $step, int $offset = 0): self
2932
    {
2933 4
        $length = $step - 1;
2934 4
        $substring = $this->substr($offset)->toString();
2935
2936 4
        if ($substring === '') {
2937
            return new static('', $this->encoding);
2938
        }
2939
2940 4
        \preg_match_all(
2941 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2942 4
            $substring,
2943 4
            $matches
2944
        );
2945
2946 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2947
    }
2948
2949
    /**
2950
     * Returns whether or not a character exists at an index. Offsets may be
2951
     * negative to count from the last character in the string. Implements
2952
     * part of the ArrayAccess interface.
2953
     *
2954
     * EXAMPLE: <code>
2955
     * </code>
2956
     *
2957
     * @param int $offset <p>The index to check.</p>
2958
     *
2959
     * @psalm-mutation-free
2960
     *
2961
     * @return bool
2962
     *              <p>Whether or not the index exists.</p>
2963
     */
2964 18
    public function offsetExists($offset): bool
2965
    {
2966 18
        return $this->utf8::str_offset_exists(
2967 18
            $this->str,
2968
            $offset,
2969 18
            $this->encoding
2970
        );
2971
    }
2972
2973
    /**
2974
     * Returns the character at the given index. Offsets may be negative to
2975
     * count from the last character in the string. Implements part of the
2976
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2977
     * does not exist.
2978
     *
2979
     * EXAMPLE: <code>
2980
     * </code>
2981
     *
2982
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2983
     *
2984
     * @throws \OutOfBoundsException
2985
     *                               <p>If the positive or negative offset does not exist.</p>
2986
     *
2987
     * @return string
2988
     *                <p>The character at the specified index.</p>
2989
     *
2990
     * @psalm-mutation-free
2991
     */
2992 6
    public function offsetGet($offset): string
2993
    {
2994 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2995
    }
2996
2997
    /**
2998
     * Implements part of the ArrayAccess interface, but throws an exception
2999
     * when called. This maintains the immutability of Stringy objects.
3000
     *
3001
     * EXAMPLE: <code>
3002
     * </code>
3003
     *
3004
     * @param int   $offset <p>The index of the character.</p>
3005
     * @param mixed $value  <p>Value to set.</p>
3006
     *
3007
     * @throws \Exception
3008
     *                    <p>When called.</p>
3009
     *
3010
     * @return void
3011
     */
3012 3
    public function offsetSet($offset, $value)
3013
    {
3014
        // Stringy is immutable, cannot directly set char
3015
        /** @noinspection ThrowRawExceptionInspection */
3016 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
3017
    }
3018
3019
    /**
3020
     * Implements part of the ArrayAccess interface, but throws an exception
3021
     * when called. This maintains the immutability of Stringy objects.
3022
     *
3023
     * EXAMPLE: <code>
3024
     * </code>
3025
     *
3026
     * @param int $offset <p>The index of the character.</p>
3027
     *
3028
     * @throws \Exception
3029
     *                    <p>When called.</p>
3030
     *
3031
     * @return void
3032
     */
3033 3
    public function offsetUnset($offset)
3034
    {
3035
        // Don't allow directly modifying the string
3036
        /** @noinspection ThrowRawExceptionInspection */
3037 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
3038
    }
3039
3040
    /**
3041
     * Pads the string to a given length with $padStr. If length is less than
3042
     * or equal to the length of the string, no padding takes places. The
3043
     * default string used for padding is a space, and the default type (one of
3044
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
3045
     * if $padType isn't one of those 3 values.
3046
     *
3047
     * EXAMPLE: <code>
3048
     * s('fòôbàř')->pad(9, '-/', 'left'); // '-/-fòôbàř'
3049
     * </code>
3050
     *
3051
     * @param int    $length  <p>Desired string length after padding.</p>
3052
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3053
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
3054
     *
3055
     * @throws \InvalidArgumentException
3056
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
3057
     *
3058
     * @return static
3059
     *                <p>Object with a padded $str.</p>
3060
     *
3061
     * @psalm-mutation-free
3062
     */
3063 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
3064
    {
3065 39
        return static::create(
3066 39
            $this->utf8::str_pad(
3067 39
                $this->str,
3068
                $length,
3069
                $padStr,
3070
                $padType,
3071 39
                $this->encoding
3072
            )
3073
        );
3074
    }
3075
3076
    /**
3077
     * Returns a new string of a given length such that both sides of the
3078
     * string are padded. Alias for pad() with a $padType of 'both'.
3079
     *
3080
     * EXAMPLE: <code>
3081
     * s('foo bar')->padBoth(9, ' '); // ' foo bar '
3082
     * </code>
3083
     *
3084
     * @param int    $length <p>Desired string length after padding.</p>
3085
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3086
     *
3087
     * @psalm-mutation-free
3088
     *
3089
     * @return static
3090
     *                <p>String with padding applied.</p>
3091
     */
3092 33
    public function padBoth(int $length, string $padStr = ' '): self
3093
    {
3094 33
        return static::create(
3095 33
            $this->utf8::str_pad_both(
3096 33
                $this->str,
3097
                $length,
3098
                $padStr,
3099 33
                $this->encoding
3100
            )
3101
        );
3102
    }
3103
3104
    /**
3105
     * Returns a new string of a given length such that the beginning of the
3106
     * string is padded. Alias for pad() with a $padType of 'left'.
3107
     *
3108
     * EXAMPLE: <code>
3109
     * s('foo bar')->padLeft(9, ' '); // '  foo bar'
3110
     * </code>
3111
     *
3112
     * @param int    $length <p>Desired string length after padding.</p>
3113
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3114
     *
3115
     * @psalm-mutation-free
3116
     *
3117
     * @return static
3118
     *                <p>String with left padding.</p>
3119
     */
3120 21
    public function padLeft(int $length, string $padStr = ' '): self
3121
    {
3122 21
        return static::create(
3123 21
            $this->utf8::str_pad_left(
3124 21
                $this->str,
3125
                $length,
3126
                $padStr,
3127 21
                $this->encoding
3128
            )
3129
        );
3130
    }
3131
3132
    /**
3133
     * Returns a new string of a given length such that the end of the string
3134
     * is padded. Alias for pad() with a $padType of 'right'.
3135
     *
3136
     * EXAMPLE: <code>
3137
     * s('foo bar')->padRight(10, '_*'); // 'foo bar_*_'
3138
     * </code>
3139
     *
3140
     * @param int    $length <p>Desired string length after padding.</p>
3141
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3142
     *
3143
     * @psalm-mutation-free
3144
     *
3145
     * @return static
3146
     *                <p>String with right padding.</p>
3147
     */
3148 21
    public function padRight(int $length, string $padStr = ' '): self
3149
    {
3150 21
        return static::create(
3151 21
            $this->utf8::str_pad_right(
3152 21
                $this->str,
3153
                $length,
3154
                $padStr,
3155 21
                $this->encoding
3156
            )
3157
        );
3158
    }
3159
3160
    /**
3161
     * Convert the string to PascalCase.
3162
     * Alias for studlyCase()
3163
     *
3164
     * EXAMPLE: <code>
3165
     * </code>
3166
     *
3167
     * @psalm-mutation-free
3168
     *
3169
     * @return static
3170
     */
3171 3
    public function pascalCase(): self
3172
    {
3173 3
        return $this->studlyCase();
3174
    }
3175
3176
    /**
3177
     * Returns a new string starting with $prefix.
3178
     *
3179
     * EXAMPLE: <code>
3180
     * s('bàř')->prepend('fòô'); // 'fòôbàř'
3181
     * </code>
3182
     *
3183
     * @param string ...$prefix <p>The string to append.</p>
3184
     *
3185
     * @psalm-mutation-free
3186
     *
3187
     * @return static
3188
     *                <p>Object with appended $prefix.</p>
3189
     */
3190 8 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...
3191
    {
3192 8
        if (\count($prefix) <= 1) {
3193
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
3194 6
            $prefix = $prefix[0];
3195
        } else {
3196
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
3197 2
            $prefix = \implode('', $prefix);
3198
        }
3199
3200 8
        return static::create($prefix . $this->str, $this->encoding);
3201
    }
3202
3203
    /**
3204
     * Returns a new string starting with $prefix.
3205
     *
3206
     * EXAMPLE: <code>
3207
     * </code>
3208
     *
3209
     * @param CollectionStringy|static ...$prefix <p>The Stringy objects to append.</p>
3210
     *
3211
     * @psalm-param CollectionStringy<int,static>|static ...$prefix
3212
     *
3213
     * @psalm-mutation-free
3214
     *
3215
     * @return static
3216
     *                <p>Object with appended $prefix.</p>
3217
     */
3218 1 View Code Duplication
    public function prependStringy(...$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...
3219
    {
3220 1
        $prefixStr = '';
3221 1
        foreach ($prefix as $prefixTmp) {
3222 1
            if ($prefixTmp instanceof CollectionStringy) {
3223 1
                $prefixStr .= $prefixTmp->implode('');
3224
            } else {
3225 1
                $prefixStr .= $prefixTmp->toString();
3226
            }
3227
        }
3228
3229 1
        return static::create($prefixStr . $this->str, $this->encoding);
3230
    }
3231
3232
    /**
3233
     * Replaces all occurrences of $pattern in $str by $replacement.
3234
     *
3235
     * EXAMPLE: <code>
3236
     * s('fòô ')->regexReplace('f[òô]+\s', 'bàř'); // 'bàř'
3237
     * s('fò')->regexReplace('(ò)', '\\1ô'); // 'fòô'
3238
     * </code>
3239
     *
3240
     * @param string $pattern     <p>The regular expression pattern.</p>
3241
     * @param string $replacement <p>The string to replace with.</p>
3242
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
3243
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
3244
     *
3245
     * @psalm-mutation-free
3246
     *
3247
     * @return static
3248
     *                <p>Object with the result2ing $str after the replacements.</p>
3249
     */
3250 29
    public function regexReplace(
3251
        string $pattern,
3252
        string $replacement,
3253
        string $options = '',
3254
        string $delimiter = '/'
3255
    ): self {
3256 29
        return static::create(
3257 29
            $this->utf8::regex_replace(
3258 29
                $this->str,
3259
                $pattern,
3260
                $replacement,
3261
                $options,
3262
                $delimiter
3263
            ),
3264 29
            $this->encoding
3265
        );
3266
    }
3267
3268
    /**
3269
     * Remove html via "strip_tags()" from the string.
3270
     *
3271
     * EXAMPLE: <code>
3272
     * s('řàb <ô>òf\', ô<br/>foo <a href="#">lall</a>')->removeHtml('<br><br/>'); // 'řàb òf\', ô<br/>foo lall'
3273
     * </code>
3274
     *
3275
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
3276
     *                              not be stripped. Default: null
3277
     *                              </p>
3278
     *
3279
     * @psalm-mutation-free
3280
     *
3281
     * @return static
3282
     */
3283 12
    public function removeHtml(string $allowableTags = ''): self
3284
    {
3285 12
        return static::create(
3286 12
            $this->utf8::remove_html($this->str, $allowableTags),
3287 12
            $this->encoding
3288
        );
3289
    }
3290
3291
    /**
3292
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
3293
     *
3294
     * EXAMPLE: <code>
3295
     * s('řàb <ô>òf\', ô<br/>foo <a href="#">lall</a>')->removeHtmlBreak(''); // 'řàb <ô>òf\', ô< foo <a href="#">lall</a>'
3296
     * </code>
3297
     *
3298
     * @param string $replacement [optional] <p>Default is a empty string.</p>
3299
     *
3300
     * @psalm-mutation-free
3301
     *
3302
     * @return static
3303
     */
3304 13
    public function removeHtmlBreak(string $replacement = ''): self
3305
    {
3306 13
        return static::create(
3307 13
            $this->utf8::remove_html_breaks($this->str, $replacement),
3308 13
            $this->encoding
3309
        );
3310
    }
3311
3312
    /**
3313
     * Returns a new string with the prefix $substring removed, if present.
3314
     *
3315
     * EXAMPLE: <code>
3316
     * s('fòôbàř')->removeLeft('fòô'); // 'bàř'
3317
     * </code>
3318
     *
3319
     * @param string $substring <p>The prefix to remove.</p>
3320
     *
3321
     * @psalm-mutation-free
3322
     *
3323
     * @return static
3324
     *                <p>Object having a $str without the prefix $substring.</p>
3325
     */
3326 36
    public function removeLeft(string $substring): self
3327
    {
3328 36
        return static::create(
3329 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
3330 36
            $this->encoding
3331
        );
3332
    }
3333
3334
    /**
3335
     * Returns a new string with the suffix $substring removed, if present.
3336
     *
3337
     * EXAMPLE: <code>
3338
     * s('fòôbàř')->removeRight('bàř'); // 'fòô'
3339
     * </code>
3340
     *
3341
     * @param string $substring <p>The suffix to remove.</p>
3342
     *
3343
     * @psalm-mutation-free
3344
     *
3345
     * @return static
3346
     *                <p>Object having a $str without the suffix $substring.</p>
3347
     */
3348 36
    public function removeRight(string $substring): self
3349
    {
3350 36
        return static::create(
3351 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
3352 36
            $this->encoding
3353
        );
3354
    }
3355
3356
    /**
3357
     * Try to remove all XSS-attacks from the string.
3358
     *
3359
     * EXAMPLE: <code>
3360
     * s('<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>')->removeXss(); // '<IMG >'
3361
     * </code>
3362
     *
3363
     * @psalm-mutation-free
3364
     *
3365
     * @return static
3366
     */
3367 12
    public function removeXss(): self
3368
    {
3369
        /**
3370
         * @var AntiXSS|null
3371
         *
3372
         * @psalm-suppress ImpureStaticVariable
3373
         */
3374 12
        static $antiXss = null;
3375
3376 12
        if ($antiXss === null) {
3377 1
            $antiXss = new AntiXSS();
3378
        }
3379
3380
        /**
3381
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
3382
         */
3383 12
        $str = $antiXss->xss_clean($this->str);
3384
3385 12
        return static::create($str, $this->encoding);
3386
    }
3387
3388
    /**
3389
     * Returns a repeated string given a multiplier.
3390
     *
3391
     * EXAMPLE: <code>
3392
     * s('α')->repeat(3); // 'ααα'
3393
     * </code>
3394
     *
3395
     * @param int $multiplier <p>The number of times to repeat the string.</p>
3396
     *
3397
     * @psalm-mutation-free
3398
     *
3399
     * @return static
3400
     *                <p>Object with a repeated str.</p>
3401
     */
3402 21
    public function repeat(int $multiplier): self
3403
    {
3404 21
        return static::create(
3405 21
            \str_repeat($this->str, $multiplier),
3406 21
            $this->encoding
3407
        );
3408
    }
3409
3410
    /**
3411
     * Replaces all occurrences of $search in $str by $replacement.
3412
     *
3413
     * EXAMPLE: <code>
3414
     * s('fòô bàř fòô bàř')->replace('fòô ', ''); // 'bàř bàř'
3415
     * </code>
3416
     *
3417
     * @param string $search        <p>The needle to search for.</p>
3418
     * @param string $replacement   <p>The string to replace with.</p>
3419
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3420
     *
3421
     * @psalm-mutation-free
3422
     *
3423
     * @return static
3424
     *                <p>Object with the resulting $str after the replacements.</p>
3425
     */
3426 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
3427
    {
3428 76
        if ($search === '' && $replacement === '') {
3429 16
            return static::create($this->str, $this->encoding);
3430
        }
3431
3432 60
        if ($this->str === '' && $search === '') {
3433 2
            return static::create($replacement, $this->encoding);
3434
        }
3435
3436 58
        if ($caseSensitive) {
3437 48
            return static::create(
3438 48
                \str_replace($search, $replacement, $this->str),
3439 48
                $this->encoding
3440
            );
3441
        }
3442
3443 10
        return static::create(
3444 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
3445 10
            $this->encoding
3446
        );
3447
    }
3448
3449
    /**
3450
     * Replaces all occurrences of $search in $str by $replacement.
3451
     *
3452
     * EXAMPLE: <code>
3453
     * s('fòô bàř lall bàř')->replaceAll(['fòÔ ', 'lall'], '', false); // 'bàř bàř'
3454
     * </code>
3455
     *
3456
     * @param string[]        $search        <p>The elements to search for.</p>
3457
     * @param string|string[] $replacement   <p>The string to replace with.</p>
3458
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3459
     *
3460
     * @psalm-mutation-free
3461
     *
3462
     * @return static
3463
     *                <p>Object with the resulting $str after the replacements.</p>
3464
     */
3465 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
3466
    {
3467 61
        if ($caseSensitive) {
3468 47
            return static::create(
3469 47
                \str_replace($search, $replacement, $this->str),
3470 47
                $this->encoding
3471
            );
3472
        }
3473
3474 14
        return static::create(
3475 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
3476 14
            $this->encoding
3477
        );
3478
    }
3479
3480
    /**
3481
     * Replaces all occurrences of $search from the beginning of string with $replacement.
3482
     *
3483
     * EXAMPLE: <code>
3484
     * s('fòô bàř fòô bàř')->replaceBeginning('fòô', ''); // ' bàř bàř'
3485
     * </code>
3486
     *
3487
     * @param string $search      <p>The string to search for.</p>
3488
     * @param string $replacement <p>The replacement.</p>
3489
     *
3490
     * @psalm-mutation-free
3491
     *
3492
     * @return static
3493
     *                <p>Object with the resulting $str after the replacements.</p>
3494
     */
3495 32
    public function replaceBeginning(string $search, string $replacement): self
3496
    {
3497 32
        return static::create(
3498 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
3499 32
            $this->encoding
3500
        );
3501
    }
3502
3503
    /**
3504
     * Replaces all occurrences of $search from the ending of string with $replacement.
3505
     *
3506
     * EXAMPLE: <code>
3507
     * s('fòô bàř fòô bàř')->replaceEnding('bàř', ''); // 'fòô bàř fòô '
3508
     * </code>
3509
     *
3510
     * @param string $search      <p>The string to search for.</p>
3511
     * @param string $replacement <p>The replacement.</p>
3512
     *
3513
     * @psalm-mutation-free
3514
     *
3515
     * @return static
3516
     *                <p>Object with the resulting $str after the replacements.</p>
3517
     */
3518 32
    public function replaceEnding(string $search, string $replacement): self
3519
    {
3520 32
        return static::create(
3521 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
3522 32
            $this->encoding
3523
        );
3524
    }
3525
3526
    /**
3527
     * Replaces first occurrences of $search from the beginning of string with $replacement.
3528
     *
3529
     * EXAMPLE: <code>
3530
     * </code>
3531
     *
3532
     * @param string $search      <p>The string to search for.</p>
3533
     * @param string $replacement <p>The replacement.</p>
3534
     *
3535
     * @psalm-mutation-free
3536
     *
3537
     * @return static
3538
     *                <p>Object with the resulting $str after the replacements.</p>
3539
     */
3540 32
    public function replaceFirst(string $search, string $replacement): self
3541
    {
3542 32
        return static::create(
3543 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
3544 32
            $this->encoding
3545
        );
3546
    }
3547
3548
    /**
3549
     * Replaces last occurrences of $search from the ending of string with $replacement.
3550
     *
3551
     * EXAMPLE: <code>
3552
     * </code>
3553
     *
3554
     * @param string $search      <p>The string to search for.</p>
3555
     * @param string $replacement <p>The replacement.</p>
3556
     *
3557
     * @psalm-mutation-free
3558
     *
3559
     * @return static
3560
     *                <p>Object with the resulting $str after the replacements.</p>
3561
     */
3562 30
    public function replaceLast(string $search, string $replacement): self
3563
    {
3564 30
        return static::create(
3565 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
3566 30
            $this->encoding
3567
        );
3568
    }
3569
3570
    /**
3571
     * Returns a reversed string. A multibyte version of strrev().
3572
     *
3573
     * EXAMPLE: <code>
3574
     * s('fòôbàř')->reverse(); // 'řàbôòf'
3575
     * </code>
3576
     *
3577
     * @psalm-mutation-free
3578
     *
3579
     * @return static
3580
     *                <p>Object with a reversed $str.</p>
3581
     */
3582 15
    public function reverse(): self
3583
    {
3584 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
3585
    }
3586
3587
    /**
3588
     * Truncates the string to a given length, while ensuring that it does not
3589
     * split words. If $substring is provided, and truncating occurs, the
3590
     * string is further truncated so that the substring may be appended without
3591
     * exceeding the desired length.
3592
     *
3593
     * EXAMPLE: <code>
3594
     * s('What are your plans today?')->safeTruncate(22, '...'); // 'What are your plans...'
3595
     * </code>
3596
     *
3597
     * @param int    $length                          <p>Desired length of the truncated string.</p>
3598
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
3599
     * @param bool   $ignoreDoNotSplitWordsForOneWord
3600
     *
3601
     * @psalm-mutation-free
3602
     *
3603
     * @return static
3604
     *                <p>Object with the resulting $str after truncating.</p>
3605
     */
3606 68
    public function safeTruncate(
3607
        int $length,
3608
        string $substring = '',
3609
        bool $ignoreDoNotSplitWordsForOneWord = true
3610
    ): self {
3611 68
        return static::create(
3612 68
            $this->utf8::str_truncate_safe(
3613 68
                $this->str,
3614
                $length,
3615
                $substring,
3616 68
                $this->encoding,
3617
                $ignoreDoNotSplitWordsForOneWord
3618
            ),
3619 68
            $this->encoding
3620
        );
3621
    }
3622
3623
    /**
3624
     * Set the internal character encoding.
3625
     *
3626
     * EXAMPLE: <code>
3627
     * </code>
3628
     *
3629
     * @param string $new_encoding <p>The desired character encoding.</p>
3630
     *
3631
     * @psalm-mutation-free
3632
     *
3633
     * @return static
3634
     */
3635 1
    public function setInternalEncoding(string $new_encoding): self
3636
    {
3637 1
        return new static($this->str, $new_encoding);
3638
    }
3639
3640
    /**
3641
     * Create a sha1 hash from the current string.
3642
     *
3643
     * EXAMPLE: <code>
3644
     * </code>
3645
     *
3646
     * @psalm-mutation-free
3647
     *
3648
     * @return static
3649
     */
3650 2
    public function sha1(): self
3651
    {
3652 2
        return static::create($this->hash('sha1'), $this->encoding);
3653
    }
3654
3655
    /**
3656
     * Create a sha256 hash from the current string.
3657
     *
3658
     * EXAMPLE: <code>
3659
     * </code>
3660
     *
3661
     * @psalm-mutation-free
3662
     *
3663
     * @return static
3664
     */
3665 2
    public function sha256(): self
3666
    {
3667 2
        return static::create($this->hash('sha256'), $this->encoding);
3668
    }
3669
3670
    /**
3671
     * Create a sha512 hash from the current string.
3672
     *
3673
     * EXAMPLE: <code>
3674
     * </code>
3675
     *
3676
     * @psalm-mutation-free
3677
     *
3678
     * @return static
3679
     */
3680 2
    public function sha512(): self
3681
    {
3682 2
        return static::create($this->hash('sha512'), $this->encoding);
3683
    }
3684
3685
    /**
3686
     * Shorten the string after $length, but also after the next word.
3687
     *
3688
     * EXAMPLE: <code>
3689
     * s('this is a test')->shortenAfterWord(2, '...'); // 'this...'
3690
     * </code>
3691
     *
3692
     * @param int    $length   <p>The given length.</p>
3693
     * @param string $strAddOn [optional] <p>Default: '…'</p>
3694
     *
3695
     * @psalm-mutation-free
3696
     *
3697
     * @return static
3698
     */
3699 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
3700
    {
3701 8
        return static::create(
3702 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
3703 8
            $this->encoding
3704
        );
3705
    }
3706
3707
    /**
3708
     * A multibyte string shuffle function. It returns a string with its
3709
     * characters in random order.
3710
     *
3711
     * EXAMPLE: <code>
3712
     * s('fòôbàř')->shuffle(); // 'àôřbòf'
3713
     * </code>
3714
     *
3715
     * @return static
3716
     *                <p>Object with a shuffled $str.</p>
3717
     */
3718 9
    public function shuffle(): self
3719
    {
3720 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
3721
    }
3722
3723
    /**
3724
     * Calculate the similarity between two strings.
3725
     *
3726
     * EXAMPLE: <code>
3727
     * </code>
3728
     *
3729
     * @param string $str <p>The delimiting string.</p>
3730
     *
3731
     * @psalm-mutation-free
3732
     *
3733
     * @return float
3734
     */
3735 2
    public function similarity(string $str): float
3736
    {
3737 2
        \similar_text($this->str, $str, $percent);
3738
3739 2
        return $percent;
3740
    }
3741
3742
    /**
3743
     * Returns the substring beginning at $start, and up to, but not including
3744
     * the index specified by $end. If $end is omitted, the function extracts
3745
     * the remaining string. If $end is negative, it is computed from the end
3746
     * of the string.
3747
     *
3748
     * EXAMPLE: <code>
3749
     * s('fòôbàř')->slice(3, -1); // 'bà'
3750
     * </code>
3751
     *
3752
     * @param int $start <p>Initial index from which to begin extraction.</p>
3753
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
3754
     *
3755
     * @psalm-mutation-free
3756
     *
3757
     * @return static
3758
     *                <p>Object with its $str being the extracted substring.</p>
3759
     */
3760 50
    public function slice(int $start, int $end = null): self
3761
    {
3762 50
        return static::create(
3763 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
3764 50
            $this->encoding
3765
        );
3766
    }
3767
3768
    /**
3769
     * Converts the string into an URL slug. This includes replacing non-ASCII
3770
     * characters with their closest ASCII equivalents, removing remaining
3771
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3772
     * $separator. The separator defaults to a single dash, and the string
3773
     * is also converted to lowercase. The language of the source string can
3774
     * also be supplied for language-specific transliteration.
3775
     *
3776
     * EXAMPLE: <code>
3777
     * s('Using strings like fòô bàř')->slugify(); // 'using-strings-like-foo-bar'
3778
     * </code>
3779
     *
3780
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
3781
     * @param string                $language              [optional] <p>Language of the source string.</p>
3782
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
3783
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
3784
     *                                                     pound ".</p>
3785
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
3786
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
3787
     *                                                     chars.</p>
3788
     *
3789
     * @psalm-mutation-free
3790
     *
3791
     * @return static
3792
     *                <p>Object whose $str has been converted to an URL slug.</p>
3793
     *
3794
     * @noinspection PhpTooManyParametersInspection
3795
     */
3796 17
    public function slugify(
3797
        string $separator = '-',
3798
        string $language = 'en',
3799
        array $replacements = [],
3800
        bool $replace_extra_symbols = true,
3801
        bool $use_str_to_lower = true,
3802
        bool $use_transliterate = false
3803
    ): self {
3804 17
        return static::create(
3805 17
            $this->ascii::to_slugify(
3806 17
                $this->str,
3807
                $separator,
3808
                $language,
3809
                $replacements,
3810
                $replace_extra_symbols,
3811
                $use_str_to_lower,
3812
                $use_transliterate
3813
            ),
3814 17
            $this->encoding
3815
        );
3816
    }
3817
3818
    /**
3819
     * Convert the string to snake_case.
3820
     *
3821
     * EXAMPLE: <code>
3822
     * </code>
3823
     *
3824
     * @psalm-mutation-free
3825
     *
3826
     * @return static
3827
     */
3828 3 View Code Duplication
    public function snakeCase(): 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...
3829
    {
3830 3
        $words = \array_map(
3831 3
            static function (self $word) {
3832 3
                return $word->toLowerCase();
3833 3
            },
3834 3
            $this->words('', true)
3835
        );
3836
3837 3
        return new static(\implode('_', $words), $this->encoding);
3838
    }
3839
3840
    /**
3841
     * Convert a string to snake_case.
3842
     *
3843
     * EXAMPLE: <code>
3844
     * s('foo1 Bar')->snakeize(); // 'foo_1_bar'
3845
     * </code>
3846
     *
3847
     * @psalm-mutation-free
3848
     *
3849
     * @return static
3850
     *                <p>Object with $str in snake_case.</p>
3851
     */
3852 40
    public function snakeize(): self
3853
    {
3854 40
        return static::create(
3855 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
3856 40
            $this->encoding
3857
        );
3858
    }
3859
3860
    /**
3861
     * Wrap the string after the first whitespace character after a given number
3862
     * of characters.
3863
     *
3864
     * EXAMPLE: <code>
3865
     * </code>
3866
     *
3867
     * @param int    $width <p>Number of characters at which to wrap.</p>
3868
     * @param string $break [optional] <p>Character used to break the string. | Default "\n"</p>
3869
     *
3870
     * @psalm-mutation-free
3871
     *
3872
     * @return static
3873
     */
3874 2
    public function softWrap(int $width, string $break = "\n"): self
3875
    {
3876 2
        return $this->lineWrapAfterWord($width, $break, false);
3877
    }
3878
3879
    /**
3880
     * Splits the string with the provided regular expression, returning an
3881
     * array of Stringy objects. An optional integer $limit will truncate the
3882
     * results.
3883
     *
3884
     * EXAMPLE: <code>
3885
     * s('foo,bar,baz')->split(',', 2); // ['foo', 'bar']
3886
     * </code>
3887
     *
3888
     * @param string $pattern <p>The regex with which to split the string.</p>
3889
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3890
     *                        limit</p>
3891
     *
3892
     * @psalm-mutation-free
3893
     *
3894
     * @return static[]
3895
     *                  <p>An array of Stringy objects.</p>
3896
     *
3897
     * @psalm-return array<int,static>
3898
     */
3899 51
    public function split(string $pattern, int $limit = null): array
3900
    {
3901 51
        if ($this->str === '') {
3902
            return [];
3903
        }
3904
3905 51
        if ($limit === null) {
3906 7
            $limit = -1;
3907
        }
3908
3909 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
3910
        /** @noinspection AlterInForeachInspection */
3911 51
        foreach ($array as $i => &$value) {
3912 45
            $value = static::create($value, $this->encoding);
3913
        }
3914
3915
        /** @noinspection PhpSillyAssignmentInspection */
3916
        /** @var static[] $array */
3917 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...
3918
3919 51
        return $array;
3920
    }
3921
3922
    /**
3923
     * Splits the string with the provided regular expression, returning an
3924
     * collection of Stringy objects. An optional integer $limit will truncate the
3925
     * results.
3926
     *
3927
     * EXAMPLE: <code>
3928
     * </code>
3929
     *
3930
     * @param string $pattern <p>The regex with which to split the string.</p>
3931
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3932
     *                        limit</p>
3933
     *
3934
     * @psalm-mutation-free
3935
     *
3936
     * @return CollectionStringy|static[]
3937
     *                                    <p>An collection of Stringy objects.</p>
3938
     *
3939
     * @psalm-return CollectionStringy<int,static>
3940
     */
3941 35
    public function splitCollection(string $pattern, int $limit = null): CollectionStringy
3942
    {
3943
        /**
3944
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3945
         */
3946 35
        return CollectionStringy::create(
3947 35
            $this->split($pattern, $limit)
3948
        );
3949
    }
3950
3951
    /**
3952
     * Returns true if the string begins with $substring, false otherwise. By
3953
     * default, the comparison is case-sensitive, but can be made insensitive
3954
     * by setting $caseSensitive to false.
3955
     *
3956
     * EXAMPLE: <code>
3957
     * s('FÒÔbàřbaz')->startsWith('fòôbàř', false); // true
3958
     * </code>
3959
     *
3960
     * @param string $substring     <p>The substring to look for.</p>
3961
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3962
     *
3963
     * @psalm-mutation-free
3964
     *
3965
     * @return bool
3966
     *              <p>Whether or not $str starts with $substring.</p>
3967
     */
3968 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
3969
    {
3970 99
        if ($caseSensitive) {
3971 53
            return $this->utf8::str_starts_with($this->str, $substring);
3972
        }
3973
3974 46
        return $this->utf8::str_istarts_with($this->str, $substring);
3975
    }
3976
3977
    /**
3978
     * Returns true if the string begins with any of $substrings, false otherwise.
3979
     * By default the comparison is case-sensitive, but can be made insensitive by
3980
     * setting $caseSensitive to false.
3981
     *
3982
     * EXAMPLE: <code>
3983
     * s('FÒÔbàřbaz')->startsWithAny(['fòô', 'bàř'], false); // true
3984
     * </code>
3985
     *
3986
     * @param string[] $substrings    <p>Substrings to look for.</p>
3987
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3988
     *
3989
     * @psalm-mutation-free
3990
     *
3991
     * @return bool
3992
     *              <p>Whether or not $str starts with $substring.</p>
3993
     */
3994 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
3995
    {
3996 35
        if ($caseSensitive) {
3997 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
3998
        }
3999
4000 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
4001
    }
4002
4003
    /**
4004
     * Remove one or more strings from the string.
4005
     *
4006
     * EXAMPLE: <code>
4007
     * </code>
4008
     *
4009
     * @param string|string[] $search One or more strings to be removed
4010
     *
4011
     * @psalm-mutation-free
4012
     *
4013
     * @return static
4014
     */
4015 3
    public function strip($search): self
4016
    {
4017 3
        if (\is_array($search)) {
4018 1
            return $this->replaceAll($search, '');
4019
        }
4020
4021 2
        return $this->replace($search, '');
4022
    }
4023
4024
    /**
4025
     * Strip all whitespace characters. This includes tabs and newline characters,
4026
     * as well as multibyte whitespace such as the thin space and ideographic space.
4027
     *
4028
     * EXAMPLE: <code>
4029
     * s('   Ο     συγγραφέας  ')->stripWhitespace(); // 'Οσυγγραφέας'
4030
     * </code>
4031
     *
4032
     * @psalm-mutation-free
4033
     *
4034
     * @return static
4035
     */
4036 36
    public function stripWhitespace(): self
4037
    {
4038 36
        return static::create(
4039 36
            $this->utf8::strip_whitespace($this->str),
4040 36
            $this->encoding
4041
        );
4042
    }
4043
4044
    /**
4045
     * Remove css media-queries.
4046
     *
4047
     * EXAMPLE: <code>
4048
     * s('test @media (min-width:660px){ .des-cla #mv-tiles{width:480px} } test ')->stripeCssMediaQueries(); // 'test  test '
4049
     * </code>
4050
     *
4051
     * @psalm-mutation-free
4052
     *
4053
     * @return static
4054
     */
4055 2
    public function stripeCssMediaQueries(): self
4056
    {
4057 2
        return static::create(
4058 2
            $this->utf8::css_stripe_media_queries($this->str),
4059 2
            $this->encoding
4060
        );
4061
    }
4062
4063
    /**
4064
     * Remove empty html-tag.
4065
     *
4066
     * EXAMPLE: <code>
4067
     * s('foo<h1></h1>bar')->stripeEmptyHtmlTags(); // 'foobar'
4068
     * </code>
4069
     *
4070
     * @psalm-mutation-free
4071
     *
4072
     * @return static
4073
     */
4074 2
    public function stripeEmptyHtmlTags(): self
4075
    {
4076 2
        return static::create(
4077 2
            $this->utf8::html_stripe_empty_tags($this->str),
4078 2
            $this->encoding
4079
        );
4080
    }
4081
4082
    /**
4083
     * Convert the string to StudlyCase.
4084
     *
4085
     * EXAMPLE: <code>
4086
     * </code>
4087
     *
4088
     * @psalm-mutation-free
4089
     *
4090
     * @return static
4091
     */
4092 6
    public function studlyCase(): self
4093
    {
4094 6
        $words = \array_map(
4095 6
            static function (self $word) {
4096 6
                return $word->substr(0, 1)
4097 6
                    ->toUpperCase()
4098 6
                    ->appendStringy($word->substr(1));
4099 6
            },
4100 6
            $this->words('', true)
4101
        );
4102
4103 6
        return new static(\implode('', $words), $this->encoding);
4104
    }
4105
4106
    /**
4107
     * Returns the substring beginning at $start with the specified $length.
4108
     * It differs from the $this->utf8::substr() function in that providing a $length of
4109
     * null will return the rest of the string, rather than an empty string.
4110
     *
4111
     * EXAMPLE: <code>
4112
     * </code>
4113
     *
4114
     * @param int $start  <p>Position of the first character to use.</p>
4115
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
4116
     *
4117
     * @psalm-mutation-free
4118
     *
4119
     * @return static
4120
     *                <p>Object with its $str being the substring.</p>
4121
     */
4122 40
    public function substr(int $start, int $length = null): self
4123
    {
4124 40
        return static::create(
4125 40
            $this->utf8::substr(
4126 40
                $this->str,
4127
                $start,
4128
                $length,
4129 40
                $this->encoding
4130
            ),
4131 40
            $this->encoding
4132
        );
4133
    }
4134
4135
    /**
4136
     * Return part of the string.
4137
     * Alias for substr()
4138
     *
4139
     * EXAMPLE: <code>
4140
     * s('fòôbàř')->substring(2, 3); // 'ôbà'
4141
     * </code>
4142
     *
4143
     * @param int $start  <p>Starting position of the substring.</p>
4144
     * @param int $length [optional] <p>Length of substring.</p>
4145
     *
4146
     * @psalm-mutation-free
4147
     *
4148
     * @return static
4149
     */
4150 3
    public function substring(int $start, int $length = null): self
4151
    {
4152 3
        if ($length === null) {
4153 2
            return $this->substr($start);
4154
        }
4155
4156 3
        return $this->substr($start, $length);
4157
    }
4158
4159
    /**
4160
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
4161
     * If no match is found returns new empty Stringy object.
4162
     *
4163
     * EXAMPLE: <code>
4164
     * </code>
4165
     *
4166
     * @param string $needle       <p>The string to look for.</p>
4167
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
4168
     *
4169
     * @psalm-mutation-free
4170
     *
4171
     * @return static
4172
     */
4173 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...
4174
    {
4175 4
        return static::create(
4176 4
            $this->utf8::str_substr_first(
4177 4
                $this->str,
4178
                $needle,
4179
                $beforeNeedle,
4180 4
                $this->encoding
4181
            ),
4182 4
            $this->encoding
4183
        );
4184
    }
4185
4186
    /**
4187
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
4188
     * If no match is found returns new empty Stringy object.
4189
     *
4190
     * EXAMPLE: <code>
4191
     * </code>
4192
     *
4193
     * @param string $needle       <p>The string to look for.</p>
4194
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
4195
     *
4196
     * @psalm-mutation-free
4197
     *
4198
     * @return static
4199
     */
4200 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...
4201
    {
4202 4
        return static::create(
4203 4
            $this->utf8::str_isubstr_first(
4204 4
                $this->str,
4205
                $needle,
4206
                $beforeNeedle,
4207 4
                $this->encoding
4208
            ),
4209 4
            $this->encoding
4210
        );
4211
    }
4212
4213
    /**
4214
     * Surrounds $str with the given substring.
4215
     *
4216
     * EXAMPLE: <code>
4217
     * s(' ͜ ')->surround('ʘ'); // 'ʘ ͜ ʘ'
4218
     * </code>
4219
     *
4220
     * @param string $substring <p>The substring to add to both sides.</P>
4221
     *
4222
     * @psalm-mutation-free
4223
     *
4224
     * @return static
4225
     *                <p>Object whose $str had the substring both prepended and appended.</p>
4226
     */
4227 15
    public function surround(string $substring): self
4228
    {
4229 15
        return static::create(
4230 15
            $substring . $this->str . $substring,
4231 15
            $this->encoding
4232
        );
4233
    }
4234
4235
    /**
4236
     * Returns a case swapped version of the string.
4237
     *
4238
     * EXAMPLE: <code>
4239
     * s('Ντανιλ')->swapCase(); // 'νΤΑΝΙΛ'
4240
     * </code>
4241
     *
4242
     * @psalm-mutation-free
4243
     *
4244
     * @return static
4245
     *                <p>Object whose $str has each character's case swapped.</P>
4246
     */
4247 15
    public function swapCase(): self
4248
    {
4249 15
        return static::create(
4250 15
            $this->utf8::swapCase($this->str, $this->encoding),
4251 15
            $this->encoding
4252
        );
4253
    }
4254
4255
    /**
4256
     * Returns a string with smart quotes, ellipsis characters, and dashes from
4257
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
4258
     * equivalents.
4259
     *
4260
     * EXAMPLE: <code>
4261
     * s('“I see…”')->tidy(); // '"I see..."'
4262
     * </code>
4263
     *
4264
     * @psalm-mutation-free
4265
     *
4266
     * @return static
4267
     *                <p>Object whose $str has those characters removed.</p>
4268
     */
4269 12
    public function tidy(): self
4270
    {
4271 12
        return static::create(
4272 12
            $this->ascii::normalize_msword($this->str),
4273 12
            $this->encoding
4274
        );
4275
    }
4276
4277
    /**
4278
     * Returns a trimmed string with the first letter of each word capitalized.
4279
     * Also accepts an array, $ignore, allowing you to list words not to be
4280
     * capitalized.
4281
     *
4282
     * EXAMPLE: <code>
4283
     * $ignore = ['at', 'by', 'for', 'in', 'of', 'on', 'out', 'to', 'the'];
4284
     * s('i like to watch television')->titleize($ignore); // 'I Like to Watch Television'
4285
     * </code>
4286
     *
4287
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
4288
     *                                               Default: null</p>
4289
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
4290
     *                                               separator === words.</p>
4291
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
4292
     *
4293
     * @psalm-mutation-free
4294
     *
4295
     * @return static
4296
     *                <p>Object with a titleized $str.</p>
4297
     */
4298 23
    public function titleize(
4299
        array $ignore = null,
4300
        string $word_define_chars = null,
4301
        string $language = null
4302
    ): self {
4303 23
        return static::create(
4304 23
            $this->utf8::str_titleize(
4305 23
                $this->str,
4306
                $ignore,
4307 23
                $this->encoding,
4308 23
                false,
4309
                $language,
4310 23
                false,
4311 23
                true,
4312
                $word_define_chars
4313
            ),
4314 23
            $this->encoding
4315
        );
4316
    }
4317
4318
    /**
4319
     * Returns a trimmed string in proper title case: Also accepts an array, $ignore, allowing you to list words not to
4320
     * be capitalized.
4321
     *
4322
     * EXAMPLE: <code>
4323
     * </code>
4324
     *
4325
     * Adapted from John Gruber's script.
4326
     *
4327
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
4328
     *
4329
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
4330
     *
4331
     * @psalm-mutation-free
4332
     *
4333
     * @return static
4334
     *                <p>Object with a titleized $str</p>
4335
     */
4336 70
    public function titleizeForHumans(array $ignore = []): self
4337
    {
4338 70
        return static::create(
4339 70
            $this->utf8::str_titleize_for_humans(
4340 70
                $this->str,
4341
                $ignore,
4342 70
                $this->encoding
4343
            ),
4344 70
            $this->encoding
4345
        );
4346
    }
4347
4348
    /**
4349
     * Returns an ASCII version of the string. A set of non-ASCII characters are
4350
     * replaced with their closest ASCII counterparts, and the rest are removed
4351
     * by default. The language or locale of the source string can be supplied
4352
     * for language-specific transliteration in any of the following formats:
4353
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
4354
     * to "aeoeue" rather than "aou" as in other languages.
4355
     *
4356
     * EXAMPLE: <code>
4357
     * s('fòôbàř')->toAscii(); // 'foobar'
4358
     * </code>
4359
     *
4360
     * @param string $language          [optional] <p>Language of the source string.</p>
4361
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
4362
     *                                  unsupported characters.</p>
4363
     *
4364
     * @psalm-mutation-free
4365
     *
4366
     * @return static
4367
     *                <p>Object whose $str contains only ASCII characters.</p>
4368
     */
4369 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
4370
    {
4371 23
        return static::create(
4372 23
            $this->ascii::to_ascii(
4373 23
                $this->str,
4374
                $language,
4375
                $removeUnsupported
4376
            ),
4377 23
            $this->encoding
4378
        );
4379
    }
4380
4381
    /**
4382
     * Returns a boolean representation of the given logical string value.
4383
     * For example, <strong>'true', '1', 'on' and 'yes'</strong> will return true. <strong>'false', '0',
4384
     * 'off', and 'no'</strong> will return false. In all instances, case is ignored.
4385
     * For other numeric strings, their sign will determine the return value.
4386
     * In addition, blank strings consisting of only whitespace will return
4387
     * false. For all other strings, the return value is a result of a
4388
     * boolean cast.
4389
     *
4390
     * EXAMPLE: <code>
4391
     * s('OFF')->toBoolean(); // false
4392
     * </code>
4393
     *
4394
     * @psalm-mutation-free
4395
     *
4396
     * @return bool
4397
     *              <p>A boolean value for the string.</p>
4398
     */
4399 45
    public function toBoolean(): bool
4400
    {
4401
        /**
4402
         * @psalm-suppress ArgumentTypeCoercion -> maybe the string looks like an int ;)
4403
         * @phpstan-ignore-next-line
4404
         */
4405 45
        return $this->utf8::to_boolean($this->str);
4406
    }
4407
4408
    /**
4409
     * Converts all characters in the string to lowercase.
4410
     *
4411
     * EXAMPLE: <code>
4412
     * s('FÒÔBÀŘ')->toLowerCase(); // 'fòôbàř'
4413
     * </code>
4414
     *
4415
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
4416
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
4417
     *
4418
     * @psalm-mutation-free
4419
     *
4420
     * @return static
4421
     *                <p>Object with all characters of $str being lowercase.</p>
4422
     */
4423 23 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...
4424
    {
4425 23
        return static::create(
4426 23
            $this->utf8::strtolower(
4427 23
                $this->str,
4428 23
                $this->encoding,
4429 23
                false,
4430
                $lang,
4431
                $tryToKeepStringLength
4432
            ),
4433 23
            $this->encoding
4434
        );
4435
    }
4436
4437
    /**
4438
     * Converts each tab in the string to some number of spaces, as defined by
4439
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
4440
     *
4441
     * EXAMPLE: <code>
4442
     * s(' String speech = "Hi"')->toSpaces(); // '    String speech = "Hi"'
4443
     * </code>
4444
     *
4445
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
4446
     *
4447
     * @psalm-mutation-free
4448
     *
4449
     * @return static
4450
     *                <p>Object whose $str has had tabs switched to spaces.</p>
4451
     */
4452 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...
4453
    {
4454 18
        if ($tabLength === 4) {
4455 9
            $tab = '    ';
4456 9
        } elseif ($tabLength === 2) {
4457 3
            $tab = '  ';
4458
        } else {
4459 6
            $tab = \str_repeat(' ', $tabLength);
4460
        }
4461
4462 18
        return static::create(
4463 18
            \str_replace("\t", $tab, $this->str),
4464 18
            $this->encoding
4465
        );
4466
    }
4467
4468
    /**
4469
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
4470
     * string.
4471
     *
4472
     * EXAMPLE: <code>
4473
     * s('fòôbàř')->toString(); // 'fòôbàř'
4474
     * </code>
4475
     *
4476
     * @psalm-mutation-free
4477
     *
4478
     * @return string
4479
     */
4480 2200
    public function toString(): string
4481
    {
4482 2200
        return (string) $this->str;
4483
    }
4484
4485
    /**
4486
     * Converts each occurrence of some consecutive number of spaces, as
4487
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
4488
     * are converted to a tab.
4489
     *
4490
     * EXAMPLE: <code>
4491
     * s('    fòô    bàř')->toTabs(); // '   fòô bàř'
4492
     * </code>
4493
     *
4494
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
4495
     *
4496
     * @psalm-mutation-free
4497
     *
4498
     * @return static
4499
     *                <p>Object whose $str has had spaces switched to tabs.</p>
4500
     */
4501 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...
4502
    {
4503 15
        if ($tabLength === 4) {
4504 9
            $tab = '    ';
4505 6
        } elseif ($tabLength === 2) {
4506 3
            $tab = '  ';
4507
        } else {
4508 3
            $tab = \str_repeat(' ', $tabLength);
4509
        }
4510
4511 15
        return static::create(
4512 15
            \str_replace($tab, "\t", $this->str),
4513 15
            $this->encoding
4514
        );
4515
    }
4516
4517
    /**
4518
     * Converts the first character of each word in the string to uppercase
4519
     * and all other chars to lowercase.
4520
     *
4521
     * EXAMPLE: <code>
4522
     * s('fòô bàř')->toTitleCase(); // 'Fòô Bàř'
4523
     * </code>
4524
     *
4525
     * @psalm-mutation-free
4526
     *
4527
     * @return static
4528
     *                <p>Object with all characters of $str being title-cased.</p>
4529
     */
4530 15
    public function toTitleCase(): self
4531
    {
4532 15
        return static::create(
4533 15
            $this->utf8::titlecase($this->str, $this->encoding),
4534 15
            $this->encoding
4535
        );
4536
    }
4537
4538
    /**
4539
     * Returns an ASCII version of the string. A set of non-ASCII characters are
4540
     * replaced with their closest ASCII counterparts, and the rest are removed
4541
     * unless instructed otherwise.
4542
     *
4543
     * EXAMPLE: <code>
4544
     * </code>
4545
     *
4546
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
4547
     *                        performance | Default: false</p>
4548
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
4549
     *
4550
     * @psalm-mutation-free
4551
     *
4552
     * @return static
4553
     *                <p>Object whose $str contains only ASCII characters.</p>
4554
     */
4555 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
4556
    {
4557 34
        return static::create(
4558 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
4559 34
            $this->encoding
4560
        );
4561
    }
4562
4563
    /**
4564
     * Converts all characters in the string to uppercase.
4565
     *
4566
     * EXAMPLE: <code>
4567
     * s('fòôbàř')->toUpperCase(); // 'FÒÔBÀŘ'
4568
     * </code>
4569
     *
4570
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
4571
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
4572
     *
4573
     * @psalm-mutation-free
4574
     *
4575
     * @return static
4576
     *                <p>Object with all characters of $str being uppercase.</p>
4577
     */
4578 26 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...
4579
    {
4580 26
        return static::create(
4581 26
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
4582 26
            $this->encoding
4583
        );
4584
    }
4585
4586
    /**
4587
     * Returns a string with whitespace removed from the start and end of the
4588
     * string. Supports the removal of unicode whitespace. Accepts an optional
4589
     * string of characters to strip instead of the defaults.
4590
     *
4591
     * EXAMPLE: <code>
4592
     * s('  fòôbàř  ')->trim(); // 'fòôbàř'
4593
     * </code>
4594
     *
4595
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
4596
     *
4597
     * @psalm-mutation-free
4598
     *
4599
     * @return static
4600
     *                <p>Object with a trimmed $str.</p>
4601
     */
4602 36
    public function trim(string $chars = null): self
4603
    {
4604 36
        return static::create(
4605 36
            $this->utf8::trim($this->str, $chars),
4606 36
            $this->encoding
4607
        );
4608
    }
4609
4610
    /**
4611
     * Returns a string with whitespace removed from the start of the string.
4612
     * Supports the removal of unicode whitespace. Accepts an optional
4613
     * string of characters to strip instead of the defaults.
4614
     *
4615
     * EXAMPLE: <code>
4616
     * s('  fòôbàř  ')->trimLeft(); // 'fòôbàř  '
4617
     * </code>
4618
     *
4619
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
4620
     *
4621
     * @psalm-mutation-free
4622
     *
4623
     * @return static
4624
     *                <p>Object with a trimmed $str.</p>
4625
     */
4626 39
    public function trimLeft(string $chars = null): self
4627
    {
4628 39
        return static::create(
4629 39
            $this->utf8::ltrim($this->str, $chars),
4630 39
            $this->encoding
4631
        );
4632
    }
4633
4634
    /**
4635
     * Returns a string with whitespace removed from the end of the string.
4636
     * Supports the removal of unicode whitespace. Accepts an optional
4637
     * string of characters to strip instead of the defaults.
4638
     *
4639
     * EXAMPLE: <code>
4640
     * s('  fòôbàř  ')->trimRight(); // '  fòôbàř'
4641
     * </code>
4642
     *
4643
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
4644
     *
4645
     * @psalm-mutation-free
4646
     *
4647
     * @return static
4648
     *                <p>Object with a trimmed $str.</p>
4649
     */
4650 39
    public function trimRight(string $chars = null): self
4651
    {
4652 39
        return static::create(
4653 39
            $this->utf8::rtrim($this->str, $chars),
4654 39
            $this->encoding
4655
        );
4656
    }
4657
4658
    /**
4659
     * Truncates the string to a given length. If $substring is provided, and
4660
     * truncating occurs, the string is further truncated so that the substring
4661
     * may be appended without exceeding the desired length.
4662
     *
4663
     * EXAMPLE: <code>
4664
     * s('What are your plans today?')->truncate(19, '...'); // 'What are your pl...'
4665
     * </code>
4666
     *
4667
     * @param int    $length    <p>Desired length of the truncated string.</p>
4668
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
4669
     *
4670
     * @psalm-mutation-free
4671
     *
4672
     * @return static
4673
     *                <p>Object with the resulting $str after truncating.</p>
4674
     */
4675 66
    public function truncate(int $length, string $substring = ''): self
4676
    {
4677 66
        return static::create(
4678 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
4679 66
            $this->encoding
4680
        );
4681
    }
4682
4683
    /**
4684
     * Returns a lowercase and trimmed string separated by underscores.
4685
     * Underscores are inserted before uppercase characters (with the exception
4686
     * of the first character of the string), and in place of spaces as well as
4687
     * dashes.
4688
     *
4689
     * EXAMPLE: <code>
4690
     * s('TestUCase')->underscored(); // 'test_u_case'
4691
     * </code>
4692
     *
4693
     * @psalm-mutation-free
4694
     *
4695
     * @return static
4696
     *                <p>Object with an underscored $str.</p>
4697
     */
4698 48
    public function underscored(): self
4699
    {
4700 48
        return $this->delimit('_');
4701
    }
4702
4703
    /**
4704
     * Returns an UpperCamelCase version of the supplied string. It trims
4705
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
4706
     * and underscores, and removes spaces, dashes, underscores.
4707
     *
4708
     * EXAMPLE: <code>
4709
     * s('Upper Camel-Case')->upperCamelize(); // 'UpperCamelCase'
4710
     * </code>
4711
     *
4712
     * @psalm-mutation-free
4713
     *
4714
     * @return static
4715
     *                <p>Object with $str in UpperCamelCase.</p>
4716
     */
4717 39
    public function upperCamelize(): self
4718
    {
4719 39
        return static::create(
4720 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
4721 39
            $this->encoding
4722
        );
4723
    }
4724
4725
    /**
4726
     * Converts the first character of the supplied string to upper case.
4727
     *
4728
     * EXAMPLE: <code>
4729
     * s('σ foo')->upperCaseFirst(); // 'Σ foo'
4730
     * </code>
4731
     *
4732
     * @psalm-mutation-free
4733
     *
4734
     * @return static
4735
     *                <p>Object with the first character of $str being upper case.</p>
4736
     */
4737 18
    public function upperCaseFirst(): self
4738
    {
4739 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
4740
    }
4741
4742
    /**
4743
     * Simple url-decoding.
4744
     *
4745
     * e.g:
4746
     * 'test+test' => 'test test'
4747
     *
4748
     * EXAMPLE: <code>
4749
     * </code>
4750
     *
4751
     * @psalm-mutation-free
4752
     *
4753
     * @return static
4754
     */
4755 1
    public function urlDecode(): self
4756
    {
4757 1
        return static::create(\urldecode($this->str));
4758
    }
4759
4760
    /**
4761
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
4762
     *
4763
     * e.g:
4764
     * 'test+test'                     => 'test test'
4765
     * 'D&#252;sseldorf'               => 'Düsseldorf'
4766
     * 'D%FCsseldorf'                  => 'Düsseldorf'
4767
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
4768
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
4769
     * 'Düsseldorf'                   => 'Düsseldorf'
4770
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
4771
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
4772
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
4773
     *
4774
     * EXAMPLE: <code>
4775
     * </code>
4776
     *
4777
     * @psalm-mutation-free
4778
     *
4779
     * @return static
4780
     */
4781 1
    public function urlDecodeMulti(): self
4782
    {
4783 1
        return static::create($this->utf8::urldecode($this->str));
4784
    }
4785
4786
    /**
4787
     * Simple url-decoding.
4788
     *
4789
     * e.g:
4790
     * 'test+test' => 'test+test
4791
     *
4792
     * EXAMPLE: <code>
4793
     * </code>
4794
     *
4795
     * @psalm-mutation-free
4796
     *
4797
     * @return static
4798
     */
4799 1
    public function urlDecodeRaw(): self
4800
    {
4801 1
        return static::create(\rawurldecode($this->str));
4802
    }
4803
4804
    /**
4805
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
4806
     *
4807
     * e.g:
4808
     * 'test+test'                     => 'test+test'
4809
     * 'D&#252;sseldorf'               => 'Düsseldorf'
4810
     * 'D%FCsseldorf'                  => 'Düsseldorf'
4811
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
4812
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
4813
     * 'Düsseldorf'                   => 'Düsseldorf'
4814
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
4815
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
4816
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
4817
     *
4818
     * EXAMPLE: <code>
4819
     * </code>
4820
     *
4821
     * @psalm-mutation-free
4822
     *
4823
     * @return static
4824
     */
4825 1
    public function urlDecodeRawMulti(): self
4826
    {
4827 1
        return static::create($this->utf8::rawurldecode($this->str));
4828
    }
4829
4830
    /**
4831
     * Simple url-encoding.
4832
     *
4833
     * e.g:
4834
     * 'test test' => 'test+test'
4835
     *
4836
     * EXAMPLE: <code>
4837
     * </code>
4838
     *
4839
     * @psalm-mutation-free
4840
     *
4841
     * @return static
4842
     */
4843 1
    public function urlEncode(): self
4844
    {
4845 1
        return static::create(\urlencode($this->str));
4846
    }
4847
4848
    /**
4849
     * Simple url-encoding.
4850
     *
4851
     * e.g:
4852
     * 'test test' => 'test%20test'
4853
     *
4854
     * EXAMPLE: <code>
4855
     * </code>
4856
     *
4857
     * @psalm-mutation-free
4858
     *
4859
     * @return static
4860
     */
4861 1
    public function urlEncodeRaw(): self
4862
    {
4863 1
        return static::create(\rawurlencode($this->str));
4864
    }
4865
4866
    /**
4867
     * Converts the string into an URL slug. This includes replacing non-ASCII
4868
     * characters with their closest ASCII equivalents, removing remaining
4869
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
4870
     * $separator. The separator defaults to a single dash, and the string
4871
     * is also converted to lowercase.
4872
     *
4873
     * EXAMPLE: <code>
4874
     * s('Using strings like fòô bàř - 1$')->urlify(); // 'using-strings-like-foo-bar-1-dollar'
4875
     * </code>
4876
     *
4877
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
4878
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
4879
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
4880
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
4881
     *
4882
     * @psalm-mutation-free
4883
     *
4884
     * @return static
4885
     *                <p>Object whose $str has been converted to an URL slug.</p>
4886
     *
4887
     * @psalm-suppress ImpureMethodCall :/
4888
     */
4889 32
    public function urlify(
4890
        string $separator = '-',
4891
        string $language = 'en',
4892
        array $replacements = [],
4893
        bool $strToLower = true
4894
    ): self {
4895
        // init
4896 32
        $str = $this->str;
4897
4898 32
        foreach ($replacements as $from => $to) {
4899 32
            $str = \str_replace($from, $to, $str);
4900
        }
4901
4902 32
        return static::create(
4903 32
            URLify::slug(
4904 32
                $str,
4905
                $language,
4906
                $separator,
4907
                $strToLower
4908
            ),
4909 32
            $this->encoding
4910
        );
4911
    }
4912
4913
    /**
4914
     * Converts the string into an valid UTF-8 string.
4915
     *
4916
     * EXAMPLE: <code>
4917
     * s('Düsseldorf')->utf8ify(); // 'Düsseldorf'
4918
     * </code>
4919
     *
4920
     * @psalm-mutation-free
4921
     *
4922
     * @return static
4923
     */
4924 2
    public function utf8ify(): self
4925
    {
4926 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
4927
    }
4928
4929
    /**
4930
     * Convert a string into an array of words.
4931
     *
4932
     * EXAMPLE: <code>
4933
     * </code>
4934
     *
4935
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4936
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4937
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4938
     *
4939
     * @psalm-mutation-free
4940
     *
4941
     * @return static[]
4942
     *
4943
     * @psalm-return array<int,static>
4944
     */
4945 14
    public function words(
4946
        string $char_list = '',
4947
        bool $remove_empty_values = false,
4948
        int $remove_short_values = null
4949
    ): array {
4950 14
        if ($remove_short_values === null) {
4951 14
            $strings = $this->utf8::str_to_words(
4952 14
                $this->str,
4953
                $char_list,
4954
                $remove_empty_values
4955
            );
4956
        } else {
4957 2
            $strings = $this->utf8::str_to_words(
4958 2
                $this->str,
4959
                $char_list,
4960
                $remove_empty_values,
4961
                $remove_short_values
4962
            );
4963
        }
4964
4965
        /** @noinspection AlterInForeachInspection */
4966 14
        foreach ($strings as &$string) {
4967 14
            $string = static::create($string);
4968
        }
4969
4970
        /** @noinspection PhpSillyAssignmentInspection */
4971
        /** @var static[] $strings */
4972 14
        $strings = $strings;
0 ignored issues
show
Bug introduced by
Why assign $strings to itself?

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

This assignement can be removed without consequences.

Loading history...
4973
4974 14
        return $strings;
4975
    }
4976
4977
    /**
4978
     * Convert a string into an collection of words.
4979
     *
4980
     * EXAMPLE: <code>
4981
     * S::create('中文空白 oöäü#s')->wordsCollection('#', true)->toStrings(); // ['中文空白', 'oöäü#s']
4982
     * </code>
4983
     *
4984
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4985
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4986
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4987
     *
4988
     * @psalm-mutation-free
4989
     *
4990
     * @return CollectionStringy|static[]
4991
     *                                    <p>An collection of Stringy objects.</p>
4992
     *
4993
     * @psalm-return CollectionStringy<int,static>
4994
     */
4995 2
    public function wordsCollection(
4996
        string $char_list = '',
4997
        bool $remove_empty_values = false,
4998
        int $remove_short_values = null
4999
    ): CollectionStringy {
5000
        /**
5001
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
5002
         */
5003 2
        return CollectionStringy::create(
5004 2
            $this->words(
5005 2
                $char_list,
5006
                $remove_empty_values,
5007
                $remove_short_values
5008
            )
5009
        );
5010
    }
5011
5012
    /**
5013
     * Surrounds $str with the given substring.
5014
     *
5015
     * EXAMPLE: <code>
5016
     * </code>
5017
     *
5018
     * @param string $substring <p>The substring to add to both sides.</P>
5019
     *
5020
     * @psalm-mutation-free
5021
     *
5022
     * @return static
5023
     *                <p>Object whose $str had the substring both prepended and appended.</p>
5024
     */
5025 10
    public function wrap(string $substring): self
5026
    {
5027 10
        return $this->surround($substring);
5028
    }
5029
5030
    /**
5031
     * Returns the replacements for the toAscii() method.
5032
     *
5033
     * @noinspection PhpUnused
5034
     *
5035
     * @psalm-mutation-free
5036
     *
5037
     * @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...
5038
     *                       <p>An array of replacements.</p>
5039
     *
5040
     * @deprecated   this is only here for backward-compatibly reasons
5041
     */
5042 1
    protected function charsArray(): array
5043
    {
5044 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
5045
    }
5046
5047
    /**
5048
     * Returns true if $str matches the supplied pattern, false otherwise.
5049
     *
5050
     * @param string $pattern <p>Regex pattern to match against.</p>
5051
     *
5052
     * @psalm-mutation-free
5053
     *
5054
     * @return bool
5055
     *              <p>Whether or not $str matches the pattern.</p>
5056
     */
5057 24
    protected function matchesPattern(string $pattern): bool
5058
    {
5059 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
5060
    }
5061
}
5062