Completed
Push — master ( 958910...74fa01 )
by Lars
01:39
created

Stringy::encode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 18
ccs 11
cts 11
cp 1
crap 2
rs 9.6666
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 13
            $suffix = $suffix[0];
262
        } else {
263 2
            $suffix = \implode('', $suffix);
264
        }
265
266 15
        return static::create($this->str . $suffix, $this->encoding);
267
    }
268
269
    /**
270
     * Append an password (limited to chars that are good readable).
271
     *
272
     * EXAMPLE: <code>
273
     * s('')->appendPassword(8); // e.g.: '89bcdfgh'
274
     * </code>
275
     *
276
     * @param int $length <p>Length of the random string.</p>
277
     *
278
     * @return static
279
     *                <p>Object with appended password.</p>
280
     */
281 2
    public function appendPassword(int $length): self
282
    {
283 2
        return $this->appendRandomString(
284
            $length,
285 2
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
286
        );
287
    }
288
289
    /**
290
     * Append an random string.
291
     *
292
     * EXAMPLE: <code>
293
     * s('')->appendUniqueIdentifier(5, 'ABCDEFGHI'); // e.g.: 'CDEHI'
294
     * </code>
295
     *
296
     * @param int    $length        <p>Length of the random string.</p>
297
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
298
     *
299
     * @return static
300
     *                <p>Object with appended random string.</p>
301
     */
302 4
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
303
    {
304 4
        $str = $this->utf8::get_random_string($length, $possibleChars);
305
306 4
        return $this->append($str);
307
    }
308
309
    /**
310
     * Returns a new string with $suffix appended.
311
     *
312
     * EXAMPLE: <code>
313
     * </code>
314
     *
315
     * @param CollectionStringy|static ...$suffix <p>The Stringy objects to append.</p>
316
     *
317
     * @phpstan-param CollectionStringy<int,static>|static ...$suffix
318
     *
319
     * @psalm-mutation-free
320
     *
321
     * @return static
322
     *                <p>Object with appended $suffix.</p>
323
     */
324 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...
325
    {
326 7
        $suffixStr = '';
327 7
        foreach ($suffix as $suffixTmp) {
328 7
            if ($suffixTmp instanceof CollectionStringy) {
329 1
                $suffixStr .= $suffixTmp->implode('');
330
            } else {
331 7
                $suffixStr .= $suffixTmp->toString();
332
            }
333
        }
334
335 7
        return static::create($this->str . $suffixStr, $this->encoding);
336
    }
337
338
    /**
339
     * Append an unique identifier.
340
     *
341
     * EXAMPLE: <code>
342
     * s('')->appendUniqueIdentifier(); // e.g.: '1f3870be274f6c49b3e31a0c6728957f'
343
     * </code>
344
     *
345
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
346
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
347
     *
348
     * @return static
349
     *                <p>Object with appended unique identifier as md5-hash.</p>
350
     */
351 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
352
    {
353 2
        return $this->append(
354 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
355
        );
356
    }
357
358
    /**
359
     * Returns the character at $index, with indexes starting at 0.
360
     *
361
     * EXAMPLE: <code>
362
     * s('fòôbàř')->at(3); // 'b'
363
     * </code>
364
     *
365
     * @param int $index <p>Position of the character.</p>
366
     *
367
     * @psalm-mutation-free
368
     *
369
     * @return static
370
     *                <p>The character at $index.</p>
371
     */
372 24
    public function at(int $index): self
373
    {
374 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
375
    }
376
377
    /**
378
     * Decode the base64 encoded string.
379
     *
380
     * EXAMPLE: <code>
381
     * </code>
382
     *
383
     * @psalm-mutation-free
384
     *
385
     * @return self
386
     */
387 2
    public function base64Decode(): self
388
    {
389 2
        return static::create(
390 2
            \base64_decode($this->str, true),
391 2
            $this->encoding
392
        );
393
    }
394
395
    /**
396
     * Encode the string to base64.
397
     *
398
     * EXAMPLE: <code>
399
     * </code>
400
     *
401
     * @psalm-mutation-free
402
     *
403
     * @return self
404
     */
405 2
    public function base64Encode(): self
406
    {
407 2
        return static::create(
408 2
            \base64_encode($this->str),
409 2
            $this->encoding
410
        );
411
    }
412
413
    /**
414
     * Creates a hash from the string using the CRYPT_BLOWFISH algorithm.
415
     *
416
     * WARNING: Using this algorithm, will result in the ```$this->str```
417
     *          being truncated to a maximum length of 72 characters.
418
     *
419
     * EXAMPLE: <code>
420
     * </code>
421
     *
422
     * @param array<array-key, int|string> $options [optional] <p>An array of bcrypt hasing options.</p>
423
     *
424
     * @psalm-mutation-free
425
     *
426
     * @return static
427
     */
428 3
    public function bcrypt(array $options = []): self
429
    {
430 3
        return new static(
431 3
            \password_hash(
432 3
                $this->str,
433
                \PASSWORD_BCRYPT,
434 3
                $options
435
            ),
436 3
            $this->encoding
437
        );
438
    }
439
440
    /**
441
     * Return part of the string occurring before a specific string.
442
     *
443
     * EXAMPLE: <code>
444
     * </code>
445
     *
446
     * @param string $string <p>The delimiting string.</p>
447
     *
448
     * @psalm-mutation-free
449
     *
450
     * @return static
451
     */
452 4
    public function before(string $string): self
453
    {
454 4
        $strArray = UTF8::str_split_pattern(
455 4
            $this->str,
456 4
            $string,
457 4
            1
458
        );
459
460 4
        return new static(
461 4
            $strArray[0] ?? '',
462 4
            $this->encoding
463
        );
464
    }
465
466
    /**
467
     * Gets the substring before the first occurrence of a separator.
468
     * If no match is found returns new empty Stringy object.
469
     *
470
     * EXAMPLE: <code>
471
     * s('</b></b>')->beforeFirst('b'); // '</'
472
     * </code>
473
     *
474
     * @param string $separator
475
     *
476
     * @psalm-mutation-free
477
     *
478
     * @return static
479
     */
480 2
    public function beforeFirst(string $separator): self
481
    {
482 2
        return static::create(
483 2
            $this->utf8::str_substr_before_first_separator(
484 2
                $this->str,
485
                $separator,
486 2
                $this->encoding
487
            )
488
        );
489
    }
490
491
    /**
492
     * Gets the substring before the first occurrence of a separator.
493
     * If no match is found returns new empty Stringy object.
494
     *
495
     * EXAMPLE: <code>
496
     * s('</B></B>')->beforeFirstIgnoreCase('b'); // '</'
497
     * </code>
498
     *
499
     * @param string $separator
500
     *
501
     * @psalm-mutation-free
502
     *
503
     * @return static
504
     */
505 2
    public function beforeFirstIgnoreCase(string $separator): self
506
    {
507 2
        return static::create(
508 2
            $this->utf8::str_isubstr_before_first_separator(
509 2
                $this->str,
510
                $separator,
511 2
                $this->encoding
512
            )
513
        );
514
    }
515
516
    /**
517
     * Gets the substring before the last occurrence of a separator.
518
     * If no match is found returns new empty Stringy object.
519
     *
520
     * EXAMPLE: <code>
521
     * s('</b></b>')->beforeLast('b'); // '</b></'
522
     * </code>
523
     *
524
     * @param string $separator
525
     *
526
     * @psalm-mutation-free
527
     *
528
     * @return static
529
     */
530 2
    public function beforeLast(string $separator): self
531
    {
532 2
        return static::create(
533 2
            $this->utf8::str_substr_before_last_separator(
534 2
                $this->str,
535
                $separator,
536 2
                $this->encoding
537
            )
538
        );
539
    }
540
541
    /**
542
     * Gets the substring before the last occurrence of a separator.
543
     * If no match is found returns new empty Stringy object.
544
     *
545
     * EXAMPLE: <code>
546
     * s('</B></B>')->beforeLastIgnoreCase('b'); // '</B></'
547
     * </code>
548
     *
549
     * @param string $separator
550
     *
551
     * @psalm-mutation-free
552
     *
553
     * @return static
554
     */
555 2
    public function beforeLastIgnoreCase(string $separator): self
556
    {
557 2
        return static::create(
558 2
            $this->utf8::str_isubstr_before_last_separator(
559 2
                $this->str,
560
                $separator,
561 2
                $this->encoding
562
            )
563
        );
564
    }
565
566
    /**
567
     * Returns the substring between $start and $end, if found, or an empty
568
     * string. An optional offset may be supplied from which to begin the
569
     * search for the start string.
570
     *
571
     * EXAMPLE: <code>
572
     * s('{foo} and {bar}')->between('{', '}'); // 'foo'
573
     * </code>
574
     *
575
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
576
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
577
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
578
     *
579
     * @psalm-mutation-free
580
     *
581
     * @return static
582
     *                <p>Object whose $str is a substring between $start and $end.</p>
583
     */
584 48
    public function between(string $start, string $end, int $offset = null): self
585
    {
586 48
        $str = $this->utf8::between(
587 48
            $this->str,
588
            $start,
589
            $end,
590 48
            (int) $offset,
591 48
            $this->encoding
592
        );
593
594 48
        return static::create($str, $this->encoding);
595
    }
596
597
    /**
598
     * Call a user function.
599
     *
600
     * EXAMPLE: <code>
601
     * S::create('foo bar lall')->callUserFunction(static function ($str) {
602
     *     return UTF8::str_limit($str, 8);
603
     * })->toString(); // "foo bar…"
604
     * </code>
605
     *
606
     * @param callable $function
607
     * @param mixed    ...$parameter
608
     *
609
     * @psalm-mutation-free
610
     *
611
     * @return static
612
     *                <p>Object having a $str changed via $function.</p>
613
     */
614 2
    public function callUserFunction(callable $function, ...$parameter): self
615
    {
616 2
        $str = $function($this->str, ...$parameter);
617
618 2
        return static::create(
619 2
            $str,
620 2
            $this->encoding
621
        );
622
    }
623
624
    /**
625
     * Returns a camelCase version of the string. Trims surrounding spaces,
626
     * capitalizes letters following digits, spaces, dashes and underscores,
627
     * and removes spaces, dashes, as well as underscores.
628
     *
629
     * EXAMPLE: <code>
630
     * s('Camel-Case')->camelize(); // 'camelCase'
631
     * </code>
632
     *
633
     * @psalm-mutation-free
634
     *
635
     * @return static
636
     *                <p>Object with $str in camelCase.</p>
637
     */
638 57
    public function camelize(): self
639
    {
640 57
        return static::create(
641 57
            $this->utf8::str_camelize($this->str, $this->encoding),
642 57
            $this->encoding
643
        );
644
    }
645
646
    /**
647
     * Returns the string with the first letter of each word capitalized,
648
     * except for when the word is a name which shouldn't be capitalized.
649
     *
650
     * EXAMPLE: <code>
651
     * s('jaap de hoop scheffer')->capitalizePersonName(); // 'Jaap de Hoop Scheffer'
652
     * </code>
653
     *
654
     * @psalm-mutation-free
655
     *
656
     * @return static
657
     *                <p>Object with $str capitalized.</p>
658
     */
659 78
    public function capitalizePersonalName(): self
660
    {
661 78
        return static::create(
662 78
            $this->utf8::str_capitalize_name($this->str),
663 78
            $this->encoding
664
        );
665
    }
666
667
    /**
668
     * Returns an array consisting of the characters in the string.
669
     *
670
     * EXAMPLE: <code>
671
     * s('fòôbàř')->chars(); // ['f', 'ò', 'ô', 'b', 'à', 'ř']
672
     * </code>
673
     *
674
     * @psalm-mutation-free
675
     *
676
     * @return string[]
677
     *                  <p>An array of string chars.</p>
678
     */
679 14
    public function chars(): array
680
    {
681
        /** @var string[] */
682 14
        return $this->utf8::str_split($this->str);
683
    }
684
685
    /**
686
     * Splits the string into chunks of Stringy objects.
687
     *
688
     * EXAMPLE: <code>
689
     * s('foobar')->chunk(3); // ['foo', 'bar']
690
     * </code>
691
     *
692
     * @param int $length [optional] <p>Max character length of each array element.</p>
693
     *
694
     * @psalm-mutation-free
695
     *
696
     * @return static[]
697
     *                  <p>An array of Stringy objects.</p>
698
     *
699
     * @phpstan-return array<int,static>
700
     */
701 13
    public function chunk(int $length = 1): array
702
    {
703 13
        if ($length < 1) {
704
            throw new \InvalidArgumentException('The chunk length must be greater than zero.');
705
        }
706
707 13
        if ($this->str === '') {
708 2
            return [];
709
        }
710
711 11
        $chunks = $this->utf8::str_split($this->str, $length);
712
713 11
        foreach ($chunks as &$value) {
714 11
            $value = static::create($value, $this->encoding);
715
        }
716
717
        /** @noinspection PhpSillyAssignmentInspection */
718
        /** @var static[] $chunks */
719 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...
720
721 11
        return $chunks;
722
    }
723
724
    /**
725
     * Splits the string into chunks of Stringy objects collection.
726
     *
727
     * EXAMPLE: <code>
728
     * </code>
729
     *
730
     * @param int $length [optional] <p>Max character length of each array element.</p>
731
     *
732
     * @psalm-mutation-free
733
     *
734
     * @return CollectionStringy|static[]
735
     *                                    <p>An collection of Stringy objects.</p>
736
     *
737
     * @phpstan-return CollectionStringy<int,static>
738
     */
739 7
    public function chunkCollection(int $length = 1): CollectionStringy
740
    {
741
        /**
742
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
743
         */
744 7
        return CollectionStringy::create(
745 7
            $this->chunk($length)
746
        );
747
    }
748
749
    /**
750
     * Trims the string and replaces consecutive whitespace characters with a
751
     * single space. This includes tabs and newline characters, as well as
752
     * multibyte whitespace such as the thin space and ideographic space.
753
     *
754
     * EXAMPLE: <code>
755
     * s('   Ο     συγγραφέας  ')->collapseWhitespace(); // 'Ο συγγραφέας'
756
     * </code>
757
     *
758
     * @psalm-mutation-free
759
     *
760
     * @return static
761
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
762
     */
763 39
    public function collapseWhitespace(): self
764
    {
765 39
        return static::create(
766 39
            $this->utf8::collapse_whitespace($this->str),
767 39
            $this->encoding
768
        );
769
    }
770
771
    /**
772
     * Returns true if the string contains $needle, false otherwise. By default
773
     * the comparison is case-sensitive, but can be made insensitive by setting
774
     * $caseSensitive to false.
775
     *
776
     * EXAMPLE: <code>
777
     * s('Ο συγγραφέας είπε')->contains('συγγραφέας'); // true
778
     * </code>
779
     *
780
     * @param string $needle        <p>Substring to look for.</p>
781
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
782
     *
783
     * @psalm-mutation-free
784
     *
785
     * @return bool
786
     *              <p>Whether or not $str contains $needle.</p>
787
     */
788 63
    public function contains(string $needle, bool $caseSensitive = true): bool
789
    {
790 63
        return $this->utf8::str_contains(
791 63
            $this->str,
792
            $needle,
793
            $caseSensitive
794
        );
795
    }
796
797
    /**
798
     * Returns true if the string contains all $needles, false otherwise. By
799
     * default the comparison is case-sensitive, but can be made insensitive by
800
     * setting $caseSensitive to false.
801
     *
802
     * EXAMPLE: <code>
803
     * s('foo & bar')->containsAll(['foo', 'bar']); // true
804
     * </code>
805
     *
806
     * @param string[] $needles       <p>SubStrings to look for.</p>
807
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
808
     *
809
     * @psalm-mutation-free
810
     *
811
     * @return bool
812
     *              <p>Whether or not $str contains $needle.</p>
813
     */
814 131
    public function containsAll(array $needles, bool $caseSensitive = true): bool
815
    {
816 131
        return $this->utf8::str_contains_all(
817 131
            $this->str,
818
            $needles,
819
            $caseSensitive
820
        );
821
    }
822
823
    /**
824
     * Returns true if the string contains any $needles, false otherwise. By
825
     * default the comparison is case-sensitive, but can be made insensitive by
826
     * setting $caseSensitive to false.
827
     *
828
     * EXAMPLE: <code>
829
     * s('str contains foo')->containsAny(['foo', 'bar']); // true
830
     * </code>
831
     *
832
     * @param string[] $needles       <p>SubStrings to look for.</p>
833
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
834
     *
835
     * @psalm-mutation-free
836
     *
837
     * @return bool
838
     *              <p>Whether or not $str contains $needle.</p>
839
     */
840 129
    public function containsAny(array $needles, bool $caseSensitive = true): bool
841
    {
842 129
        return $this->utf8::str_contains_any(
843 129
            $this->str,
844
            $needles,
845
            $caseSensitive
846
        );
847
    }
848
849
    /**
850
     * Checks if string starts with "BOM" (Byte Order Mark Character) character.
851
     *
852
     * EXAMPLE: <code>s("\xef\xbb\xbf foobar")->containsBom(); // true</code>
853
     *
854
     * @psalm-mutation-free
855
     *
856
     * @return bool
857
     *              <strong>true</strong> if the string has BOM at the start,<br>
858
     *              <strong>false</strong> otherwise
859
     */
860
    public function containsBom(): bool
861
    {
862
        return $this->utf8::string_has_bom($this->str);
863
    }
864
865
    /**
866
     * Returns the length of the string, implementing the countable interface.
867
     *
868
     * EXAMPLE: <code>
869
     * </code>
870
     *
871
     * @psalm-mutation-free
872
     *
873
     * @return int
874
     *             <p>The number of characters in the string, given the encoding.</p>
875
     */
876 3
    public function count(): int
877
    {
878 3
        return $this->length();
879
    }
