Completed
Push — master ( 700242...1710f2 )
by Lars
04:13
created

Stringy::isEqualsCaseInsensitive()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 23

Duplication

Lines 16
Ratio 69.57 %

Code Coverage

Tests 9
CRAP Score 6.2163

Importance

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