Completed
Push — master ( 3c9715...f60c04 )
by Lars
01:28
created

Stringy::lineWrapAfterWord()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 18
Ratio 100 %

Code Coverage

Tests 10
CRAP Score 1

Importance

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