880
881
    /**
882
     * Returns the number of occurrences of $substring in the given string.
883
     * By default, the comparison is case-sensitive, but can be made insensitive
884
     * by setting $caseSensitive to false.
885
     *
886
     * EXAMPLE: <code>
887
     * s('Ο συγγραφέας είπε')->countSubstr('α'); // 2
888
     * </code>
889
     *
890
     * @param string $substring     <p>The substring to search for.</p>
891
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
892
     *
893
     * @psalm-mutation-free
894
     *
895
     * @return int
896
     */
897 45
    public function countSubstr(string $substring, bool $caseSensitive = true): int
898
    {
899 45
        return $this->utf8::substr_count_simple(
900 45
            $this->str,
901
            $substring,
902
            $caseSensitive,
903 45
            $this->encoding
904
        );
905
    }
906
907
    /**
908
     * Calculates the crc32 polynomial of a string.
909
     *
910
     * EXAMPLE: <code>
911
     * </code>
912
     *
913
     * @psalm-mutation-free
914
     *
915
     * @return int
916
     */
917 2
    public function crc32(): int
918
    {
919 2
        return \crc32($this->str);
920
    }
921
922
    /**
923
     * Creates a Stringy object and assigns both str and encoding properties
924
     * the supplied values. $str is cast to a string prior to assignment, and if
925
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
926
     * then returns the initialized object. Throws an InvalidArgumentException
927
     * if the first argument is an array or object without a __toString method.
928
     *
929
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
930
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
931
     *
932
     * @throws \InvalidArgumentException
933
     *                                   <p>if an array or object without a
934
     *                                   __toString method is passed as the first argument</p>
935
     *
936
     * @return static
937
     *                <p>A Stringy object.</p>
938
     * @phpstan-pure
939
     */
940 3568
    public static function create($str = '', string $encoding = null): self
941
    {
942 3568
        return new static($str, $encoding);
943
    }
944
945
    /**
946
     * One-way string encryption (hashing).
947
     *
948
     * Hash the string using the standard Unix DES-based algorithm or an
949
     * alternative algorithm that may be available on the system.
950
     *
951
     * PS: if you need encrypt / decrypt, please use ```static::encrypt($password)```
952
     *     and ```static::decrypt($password)```
953
     *
954
     * EXAMPLE: <code>
955
     * </code>
956
     *
957
     * @param string $salt <p>A salt string to base the hashing on.</p>
958
     *
959
     * @psalm-mutation-free
960
     *
961
     * @return static
962
     */
963 3
    public function crypt(string $salt): self
964
    {
965 3
        return new static(
966 3
            \crypt(
967 3
                $this->str,
968 3
                $salt
969
            ),
970 3
            $this->encoding
971
        );
972
    }
973
974
    /**
975
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
976
     * inserted before uppercase characters (with the exception of the first
977
     * character of the string), and in place of spaces as well as underscores.
978
     *
979
     * EXAMPLE: <code>
980
     * s('fooBar')->dasherize(); // 'foo-bar'
981
     * </code>
982
     *
983
     * @psalm-mutation-free
984
     *
985
     * @return static
986
     *                <p>Object with a dasherized $str</p>
987
     */
988 57
    public function dasherize(): self
989
    {
990 57
        return static::create(
991 57
            $this->utf8::str_dasherize($this->str),
992 57
            $this->encoding
993
        );
994
    }
995
996
    /**
997
     * Decrypt the string.
998
     *
999
     * EXAMPLE: <code>
1000
     * </code>
1001
     *
1002
     * @param string $password The key for decrypting
1003
     *
1004
     * @psalm-mutation-free
1005
     *
1006
     * @return static
1007
     */
1008 5
    public function decrypt(string $password): self
1009
    {
1010
        /**
1011
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff
1012
         */
1013 5
        return new static(
1014 5
            Crypto::decryptWithPassword($this->str, $password),
1015 3
            $this->encoding
1016
        );
1017
    }
1018
1019
    /**
1020
     * Returns a lowercase and trimmed string separated by the given delimiter.
1021
     * Delimiters are inserted before uppercase characters (with the exception
1022
     * of the first character of the string), and in place of spaces, dashes,
1023
     * and underscores. Alpha delimiters are not converted to lowercase.
1024
     *
1025
     * EXAMPLE: <code>
1026
     * s('fooBar')->delimit('::'); // 'foo::bar'
1027
     * </code>
1028
     *
1029
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
1030
     *
1031
     * @psalm-mutation-free
1032
     *
1033
     * @return static
1034
     *                <p>Object with a delimited $str.</p>
1035
     */
1036 90
    public function delimit(string $delimiter): self
1037
    {
1038 90
        return static::create(
1039 90
            $this->utf8::str_delimit($this->str, $delimiter),
1040 90
            $this->encoding
1041
        );
1042
    }
1043
1044
    /**
1045
     * Encode the given string into the given $encoding + set the internal character encoding.
1046
     *
1047
     * EXAMPLE: <code>
1048
     * </code>
1049
     *
1050
     * @param string $new_encoding         <p>The desired character encoding.</p>
1051
     * @param bool   $auto_detect_encoding [optional] <p>Auto-detect the current string-encoding</p>
1052
     *
1053
     * @psalm-mutation-free
1054
     *
1055
     * @return static
1056
     */
1057 2
    public function encode(string $new_encoding, bool $auto_detect_encoding = false): self
1058
    {
1059 2
        if ($auto_detect_encoding) {
1060 1
            $str = $this->utf8::encode(
1061 1
                $new_encoding,
1062 1
                $this->str
1063
            );
1064
        } else {
1065 1
            $str = $this->utf8::encode(
1066 1
                $new_encoding,
1067 1
                $this->str,
1068 1
                false,
1069 1
                $this->encoding
1070
            );
1071
        }
1072
1073 2
        return new static($str, $new_encoding);
1074
    }
1075
1076
    /**
1077
     * Encrypt the string.
1078
     *
1079
     * EXAMPLE: <code>
1080
     * </code>
1081
     *
1082
     * @param string $password <p>The key for encrypting</p>
1083
     *
1084
     * @psalm-mutation-free
1085
     *
1086
     * @return static
1087
     */
1088 4
    public function encrypt(string $password): self
1089
    {
1090
        /**
1091
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff
1092
         */
1093 4
        return new static(
1094 4
            Crypto::encryptWithPassword($this->str, $password),
1095 4
            $this->encoding
1096
        );
1097
    }
1098
1099
    /**
1100
     * Returns true if the string ends with $substring, false otherwise. By
1101
     * default, the comparison is case-sensitive, but can be made insensitive
1102
     * by setting $caseSensitive to false.
1103
     *
1104
     * EXAMPLE: <code>
1105
     * s('fòôbàř')->endsWith('bàř', true); // true
1106
     * </code>
1107
     *
1108
     * @param string $substring     <p>The substring to look for.</p>
1109
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1110
     *
1111
     * @psalm-mutation-free
1112
     *
1113
     * @return bool
1114
     *              <p>Whether or not $str ends with $substring.</p>
1115
     */
1116 97
    public function endsWith(string $substring, bool $caseSensitive = true): bool
1117
    {
1118 97
        if ($caseSensitive) {
1119 53
            return $this->utf8::str_ends_with($this->str, $substring);
1120
        }
1121
1122 44
        return $this->utf8::str_iends_with($this->str, $substring);
1123
    }
1124
1125
    /**
1126
     * Returns true if the string ends with any of $substrings, false otherwise.
1127
     * By default, the comparison is case-sensitive, but can be made insensitive
1128
     * by setting $caseSensitive to false.
1129
     *
1130
     * EXAMPLE: <code>
1131
     * s('fòôbàř')->endsWithAny(['bàř', 'baz'], true); // true
1132
     * </code>
1133
     *
1134
     * @param string[] $substrings    <p>Substrings to look for.</p>
1135
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1136
     *
1137
     * @psalm-mutation-free
1138
     *
1139
     * @return bool
1140
     *              <p>Whether or not $str ends with $substring.</p>
1141
     */
1142 33
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
1143
    {
1144 33
        if ($caseSensitive) {
1145 21
            return $this->utf8::str_ends_with_any($this->str, $substrings);
1146
        }
1147
1148 12
        return $this->utf8::str_iends_with_any($this->str, $substrings);
1149
    }
1150
1151
    /**
1152
     * Ensures that the string begins with $substring. If it doesn't, it's
1153
     * prepended.
1154
     *
1155
     * EXAMPLE: <code>
1156
     * s('foobar')->ensureLeft('http://'); // 'http://foobar'
1157
     * </code>
1158
     *
1159
     * @param string $substring <p>The substring to add if not present.</p>
1160
     *
1161
     * @psalm-mutation-free
1162
     *
1163
     * @return static
1164
     *                <p>Object with its $str prefixed by the $substring.</p>
1165
     */
1166 30
    public function ensureLeft(string $substring): self
1167
    {
1168 30
        return static::create(
1169 30
            $this->utf8::str_ensure_left($this->str, $substring),
1170 30
            $this->encoding
1171
        );
1172
    }
1173
1174
    /**
1175
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
1176
     *
1177
     * EXAMPLE: <code>
1178
     * s('foobar')->ensureRight('.com'); // 'foobar.com'
1179
     * </code>
1180
     *
1181
     * @param string $substring <p>The substring to add if not present.</p>
1182
     *
1183
     * @psalm-mutation-free
1184
     *
1185
     * @return static
1186
     *                <p>Object with its $str suffixed by the $substring.</p>
1187
     */
1188 30
    public function ensureRight(string $substring): self
1189
    {
1190 30
        return static::create(
1191 30
            $this->utf8::str_ensure_right($this->str, $substring),
1192 30
            $this->encoding
1193
        );
1194
    }
1195
1196
    /**
1197
     * Create a escape html version of the string via "htmlspecialchars()".
1198
     *
1199
     * EXAMPLE: <code>
1200
     * s('<∂∆ onerror="alert(xss)">')->escape(); // '&lt;∂∆ onerror=&quot;alert(xss)&quot;&gt;'
1201
     * </code>
1202
     *
1203
     * @psalm-mutation-free
1204
     *
1205
     * @return static
1206
     */
1207 12
    public function escape(): self
1208
    {
1209 12
        return static::create(
1210 12
            $this->utf8::htmlspecialchars(
1211 12
                $this->str,
1212 12
                \ENT_QUOTES | \ENT_SUBSTITUTE,
1213 12
                $this->encoding
1214
            ),
1215 12
            $this->encoding
1216
        );
1217
    }
1218
1219
    /**
1220
     * Split a string by a string.
1221
     *
1222
     * EXAMPLE: <code>
1223
     * </code>
1224
     *
1225
     * @param string $delimiter <p>The boundary string</p>
1226
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1227
     *                          collection.</p>
1228
     *
1229
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1230
     *   element containing the rest of string.
1231
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1232
     *   - If the limit parameter is zero, then this is treated as 1
1233
     *
1234
     * @psalm-mutation-free
1235
     *
1236
     * @return array<int,static>
1237
     */
1238 3
    public function explode(string $delimiter, int $limit = \PHP_INT_MAX): array
1239
    {
1240 3
        if ($this->str === '') {
1241
            return [];
1242
        }
1243
1244 3
        $strings = \explode($delimiter, $this->str, $limit);
1245
        /** @phpstan-ignore-next-line - if "$delimiter" is an empty string, then "explode()" will return "false" */
1246 3
        if ($strings === false) {
1247
            $strings = [];
1248
        }
1249
1250 3
        return \array_map(
1251 3
            function ($str) {
1252 3
                return new static($str, $this->encoding);
1253
            },
1254 3
            $strings
1255
        );
1256
    }
1257
1258
    /**
1259
     * Split a string by a string.
1260
     *
1261
     * EXAMPLE: <code>
1262
     * </code>
1263
     *
1264
     * @param string $delimiter <p>The boundary string</p>
1265
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1266
     *                          collection.</p>
1267
     *
1268
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1269
     *   element containing the rest of string.
1270
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1271
     *   - If the limit parameter is zero, then this is treated as 1
1272
     *
1273
     * @psalm-mutation-free
1274
     *
1275
     * @return CollectionStringy|static[]
1276
     *                                    <p>An collection of Stringy objects.</p>
1277
     *
1278
     * @phpstan-return CollectionStringy<int,static>
1279
     */
1280 1
    public function explodeCollection(string $delimiter, int $limit = \PHP_INT_MAX): CollectionStringy
1281
    {
1282
        /**
1283
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
1284
         */
1285 1
        return CollectionStringy::create(
1286 1
            $this->explode($delimiter, $limit)
1287
        );
1288
    }
1289
1290
    /**
1291
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
1292
     *
1293
     * EXAMPLE: <code>
1294
     * $sentence = 'This is only a Fork of Stringy, take a look at the new features.';
1295
     * s($sentence)->extractText('Stringy'); // '...Fork of Stringy...'
1296
     * </code>
1297
     *
1298
     * @param string   $search
1299
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
1300
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
1301
     *
1302
     * @psalm-mutation-free
1303
     *
1304
     * @return static
1305
     */
1306 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
1307
    {
1308 2
        return static::create(
1309 2
            $this->utf8::extract_text(
1310 2
                $this->str,
1311
                $search,
1312
                $length,
1313
                $replacerForSkippedText,
1314 2
                $this->encoding
1315
            ),
1316 2
            $this->encoding
1317
        );
1318
    }
1319
1320
    /**
1321
     * Returns the first $n characters of the string.
1322
     *
1323
     * EXAMPLE: <code>
1324
     * s('fòôbàř')->first(3); // 'fòô'
1325
     * </code>
1326
     *
1327
     * @param int $n <p>Number of characters to retrieve from the start.</p>
1328
     *
1329
     * @psalm-mutation-free
1330
     *
1331
     * @return static
1332
     *                <p>Object with its $str being the first $n chars.</p>
1333
     */
1334 37
    public function first(int $n): self
1335
    {
1336 37
        return static::create(
1337 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
1338 37
            $this->encoding
1339
        );
1340
    }
1341
1342
    /**
1343
     * Return a formatted string via sprintf + named parameters via array syntax.
1344
     *
1345
     * <p>
1346
     * <br>
1347
     * It will use "sprintf()" so you can use e.g.:
1348
     * <br>
1349
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
1350
     * <br>
1351
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
1352
     * <br>
1353
     * <br>
1354
     * But you can also use named parameter via array syntax e.g.:
1355
     * <br>
1356
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
1357
     * </p>
1358
     *
1359
     * EXAMPLE: <code>
1360
     * $input = 'one: %2$d, %1$s: 2, %:text_three: %3$d';
1361
     * s($input)->format(['text_three' => '%4$s'], 'two', 1, 3, 'three'); // 'One: 1, two: 2, three: 3'
1362
     * </code>
1363
     *
1364
     * @param mixed ...$args [optional]
1365
     *
1366
     * @psalm-mutation-free
1367
     *
1368
     * @return static
1369
     *                <p>A Stringy object produced according to the formatting string
1370
     *                format.</p>
1371
     */
1372 10
    public function format(...$args): self
1373
    {
1374
        // init
1375 10
        $str = $this->str;
1376
1377 10
        if (\strpos($this->str, '%:') !== false) {
1378 8
            $offset = null;
1379 8
            $replacement = null;
1380
            /** @noinspection AlterInForeachInspection */
1381 8
            foreach ($args as $key => &$arg) {
1382 8
                if (!\is_array($arg)) {
1383 4
                    continue;
1384
                }
1385
1386 8
                foreach ($arg as $name => $param) {
1387 8
                    $name = (string) $name;
1388
1389 8
                    if (\strpos($name, '%:') !== 0) {
1390 8
                        $nameTmp = '%:' . $name;
1391
                    } else {
1392
                        $nameTmp = $name;
1393
                    }
1394
1395 8
                    if ($offset === null) {
1396 8
                        $offset = \strpos($str, $nameTmp);
1397
                    } else {
1398 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
1399
                    }
1400 8
                    if ($offset === false) {
1401 4
                        continue;
1402
                    }
1403
1404 8
                    unset($arg[$name]);
1405
1406 8
                    $str = \substr_replace($str, (string) $param, (int) $offset, \strlen($nameTmp));
1407
                }
1408
1409 8
                unset($args[$key]);
1410
            }
1411
        }
1412
1413 10
        $str = \str_replace('%:', '%%:', $str);
1414
1415 10
        return static::create(
1416 10
            \sprintf($str, ...$args),
1417 10
            $this->encoding
1418
        );
1419
    }
1420
1421
    /**
1422
     * Returns the encoding used by the Stringy object.
1423
     *
1424
     * EXAMPLE: <code>
1425
     * s('fòôbàř', 'UTF-8')->getEncoding(); // 'UTF-8'
1426
     * </code>
1427
     *
1428
     * @psalm-mutation-free
1429
     *
1430
     * @return string
1431
     *                <p>The current value of the $encoding property.</p>
1432
     */
1433 25
    public function getEncoding(): string
1434
    {
1435 25
        return $this->encoding;
1436
    }
1437
1438
    /**
1439
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
1440
     * interface. The ArrayIterator's constructor is passed an array of chars
1441
     * in the multibyte string. This enables the use of foreach with instances
1442
     * of Stringy\Stringy.
1443
     *
1444
     * EXAMPLE: <code>
1445
     * </code>
1446
     *
1447
     * @psalm-mutation-free
1448
     *
1449
     * @return \ArrayIterator
1450
     *                        <p>An iterator for the characters in the string.</p>
1451
     *
1452
     * @phpstan-return \ArrayIterator<array-key,string>
1453
     */
1454 3
    public function getIterator(): \ArrayIterator
1455
    {
1456 3
        return new \ArrayIterator($this->chars());
1457
    }
1458
1459
    /**
1460
     * Wrap the string after an exact number of characters.
1461
     *
1462
     * EXAMPLE: <code>
1463
     * </code>
1464
     *
1465
     * @param int    $width <p>Number of characters at which to wrap.</p>
1466
     * @param string $break [optional] <p>Character used to break the string. | Default: "\n"</p>
1467
     *
1468
     * @psalm-mutation-free
1469
     *
1470
     * @return static
1471
     */
1472 2
    public function hardWrap($width, $break = "\n"): self
1473
    {
1474 2
        return $this->lineWrap($width, $break, false);
1475
    }
1476
1477
    /**
1478
     * Returns true if the string contains a lower case char, false otherwise
1479
     *
1480
     * EXAMPLE: <code>
1481
     * s('fòôbàř')->hasLowerCase(); // true
1482
     * </code>
1483
     *
1484
     * @psalm-mutation-free
1485
     *
1486
     * @return bool
1487
     *              <p>Whether or not the string contains a lower case character.</p>
1488
     */
1489 36
    public function hasLowerCase(): bool
1490
    {
1491 36
        return $this->utf8::has_lowercase($this->str);
1492
    }
1493
1494
    /**
1495
     * Returns true if the string contains an upper case char, false otherwise.
1496
     *
1497
     * EXAMPLE: <code>
1498
     * s('fòôbàř')->hasUpperCase(); // false
1499
     * </code>
1500
     *
1501
     * @psalm-mutation-free
1502
     *
1503
     * @return bool
1504
     *              <p>Whether or not the string contains an upper case character.</p>
1505
     */
1506 36
    public function hasUpperCase(): bool
1507
    {
1508 36
        return $this->utf8::has_uppercase($this->str);
1509
    }
1510
1511
    /**
1512
     * Generate a hash value (message digest).
1513
     *
1514
     * EXAMPLE: <code>
1515
     * </code>
1516
     *
1517
     * @see https://php.net/manual/en/function.hash.php
1518
     *
1519
     * @param string $algorithm
1520
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
1521
     *
1522
     * @psalm-mutation-free
1523
     *
1524
     * @return static
1525
     */
1526 8
    public function hash($algorithm): self
1527
    {
1528 8
        return static::create(\hash($algorithm, $this->str), $this->encoding);
1529
    }
1530
1531
    /**
1532
     * Decode the string from hex.
1533
     *
1534
     * EXAMPLE: <code>
1535
     * </code>
1536
     *
1537
     * @psalm-mutation-free
1538
     *
1539
     * @return static
1540
     */
1541 2
    public function hexDecode(): self
1542
    {
1543 2
        $string = \preg_replace_callback(
1544
            '/\\\\x([0-9A-Fa-f]+)/',
1545 2
            function (array $matched) {
1546 2
                return (string) $this->utf8::hex_to_chr($matched[1]);
1547
            },
1548 2
            $this->str
1549
        );
1550
1551 2
        return static::create(
1552 2
            $string,
1553 2
            $this->encoding
1554
        );
1555
    }
1556
1557
    /**
1558
     * Encode string to hex.
1559
     *
1560
     * EXAMPLE: <code>
1561
     * </code>
1562
     *
1563
     * @psalm-mutation-free
1564
     *
1565
     * @return static
1566
     */
1567 2
    public function hexEncode(): self
1568
    {
1569 2
        $string = \array_reduce(
1570 2
            $this->chars(),
1571 2
            function (string $str, string $char) {
1572 2
                return $str . $this->utf8::chr_to_hex($char);
1573
            },
1574 2
            ''
1575
        );
1576
1577 2
        return static::create(
1578 2
            $string,
1579 2
            $this->encoding
1580
        );
1581
    }
1582
1583
    /**
1584
     * Convert all HTML entities to their applicable characters.
1585
     *
1586
     * EXAMPLE: <code>
1587
     * s('&amp;')->htmlDecode(); // '&'
1588
     * </code>
1589
     *
1590
     * @param int $flags [optional] <p>
1591
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1592
     *                   which document type to use. The default is ENT_COMPAT.
1593
     *                   <table>
1594
     *                   Available <i>flags</i> constants
1595
     *                   <tr valign="top">
1596
     *                   <td>Constant Name</td>
1597
     *                   <td>Description</td>
1598
     *                   </tr>
1599
     *                   <tr valign="top">
1600
     *                   <td><b>ENT_COMPAT</b></td>
1601
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1602
     *                   </tr>
1603
     *                   <tr valign="top">
1604
     *                   <td><b>ENT_QUOTES</b></td>
1605
     *                   <td>Will convert both double and single quotes.</td>
1606
     *                   </tr>
1607
     *                   <tr valign="top">
1608
     *                   <td><b>ENT_NOQUOTES</b></td>
1609
     *                   <td>Will leave both double and single quotes unconverted.</td>
1610
     *                   </tr>
1611
     *                   <tr valign="top">
1612
     *                   <td><b>ENT_HTML401</b></td>
1613
     *                   <td>
1614
     *                   Handle code as HTML 4.01.
1615
     *                   </td>
1616
     *                   </tr>
1617
     *                   <tr valign="top">
1618
     *                   <td><b>ENT_XML1</b></td>
1619
     *                   <td>
1620
     *                   Handle code as XML 1.
1621
     *                   </td>
1622
     *                   </tr>
1623
     *                   <tr valign="top">
1624
     *                   <td><b>ENT_XHTML</b></td>
1625
     *                   <td>
1626
     *                   Handle code as XHTML.
1627
     *                   </td>
1628
     *                   </tr>
1629
     *                   <tr valign="top">
1630
     *                   <td><b>ENT_HTML5</b></td>
1631
     *                   <td>
1632
     *                   Handle code as HTML 5.
1633
     *                   </td>
1634
     *                   </tr>
1635
     *                   </table>
1636
     *                   </p>
1637
     *
1638
     * @psalm-mutation-free
1639
     *
1640
     * @return static
1641
     *                <p>Object with the resulting $str after being html decoded.</p>
1642
     */
1643 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...
1644
    {
1645 15
        return static::create(
1646 15
            $this->utf8::html_entity_decode(
1647 15
                $this->str,
1648
                $flags,
1649 15
                $this->encoding
1650
            ),
1651 15
            $this->encoding
1652
        );
1653
    }
1654
1655
    /**
1656
     * Convert all applicable characters to HTML entities.
1657
     *
1658
     * EXAMPLE: <code>
1659
     * s('&')->htmlEncode(); // '&amp;'
1660
     * </code>
1661
     *
1662
     * @param int $flags [optional] <p>
1663
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1664
     *                   which document type to use. The default is ENT_COMPAT.
1665
     *                   <table>
1666
     *                   Available <i>flags</i> constants
1667
     *                   <tr valign="top">
1668
     *                   <td>Constant Name</td>
1669
     *                   <td>Description</td>
1670
     *                   </tr>
1671
     *                   <tr valign="top">
1672
     *                   <td><b>ENT_COMPAT</b></td>
1673
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1674
     *                   </tr>
1675
     *                   <tr valign="top">
1676
     *                   <td><b>ENT_QUOTES</b></td>
1677
     *                   <td>Will convert both double and single quotes.</td>
1678
     *                   </tr>
1679
     *                   <tr valign="top">
1680
     *                   <td><b>ENT_NOQUOTES</b></td>
1681
     *                   <td>Will leave both double and single quotes unconverted.</td>
1682
     *                   </tr>
1683
     *                   <tr valign="top">
1684
     *                   <td><b>ENT_HTML401</b></td>
1685
     *                   <td>
1686
     *                   Handle code as HTML 4.01.
1687
     *                   </td>
1688
     *                   </tr>
1689
     *                   <tr valign="top">
1690
     *                   <td><b>ENT_XML1</b></td>
1691
     *                   <td>
1692
     *                   Handle code as XML 1.
1693
     *                   </td>
1694
     *                   </tr>
1695
     *                   <tr valign="top">
1696
     *                   <td><b>ENT_XHTML</b></td>
1697
     *                   <td>
1698
     *                   Handle code as XHTML.
1699
     *                   </td>
1700
     *                   </tr>
1701
     *                   <tr valign="top">
1702
     *                   <td><b>ENT_HTML5</b></td>
1703
     *                   <td>
1704
     *                   Handle code as HTML 5.
1705
     *                   </td>
1706
     *                   </tr>
1707
     *                   </table>
1708
     *                   </p>
1709
     *
1710
     * @psalm-mutation-free
1711
     *
1712
     * @return static
1713
     *                <p>Object with the resulting $str after being html encoded.</p>
1714
     */
1715 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...
1716
    {
1717 15
        return static::create(
1718 15
            $this->utf8::htmlentities(
1719 15
                $this->str,
1720
                $flags,
1721 15
                $this->encoding
1722
            ),
1723 15
            $this->encoding
1724
        );
1725
    }
1726
1727
    /**
1728
     * Capitalizes the first word of the string, replaces underscores with
1729
     * spaces, and strips '_id'.
1730
     *
1731
     * EXAMPLE: <code>
1732
     * s('author_id')->humanize(); // 'Author'
1733
     * </code>
1734
     *
1735
     * @psalm-mutation-free
1736
     *
1737
     * @return static
1738
     *                <p>Object with a humanized $str.</p>
1739
     */
1740 9
    public function humanize(): self
1741
    {
1742 9
        return static::create(
1743 9
            $this->utf8::str_humanize($this->str),
1744 9
            $this->encoding
1745
        );
1746
    }
1747
1748
    /**
1749
     * Determine if the current string exists in another string. By
1750
     * default, the comparison is case-sensitive, but can be made insensitive
1751
     * by setting $caseSensitive to false.
1752
     *
1753
     * EXAMPLE: <code>
1754
     * </code>
1755
     *
1756
     * @param string $str           <p>The string to compare against.</p>
1757
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1758
     *
1759
     * @psalm-mutation-free
1760
     *
1761
     * @return bool
1762
     */
1763 3
    public function in(string $str, bool $caseSensitive = true): bool
1764
    {
1765 3
        if ($caseSensitive) {
1766 2
            return \strpos($str, $this->str) !== false;
1767
        }
1768
1769 1
        return \stripos($str, $this->str) !== false;
1770
    }
1771
1772
    /**
1773
     * Returns the index of the first occurrence of $needle in the string,
1774
     * and false if not found. Accepts an optional offset from which to begin
1775
     * the search.
1776
     *
1777
     * EXAMPLE: <code>
1778
     * s('string')->indexOf('ing'); // 3
1779
     * </code>
1780
     *
1781
     * @param string $needle <p>Substring to look for.</p>
1782
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1783
     *
1784
     * @psalm-mutation-free
1785
     *
1786
     * @return false|int
1787
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1788
     */
1789 31
    public function indexOf(string $needle, int $offset = 0)
1790
    {
1791 31
        return $this->utf8::strpos(
1792 31
            $this->str,
1793
            $needle,
1794
            $offset,
1795 31
            $this->encoding
1796
        );
1797
    }
1798
1799
    /**
1800
     * Returns the index of the first occurrence of $needle in the string,
1801
     * and false if not found. Accepts an optional offset from which to begin
1802
     * the search.
1803
     *
1804
     * EXAMPLE: <code>
1805
     * s('string')->indexOfIgnoreCase('ING'); // 3
1806
     * </code>
1807
     *
1808
     * @param string $needle <p>Substring to look for.</p>
1809
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1810
     *
1811
     * @psalm-mutation-free
1812
     *
1813
     * @return false|int
1814
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1815
     */
1816 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1817
    {
1818 20
        return $this->utf8::stripos(
1819 20
            $this->str,
1820
            $needle,
1821
            $offset,
1822 20
            $this->encoding
1823
        );
1824
    }
1825
1826
    /**
1827
     * Returns the index of the last occurrence of $needle in the string,
1828
     * and false if not found. Accepts an optional offset from which to begin
1829
     * the search. Offsets may be negative to count from the last character
1830
     * in the string.
1831
     *
1832
     * EXAMPLE: <code>
1833
     * s('foobarfoo')->indexOfLast('foo'); // 10
1834
     * </code>
1835
     *
1836
     * @param string $needle <p>Substring to look for.</p>
1837
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1838
     *
1839
     * @psalm-mutation-free
1840
     *
1841
     * @return false|int
1842
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1843
     */
1844 31
    public function indexOfLast(string $needle, int $offset = 0)
1845
    {
1846 31
        return $this->utf8::strrpos(
1847 31
            $this->str,
1848
            $needle,
1849
            $offset,
1850 31
            $this->encoding
1851
        );
1852
    }
1853
1854
    /**
1855
     * Returns the index of the last occurrence of $needle in the string,
1856
     * and false if not found. Accepts an optional offset from which to begin
1857
     * the search. Offsets may be negative to count from the last character
1858
     * in the string.
1859
     *
1860
     * EXAMPLE: <code>
1861
     * s('fooBarFoo')->indexOfLastIgnoreCase('foo'); // 10
1862
     * </code>
1863
     *
1864
     * @param string $needle <p>Substring to look for.</p>
1865
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1866
     *
1867
     * @psalm-mutation-free
1868
     *
1869
     * @return false|int
1870
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1871
     */
1872 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1873
    {
1874 20
        return $this->utf8::strripos(
1875 20
            $this->str,
1876
            $needle,
1877
            $offset,
1878 20
            $this->encoding
1879
        );
1880
    }
1881
1882
    /**
1883
     * Inserts $substring into the string at the $index provided.
1884
     *
1885
     * EXAMPLE: <code>
1886
     * s('fòôbř')->insert('à', 4); // 'fòôbàř'
1887
     * </code>
1888
     *
1889
     * @param string $substring <p>String to be inserted.</p>
1890
     * @param int    $index     <p>The index at which to insert the substring.</p>
1891
     *
1892
     * @psalm-mutation-free
1893
     *
1894
     * @return static
1895
     *                <p>Object with the resulting $str after the insertion.</p>
1896
     */
1897 24
    public function insert(string $substring, int $index): self
1898
    {
1899 24
        return static::create(
1900 24
            $this->utf8::str_insert(
1901 24
                $this->str,
1902
                $substring,
1903
                $index,
1904 24
                $this->encoding
1905
            ),
1906 24
            $this->encoding
1907
        );
1908
    }
1909
1910
    /**
1911
     * Returns true if the string contains the $pattern, otherwise false.
1912
     *
1913
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1914
     * expression wildcards.
1915
     *
1916
     * EXAMPLE: <code>
1917
     * s('Foo\\Bar\\Lall')->is('*\\Bar\\*'); // true
1918
     * </code>
1919
     *
1920
     * @credit Originally from Laravel, thanks Taylor.
1921
     *
1922
     * @param string $pattern <p>The string or pattern to match against.</p>
1923
     *
1924
     * @psalm-mutation-free
1925
     *
1926
     * @return bool
1927
     *              <p>Whether or not we match the provided pattern.</p>
1928
     */
1929 26
    public function is(string $pattern): bool
1930
    {
1931 26
        if ($this->toString() === $pattern) {
1932 2
            return true;
1933
        }
1934
1935 24
        $quotedPattern = \preg_quote($pattern, '/');
1936 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1937
1938 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1939
    }
1940
1941
    /**
1942
     * Returns true if the string contains only alphabetic chars, false otherwise.
1943
     *
1944
     * EXAMPLE: <code>
1945
     * s('丹尼爾')->isAlpha(); // true
1946
     * </code>
1947
     *
1948
     * @psalm-mutation-free
1949
     *
1950
     * @return bool
1951
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1952
     */
1953 30
    public function isAlpha(): bool
1954
    {
1955 30
        return $this->utf8::is_alpha($this->str);
1956
    }
1957
1958
    /**
1959
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1960
     *
1961
     * EXAMPLE: <code>
1962
     * s('دانيال1')->isAlphanumeric(); // true
1963
     * </code>
1964
     *
1965
     * @psalm-mutation-free
1966
     *
1967
     * @return bool
1968
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1969
     */
1970 39
    public function isAlphanumeric(): bool
1971
    {
1972 39
        return $this->utf8::is_alphanumeric($this->str);
1973
    }
1974
1975
    /**
1976
     * Checks if a string is 7 bit ASCII.
1977
     *
1978
     * EXAMPLE: <code>s('白')->isAscii; // false</code>
1979
     *
1980
     * @psalm-mutation-free
1981
     *
1982
     * @return bool
1983
     *              <p>
1984
     *              <strong>true</strong> if it is ASCII<br>
1985
     *              <strong>false</strong> otherwise
1986
     *              </p>
1987
     *
1988
     * @noinspection GetSetMethodCorrectnessInspection
1989
     */
1990
    public function isAscii(): bool
1991
    {
1992
        return $this->utf8::is_ascii($this->str);
1993
    }
1994
1995
    /**
1996
     * Returns true if the string is base64 encoded, false otherwise.
1997
     *
1998
     * EXAMPLE: <code>
1999
     * s('Zm9vYmFy')->isBase64(); // true
2000
     * </code>
2001
     *
2002
     * @param bool $emptyStringIsValid
2003
     *
2004
     * @psalm-mutation-free
2005
     *
2006
     * @return bool
2007
     *              <p>Whether or not $str is base64 encoded.</p>
2008
     */
2009 21
    public function isBase64($emptyStringIsValid = true): bool
2010
    {
2011 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
2012
    }
2013
2014
    /**
2015
     * Check if the input is binary... (is look like a hack).
2016
     *
2017
     * EXAMPLE: <code>s(01)->isBinary(); // true</code>
2018
     *
2019
     * @psalm-mutation-free
2020
     *
2021
     * @return bool
2022
     */
2023
    public function isBinary(): bool
2024
    {
2025
        return $this->utf8::is_binary($this->str);
2026
    }
2027
2028
    /**
2029
     * Returns true if the string contains only whitespace chars, false otherwise.
2030
     *
2031
     * EXAMPLE: <code>
2032
     * s("\n\t  \v\f")->isBlank(); // true
2033
     * </code>
2034
     *
2035
     * @psalm-mutation-free
2036
     *
2037
     * @return bool
2038
     *              <p>Whether or not $str contains only whitespace characters.</p>
2039
     */
2040 45
    public function isBlank(): bool
2041
    {
2042 45
        return $this->utf8::is_blank($this->str);
2043
    }
2044
2045
    /**
2046
     * Checks if the given string is equal to any "Byte Order Mark".
2047
     *
2048
     * WARNING: Use "s::string_has_bom()" if you will check BOM in a string.
2049
     *
2050
     * EXAMPLE: <code>s->("\xef\xbb\xbf")->isBom(); // true</code>
2051
     *
2052
     * @psalm-mutation-free
2053
     *
2054
     * @return bool
2055
     *              <p><strong>true</strong> if the $utf8_chr is Byte Order Mark, <strong>false</strong> otherwise.</p>
2056
     */
2057
    public function isBom(): bool
2058
    {
2059
        return $this->utf8::is_bom($this->str);
2060
    }
2061
2062
    /**
2063
     * Returns true if the string contains a valid E-Mail address, false otherwise.
2064
     *
2065
     * EXAMPLE: <code>
2066
     * s('[email protected]')->isEmail(); // true
2067
     * </code>
2068
     *
2069
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
2070
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
2071
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
2072
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
2073
     *
2074
     * @psalm-mutation-free
2075
     *
2076
     * @return bool
2077
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
2078
     */
2079 2
    public function isEmail(
2080
        bool $useExampleDomainCheck = false,
2081
        bool $useTypoInDomainCheck = false,
2082
        bool $useTemporaryDomainCheck = false,
2083
        bool $useDnsCheck = false
2084
    ): bool {
2085
        /**
2086
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
2087
         */
2088 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
2089
    }
2090
2091
    /**
2092
     * Determine whether the string is considered to be empty.
2093
     *
2094
     * A variable is considered empty if it does not exist or if its value equals FALSE.
2095
     *
2096
     * EXAMPLE: <code>
2097
     * s('')->isEmpty(); // true
2098
     * </code>
2099
     *
2100
     * @psalm-mutation-free
2101
     *
2102
     * @return bool
2103
     *              <p>Whether or not $str is empty().</p>
2104
     */
2105 10
    public function isEmpty(): bool
2106
    {
2107 10
        return $this->utf8::is_empty($this->str);
2108
    }
2109
2110
    /**
2111
     * Determine whether the string is equals to $str.
2112
     * Alias for isEqualsCaseSensitive()
2113
     *
2114
     * EXAMPLE: <code>
2115
     * s('foo')->isEquals('foo'); // true
2116
     * </code>
2117
     *
2118
     * @param string|Stringy ...$str
2119
     *
2120
     * @psalm-mutation-free
2121
     *
2122
     * @return bool
2123
     */
2124 13
    public function isEquals(...$str): bool
2125
    {
2126 13
        return $this->isEqualsCaseSensitive(...$str);
2127
    }
2128
2129
    /**
2130
     * Determine whether the string is equals to $str.
2131
     *
2132
     * EXAMPLE: <code>
2133
     * </code>
2134
     *
2135
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
2136
     *
2137
     * @psalm-mutation-free
2138
     *
2139
     * @return bool
2140
     *              <p>Whether or not $str is equals.</p>
2141
     */
2142 3
    public function isEqualsCaseInsensitive(...$str): bool
2143
    {
2144 3
        $strUpper = $this->toUpperCase()->str;
2145
2146 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...
2147
            /**
2148
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
2149
             */
2150 3
            if ($strTmp instanceof self) {
2151
                if ($strUpper !== $strTmp->toUpperCase()->str) {
2152
                    return false;
2153
                }
2154 3
            } elseif (\is_scalar($strTmp)) {
2155 3
                if ($strUpper !== $this->utf8::strtoupper((string) $strTmp, $this->encoding)) {
2156 3
                    return false;
2157
                }
2158
            } else {
2159
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
2160
            }
2161
        }
2162
2163 3
        return true;
2164
    }
2165
2166
    /**
2167
     * Determine whether the string is equals to $str.
2168
     *
2169
     * EXAMPLE: <code>
2170
     * </code>
2171
     *
2172
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
2173
     *
2174
     * @psalm-mutation-free
2175
     *
2176
     * @return bool
2177
     *              <p>Whether or not $str is equals.</p>
2178
     */
2179 14
    public function isEqualsCaseSensitive(...$str): bool
2180
    {
2181 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...
2182
            /**
2183
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
2184
             */
2185 14
            if ($strTmp instanceof self) {
2186 2
                if ($this->str !== $strTmp->str) {
2187 2
                    return false;
2188
                }
2189 12
            } elseif (\is_scalar($strTmp)) {
2190 12
                if ($this->str !== (string) $strTmp) {
2191 12
                    return false;
2192
                }
2193
            } else {
2194
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
2195
            }
2196
        }
2197
2198 3
        return true;
2199
    }
2200
2201
    /**
2202
     * Returns true if the string contains only hexadecimal chars, false otherwise.
2203
     *
2204
     * EXAMPLE: <code>
2205
     * s('A102F')->isHexadecimal(); // true
2206
     * </code>
2207
     *
2208
     * @psalm-mutation-free
2209
     *
2210
     * @return bool
2211
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
2212
     */
2213 39
    public function isHexadecimal(): bool
2214
    {
2215 39
        return $this->utf8::is_hexadecimal($this->str);
2216
    }
2217
2218
    /**
2219
     * Returns true if the string contains HTML-Tags, false otherwise.
2220
     *
2221
     * EXAMPLE: <code>
2222
     * s('<h1>foo</h1>')->isHtml(); // true
2223
     * </code>
2224
     *
2225
     * @psalm-mutation-free
2226
     *
2227
     * @return bool
2228
     *              <p>Whether or not $str contains HTML-Tags.</p>
2229
     */
2230 2
    public function isHtml(): bool
2231
    {
2232 2
        return $this->utf8::is_html($this->str);
2233
    }
2234
2235
    /**
2236
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
2237
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
2238
     * in that an empty string is not considered valid JSON.
2239
     *
2240
     * EXAMPLE: <code>
2241
     * s('{"foo":"bar"}')->isJson(); // true
2242
     * </code>
2243
     *
2244
     * @param bool $onlyArrayOrObjectResultsAreValid
2245
     *
2246
     * @psalm-mutation-free
2247
     *
2248
     * @return bool
2249
     *              <p>Whether or not $str is JSON.</p>
2250
     */
2251 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
2252
    {
2253
        /**
2254
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff?
2255
         */
2256 60
        return $this->utf8::is_json(
2257 60
            $this->str,
2258
            $onlyArrayOrObjectResultsAreValid
2259
        );
2260
    }
2261
2262
    /**
2263
     * Returns true if the string contains only lower case chars, false otherwise.
2264
     *
2265
     * EXAMPLE: <code>
2266
     * s('fòôbàř')->isLowerCase(); // true
2267
     * </code>
2268
     *
2269
     * @psalm-mutation-free
2270
     *
2271
     * @return bool
2272
     *              <p>Whether or not $str contains only lower case characters.</p>
2273
     */
2274 24
    public function isLowerCase(): bool
2275
    {
2276 24
        return $this->utf8::is_lowercase($this->str);
2277
    }
2278
2279
    /**
2280
     * Determine whether the string is considered to be NOT empty.
2281
     *
2282
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
2283
     *
2284
     * EXAMPLE: <code>
2285
     * s('')->isNotEmpty(); // false
2286
     * </code>
2287
     *
2288
     * @psalm-mutation-free
2289
     *
2290
     * @return bool
2291
     *              <p>Whether or not $str is empty().</p>
2292
     */
2293 10
    public function isNotEmpty(): bool
2294
    {
2295 10
        return !$this->utf8::is_empty($this->str);
2296
    }
2297
2298
    /**
2299
     * Determine if the string is composed of numeric characters.
2300
     *
2301
     * EXAMPLE: <code>
2302
     * </code>
2303
     *
2304
     * @psalm-mutation-free
2305
     *
2306
     * @return bool
2307
     */
2308 4
    public function isNumeric(): bool
2309
    {
2310 4
        return \is_numeric($this->str);
2311
    }
2312
2313
    /**
2314
     * Determine if the string is composed of printable (non-invisible) characters.
2315
     *
2316
     * EXAMPLE: <code>
2317
     * </code>
2318
     *
2319
     * @psalm-mutation-free
2320
     *
2321
     * @return bool
2322
     */
2323 3
    public function isPrintable(): bool
2324
    {
2325 3
        return $this->utf8::is_printable($this->str);
2326
    }
2327
2328
    /**
2329
     * Determine if the string is composed of punctuation characters.
2330
     *
2331
     * EXAMPLE: <code>
2332
     * </code>
2333
     *
2334
     * @psalm-mutation-free
2335
     *
2336
     * @return bool
2337
     */
2338 3
    public function isPunctuation(): bool
2339
    {
2340 3
        return $this->utf8::is_punctuation($this->str);
2341
    }
2342
2343
    /**
2344
     * Returns true if the string is serialized, false otherwise.
2345
     *
2346
     * EXAMPLE: <code>
2347
     * s('a:1:{s:3:"foo";s:3:"bar";}')->isSerialized(); // true
2348
     * </code>
2349
     *
2350
     * @psalm-mutation-free
2351
     *
2352
     * @return bool
2353
     *              <p>Whether or not $str is serialized.</p>
2354
     */
2355 21
    public function isSerialized(): bool
2356
    {
2357 21
        return $this->utf8::is_serialized($this->str);
2358
    }
2359
2360
    /**
2361
     * Check if two strings are similar.
2362
     *
2363
     * EXAMPLE: <code>
2364
     * </code>
2365
     *
2366
     * @param string $str                     <p>The string to compare against.</p>
2367
     * @param float  $minPercentForSimilarity [optional] <p>The percentage of needed similarity. | Default: 80%</p>
2368
     *
2369
     * @psalm-mutation-free
2370
     *
2371
     * @return bool
2372
     */
2373 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
2374
    {
2375 2
        return $this->similarity($str) >= $minPercentForSimilarity;
2376
    }
2377
2378
    /**
2379
     * Returns true if the string contains only lower case chars, false
2380
     * otherwise.
2381
     *
2382
     * EXAMPLE: <code>
2383
     * s('FÒÔBÀŘ')->isUpperCase(); // true
2384
     * </code>
2385
     *
2386
     * @psalm-mutation-free
2387
     *
2388
     * @return bool
2389
     *              <p>Whether or not $str contains only lower case characters.</p>
2390
     */
2391 24
    public function isUpperCase(): bool
2392
    {
2393 24
        return $this->utf8::is_uppercase($this->str);
2394
    }
2395
2396
    /**
2397
     * /**
2398
     * Check if $url is an correct url.
2399
     *
2400
     * @param bool $disallow_localhost
2401
     *
2402
     * @psalm-mutation-free
2403
     *
2404
     * @return bool
2405
     */
2406
    public function isUrl(bool $disallow_localhost = false): bool
2407
    {
2408
        return $this->utf8::is_url($this->str, $disallow_localhost);
2409
    }
2410
2411
    /**
2412
     * Check if the string is UTF-16.
2413
     *
2414
     * @psalm-mutation-free
2415
     *
2416
     * @return false|int
2417
     *                   <strong>false</strong> if is't not UTF-16,<br>
2418
     *                   <strong>1</strong> for UTF-16LE,<br>
2419
     *                   <strong>2</strong> for UTF-16BE
2420
     */
2421
    public function isUtf16()
2422
    {
2423
        return $this->utf8::is_utf16($this->str);
2424
    }
2425
2426
    /**
2427
     * Check if the string is UTF-32.
2428
     *
2429
     * @psalm-mutation-free
2430
     *
2431
     * @return false|int
2432
     *                   <strong>false</strong> if is't not UTF-32,<br>
2433
     *                   <strong>1</strong> for UTF-32LE,<br>
2434
     *                   <strong>2</strong> for UTF-32BE
2435
     */
2436
    public function isUtf32()
2437
    {
2438
        return $this->utf8::is_utf32($this->str);
2439
    }
2440
2441
    /**
2442
     * Checks whether the passed input contains only byte sequences that appear valid UTF-8.
2443
     *
2444
     * EXAMPLE: <code>
2445
     * s('Iñtërnâtiônàlizætiøn')->isUtf8(); // true
2446
     * //
2447
     * s("Iñtërnâtiônàlizætiøn\xA0\xA1")->isUtf8(); // false
2448
     * </code>
2449
     *
2450
     * @param bool $strict <p>Check also if the string is not UTF-16 or UTF-32.</p>
2451
     *
2452
     * @psalm-mutation-free
2453
     *
2454
     * @return bool
2455
     */
2456
    public function isUtf8(bool $strict = false): bool
2457
    {
2458
        return $this->utf8::is_utf8($this->str, $strict);
2459
    }
2460
2461
    /**
2462
     * Returns true if the string contains only whitespace chars, false otherwise.
2463
     *
2464
     * EXAMPLE: <code>
2465
     * </code>
2466
     *
2467
     * @psalm-mutation-free
2468
     *
2469
     * @return bool
2470
     *              <p>Whether or not $str contains only whitespace characters.</p>
2471
     */
2472 30
    public function isWhitespace(): bool
2473
    {
2474 30
        return $this->isBlank();
2475
    }
2476
2477
    /**
2478
     * Returns value which can be serialized by json_encode().
2479
     *
2480
     * EXAMPLE: <code>
2481
     * </code>
2482
     *
2483
     * @noinspection ReturnTypeCanBeDeclaredInspection
2484
     *
2485
     * @psalm-mutation-free
2486
     *
2487
     * @return string The current value of the $str property
2488
     */
2489 2
    public function jsonSerialize()
2490
    {
2491 2
        return (string) $this;
2492
    }
2493
2494
    /**
2495
     * Convert the string to kebab-case.
2496
     *
2497
     * EXAMPLE: <code>
2498
     * </code>
2499
     *
2500
     * @psalm-mutation-free
2501
     *
2502
     * @return static
2503
     */
2504 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...
2505
    {
2506 3
        $words = \array_map(
2507 3
            static function (self $word) {
2508 3
                return $word->toLowerCase();
2509
            },
2510 3
            $this->words('', true)
2511
        );
2512
2513 3
        return new static(\implode('-', $words), $this->encoding);
2514
    }
2515
2516
    /**
2517
     * Returns the last $n characters of the string.
2518
     *
2519
     * EXAMPLE: <code>
2520
     * s('fòôbàř')->last(3); // 'bàř'
2521
     * </code>
2522
     *
2523
     * @param int $n <p>Number of characters to retrieve from the end.</p>
2524
     *
2525
     * @psalm-mutation-free
2526
     *
2527
     * @return static
2528
     *                <p>Object with its $str being the last $n chars.</p>
2529
     */
2530 36
    public function last(int $n): self
2531
    {
2532 36
        return static::create(
2533 36
            $this->utf8::str_last_char(
2534 36
                $this->str,
2535
                $n,
2536 36
                $this->encoding
2537
            ),
2538 36
            $this->encoding
2539
        );
2540
    }
2541
2542
    /**
2543
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2544
     * If no match is found returns new empty Stringy object.
2545
     *
2546
     * EXAMPLE: <code>
2547
     * </code>
2548
     *
2549
     * @param string $needle       <p>The string to look for.</p>
2550
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2551
     *
2552
     * @psalm-mutation-free
2553
     *
2554
     * @return static
2555
     */
2556 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...
2557
    {
2558 4
        return static::create(
2559 4
            $this->utf8::str_substr_last(
2560 4
                $this->str,
2561
                $needle,
2562
                $beforeNeedle,
2563 4
                $this->encoding
2564
            ),
2565 4
            $this->encoding
2566
        );
2567
    }
2568
2569
    /**
2570
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2571
     * If no match is found returns new empty Stringy object.
2572
     *
2573
     * EXAMPLE: <code>
2574
     * </code>
2575
     *
2576
     * @param string $needle       <p>The string to look for.</p>
2577
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2578
     *
2579
     * @psalm-mutation-free
2580
     *
2581
     * @return static
2582
     */
2583 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...
2584
    {
2585 2
        return static::create(
2586 2
            $this->utf8::str_isubstr_last(
2587 2
                $this->str,
2588
                $needle,
2589
                $beforeNeedle,
2590 2
                $this->encoding
2591
            ),
2592 2
            $this->encoding
2593
        );
2594
    }
2595
2596
    /**
2597
     * Returns the length of the string.
2598
     *
2599
     * EXAMPLE: <code>
2600
     * s('fòôbàř')->length(); // 6
2601
     * </code>
2602
     *
2603
     * @psalm-mutation-free
2604
     *
2605
     * @return int
2606
     *             <p>The number of characters in $str given the encoding.</p>
2607
     */
2608 17
    public function length(): int
2609
    {
2610 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
2611
    }
2612
2613
    /**
2614
     * Line-Wrap the string after $limit, but also after the next word.
2615
     *
2616
     * EXAMPLE: <code>
2617
     * </code>
2618
     *
2619
     * @param int         $limit           [optional] <p>The column width.</p>
2620
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2621
     * @param bool        $add_final_break [optional] <p>
2622
     *                                     If this flag is true, then the method will add a $break at the end
2623
     *                                     of the result string.
2624
     *                                     </p>
2625
     * @param string|null $delimiter       [optional] <p>
2626
     *                                     You can change the default behavior, where we split the string by newline.
2627
     *                                     </p>
2628
     *
2629
     * @psalm-mutation-free
2630
     *
2631
     * @return static
2632
     */
2633 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...
2634
        int $limit,
2635
        string $break = "\n",
2636
        bool $add_final_break = true,
2637
        string $delimiter = null
2638
    ): self {
2639 3
        return static::create(
2640 3
            $this->utf8::wordwrap_per_line(
2641 3
                $this->str,
2642
                $limit,
2643
                $break,
2644 3
                true,
2645
                $add_final_break,
2646
                $delimiter
2647
            ),
2648 3
            $this->encoding
2649
        );
2650
    }
2651
2652
    /**
2653
     * Line-Wrap the string after $limit, but also after the next word.
2654
     *
2655
     * EXAMPLE: <code>
2656
     * </code>
2657
     *
2658
     * @param int         $limit           [optional] <p>The column width.</p>
2659
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2660
     * @param bool        $add_final_break [optional] <p>
2661
     *                                     If this flag is true, then the method will add a $break at the end
2662
     *                                     of the result string.
2663
     *                                     </p>
2664
     * @param string|null $delimiter       [optional] <p>
2665
     *                                     You can change the default behavior, where we split the string by newline.
2666
     *                                     </p>
2667
     *
2668
     * @psalm-mutation-free
2669
     *
2670
     * @return static
2671
     */
2672 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...
2673
        int $limit,
2674
        string $break = "\n",
2675
        bool $add_final_break = true,
2676
        string $delimiter = null
2677
    ): self {
2678 4
        return static::create(
2679 4
            $this->utf8::wordwrap_per_line(
2680 4
                $this->str,
2681
                $limit,
2682
                $break,
2683 4
                false,
2684
                $add_final_break,
2685
                $delimiter
2686
            ),
2687 4
            $this->encoding
2688
        );
2689
    }
2690
2691
    /**
2692
     * Splits on newlines and carriage returns, returning an array of Stringy
2693
     * objects corresponding to the lines in the string.
2694
     *
2695
     * EXAMPLE: <code>
2696
     * s("fòô\r\nbàř\n")->lines(); // ['fòô', 'bàř', '']
2697
     * </code>
2698
     *
2699
     * @psalm-mutation-free
2700
     *
2701
     * @return static[]
2702
     *                  <p>An array of Stringy objects.</p>
2703
     *
2704
     * @phpstan-return array<int,static>
2705
     */
2706 51
    public function lines(): array
2707
    {
2708 51
        if ($this->str === '') {
2709 3
            return [static::create('')];
2710
        }
2711
2712 48
        $strings = $this->utf8::str_to_lines($this->str);
2713
        /** @noinspection AlterInForeachInspection */
2714 48
        foreach ($strings as &$str) {
2715 48
            $str = static::create($str, $this->encoding);
2716
        }
2717
2718
        /** @noinspection PhpSillyAssignmentInspection */
2719
        /** @var static[] $strings */
2720 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...
2721
2722 48
        return $strings;
2723
    }
2724
2725
    /**
2726
     * Splits on newlines and carriage returns, returning an array of Stringy
2727
     * objects corresponding to the lines in the string.
2728
     *
2729
     * EXAMPLE: <code>
2730
     * </code>
2731
     *
2732
     * @psalm-mutation-free
2733
     *
2734
     * @return CollectionStringy|static[]
2735
     *                                    <p>An collection of Stringy objects.</p>
2736
     *
2737
     * @phpstan-return CollectionStringy<int,static>
2738
     */
2739 34
    public function linesCollection(): CollectionStringy
2740
    {
2741
        /**
2742
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2743
         */
2744 34
        return CollectionStringy::create(
2745 34
            $this->lines()
2746
        );
2747
    }
2748
2749
    /**
2750
     * Returns the longest common prefix between the string and $otherStr.
2751
     *
2752
     * EXAMPLE: <code>
2753
     * s('foobar')->longestCommonPrefix('foobaz'); // 'fooba'
2754
     * </code>
2755
     *
2756
     * @param string $otherStr <p>Second string for comparison.</p>
2757
     *
2758
     * @psalm-mutation-free
2759
     *
2760
     * @return static
2761
     *                <p>Object with its $str being the longest common prefix.</p>
2762
     */
2763 30
    public function longestCommonPrefix(string $otherStr): self
2764
    {
2765 30
        return static::create(
2766 30
            $this->utf8::str_longest_common_prefix(
2767 30
                $this->str,
2768
                $otherStr,
2769 30
                $this->encoding
2770
            ),
2771 30
            $this->encoding
2772
        );
2773
    }
2774
2775
    /**
2776
     * Returns the longest common substring between the string and $otherStr.
2777
     * In the case of ties, it returns that which occurs first.
2778
     *
2779
     * EXAMPLE: <code>
2780
     * s('foobar')->longestCommonSubstring('boofar'); // 'oo'
2781
     * </code>
2782
     *
2783
     * @param string $otherStr <p>Second string for comparison.</p>
2784
     *
2785
     * @psalm-mutation-free
2786
     *
2787
     * @return static
2788
     *                <p>Object with its $str being the longest common substring.</p>
2789
     */
2790 30
    public function longestCommonSubstring(string $otherStr): self
2791
    {
2792 30
        return static::create(
2793 30
            $this->utf8::str_longest_common_substring(
2794 30
                $this->str,
2795
                $otherStr,
2796 30
                $this->encoding
2797
            ),
2798 30
            $this->encoding
2799
        );
2800
    }
2801
2802
    /**
2803
     * Returns the longest common suffix between the string and $otherStr.
2804
     *
2805
     * EXAMPLE: <code>
2806
     * s('fòôbàř')->longestCommonSuffix('fòrbàř'); // 'bàř'
2807
     * </code>
2808
     *
2809
     * @param string $otherStr <p>Second string for comparison.</p>
2810
     *
2811
     * @psalm-mutation-free
2812
     *
2813
     * @return static
2814
     *                <p>Object with its $str being the longest common suffix.</p>
2815
     */
2816 30
    public function longestCommonSuffix(string $otherStr): self
2817
    {
2818 30
        return static::create(
2819 30
            $this->utf8::str_longest_common_suffix(
2820 30
                $this->str,
2821
                $otherStr,
2822 30
                $this->encoding
2823
            ),
2824 30
            $this->encoding
2825
        );
2826
    }
2827
2828
    /**
2829
     * Converts the first character of the string to lower case.
2830
     *
2831
     * EXAMPLE: <code>
2832
     * s('Σ Foo')->lowerCaseFirst(); // 'σ Foo'
2833
     * </code>
2834
     *
2835
     * @psalm-mutation-free
2836
     *
2837
     * @return static
2838
     *                <p>Object with the first character of $str being lower case.</p>
2839
     */
2840 16
    public function lowerCaseFirst(): self
2841
    {
2842 16
        return static::create(
2843 16
            $this->utf8::lcfirst($this->str, $this->encoding),
2844 16
            $this->encoding
2845
        );
2846
    }
2847
2848
    /**
2849
     * Determine if the string matches another string regardless of case.
2850
     * Alias for isEqualsCaseInsensitive()
2851
     *
2852
     * EXAMPLE: <code>
2853
     * </code>
2854
     *
2855
     * @psalm-mutation-free
2856
     *
2857
     * @param string|Stringy ...$str
2858
     *                               <p>The string to compare against.</p>
2859
     *
2860
     * @psalm-mutation-free
2861
     *
2862
     * @return bool
2863
     */
2864 3
    public function matchCaseInsensitive(...$str): bool
2865
    {
2866 3
        return $this->isEqualsCaseInsensitive(...$str);
2867
    }
2868
2869
    /**
2870
     * Determine if the string matches another string.
2871
     * Alias for isEqualsCaseSensitive()
2872
     *
2873
     * EXAMPLE: <code>
2874
     * </code>
2875
     *
2876
     * @psalm-mutation-free
2877
     *
2878
     * @param string|Stringy ...$str
2879
     *                               <p>The string to compare against.</p>
2880
     *
2881
     * @psalm-mutation-free
2882
     *
2883
     * @return bool
2884
     */
2885 7
    public function matchCaseSensitive(...$str): bool
2886
    {
2887 7
        return $this->isEqualsCaseSensitive(...$str);
2888
    }
2889
2890
    /**
2891
     * Create a md5 hash from the current string.
2892
     *
2893
     * @psalm-mutation-free
2894
     *
2895
     * @return static
2896
     */
2897 2
    public function md5(): self
2898
    {
2899 2
        return static::create($this->hash('md5'), $this->encoding);
2900
    }
2901
2902
    /**
2903
     * Replace all breaks [<br> | \r\n | \r | \n | ...] into "<br>".
2904
     *
2905
     * EXAMPLE: <code>
2906
     * </code>
2907
     *
2908
     * @return static
2909
     */
2910 1
    public function newLineToHtmlBreak(): self
2911
    {
2912 1
        return $this->removeHtmlBreak('<br>');
2913
    }
2914
2915
    /**
2916
     * Get every nth character of the string.
2917
     *
2918
     * EXAMPLE: <code>
2919
     * </code>
2920
     *
2921
     * @param int $step   <p>The number of characters to step.</p>
2922
     * @param int $offset [optional] <p>The string offset to start at.</p>
2923
     *
2924
     * @psalm-mutation-free
2925
     *
2926
     * @return static
2927
     */
2928 4
    public function nth(int $step, int $offset = 0): self
2929
    {
2930 4
        $length = $step - 1;
2931 4
        $substring = $this->substr($offset)->toString();
2932
2933 4
        if ($substring === '') {
2934
            return new static('', $this->encoding);
2935
        }
2936
2937 4
        \preg_match_all(
2938 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2939 4
            $substring,
2940 4
            $matches
2941
        );
2942
2943 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2944
    }
2945
2946
    /**
2947
     * Returns whether or not a character exists at an index. Offsets may be
2948
     * negative to count from the last character in the string. Implements
2949
     * part of the ArrayAccess interface.
2950
     *
2951
     * EXAMPLE: <code>
2952
     * </code>
2953
     *
2954
     * @param int $offset <p>The index to check.</p>
2955
     *
2956
     * @psalm-mutation-free
2957
     *
2958
     * @return bool
2959
     *              <p>Whether or not the index exists.</p>
2960
     */
2961 18
    public function offsetExists($offset): bool
2962
    {
2963 18
        return $this->utf8::str_offset_exists(
2964 18
            $this->str,
2965
            $offset,
2966 18
            $this->encoding
2967
        );
2968
    }
2969
2970
    /**
2971
     * Returns the character at the given index. Offsets may be negative to
2972
     * count from the last character in the string. Implements part of the
2973
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2974
     * does not exist.
2975
     *
2976
     * EXAMPLE: <code>
2977
     * </code>
2978
     *
2979
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2980
     *
2981
     * @throws \OutOfBoundsException
2982
     *                               <p>If the positive or negative offset does not exist.</p>
2983
     *
2984
     * @return string
2985
     *                <p>The character at the specified index.</p>
2986
     *
2987
     * @psalm-mutation-free
2988
     */
2989 6
    public function offsetGet($offset): string
2990
    {
2991 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2992
    }
2993
2994
    /**
2995
     * Implements part of the ArrayAccess interface, but throws an exception
2996
     * when called. This maintains the immutability of Stringy objects.
2997
     *
2998
     * EXAMPLE: <code>
2999
     * </code>
3000
     *
3001
     * @param int   $offset <p>The index of the character.</p>
3002
     * @param mixed $value  <p>Value to set.</p>
3003
     *
3004
     * @throws \Exception
3005
     *                    <p>When called.</p>
3006
     *
3007
     * @return void
3008
     */
3009 3
    public function offsetSet($offset, $value)
3010
    {
3011
        // Stringy is immutable, cannot directly set char
3012 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
3013
    }
3014
3015
    /**
3016
     * Implements part of the ArrayAccess interface, but throws an exception
3017
     * when called. This maintains the immutability of Stringy objects.
3018
     *
3019
     * EXAMPLE: <code>
3020
     * </code>
3021
     *
3022
     * @param int $offset <p>The index of the character.</p>
3023
     *
3024
     * @throws \Exception
3025
     *                    <p>When called.</p>
3026
     *
3027
     * @return void
3028
     */
3029 3
    public function offsetUnset($offset)
3030
    {
3031
        // Don't allow directly modifying the string
3032 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
3033
    }
3034
3035
    /**
3036
     * Pads the string to a given length with $padStr. If length is less than
3037
     * or equal to the length of the string, no padding takes places. The
3038
     * default string used for padding is a space, and the default type (one of
3039
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
3040
     * if $padType isn't one of those 3 values.
3041
     *
3042
     * EXAMPLE: <code>
3043
     * s('fòôbàř')->pad(9, '-/', 'left'); // '-/-fòôbàř'
3044
     * </code>
3045
     *
3046
     * @param int    $length  <p>Desired string length after padding.</p>
3047
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3048
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
3049
     *
3050
     * @throws \InvalidArgumentException
3051
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
3052
     *
3053
     * @return static
3054
     *                <p>Object with a padded $str.</p>
3055
     *
3056
     * @psalm-mutation-free
3057
     */
3058 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
3059
    {
3060 39
        return static::create(
3061 39
            $this->utf8::str_pad(
3062 39
                $this->str,
3063
                $length,
3064
                $padStr,
3065
                $padType,
3066 39
                $this->encoding
3067
            )
3068
        );
3069
    }
3070
3071
    /**
3072
     * Returns a new string of a given length such that both sides of the
3073
     * string are padded. Alias for pad() with a $padType of 'both'.
3074
     *
3075
     * EXAMPLE: <code>
3076
     * s('foo bar')->padBoth(9, ' '); // ' foo bar '
3077
     * </code>
3078
     *
3079
     * @param int    $length <p>Desired string length after padding.</p>
3080
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3081
     *
3082
     * @psalm-mutation-free
3083
     *
3084
     * @return static
3085
     *                <p>String with padding applied.</p>
3086
     */
3087 33
    public function padBoth(int $length, string $padStr = ' '): self
3088
    {
3089 33
        return static::create(
3090 33
            $this->utf8::str_pad_both(
3091 33
                $this->str,
3092
                $length,
3093
                $padStr,
3094 33
                $this->encoding
3095
            )
3096
        );
3097
    }
3098
3099
    /**
3100
     * Returns a new string of a given length such that the beginning of the
3101
     * string is padded. Alias for pad() with a $padType of 'left'.
3102
     *
3103
     * EXAMPLE: <code>
3104
     * s('foo bar')->padLeft(9, ' '); // '  foo bar'
3105
     * </code>
3106
     *
3107
     * @param int    $length <p>Desired string length after padding.</p>
3108
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3109
     *
3110
     * @psalm-mutation-free
3111
     *
3112
     * @return static
3113
     *                <p>String with left padding.</p>
3114
     */
3115 21
    public function padLeft(int $length, string $padStr = ' '): self
3116
    {
3117 21
        return static::create(
3118 21
            $this->utf8::str_pad_left(
3119 21
                $this->str,
3120
                $length,
3121
                $padStr,
3122 21
                $this->encoding
3123
            )
3124
        );
3125
    }
3126
3127
    /**
3128
     * Returns a new string of a given length such that the end of the string
3129
     * is padded. Alias for pad() with a $padType of 'right'.
3130
     *
3131
     * EXAMPLE: <code>
3132
     * s('foo bar')->padRight(10, '_*'); // 'foo bar_*_'
3133
     * </code>
3134
     *
3135
     * @param int    $length <p>Desired string length after padding.</p>
3136
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
3137
     *
3138
     * @psalm-mutation-free
3139
     *
3140
     * @return static
3141
     *                <p>String with right padding.</p>
3142
     */
3143 21
    public function padRight(int $length, string $padStr = ' '): self
3144
    {
3145 21
        return static::create(
3146 21
            $this->utf8::str_pad_right(
3147 21
                $this->str,
3148
                $length,
3149
                $padStr,
3150 21
                $this->encoding
3151
            )
3152
        );
3153
    }
3154
3155
    /**
3156
     * Convert the string to PascalCase.
3157
     * Alias for studlyCase()
3158
     *
3159
     * EXAMPLE: <code>
3160
     * </code>
3161
     *
3162
     * @psalm-mutation-free
3163
     *
3164
     * @return static
3165
     */
3166 3
    public function pascalCase(): self
3167
    {
3168 3
        return $this->studlyCase();
3169
    }
3170
3171
    /**
3172
     * Returns a new string starting with $prefix.
3173
     *
3174
     * EXAMPLE: <code>
3175
     * s('bàř')->prepend('fòô'); // 'fòôbàř'
3176
     * </code>
3177
     *
3178
     * @param string ...$prefix <p>The string to append.</p>
3179
     *
3180
     * @psalm-mutation-free
3181
     *
3182
     * @return static
3183
     *                <p>Object with appended $prefix.</p>
3184
     */
3185 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...
3186
    {
3187 8
        if (\count($prefix) <= 1) {
3188 6
            $prefix = $prefix[0];
3189
        } else {
3190 2
            $prefix = \implode('', $prefix);
3191
        }
3192
3193 8
        return static::create($prefix . $this->str, $this->encoding);
3194
    }
3195
3196
    /**
3197
     * Returns a new string starting with $prefix.
3198
     *
3199
     * EXAMPLE: <code>
3200
     * </code>
3201
     *
3202
     * @param CollectionStringy|static ...$prefix <p>The Stringy objects to append.</p>
3203
     *
3204
     * @phpstan-param CollectionStringy<int,static>|static ...$prefix
3205
     *
3206
     * @psalm-mutation-free
3207
     *
3208
     * @return static
3209
     *                <p>Object with appended $prefix.</p>
3210
     */
3211 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...
3212
    {
3213 1
        $prefixStr = '';
3214 1
        foreach ($prefix as $prefixTmp) {
3215 1
            if ($prefixTmp instanceof CollectionStringy) {
3216 1
                $prefixStr .= $prefixTmp->implode('');
3217
            } else {
3218 1
                $prefixStr .= $prefixTmp->toString();
3219
            }
3220
        }
3221
3222 1
        return static::create($prefixStr . $this->str, $this->encoding);
3223
    }
3224
3225
    /**
3226
     * Replaces all occurrences of $pattern in $str by $replacement.
3227
     *
3228
     * EXAMPLE: <code>
3229
     * s('fòô ')->regexReplace('f[òô]+\s', 'bàř'); // 'bàř'
3230
     * s('fò')->regexReplace('(ò)', '\\1ô'); // 'fòô'
3231
     * </code>
3232
     *
3233
     * @param string $pattern     <p>The regular expression pattern.</p>
3234
     * @param string $replacement <p>The string to replace with.</p>
3235
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
3236
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
3237
     *
3238
     * @psalm-mutation-free
3239
     *
3240
     * @return static
3241
     *                <p>Object with the result2ing $str after the replacements.</p>
3242
     */
3243 29
    public function regexReplace(
3244
        string $pattern,
3245
        string $replacement,
3246
        string $options = '',
3247
        string $delimiter = '/'
3248
    ): self {
3249 29
        return static::create(
3250 29
            $this->utf8::regex_replace(
3251 29
                $this->str,
3252
                $pattern,
3253
                $replacement,
3254
                $options,
3255
                $delimiter
3256
            ),
3257 29
            $this->encoding
3258
        );
3259
    }
3260
3261
    /**
3262
     * Remove html via "strip_tags()" from the string.
3263
     *
3264
     * EXAMPLE: <code>
3265
     * s('řàb <ô>òf\', ô<br/>foo <a href="#">lall</a>')->removeHtml('<br><br/>'); // 'řàb òf\', ô<br/>foo lall'
3266
     * </code>
3267
     *
3268
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
3269
     *                              not be stripped. Default: null
3270
     *                              </p>
3271
     *
3272
     * @psalm-mutation-free
3273
     *
3274
     * @return static
3275
     */
3276 12
    public function removeHtml(string $allowableTags = ''): self
3277
    {
3278 12
        return static::create(
3279 12
            $this->utf8::remove_html($this->str, $allowableTags),
3280 12
            $this->encoding
3281
        );
3282
    }
3283
3284
    /**
3285
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
3286
     *
3287
     * EXAMPLE: <code>
3288
     * s('řàb <ô>òf\', ô<br/>foo <a href="#">lall</a>')->removeHtmlBreak(''); // 'řàb <ô>òf\', ô< foo <a href="#">lall</a>'
3289
     * </code>
3290
     *
3291
     * @param string $replacement [optional] <p>Default is a empty string.</p>
3292
     *
3293
     * @psalm-mutation-free
3294
     *
3295
     * @return static
3296
     */
3297 13
    public function removeHtmlBreak(string $replacement = ''): self
3298
    {
3299 13
        return static::create(
3300 13
            $this->utf8::remove_html_breaks($this->str, $replacement),
3301 13
            $this->encoding
3302
        );
3303
    }
3304
3305
    /**
3306
     * Returns a new string with the prefix $substring removed, if present.
3307
     *
3308
     * EXAMPLE: <code>
3309
     * s('fòôbàř')->removeLeft('fòô'); // 'bàř'
3310
     * </code>
3311
     *
3312
     * @param string $substring <p>The prefix to remove.</p>
3313
     *
3314
     * @psalm-mutation-free
3315
     *
3316
     * @return static
3317
     *                <p>Object having a $str without the prefix $substring.</p>
3318
     */
3319 36
    public function removeLeft(string $substring): self
3320
    {
3321 36
        return static::create(
3322 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
3323 36
            $this->encoding
3324
        );
3325
    }
3326
3327
    /**
3328
     * Returns a new string with the suffix $substring removed, if present.
3329
     *
3330
     * EXAMPLE: <code>
3331
     * s('fòôbàř')->removeRight('bàř'); // 'fòô'
3332
     * </code>
3333
     *
3334
     * @param string $substring <p>The suffix to remove.</p>
3335
     *
3336
     * @psalm-mutation-free
3337
     *
3338
     * @return static
3339
     *                <p>Object having a $str without the suffix $substring.</p>
3340
     */
3341 36
    public function removeRight(string $substring): self
3342
    {
3343 36
        return static::create(
3344 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
3345 36
            $this->encoding
3346
        );
3347
    }
3348
3349
    /**
3350
     * Try to remove all XSS-attacks from the string.
3351
     *
3352
     * EXAMPLE: <code>
3353
     * 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 >'
3354
     * </code>
3355
     *
3356
     * @psalm-mutation-free
3357
     *
3358
     * @return static
3359
     */
3360 12
    public function removeXss(): self
3361
    {
3362
        /**
3363
         * @var AntiXSS|null
3364
         *
3365
         * @psalm-suppress ImpureStaticVariable
3366
         */
3367 12
        static $antiXss = null;
3368
3369 12
        if ($antiXss === null) {
3370 1
            $antiXss = new AntiXSS();
3371
        }
3372
3373
        /**
3374
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
3375
         */
3376 12
        $str = $antiXss->xss_clean($this->str);
3377
3378 12
        return static::create($str, $this->encoding);
3379
    }
3380
3381
    /**
3382
     * Returns a repeated string given a multiplier.
3383
     *
3384
     * EXAMPLE: <code>
3385
     * s('α')->repeat(3); // 'ααα'
3386
     * </code>
3387
     *
3388
     * @param int $multiplier <p>The number of times to repeat the string.</p>
3389
     *
3390
     * @psalm-mutation-free
3391
     *
3392
     * @return static
3393
     *                <p>Object with a repeated str.</p>
3394
     */
3395 21
    public function repeat(int $multiplier): self
3396
    {
3397 21
        return static::create(
3398 21
            \str_repeat($this->str, $multiplier),
3399 21
            $this->encoding
3400
        );
3401
    }
3402
3403
    /**
3404
     * Replaces all occurrences of $search in $str by $replacement.
3405
     *
3406
     * EXAMPLE: <code>
3407
     * s('fòô bàř fòô bàř')->replace('fòô ', ''); // 'bàř bàř'
3408
     * </code>
3409
     *
3410
     * @param string $search        <p>The needle to search for.</p>
3411
     * @param string $replacement   <p>The string to replace with.</p>
3412
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3413
     *
3414
     * @psalm-mutation-free
3415
     *
3416
     * @return static
3417
     *                <p>Object with the resulting $str after the replacements.</p>
3418
     */
3419 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
3420
    {
3421 76
        if ($search === '' && $replacement === '') {
3422 16
            return static::create($this->str, $this->encoding);
3423
        }
3424
3425 60
        if ($this->str === '' && $search === '') {
3426 2
            return static::create($replacement, $this->encoding);
3427
        }
3428
3429 58
        if ($caseSensitive) {
3430 48
            return static::create(
3431 48
                \str_replace($search, $replacement, $this->str),
3432 48
                $this->encoding
3433
            );
3434
        }
3435
3436 10
        return static::create(
3437 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
3438 10
            $this->encoding
3439
        );
3440
    }
3441
3442
    /**
3443
     * Replaces all occurrences of $search in $str by $replacement.
3444
     *
3445
     * EXAMPLE: <code>
3446
     * s('fòô bàř lall bàř')->replaceAll(['fòÔ ', 'lall'], '', false); // 'bàř bàř'
3447
     * </code>
3448
     *
3449
     * @param string[]        $search        <p>The elements to search for.</p>
3450
     * @param string|string[] $replacement   <p>The string to replace with.</p>
3451
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3452
     *
3453
     * @psalm-mutation-free
3454
     *
3455
     * @return static
3456
     *                <p>Object with the resulting $str after the replacements.</p>
3457
     */
3458 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
3459
    {
3460 61
        if ($caseSensitive) {
3461 47
            return static::create(
3462 47
                \str_replace($search, $replacement, $this->str),
3463 47
                $this->encoding
3464
            );
3465
        }
3466
3467 14
        return static::create(
3468 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
3469 14
            $this->encoding
3470
        );
3471
    }
3472
3473
    /**
3474
     * Replaces all occurrences of $search from the beginning of string with $replacement.
3475
     *
3476
     * EXAMPLE: <code>
3477
     * s('fòô bàř fòô bàř')->replaceBeginning('fòô', ''); // ' bàř bàř'
3478
     * </code>
3479
     *
3480
     * @param string $search      <p>The string to search for.</p>
3481
     * @param string $replacement <p>The replacement.</p>
3482
     *
3483
     * @psalm-mutation-free
3484
     *
3485
     * @return static
3486
     *                <p>Object with the resulting $str after the replacements.</p>
3487
     */
3488 32
    public function replaceBeginning(string $search, string $replacement): self
3489
    {
3490 32
        return static::create(
3491 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
3492 32
            $this->encoding
3493
        );
3494
    }
3495
3496
    /**
3497
     * Replaces all occurrences of $search from the ending of string with $replacement.
3498
     *
3499
     * EXAMPLE: <code>
3500
     * s('fòô bàř fòô bàř')->replaceEnding('bàř', ''); // 'fòô bàř fòô '
3501
     * </code>
3502
     *
3503
     * @param string $search      <p>The string to search for.</p>
3504
     * @param string $replacement <p>The replacement.</p>
3505
     *
3506
     * @psalm-mutation-free
3507
     *
3508
     * @return static
3509
     *                <p>Object with the resulting $str after the replacements.</p>
3510
     */
3511 32
    public function replaceEnding(string $search, string $replacement): self
3512
    {
3513 32
        return static::create(
3514 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
3515 32
            $this->encoding
3516
        );
3517
    }
3518
3519
    /**
3520
     * Replaces first occurrences of $search from the beginning of string with $replacement.
3521
     *
3522
     * EXAMPLE: <code>
3523
     * </code>
3524
     *
3525
     * @param string $search      <p>The string to search for.</p>
3526
     * @param string $replacement <p>The replacement.</p>
3527
     *
3528
     * @psalm-mutation-free
3529
     *
3530
     * @return static
3531
     *                <p>Object with the resulting $str after the replacements.</p>
3532
     */
3533 32
    public function replaceFirst(string $search, string $replacement): self
3534
    {
3535 32
        return static::create(
3536 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
3537 32
            $this->encoding
3538
        );
3539
    }
3540
3541
    /**
3542
     * Replaces last occurrences of $search from the ending of string with $replacement.
3543
     *
3544
     * EXAMPLE: <code>
3545
     * </code>
3546
     *
3547
     * @param string $search      <p>The string to search for.</p>
3548
     * @param string $replacement <p>The replacement.</p>
3549
     *
3550
     * @psalm-mutation-free
3551
     *
3552
     * @return static
3553
     *                <p>Object with the resulting $str after the replacements.</p>
3554
     */
3555 30
    public function replaceLast(string $search, string $replacement): self
3556
    {
3557 30
        return static::create(
3558 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
3559 30
            $this->encoding
3560
        );
3561
    }
3562
3563
    /**
3564
     * Returns a reversed string. A multibyte version of strrev().
3565
     *
3566
     * EXAMPLE: <code>
3567
     * s('fòôbàř')->reverse(); // 'řàbôòf'
3568
     * </code>
3569
     *
3570
     * @psalm-mutation-free
3571
     *
3572
     * @return static
3573
     *                <p>Object with a reversed $str.</p>
3574
     */
3575 15
    public function reverse(): self
3576
    {
3577 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
3578
    }
3579
3580
    /**
3581
     * Truncates the string to a given length, while ensuring that it does not
3582
     * split words. If $substring is provided, and truncating occurs, the
3583
     * string is further truncated so that the substring may be appended without
3584
     * exceeding the desired length.
3585
     *
3586
     * EXAMPLE: <code>
3587
     * s('What are your plans today?')->safeTruncate(22, '...'); // 'What are your plans...'
3588
     * </code>
3589
     *
3590
     * @param int    $length                          <p>Desired length of the truncated string.</p>
3591
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
3592
     * @param bool   $ignoreDoNotSplitWordsForOneWord
3593
     *
3594
     * @psalm-mutation-free
3595
     *
3596
     * @return static
3597
     *                <p>Object with the resulting $str after truncating.</p>
3598
     */
3599 68
    public function safeTruncate(
3600
        int $length,
3601
        string $substring = '',
3602
        bool $ignoreDoNotSplitWordsForOneWord = true
3603
    ): self {
3604 68
        return static::create(
3605 68
            $this->utf8::str_truncate_safe(
3606 68
                $this->str,
3607
                $length,
3608
                $substring,
3609 68
                $this->encoding,
3610
                $ignoreDoNotSplitWordsForOneWord
3611
            ),
3612 68
            $this->encoding
3613
        );
3614
    }
3615
3616
    /**
3617
     * Set the internal character encoding.
3618
     *
3619
     * EXAMPLE: <code>
3620
     * </code>
3621
     *
3622
     * @param string $new_encoding <p>The desired character encoding.</p>
3623
     *
3624
     * @psalm-mutation-free
3625
     *
3626
     * @return static
3627
     */
3628 1
    public function setInternalEncoding(string $new_encoding): self
3629
    {
3630 1
        return new static($this->str, $new_encoding);
3631
    }
3632
3633
    /**
3634
     * Create a sha1 hash from the current string.
3635
     *
3636
     * EXAMPLE: <code>
3637
     * </code>
3638
     *
3639
     * @psalm-mutation-free
3640
     *
3641
     * @return static
3642
     */
3643 2
    public function sha1(): self
3644
    {
3645 2
        return static::create($this->hash('sha1'), $this->encoding);
3646
    }
3647
3648
    /**
3649
     * Create a sha256 hash from the current string.
3650
     *
3651
     * EXAMPLE: <code>
3652
     * </code>
3653
     *
3654
     * @psalm-mutation-free
3655
     *
3656
     * @return static
3657
     */
3658 2
    public function sha256(): self
3659
    {
3660 2
        return static::create($this->hash('sha256'), $this->encoding);
3661
    }
3662
3663
    /**
3664
     * Create a sha512 hash from the current string.
3665
     *
3666
     * EXAMPLE: <code>
3667
     * </code>
3668
     *
3669
     * @psalm-mutation-free
3670
     *
3671
     * @return static
3672
     */
3673 2
    public function sha512(): self
3674
    {
3675 2
        return static::create($this->hash('sha512'), $this->encoding);
3676
    }
3677
3678
    /**
3679
     * Shorten the string after $length, but also after the next word.
3680
     *
3681
     * EXAMPLE: <code>
3682
     * s('this is a test')->shortenAfterWord(2, '...'); // 'this...'
3683
     * </code>
3684
     *
3685
     * @param int    $length   <p>The given length.</p>
3686
     * @param string $strAddOn [optional] <p>Default: '…'</p>
3687
     *
3688
     * @psalm-mutation-free
3689
     *
3690
     * @return static
3691
     */
3692 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
3693
    {
3694 8
        return static::create(
3695 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
3696 8
            $this->encoding
3697
        );
3698
    }
3699
3700
    /**
3701
     * A multibyte string shuffle function. It returns a string with its
3702
     * characters in random order.
3703
     *
3704
     * EXAMPLE: <code>
3705
     * s('fòôbàř')->shuffle(); // 'àôřbòf'
3706
     * </code>
3707
     *
3708
     * @return static
3709
     *                <p>Object with a shuffled $str.</p>
3710
     */
3711 9
    public function shuffle(): self
3712
    {
3713 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
3714
    }
3715
3716
    /**
3717
     * Calculate the similarity between two strings.
3718
     *
3719
     * EXAMPLE: <code>
3720
     * </code>
3721
     *
3722
     * @param string $str <p>The delimiting string.</p>
3723
     *
3724
     * @psalm-mutation-free
3725
     *
3726
     * @return float
3727
     */
3728 2
    public function similarity(string $str): float
3729
    {
3730 2
        \similar_text($this->str, $str, $percent);
3731
3732 2
        return $percent;
3733
    }
3734
3735
    /**
3736
     * Returns the substring beginning at $start, and up to, but not including
3737
     * the index specified by $end. If $end is omitted, the function extracts
3738
     * the remaining string. If $end is negative, it is computed from the end
3739
     * of the string.
3740
     *
3741
     * EXAMPLE: <code>
3742
     * s('fòôbàř')->slice(3, -1); // 'bà'
3743
     * </code>
3744
     *
3745
     * @param int $start <p>Initial index from which to begin extraction.</p>
3746
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
3747
     *
3748
     * @psalm-mutation-free
3749
     *
3750
     * @return static
3751
     *                <p>Object with its $str being the extracted substring.</p>
3752
     */
3753 50
    public function slice(int $start, int $end = null): self
3754
    {
3755 50
        return static::create(
3756 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
3757 50
            $this->encoding
3758
        );
3759
    }
3760
3761
    /**
3762
     * Converts the string into an URL slug. This includes replacing non-ASCII
3763
     * characters with their closest ASCII equivalents, removing remaining
3764
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3765
     * $separator. The separator defaults to a single dash, and the string
3766
     * is also converted to lowercase. The language of the source string can
3767
     * also be supplied for language-specific transliteration.
3768
     *
3769
     * EXAMPLE: <code>
3770
     * s('Using strings like fòô bàř')->slugify(); // 'using-strings-like-foo-bar'
3771
     * </code>
3772
     *
3773
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
3774
     * @param string                $language              [optional] <p>Language of the source string.</p>
3775
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
3776
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
3777
     *                                                     pound ".</p>
3778
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
3779
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
3780
     *                                                     chars.</p>
3781
     *
3782
     * @psalm-mutation-free
3783
     *
3784
     * @return static
3785
     *                <p>Object whose $str has been converted to an URL slug.</p>
3786
     *
3787
     * @noinspection PhpTooManyParametersInspection
3788
     */
3789 17
    public function slugify(
3790
        string $separator = '-',
3791
        string $language = 'en',
3792
        array $replacements = [],
3793
        bool $replace_extra_symbols = true,
3794
        bool $use_str_to_lower = true,
3795
        bool $use_transliterate = false
3796
    ): self {
3797 17
        return static::create(
3798 17
            $this->ascii::to_slugify(
3799 17
                $this->str,
3800
                $separator,
3801
                $language,
3802
                $replacements,
3803
                $replace_extra_symbols,
3804
                $use_str_to_lower,
3805
                $use_transliterate
3806
            ),
3807 17
            $this->encoding
3808
        );
3809
    }
3810
3811
    /**
3812
     * Convert the string to snake_case.
3813
     *
3814
     * EXAMPLE: <code>
3815
     * </code>
3816
     *
3817
     * @psalm-mutation-free
3818
     *
3819
     * @return static
3820
     */
3821 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...
3822
    {
3823 3
        $words = \array_map(
3824 3
            static function (self $word) {
3825 3
                return $word->toLowerCase();
3826
            },
3827 3
            $this->words('', true)
3828
        );
3829
3830 3
        return new static(\implode('_', $words), $this->encoding);
3831
    }
3832
3833
    /**
3834
     * Convert a string to snake_case.
3835
     *
3836
     * EXAMPLE: <code>
3837
     * s('foo1 Bar')->snakeize(); // 'foo_1_bar'
3838
     * </code>
3839
     *
3840
     * @psalm-mutation-free
3841
     *
3842
     * @return static
3843
     *                <p>Object with $str in snake_case.</p>
3844
     */
3845 40
    public function snakeize(): self
3846
    {
3847 40
        return static::create(
3848 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
3849 40
            $this->encoding
3850
        );
3851
    }
3852
3853
    /**
3854
     * Wrap the string after the first whitespace character after a given number
3855
     * of characters.
3856
     *
3857
     * EXAMPLE: <code>
3858
     * </code>
3859
     *
3860
     * @param int    $width <p>Number of characters at which to wrap.</p>
3861
     * @param string $break [optional] <p>Character used to break the string. | Default "\n"</p>
3862
     *
3863
     * @psalm-mutation-free
3864
     *
3865
     * @return static
3866
     */
3867 2
    public function softWrap(int $width, string $break = "\n"): self
3868
    {
3869 2
        return $this->lineWrapAfterWord($width, $break, false);
3870
    }
3871
3872
    /**
3873
     * Splits the string with the provided regular expression, returning an
3874
     * array of Stringy objects. An optional integer $limit will truncate the
3875
     * results.
3876
     *
3877
     * EXAMPLE: <code>
3878
     * s('foo,bar,baz')->split(',', 2); // ['foo', 'bar']
3879
     * </code>
3880
     *
3881
     * @param string $pattern <p>The regex with which to split the string.</p>
3882
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3883
     *                        limit</p>
3884
     *
3885
     * @psalm-mutation-free
3886
     *
3887
     * @return static[]
3888
     *                  <p>An array of Stringy objects.</p>
3889
     *
3890
     * @phpstan-return array<int,static>
3891
     */
3892 51
    public function split(string $pattern, int $limit = null): array
3893
    {
3894 51
        if ($this->str === '') {
3895
            return [];
3896
        }
3897
3898 51
        if ($limit === null) {
3899 7
            $limit = -1;
3900
        }
3901
3902 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
3903 51
        foreach ($array as &$value) {
3904 45
            $value = static::create($value, $this->encoding);
3905
        }
3906
3907
        /** @noinspection PhpSillyAssignmentInspection */
3908
        /** @var static[] $array */
3909 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...
3910
3911 51
        return $array;
3912
    }
3913
3914
    /**
3915
     * Splits the string with the provided regular expression, returning an
3916
     * collection of Stringy objects. An optional integer $limit will truncate the
3917
     * results.
3918
     *
3919
     * EXAMPLE: <code>
3920
     * </code>
3921
     *
3922
     * @param string $pattern <p>The regex with which to split the string.</p>
3923
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3924
     *                        limit</p>
3925
     *
3926
     * @psalm-mutation-free
3927
     *
3928
     * @return CollectionStringy|static[]
3929
     *                                    <p>An collection of Stringy objects.</p>
3930
     *
3931
     * @phpstan-return CollectionStringy<int,static>
3932
     */
3933 35
    public function splitCollection(string $pattern, int $limit = null): CollectionStringy
3934
    {
3935
        /**
3936
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3937
         */
3938 35
        return CollectionStringy::create(
3939 35
            $this->split($pattern, $limit)
3940
        );
3941
    }
3942
3943
    /**
3944
     * Returns true if the string begins with $substring, false otherwise. By
3945
     * default, the comparison is case-sensitive, but can be made insensitive
3946
     * by setting $caseSensitive to false.
3947
     *
3948
     * EXAMPLE: <code>
3949
     * s('FÒÔbàřbaz')->startsWith('fòôbàř', false); // true
3950
     * </code>
3951
     *
3952
     * @param string $substring     <p>The substring to look for.</p>
3953
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3954
     *
3955
     * @psalm-mutation-free
3956
     *
3957
     * @return bool
3958
     *              <p>Whether or not $str starts with $substring.</p>
3959
     */
3960 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
3961
    {
3962 99
        if ($caseSensitive) {
3963 53
            return $this->utf8::str_starts_with($this->str, $substring);
3964
        }
3965
3966 46
        return $this->utf8::str_istarts_with($this->str, $substring);
3967
    }
3968
3969
    /**
3970
     * Returns true if the string begins with any of $substrings, false otherwise.
3971
     * By default the comparison is case-sensitive, but can be made insensitive by
3972
     * setting $caseSensitive to false.
3973
     *
3974
     * EXAMPLE: <code>
3975
     * s('FÒÔbàřbaz')->startsWithAny(['fòô', 'bàř'], false); // true
3976
     * </code>
3977
     *
3978
     * @param string[] $substrings    <p>Substrings to look for.</p>
3979
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3980
     *
3981
     * @psalm-mutation-free
3982
     *
3983
     * @return bool
3984
     *              <p>Whether or not $str starts with $substring.</p>
3985
     */
3986 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
3987
    {
3988 35
        if ($caseSensitive) {
3989 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
3990
        }
3991
3992 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
3993
    }
3994
3995
    /**
3996
     * Remove one or more strings from the string.
3997
     *
3998
     * EXAMPLE: <code>
3999
     * </code>
4000
     *
4001
     * @param string|string[] $search One or more strings to be removed
4002
     *
4003
     * @psalm-mutation-free
4004
     *
4005
     * @return static
4006
     */
4007 3
    public function strip($search): self
4008
    {
4009 3
        if (\is_array($search)) {
4010 1
            return $this->replaceAll($search, '');
4011
        }
4012
4013 2
        return $this->replace($search, '');
4014
    }
4015
4016
    /**
4017
     * Strip all whitespace characters. This includes tabs and newline characters,
4018
     * as well as multibyte whitespace such as the thin space and ideographic space.
4019
     *
4020
     * EXAMPLE: <code>
4021
     * s('   Ο     συγγραφέας  ')->stripWhitespace(); // 'Οσυγγραφέας'
4022
     * </code>
4023
     *
4024
     * @psalm-mutation-free
4025
     *
4026
     * @return static
4027
     */
4028 36
    public function stripWhitespace(): self
4029
    {
4030 36
        return static::create(
4031 36
            $this->utf8::strip_whitespace($this->str),
4032 36
            $this->encoding
4033
        );
4034
    }
4035
4036
    /**
4037
     * Remove css media-queries.
4038
     *
4039
     * EXAMPLE: <code>
4040
     * s('test @media (min-width:660px){ .des-cla #mv-tiles{width:480px} } test ')->stripeCssMediaQueries(); // 'test  test '
4041
     * </code>
4042
     *
4043
     * @psalm-mutation-free
4044
     *
4045
     * @return static
4046
     */
4047 2
    public function stripeCssMediaQueries(): self
4048
    {
4049 2
        return static::create(
4050 2
            $this->utf8::css_stripe_media_queries($this->str),
4051 2
            $this->encoding
4052
        );
4053
    }
4054
4055
    /**
4056
     * Remove empty html-tag.
4057
     *
4058
     * EXAMPLE: <code>
4059
     * s('foo<h1></h1>bar')->stripeEmptyHtmlTags(); // 'foobar'
4060
     * </code>
4061
     *
4062
     * @psalm-mutation-free
4063
     *
4064
     * @return static
4065
     */
4066 2
    public function stripeEmptyHtmlTags(): self
4067
    {
4068 2
        return static::create(
4069 2
            $this->utf8::html_stripe_empty_tags($this->str),
4070 2
            $this->encoding
4071
        );
4072
    }
4073
4074
    /**
4075
     * Convert the string to StudlyCase.
4076
     *
4077
     * EXAMPLE: <code>
4078
     * </code>
4079
     *
4080
     * @psalm-mutation-free
4081
     *
4082
     * @return static
4083
     */
4084 6
    public function studlyCase(): self
4085
    {
4086 6
        $words = \array_map(
4087 6
            static function (self $word) {
4088 6
                return $word->substr(0, 1)
4089 6
                    ->toUpperCase()
4090 6
                    ->appendStringy($word->substr(1));
4091
            },
4092 6
            $this->words('', true)
4093
        );
4094
4095 6
        return new static(\implode('', $words), $this->encoding);
4096
    }
4097
4098
    /**
4099
     * Returns the substring beginning at $start with the specified $length.
4100
     * It differs from the $this->utf8::substr() function in that providing a $length of
4101
     * null will return the rest of the string, rather than an empty string.
4102
     *
4103
     * EXAMPLE: <code>
4104
     * </code>
4105
     *
4106
     * @param int $start  <p>Position of the first character to use.</p>
4107
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
4108
     *
4109
     * @psalm-mutation-free
4110
     *
4111
     * @return static
4112
     *                <p>Object with its $str being the substring.</p>
4113
     */
4114 40
    public function substr(int $start, int $length = null): self
4115
    {
4116 40
        return static::create(
4117 40
            $this->utf8::substr(
4118 40
                $this->str,
4119
                $start,
4120
                $length,
4121 40
                $this->encoding
4122
            ),
4123 40
            $this->encoding
4124
        );
4125
    }
4126
4127
    /**
4128
     * Return part of the string.
4129
     * Alias for substr()
4130
     *
4131
     * EXAMPLE: <code>
4132
     * s('fòôbàř')->substring(2, 3); // 'ôbà'
4133
     * </code>
4134
     *
4135
     * @param int $start  <p>Starting position of the substring.</p>
4136
     * @param int $length [optional] <p>Length of substring.</p>
4137
     *
4138
     * @psalm-mutation-free
4139
     *
4140
     * @return static
4141
     */
4142 3
    public function substring(int $start, int $length = null): self
4143
    {
4144 3
        if ($length === null) {
4145 2
            return $this->substr($start);
4146
        }
4147
4148 3
        return $this->substr($start, $length);
4149
    }
4150
4151
    /**
4152
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
4153
     * If no match is found returns new empty Stringy object.
4154
     *
4155
     * EXAMPLE: <code>
4156
     * </code>
4157
     *
4158
     * @param string $needle       <p>The string to look for.</p>
4159
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
4160
     *
4161
     * @psalm-mutation-free
4162
     *
4163
     * @return static
4164
     */
4165 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...
4166
    {
4167 4
        return static::create(
4168 4
            $this->utf8::str_substr_first(
4169 4
                $this->str,
4170
                $needle,
4171
                $beforeNeedle,
4172 4
                $this->encoding
4173
            ),
4174 4
            $this->encoding
4175
        );
4176
    }
4177
4178
    /**
4179
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
4180
     * If no match is found returns new empty Stringy object.
4181
     *
4182
     * EXAMPLE: <code>
4183
     * </code>
4184
     *
4185
     * @param string $needle       <p>The string to look for.</p>
4186
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
4187
     *
4188
     * @psalm-mutation-free
4189
     *
4190
     * @return static
4191
     */
4192 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...
4193
    {
4194 4
        return static::create(
4195 4
            $this->utf8::str_isubstr_first(
4196 4
                $this->str,
4197
                $needle,
4198
                $beforeNeedle,
4199 4
                $this->encoding
4200
            ),
4201 4
            $this->encoding
4202
        );
4203
    }
4204
4205
    /**
4206
     * Surrounds $str with the given substring.
4207
     *
4208
     * EXAMPLE: <code>
4209
     * s(' ͜ ')->surround('ʘ'); // 'ʘ ͜ ʘ'
4210
     * </code>
4211
     *
4212
     * @param string $substring <p>The substring to add to both sides.</P>
4213
     *
4214
     * @psalm-mutation-free
4215
     *
4216
     * @return static
4217
     *                <p>Object whose $str had the substring both prepended and appended.</p>
4218
     */
4219 15
    public function surround(string $substring): self
4220
    {
4221 15
        return static::create(
4222 15
            $substring . $this->str . $substring,
4223 15
            $this->encoding
4224
        );
4225
    }
4226
4227
    /**
4228
     * Returns a case swapped version of the string.
4229
     *
4230
     * EXAMPLE: <code>
4231
     * s('Ντανιλ')->swapCase(); // 'νΤΑΝΙΛ'
4232
     * </code>
4233
     *
4234
     * @psalm-mutation-free
4235
     *
4236
     * @return static
4237
     *                <p>Object whose $str has each character's case swapped.</P>
4238
     */
4239 15
    public function swapCase(): self
4240
    {
4241 15
        return static::create(
4242 15
            $this->utf8::swapCase($this->str, $this->encoding),
4243 15
            $this->encoding
4244
        );
4245
    }
4246
4247
    /**
4248
     * Returns a string with smart quotes, ellipsis characters, and dashes from
4249
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
4250
     * equivalents.
4251
     *
4252
     * EXAMPLE: <code>
4253
     * s('“I see…”')->tidy(); // '"I see..."'
4254
     * </code>
4255
     *
4256
     * @psalm-mutation-free
4257
     *
4258
     * @return static
4259
     *                <p>Object whose $str has those characters removed.</p>
4260
     */
4261 12
    public function tidy(): self
4262
    {
4263 12
        return static::create(
4264 12
            $this->ascii::normalize_msword($this->str),
4265 12
            $this->encoding
4266
        );
4267
    }
4268
4269
    /**
4270
     * Returns a trimmed string with the first letter of each word capitalized.
4271
     * Also accepts an array, $ignore, allowing you to list words not to be
4272
     * capitalized.
4273
     *
4274
     * EXAMPLE: <code>
4275
     * $ignore = ['at', 'by', 'for', 'in', 'of', 'on', 'out', 'to', 'the'];
4276
     * s('i like to watch television')->titleize($ignore); // 'I Like to Watch Television'
4277
     * </code>
4278
     *
4279
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
4280
     *                                               Default: null</p>
4281
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
4282
     *                                               separator === words.</p>
4283
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
4284
     *
4285
     * @psalm-mutation-free
4286
     *
4287
     * @return static
4288
     *                <p>Object with a titleized $str.</p>
4289
     */
4290 23
    public function titleize(
4291
        array $ignore = null,
4292
        string $word_define_chars = null,
4293
        string $language = null
4294
    ): self {
4295 23
        return static::create(
4296 23
            $this->utf8::str_titleize(
4297 23
                $this->str,
4298
                $ignore,
4299 23
                $this->encoding,
4300 23
                false,
4301
                $language,
4302 23
                false,
4303 23
                true,
4304
                $word_define_chars
4305
            ),
4306 23
            $this->encoding
4307
        );
4308
    }
4309
4310
    /**
4311
     * Returns a trimmed string in proper title case: Also accepts an array, $ignore, allowing you to list words not to
4312
     * be capitalized.
4313
     *
4314
     * EXAMPLE: <code>
4315
     * </code>
4316
     *
4317
     * Adapted from John Gruber's script.
4318
     *
4319
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
4320
     *
4321
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
4322
     *
4323
     * @psalm-mutation-free
4324
     *
4325
     * @return static
4326
     *                <p>Object with a titleized $str</p>
4327
     */
4328 70
    public function titleizeForHumans(array $ignore = []): self
4329
    {
4330 70
        return static::create(
4331 70
            $this->utf8::str_titleize_for_humans(
4332 70
                $this->str,
4333
                $ignore,
4334 70
                $this->encoding
4335
            ),
4336 70
            $this->encoding
4337
        );
4338
    }
4339
4340
    /**
4341
     * Returns an ASCII version of the string. A set of non-ASCII characters are
4342
     * replaced with their closest ASCII counterparts, and the rest are removed
4343
     * by default. The language or locale of the source string can be supplied
4344
     * for language-specific transliteration in any of the following formats:
4345
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
4346
     * to "aeoeue" rather than "aou" as in other languages.
4347
     *
4348
     * EXAMPLE: <code>
4349
     * s('fòôbàř')->toAscii(); // 'foobar'
4350
     * </code>
4351
     *
4352
     * @param string $language          [optional] <p>Language of the source string.</p>
4353
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
4354
     *                                  unsupported characters.</p>
4355
     *
4356
     * @psalm-mutation-free
4357
     *
4358
     * @return static
4359
     *                <p>Object whose $str contains only ASCII characters.</p>
4360
     */
4361 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
4362
    {
4363 23
        return static::create(
4364 23
            $this->ascii::to_ascii(
4365 23
                $this->str,
4366
                $language,
4367
                $removeUnsupported
4368
            ),
4369 23
            $this->encoding
4370
        );
4371
    }
4372
4373
    /**
4374
     * Returns a boolean representation of the given logical string value.
4375
     * For example, <strong>'true', '1', 'on' and 'yes'</strong> will return true. <strong>'false', '0',
4376
     * 'off', and 'no'</strong> will return false. In all instances, case is ignored.
4377
     * For other numeric strings, their sign will determine the return value.
4378
     * In addition, blank strings consisting of only whitespace will return
4379
     * false. For all other strings, the return value is a result of a
4380
     * boolean cast.
4381
     *
4382
     * EXAMPLE: <code>
4383
     * s('OFF')->toBoolean(); // false
4384
     * </code>
4385
     *
4386
     * @psalm-mutation-free
4387
     *
4388
     * @return bool
4389
     *              <p>A boolean value for the string.</p>
4390
     */
4391 45
    public function toBoolean(): bool
4392
    {
4393
        /**
4394
         * @psalm-suppress ArgumentTypeCoercion -> maybe the string looks like an int ;)
4395
         * @phpstan-ignore-next-line
4396
         */
4397 45
        return $this->utf8::to_boolean($this->str);
4398
    }
4399
4400
    /**
4401
     * Converts all characters in the string to lowercase.
4402
     *
4403
     * EXAMPLE: <code>
4404
     * s('FÒÔBÀŘ')->toLowerCase(); // 'fòôbàř'
4405
     * </code>
4406
     *
4407
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
4408
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
4409
     *
4410
     * @psalm-mutation-free
4411
     *
4412
     * @return static
4413
     *                <p>Object with all characters of $str being lowercase.</p>
4414
     */
4415 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...
4416
    {
4417 23
        return static::create(
4418 23
            $this->utf8::strtolower(
4419 23
                $this->str,
4420 23
                $this->encoding,
4421 23
                false,
4422
                $lang,
4423
                $tryToKeepStringLength
4424
            ),
4425 23
            $this->encoding
4426
        );
4427
    }
4428
4429
    /**
4430
     * Converts each tab in the string to some number of spaces, as defined by
4431
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
4432
     *
4433
     * EXAMPLE: <code>
4434
     * s(' String speech = "Hi"')->toSpaces(); // '    String speech = "Hi"'
4435
     * </code>
4436
     *
4437
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
4438
     *
4439
     * @psalm-mutation-free
4440
     *
4441
     * @return static
4442
     *                <p>Object whose $str has had tabs switched to spaces.</p>
4443
     */
4444 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...
4445
    {
4446 18
        if ($tabLength === 4) {
4447 9
            $tab = '    ';
4448 9
        } elseif ($tabLength === 2) {
4449 3
            $tab = '  ';
4450
        } else {
4451 6
            $tab = \str_repeat(' ', $tabLength);
4452
        }
4453
4454 18
        return static::create(
4455 18
            \str_replace("\t", $tab, $this->str),
4456 18
            $this->encoding
4457
        );
4458
    }
4459
4460
    /**
4461
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
4462
     * string.
4463
     *
4464
     * EXAMPLE: <code>
4465
     * s('fòôbàř')->toString(); // 'fòôbàř'
4466
     * </code>
4467
     *
4468
     * @psalm-mutation-free
4469
     *
4470
     * @return string
4471
     */
4472 2200
    public function toString(): string
4473
    {
4474 2200
        return (string) $this->str;
4475
    }
4476
4477
    /**
4478
     * Converts each occurrence of some consecutive number of spaces, as
4479
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
4480
     * are converted to a tab.
4481
     *
4482
     * EXAMPLE: <code>
4483
     * s('    fòô    bàř')->toTabs(); // '   fòô bàř'
4484
     * </code>
4485
     *
4486
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
4487
     *
4488
     * @psalm-mutation-free
4489
     *
4490
     * @return static
4491
     *                <p>Object whose $str has had spaces switched to tabs.</p>
4492
     */
4493 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...
4494
    {
4495 15
        if ($tabLength === 4) {
4496 9
            $tab = '    ';
4497 6
        } elseif ($tabLength === 2) {
4498 3
            $tab = '  ';
4499
        } else {
4500 3
            $tab = \str_repeat(' ', $tabLength);
4501
        }
4502
4503 15
        return static::create(
4504 15
            \str_replace($tab, "\t", $this->str),
4505 15
            $this->encoding
4506
        );
4507
    }
4508
4509
    /**
4510
     * Converts the first character of each word in the string to uppercase
4511
     * and all other chars to lowercase.
4512
     *
4513
     * EXAMPLE: <code>
4514
     * s('fòô bàř')->toTitleCase(); // 'Fòô Bàř'
4515
     * </code>
4516
     *
4517
     * @psalm-mutation-free
4518
     *
4519
     * @return static
4520
     *                <p>Object with all characters of $str being title-cased.</p>
4521
     */
4522 15
    public function toTitleCase(): self
4523
    {
4524 15
        return static::create(
4525 15
            $this->utf8::titlecase($this->str, $this->encoding),
4526 15
            $this->encoding
4527
        );
4528
    }
4529
4530
    /**
4531
     * Returns an ASCII version of the string. A set of non-ASCII characters are
4532
     * replaced with their closest ASCII counterparts, and the rest are removed
4533
     * unless instructed otherwise.
4534
     *
4535
     * EXAMPLE: <code>
4536
     * </code>
4537
     *
4538
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
4539
     *                        performance | Default: false</p>
4540
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
4541
     *
4542
     * @psalm-mutation-free
4543
     *
4544
     * @return static
4545
     *                <p>Object whose $str contains only ASCII characters.</p>
4546
     */
4547 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
4548
    {
4549 34
        return static::create(
4550 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
4551 34
            $this->encoding
4552
        );
4553
    }
4554
4555
    /**
4556
     * Converts all characters in the string to uppercase.
4557
     *
4558
     * EXAMPLE: <code>
4559
     * s('fòôbàř')->toUpperCase(); // 'FÒÔBÀŘ'
4560
     * </code>
4561
     *
4562
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
4563
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
4564
     *
4565
     * @psalm-mutation-free
4566
     *
4567
     * @return static
4568
     *                <p>Object with all characters of $str being uppercase.</p>
4569
     */
4570 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...
4571
    {
4572 26
        return static::create(
4573 26
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
4574 26
            $this->encoding
4575
        );
4576
    }
4577
4578
    /**
4579
     * Returns a string with whitespace removed from the start and end of the
4580
     * string. Supports the removal of unicode whitespace. Accepts an optional
4581
     * string of characters to strip instead of the defaults.
4582
     *
4583
     * EXAMPLE: <code>
4584
     * s('  fòôbàř  ')->trim(); // 'fòôbàř'
4585
     * </code>
4586
     *
4587
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
4588
     *
4589
     * @psalm-mutation-free
4590
     *
4591
     * @return static
4592
     *                <p>Object with a trimmed $str.</p>
4593
     */
4594 36
    public function trim(string $chars = null): self
4595
    {
4596 36
        return static::create(
4597 36
            $this->utf8::trim($this->str, $chars),
4598 36
            $this->encoding
4599
        );
4600
    }
4601
4602
    /**
4603
     * Returns a string with whitespace removed from the start of the string.
4604
     * Supports the removal of unicode whitespace. Accepts an optional
4605
     * string of characters to strip instead of the defaults.
4606
     *
4607
     * EXAMPLE: <code>
4608
     * s('  fòôbàř  ')->trimLeft(); // 'fòôbàř  '
4609
     * </code>
4610
     *
4611
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
4612
     *
4613
     * @psalm-mutation-free
4614
     *
4615
     * @return static
4616
     *                <p>Object with a trimmed $str.</p>
4617
     */
4618 39
    public function trimLeft(string $chars = null): self
4619
    {
4620 39
        return static::create(
4621 39
            $this->utf8::ltrim($this->str, $chars),
4622 39
            $this->encoding
4623
        );
4624
    }
4625
4626
    /**
4627
     * Returns a string with whitespace removed from the end of the string.
4628
     * Supports the removal of unicode whitespace. Accepts an optional
4629
     * string of characters to strip instead of the defaults.
4630
     *
4631
     * EXAMPLE: <code>
4632
     * s('  fòôbàř  ')->trimRight(); // '  fòôbàř'
4633
     * </code>
4634
     *
4635
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
4636
     *
4637
     * @psalm-mutation-free
4638
     *
4639
     * @return static
4640
     *                <p>Object with a trimmed $str.</p>
4641
     */
4642 39
    public function trimRight(string $chars = null): self
4643
    {
4644 39
        return static::create(
4645 39
            $this->utf8::rtrim($this->str, $chars),
4646 39
            $this->encoding
4647
        );
4648
    }
4649
4650
    /**
4651
     * Truncates the string to a given length. If $substring is provided, and
4652
     * truncating occurs, the string is further truncated so that the substring
4653
     * may be appended without exceeding the desired length.
4654
     *
4655
     * EXAMPLE: <code>
4656
     * s('What are your plans today?')->truncate(19, '...'); // 'What are your pl...'
4657
     * </code>
4658
     *
4659
     * @param int    $length    <p>Desired length of the truncated string.</p>
4660
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
4661
     *
4662
     * @psalm-mutation-free
4663
     *
4664
     * @return static
4665
     *                <p>Object with the resulting $str after truncating.</p>
4666
     */
4667 66
    public function truncate(int $length, string $substring = ''): self
4668
    {
4669 66
        return static::create(
4670 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
4671 66
            $this->encoding
4672
        );
4673
    }
4674
4675
    /**
4676
     * Returns a lowercase and trimmed string separated by underscores.
4677
     * Underscores are inserted before uppercase characters (with the exception
4678
     * of the first character of the string), and in place of spaces as well as
4679
     * dashes.
4680
     *
4681
     * EXAMPLE: <code>
4682
     * s('TestUCase')->underscored(); // 'test_u_case'
4683
     * </code>
4684
     *
4685
     * @psalm-mutation-free
4686
     *
4687
     * @return static
4688
     *                <p>Object with an underscored $str.</p>
4689
     */
4690 48
    public function underscored(): self
4691
    {
4692 48
        return $this->delimit('_');
4693
    }
4694
4695
    /**
4696
     * Returns an UpperCamelCase version of the supplied string. It trims
4697
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
4698
     * and underscores, and removes spaces, dashes, underscores.
4699
     *
4700
     * EXAMPLE: <code>
4701
     * s('Upper Camel-Case')->upperCamelize(); // 'UpperCamelCase'
4702
     * </code>
4703
     *
4704
     * @psalm-mutation-free
4705
     *
4706
     * @return static
4707
     *                <p>Object with $str in UpperCamelCase.</p>
4708
     */
4709 39
    public function upperCamelize(): self
4710
    {
4711 39
        return static::create(
4712 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
4713 39
            $this->encoding
4714
        );
4715
    }
4716
4717
    /**
4718
     * Converts the first character of the supplied string to upper case.
4719
     *
4720
     * EXAMPLE: <code>
4721
     * s('σ foo')->upperCaseFirst(); // 'Σ foo'
4722
     * </code>
4723
     *
4724
     * @psalm-mutation-free
4725
     *
4726
     * @return static
4727
     *                <p>Object with the first character of $str being upper case.</p>
4728
     */
4729 18
    public function upperCaseFirst(): self
4730
    {
4731 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
4732
    }
4733
4734
    /**
4735
     * Simple url-decoding.
4736
     *
4737
     * e.g:
4738
     * 'test+test' => 'test test'
4739
     *
4740
     * EXAMPLE: <code>
4741
     * </code>
4742
     *
4743
     * @psalm-mutation-free
4744
     *
4745
     * @return static
4746
     */
4747 1
    public function urlDecode(): self
4748
    {
4749 1
        return static::create(\urldecode($this->str));
4750
    }
4751
4752
    /**
4753
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
4754
     *
4755
     * e.g:
4756
     * 'test+test'                     => 'test test'
4757
     * 'D&#252;sseldorf'               => 'Düsseldorf'
4758
     * 'D%FCsseldorf'                  => 'Düsseldorf'
4759
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
4760
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
4761
     * 'Düsseldorf'                   => 'Düsseldorf'
4762
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
4763
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
4764
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
4765
     *
4766
     * EXAMPLE: <code>
4767
     * </code>
4768
     *
4769
     * @psalm-mutation-free
4770
     *
4771
     * @return static
4772
     */
4773 1
    public function urlDecodeMulti(): self
4774
    {
4775 1
        return static::create($this->utf8::urldecode($this->str));
4776
    }
4777
4778
    /**
4779
     * Simple url-decoding.
4780
     *
4781
     * e.g:
4782
     * 'test+test' => 'test+test
4783
     *
4784
     * EXAMPLE: <code>
4785
     * </code>
4786
     *
4787
     * @psalm-mutation-free
4788
     *
4789
     * @return static
4790
     */
4791 1
    public function urlDecodeRaw(): self
4792
    {
4793 1
        return static::create(\rawurldecode($this->str));
4794
    }
4795
4796
    /**
4797
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
4798
     *
4799
     * e.g:
4800
     * 'test+test'                     => 'test+test'
4801
     * 'D&#252;sseldorf'               => 'Düsseldorf'
4802
     * 'D%FCsseldorf'                  => 'Düsseldorf'
4803
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
4804
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
4805
     * 'Düsseldorf'                   => 'Düsseldorf'
4806
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
4807
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
4808
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
4809
     *
4810
     * EXAMPLE: <code>
4811
     * </code>
4812
     *
4813
     * @psalm-mutation-free
4814
     *
4815
     * @return static
4816
     */
4817 1
    public function urlDecodeRawMulti(): self
4818
    {
4819 1
        return static::create($this->utf8::rawurldecode($this->str));
4820
    }
4821
4822
    /**
4823
     * Simple url-encoding.
4824
     *
4825
     * e.g:
4826
     * 'test test' => 'test+test'
4827
     *
4828
     * EXAMPLE: <code>
4829
     * </code>
4830
     *
4831
     * @psalm-mutation-free
4832
     *
4833
     * @return static
4834
     */
4835 1
    public function urlEncode(): self
4836
    {
4837 1
        return static::create(\urlencode($this->str));
4838
    }
4839
4840
    /**
4841
     * Simple url-encoding.
4842
     *
4843
     * e.g:
4844
     * 'test test' => 'test%20test'
4845
     *
4846
     * EXAMPLE: <code>
4847
     * </code>
4848
     *
4849
     * @psalm-mutation-free
4850
     *
4851
     * @return static
4852
     */
4853 1
    public function urlEncodeRaw(): self
4854
    {
4855 1
        return static::create(\rawurlencode($this->str));
4856
    }
4857
4858
    /**
4859
     * Converts the string into an URL slug. This includes replacing non-ASCII
4860
     * characters with their closest ASCII equivalents, removing remaining
4861
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
4862
     * $separator. The separator defaults to a single dash, and the string
4863
     * is also converted to lowercase.
4864
     *
4865
     * EXAMPLE: <code>
4866
     * s('Using strings like fòô bàř - 1$')->urlify(); // 'using-strings-like-foo-bar-1-dollar'
4867
     * </code>
4868
     *
4869
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
4870
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
4871
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
4872
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
4873
     *
4874
     * @psalm-mutation-free
4875
     *
4876
     * @return static
4877
     *                <p>Object whose $str has been converted to an URL slug.</p>
4878
     *
4879
     * @psalm-suppress ImpureMethodCall :/
4880
     */
4881 32
    public function urlify(
4882
        string $separator = '-',
4883
        string $language = 'en',
4884
        array $replacements = [],
4885
        bool $strToLower = true
4886
    ): self {
4887
        // init
4888 32
        $str = $this->str;
4889
4890 32
        foreach ($replacements as $from => $to) {
4891 32
            $str = \str_replace($from, $to, $str);
4892
        }
4893
4894 32
        return static::create(
4895 32
            URLify::slug(
4896 32
                $str,
4897
                $language,
4898
                $separator,
4899
                $strToLower
4900
            ),
4901 32
            $this->encoding
4902
        );
4903
    }
4904
4905
    /**
4906
     * Converts the string into an valid UTF-8 string.
4907
     *
4908
     * EXAMPLE: <code>
4909
     * s('Düsseldorf')->utf8ify(); // 'Düsseldorf'
4910
     * </code>
4911
     *
4912
     * @psalm-mutation-free
4913
     *
4914
     * @return static
4915
     */
4916 2
    public function utf8ify(): self
4917
    {
4918 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
4919
    }
4920
4921
    /**
4922
     * Convert a string into an array of words.
4923
     *
4924
     * EXAMPLE: <code>
4925
     * </code>
4926
     *
4927
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4928
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4929
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4930
     *
4931
     * @psalm-mutation-free
4932
     *
4933
     * @return static[]
4934
     *
4935
     * @phpstan-return array<int,static>
4936
     */
4937 14
    public function words(
4938
        string $char_list = '',
4939
        bool $remove_empty_values = false,
4940
        int $remove_short_values = null
4941
    ): array {
4942 14
        if ($remove_short_values === null) {
4943 14
            $strings = $this->utf8::str_to_words(
4944 14
                $this->str,
4945
                $char_list,
4946
                $remove_empty_values
4947
            );
4948
        } else {
4949 2
            $strings = $this->utf8::str_to_words(
4950 2
                $this->str,
4951
                $char_list,
4952
                $remove_empty_values,
4953
                $remove_short_values
4954
            );
4955
        }
4956
4957
        /** @noinspection AlterInForeachInspection */
4958 14
        foreach ($strings as &$string) {
4959 14
            $string = static::create($string);
4960
        }
4961
4962
        /** @noinspection PhpSillyAssignmentInspection */
4963
        /** @var static[] $strings */
4964 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...
4965
4966 14
        return $strings;
4967
    }
4968
4969
    /**
4970
     * Convert a string into an collection of words.
4971
     *
4972
     * EXAMPLE: <code>
4973
     * S::create('中文空白 oöäü#s')->wordsCollection('#', true)->toStrings(); // ['中文空白', 'oöäü#s']
4974
     * </code>
4975
     *
4976
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4977
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4978
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4979
     *
4980
     * @psalm-mutation-free
4981
     *
4982
     * @return CollectionStringy|static[]
4983
     *                                    <p>An collection of Stringy objects.</p>
4984
     *
4985
     * @phpstan-return CollectionStringy<int,static>
4986
     */
4987 2
    public function wordsCollection(
4988
        string $char_list = '',
4989
        bool $remove_empty_values = false,
4990
        int $remove_short_values = null
4991
    ): CollectionStringy {
4992
        /**
4993
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
4994
         */
4995 2
        return CollectionStringy::create(
4996 2
            $this->words(
4997 2
                $char_list,
4998
                $remove_empty_values,
4999
                $remove_short_values
5000
            )
5001
        );
5002
    }
5003
5004
    /**
5005
     * Surrounds $str with the given substring.
5006
     *
5007
     * EXAMPLE: <code>
5008
     * </code>
5009
     *
5010
     * @param string $substring <p>The substring to add to both sides.</P>
5011
     *
5012
     * @psalm-mutation-free
5013
     *
5014
     * @return static
5015
     *                <p>Object whose $str had the substring both prepended and appended.</p>
5016
     */
5017 10
    public function wrap(string $substring): self
5018
    {
5019 10
        return $this->surround($substring);
5020
    }
5021
5022
    /**
5023
     * Returns the replacements for the toAscii() method.
5024
     *
5025
     * @psalm-mutation-free
5026
     *
5027
     * @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...
5028
     *                       <p>An array of replacements.</p>
5029
     *
5030
     * @deprecated   this is only here for backward-compatibly reasons
5031
     */
5032 1
    protected function charsArray(): array
5033
    {
5034 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
5035
    }
5036
5037
    /**
5038
     * Returns true if $str matches the supplied pattern, false otherwise.
5039
     *
5040
     * @param string $pattern <p>Regex pattern to match against.</p>
5041
     *
5042
     * @psalm-mutation-free
5043
     *
5044
     * @return bool
5045
     *              <p>Whether or not $str matches the pattern.</p>
5046
     */
5047 24
    protected function matchesPattern(string $pattern): bool
5048
    {
5049 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
5050
    }
5051
}
5052