Completed
Push — master ( dc809d...ea43b1 )
by Lars
03:20
created

Stringy::split()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4.016

Importance

Changes 0
Metric Value
cc 4
nc 5
nop 2
dl 0
loc 22
ccs 9
cts 10
cp 0.9
crap 4.016
rs 9.568
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stringy;
6
7
use Defuse\Crypto\Crypto;
8
use voku\helper\AntiXSS;
9
use voku\helper\ASCII;
10
use voku\helper\EmailCheck;
11
use voku\helper\URLify;
12
use voku\helper\UTF8;
13
14
/**
15
 * @template-implements \IteratorAggregate<string>
16
 * @template-implements \ArrayAccess<array-key,string>
17
 */
18
class Stringy implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
19
{
20
    /**
21
     * An instance's string.
22
     *
23
     * @var string
24
     */
25
    protected $str;
26
27
    /**
28
     * The string's encoding, which should be one of the mbstring module's
29
     * supported encodings.
30
     *
31
     * @var string
32
     */
33
    protected $encoding;
34
35
    /**
36
     * @var UTF8
37
     */
38
    private $utf8;
39
40
    /**
41
     * @var ASCII
42
     */
43
    private $ascii;
44
45
    /**
46
     * Initializes a Stringy object and assigns both str and encoding properties
47
     * the supplied values. $str is cast to a string prior to assignment, and if
48
     * $encoding is not specified, it defaults to mb_internal_encoding(). Throws
49
     * an InvalidArgumentException if the first argument is an array or object
50
     * without a __toString method.
51
     *
52
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
53
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
54
     *
55
     * @throws \InvalidArgumentException
56
     *                                   <p>if an array or object without a
57
     *                                   __toString method is passed as the first argument</p>
58
     *
59
     * @psalm-mutation-free
60
     */
61 3637
    public function __construct($str = '', string $encoding = null)
62
    {
63 3637
        if (\is_array($str)) {
64 3
            throw new \InvalidArgumentException(
65 3
                'Passed value cannot be an array'
66
            );
67
        }
68
69
        if (
70 3634
            \is_object($str)
71
            &&
72 3634
            !\method_exists($str, '__toString')
73
        ) {
74 3
            throw new \InvalidArgumentException(
75 3
                'Passed object must have a __toString method'
76
            );
77
        }
78
79 3631
        $this->str = (string) $str;
80
81 3631
        static $ASCII = null;
82 3631
        if ($ASCII === null) {
83
            $ASCII = new ASCII();
84
        }
85 3631
        $this->ascii = $ASCII;
86
87 3631
        static $UTF8 = null;
88 3631
        if ($UTF8 === null) {
89
            $UTF8 = new UTF8();
90
        }
91 3631
        $this->utf8 = $UTF8;
92
93 3631
        if ($encoding !== 'UTF-8') {
94 2461
            $this->encoding = $this->utf8::normalize_encoding($encoding, 'UTF-8');
95
        } else {
96 2701
            $this->encoding = $encoding;
97
        }
98 3631
    }
99
100
    /**
101
     * Returns the value in $str.
102
     *
103
     * @psalm-mutation-free
104
     *
105
     * @return string
106
     *                <p>The current value of the $str property.</p>
107
     */
108 1143
    public function __toString()
109
    {
110 1143
        return (string) $this->str;
111
    }
112
113
    /**
114
     * Return part of the string occurring after a specific string.
115
     *
116
     * @param string $string <p>The delimiting string.</p>
117
     *
118
     * @psalm-mutation-free
119
     *
120
     * @return static
121
     */
122 4
    public function after(string $string): self
123
    {
124 4
        $strArray = UTF8::str_split_pattern(
125 4
            $this->str,
126 4
            $string
127
        );
128
129 4
        unset($strArray[0]);
130
131 4
        return new static(
132 4
            \implode(' ', $strArray),
133 4
            $this->encoding
134
        );
135
    }
136
137
    /**
138
     * Gets the substring after the first occurrence of a separator.
139
     * If no match is found returns new empty Stringy object.
140
     *
141
     * @param string $separator
142
     *
143
     * @psalm-mutation-free
144
     *
145
     * @return static
146
     */
147 3
    public function afterFirst(string $separator): self
148
    {
149 3
        return static::create(
150 3
            $this->utf8::str_substr_after_first_separator(
151 3
                $this->str,
152 3
                $separator,
153 3
                $this->encoding
154
            )
155
        );
156
    }
157
158
    /**
159
     * Gets the substring after the first occurrence of a separator.
160
     * If no match is found returns new empty Stringy object.
161
     *
162
     * @param string $separator
163
     *
164
     * @psalm-mutation-free
165
     *
166
     * @return static
167
     */
168 2
    public function afterFirstIgnoreCase(string $separator): self
169
    {
170 2
        return static::create(
171 2
            $this->utf8::str_isubstr_after_first_separator(
172 2
                $this->str,
173 2
                $separator,
174 2
                $this->encoding
175
            )
176
        );
177
    }
178
179
    /**
180
     * Gets the substring after the last occurrence of a separator.
181
     * If no match is found returns new empty Stringy object.
182
     *
183
     * @param string $separator
184
     *
185
     * @psalm-mutation-free
186
     *
187
     * @return static
188
     */
189 2
    public function afterLast(string $separator): self
190
    {
191 2
        return static::create(
192 2
            $this->utf8::str_substr_after_last_separator(
193 2
                $this->str,
194 2
                $separator,
195 2
                $this->encoding
196
            )
197
        );
198
    }
199
200
    /**
201
     * Gets the substring after the last occurrence of a separator.
202
     * If no match is found returns new empty Stringy object.
203
     *
204
     * @param string $separator
205
     *
206
     * @psalm-mutation-free
207
     *
208
     * @return static
209
     */
210 2
    public function afterLastIgnoreCase(string $separator): self
211
    {
212 2
        return static::create(
213 2
            $this->utf8::str_isubstr_after_last_separator(
214 2
                $this->str,
215 2
                $separator,
216 2
                $this->encoding
217
            )
218
        );
219
    }
220
221
    /**
222
     * Returns a new string with $suffix appended.
223
     *
224
     * @param string ...$suffix <p>The string to append.</p>
225
     *
226
     * @psalm-mutation-free
227
     *
228
     * @return static
229
     *                <p>Object with appended $suffix.</p>
230
     *
231
     * @noinspection PhpDocSignatureInspection
232
     */
233 15 View Code Duplication
    public function append(string ...$suffix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
234
    {
235 15
        if (\count($suffix) <= 1) {
236
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
237 13
            $suffix = $suffix[0];
238
        } else {
239
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
240 2
            $suffix = \implode('', $suffix);
241
        }
242
243 15
        return static::create($this->str . $suffix, $this->encoding);
244
    }
245
246
    /**
247
     * Append an password (limited to chars that are good readable).
248
     *
249
     * @param int $length <p>Length of the random string.</p>
250
     *
251
     * @return static
252
     *                <p>Object with appended password.</p>
253
     */
254 2
    public function appendPassword(int $length): self
255
    {
256 2
        return $this->appendRandomString(
257 2
            $length,
258 2
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
259
        );
260
    }
261
262
    /**
263
     * Append an random string.
264
     *
265
     * @param int    $length        <p>Length of the random string.</p>
266
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
267
     *
268
     * @return static
269
     *                <p>Object with appended random string.</p>
270
     */
271 4
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
272
    {
273 4
        $str = $this->utf8::get_random_string($length, $possibleChars);
274
275 4
        return $this->append($str);
276
    }
277
278
    /**
279
     * Returns a new string with $suffix appended.
280
     *
281
     * @param CollectionStringy|static ...$suffix <p>The Stringy objects to append.</p>
282
     *
283
     * @psalm-param CollectionStringy<int,static>|static ...$suffix
284
     *
285
     * @psalm-mutation-free
286
     *
287
     * @return static
288
     *                <p>Object with appended $suffix.</p>
289
     */
290 7 View Code Duplication
    public function appendStringy(...$suffix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
291
    {
292 7
        $suffixStr = '';
293 7
        foreach ($suffix as $suffixTmp) {
294 7
            if ($suffixTmp instanceof CollectionStringy) {
295 1
                $suffixStr .= $suffixTmp->implode('');
296
            } else {
297 7
                $suffixStr .= $suffixTmp->toString();
298
            }
299
        }
300
301 7
        return static::create($this->str . $suffixStr, $this->encoding);
302
    }
303
304
    /**
305
     * Append an unique identifier.
306
     *
307
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
308
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
309
     *
310
     * @return static
311
     *                <p>Object with appended unique identifier as md5-hash.</p>
312
     */
313 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
314
    {
315 2
        return $this->append(
316 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
317
        );
318
    }
319
320
    /**
321
     * Returns the character at $index, with indexes starting at 0.
322
     *
323
     * @param int $index <p>Position of the character.</p>
324
     *
325
     * @psalm-mutation-free
326
     *
327
     * @return static
328
     *                <p>The character at $index.</p>
329
     */
330 24
    public function at(int $index): self
331
    {
332 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
333
    }
334
335
    /**
336
     * Decode the base64 encoded string.
337
     *
338
     * @psalm-mutation-free
339
     *
340
     * @return self
341
     */
342 2
    public function base64Decode(): self
343
    {
344 2
        return static::create(
345 2
            \base64_decode($this->str, true),
346 2
            $this->encoding
347
        );
348
    }
349
350
    /**
351
     * Encode the string to base64.
352
     *
353
     * @psalm-mutation-free
354
     *
355
     * @return self
356
     */
357 2
    public function base64Encode(): self
358
    {
359 2
        return static::create(
360 2
            \base64_encode($this->str),
361 2
            $this->encoding
362
        );
363
    }
364
365
    /**
366
     * Creates a hash from the string using the CRYPT_BLOWFISH algorithm.
367
     *
368
     * WARNING: Using this algorithm, will result in the ```$this->str```
369
     *          being truncated to a maximum length of 72 characters.
370
     *
371
     * @param array<array-key, int|string> $options [optional] <p>An array of bcrypt hasing options.</p>
372
     *
373
     * @psalm-mutation-free
374
     *
375
     * @return static
376
     */
377 3
    public function bcrypt(array $options = []): self
378
    {
379 3
        return new static(
380 3
            \password_hash(
381 3
                $this->str,
382 3
                \PASSWORD_BCRYPT,
383 3
                $options
384
            ),
385 3
            $this->encoding
386
        );
387
    }
388
389
    /**
390
     * Return part of the string occurring before a specific string.
391
     *
392
     * @param string $string <p>The delimiting string.</p>
393
     *
394
     * @psalm-mutation-free
395
     *
396
     * @return static
397
     */
398 4
    public function before(string $string): self
399
    {
400 4
        $strArray = UTF8::str_split_pattern(
401 4
            $this->str,
402 4
            $string,
403 4
            1
404
        );
405
406 4
        return new static(
407 4
            $strArray[0] ?? '',
408 4
            $this->encoding
409
        );
410
    }
411
412
    /**
413
     * Gets the substring before the first occurrence of a separator.
414
     * If no match is found returns new empty Stringy object.
415
     *
416
     * @param string $separator
417
     *
418
     * @psalm-mutation-free
419
     *
420
     * @return static
421
     */
422 2
    public function beforeFirst(string $separator): self
423
    {
424 2
        return static::create(
425 2
            $this->utf8::str_substr_before_first_separator(
426 2
                $this->str,
427 2
                $separator,
428 2
                $this->encoding
429
            )
430
        );
431
    }
432
433
    /**
434
     * Gets the substring before the first occurrence of a separator.
435
     * If no match is found returns new empty Stringy object.
436
     *
437
     * @param string $separator
438
     *
439
     * @psalm-mutation-free
440
     *
441
     * @return static
442
     */
443 2
    public function beforeFirstIgnoreCase(string $separator): self
444
    {
445 2
        return static::create(
446 2
            $this->utf8::str_isubstr_before_first_separator(
447 2
                $this->str,
448 2
                $separator,
449 2
                $this->encoding
450
            )
451
        );
452
    }
453
454
    /**
455
     * Gets the substring before the last occurrence of a separator.
456
     * If no match is found returns new empty Stringy object.
457
     *
458
     * @param string $separator
459
     *
460
     * @psalm-mutation-free
461
     *
462
     * @return static
463
     */
464 2
    public function beforeLast(string $separator): self
465
    {
466 2
        return static::create(
467 2
            $this->utf8::str_substr_before_last_separator(
468 2
                $this->str,
469 2
                $separator,
470 2
                $this->encoding
471
            )
472
        );
473
    }
474
475
    /**
476
     * Gets the substring before the last occurrence of a separator.
477
     * If no match is found returns new empty Stringy object.
478
     *
479
     * @param string $separator
480
     *
481
     * @psalm-mutation-free
482
     *
483
     * @return static
484
     */
485 2
    public function beforeLastIgnoreCase(string $separator): self
486
    {
487 2
        return static::create(
488 2
            $this->utf8::str_isubstr_before_last_separator(
489 2
                $this->str,
490 2
                $separator,
491 2
                $this->encoding
492
            )
493
        );
494
    }
495
496
    /**
497
     * Returns the substring between $start and $end, if found, or an empty
498
     * string. An optional offset may be supplied from which to begin the
499
     * search for the start string.
500
     *
501
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
502
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
503
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
504
     *
505
     * @psalm-mutation-free
506
     *
507
     * @return static
508
     *                <p>Object whose $str is a substring between $start and $end.</p>
509
     */
510 48
    public function between(string $start, string $end, int $offset = null): self
511
    {
512
        /** @noinspection UnnecessaryCastingInspection */
513 48
        $str = $this->utf8::between(
514 48
            $this->str,
515 48
            $start,
516 48
            $end,
517 48
            (int) $offset,
518 48
            $this->encoding
519
        );
520
521 48
        return static::create($str, $this->encoding);
522
    }
523
524
    /**
525
     * Returns a camelCase version of the string. Trims surrounding spaces,
526
     * capitalizes letters following digits, spaces, dashes and underscores,
527
     * and removes spaces, dashes, as well as underscores.
528
     *
529
     * @psalm-mutation-free
530
     *
531
     * @return static
532
     *                <p>Object with $str in camelCase.</p>
533
     */
534 57
    public function camelize(): self
535
    {
536 57
        return static::create(
537 57
            $this->utf8::str_camelize($this->str, $this->encoding),
538 57
            $this->encoding
539
        );
540
    }
541
542
    /**
543
     * Returns the string with the first letter of each word capitalized,
544
     * except for when the word is a name which shouldn't be capitalized.
545
     *
546
     * @psalm-mutation-free
547
     *
548
     * @return static
549
     *                <p>Object with $str capitalized.</p>
550
     */
551 78
    public function capitalizePersonalName(): self
552
    {
553 78
        return static::create(
554 78
            $this->utf8::str_capitalize_name($this->str),
555 78
            $this->encoding
556
        );
557
    }
558
559
    /**
560
     * Returns an array consisting of the characters in the string.
561
     *
562
     * @psalm-mutation-free
563
     *
564
     * @return string[]
565
     *                  <p>An array of string chars.</p>
566
     */
567 14
    public function chars(): array
568
    {
569 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 3565
    public static function create($str = '', string $encoding = null): self
780
    {
781 3565
        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 3
            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 2
            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 2
            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 3
            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
     * Replace all breaks [<br> | \r\n | \r | \n | ...] into "<br>".
2371
     *
2372
     * @return static
2373
     */
2374 1
    public function newLineToHtmlBreak(): self
2375
    {
2376 1
        return $this->removeHtmlBreak('<br>');
2377
    }
2378
2379
    /**
2380
     * Get every nth character of the string.
2381
     *
2382
     * @param int $step   <p>The number of characters to step.</p>
2383
     * @param int $offset [optional] <p>The string offset to start at.</p>
2384
     *
2385
     * @psalm-mutation-free
2386
     *
2387
     * @return static
2388
     */
2389 4
    public function nth(int $step, int $offset = 0): self
2390
    {
2391 4
        $length = $step - 1;
2392 4
        $substring = $this->substr($offset)->toString();
2393
2394 4
        if ($substring === '') {
2395
            return new static('', $this->encoding);
2396
        }
2397
2398 4
        \preg_match_all(
2399 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2400 4
            $substring,
2401 4
            $matches
2402
        );
2403
2404 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2405
    }
2406
2407
    /**
2408
     * Returns whether or not a character exists at an index. Offsets may be
2409
     * negative to count from the last character in the string. Implements
2410
     * part of the ArrayAccess interface.
2411
     *
2412
     * @param int $offset <p>The index to check.</p>
2413
     *
2414
     * @psalm-mutation-free
2415
     *
2416
     * @return bool
2417
     *              <p>Whether or not the index exists.</p>
2418
     */
2419 18
    public function offsetExists($offset): bool
2420
    {
2421 18
        return $this->utf8::str_offset_exists(
2422 18
            $this->str,
2423 18
            $offset,
2424 18
            $this->encoding
2425
        );
2426
    }
2427
2428
    /**
2429
     * Returns the character at the given index. Offsets may be negative to
2430
     * count from the last character in the string. Implements part of the
2431
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2432
     * does not exist.
2433
     *
2434
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2435
     *
2436
     * @throws \OutOfBoundsException
2437
     *                               <p>If the positive or negative offset does not exist.</p>
2438
     *
2439
     * @return string
2440
     *                <p>The character at the specified index.</p>
2441
     *
2442
     * @psalm-mutation-free
2443
     */
2444 6
    public function offsetGet($offset): string
2445
    {
2446 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2447
    }
2448
2449
    /**
2450
     * Implements part of the ArrayAccess interface, but throws an exception
2451
     * when called. This maintains the immutability of Stringy objects.
2452
     *
2453
     * @param int   $offset <p>The index of the character.</p>
2454
     * @param mixed $value  <p>Value to set.</p>
2455
     *
2456
     * @throws \Exception
2457
     *                    <p>When called.</p>
2458
     *
2459
     * @return void
2460
     */
2461 3
    public function offsetSet($offset, $value)
2462
    {
2463
        // Stringy is immutable, cannot directly set char
2464
        /** @noinspection ThrowRawExceptionInspection */
2465 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
2466
    }
2467
2468
    /**
2469
     * Implements part of the ArrayAccess interface, but throws an exception
2470
     * when called. This maintains the immutability of Stringy objects.
2471
     *
2472
     * @param int $offset <p>The index of the character.</p>
2473
     *
2474
     * @throws \Exception
2475
     *                    <p>When called.</p>
2476
     *
2477
     * @return void
2478
     */
2479 3
    public function offsetUnset($offset)
2480
    {
2481
        // Don't allow directly modifying the string
2482
        /** @noinspection ThrowRawExceptionInspection */
2483 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
2484
    }
2485
2486
    /**
2487
     * Pads the string to a given length with $padStr. If length is less than
2488
     * or equal to the length of the string, no padding takes places. The
2489
     * default string used for padding is a space, and the default type (one of
2490
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
2491
     * if $padType isn't one of those 3 values.
2492
     *
2493
     * @param int    $length  <p>Desired string length after padding.</p>
2494
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2495
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
2496
     *
2497
     * @throws \InvalidArgumentException
2498
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
2499
     *
2500
     * @return static
2501
     *                <p>Object with a padded $str.</p>
2502
     *
2503
     * @psalm-mutation-free
2504
     */
2505 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
2506
    {
2507 39
        return static::create(
2508 39
            $this->utf8::str_pad(
2509 39
                $this->str,
2510 39
                $length,
2511 39
                $padStr,
2512 39
                $padType,
2513 39
                $this->encoding
2514
            )
2515
        );
2516
    }
2517
2518
    /**
2519
     * Returns a new string of a given length such that both sides of the
2520
     * string are padded. Alias for pad() with a $padType of 'both'.
2521
     *
2522
     * @param int    $length <p>Desired string length after padding.</p>
2523
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2524
     *
2525
     * @psalm-mutation-free
2526
     *
2527
     * @return static
2528
     *                <p>String with padding applied.</p>
2529
     */
2530 33
    public function padBoth(int $length, string $padStr = ' '): self
2531
    {
2532 33
        return static::create(
2533 33
            $this->utf8::str_pad_both(
2534 33
                $this->str,
2535 33
                $length,
2536 33
                $padStr,
2537 33
                $this->encoding
2538
            )
2539
        );
2540
    }
2541
2542
    /**
2543
     * Returns a new string of a given length such that the beginning of the
2544
     * string is padded. Alias for pad() with a $padType of 'left'.
2545
     *
2546
     * @param int    $length <p>Desired string length after padding.</p>
2547
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2548
     *
2549
     * @psalm-mutation-free
2550
     *
2551
     * @return static
2552
     *                <p>String with left padding.</p>
2553
     */
2554 21
    public function padLeft(int $length, string $padStr = ' '): self
2555
    {
2556 21
        return static::create(
2557 21
            $this->utf8::str_pad_left(
2558 21
                $this->str,
2559 21
                $length,
2560 21
                $padStr,
2561 21
                $this->encoding
2562
            )
2563
        );
2564
    }
2565
2566
    /**
2567
     * Returns a new string of a given length such that the end of the string
2568
     * is padded. Alias for pad() with a $padType of 'right'.
2569
     *
2570
     * @param int    $length <p>Desired string length after padding.</p>
2571
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2572
     *
2573
     * @psalm-mutation-free
2574
     *
2575
     * @return static
2576
     *                <p>String with right padding.</p>
2577
     */
2578 21
    public function padRight(int $length, string $padStr = ' '): self
2579
    {
2580 21
        return static::create(
2581 21
            $this->utf8::str_pad_right(
2582 21
                $this->str,
2583 21
                $length,
2584 21
                $padStr,
2585 21
                $this->encoding
2586
            )
2587
        );
2588
    }
2589
2590
    /**
2591
     * Convert the string to PascalCase.
2592
     * Alias for studlyCase()
2593
     *
2594
     * @psalm-mutation-free
2595
     *
2596
     * @return static
2597
     */
2598 3
    public function pascalCase(): self
2599
    {
2600 3
        return $this->studlyCase();
2601
    }
2602
2603
    /**
2604
     * Returns a new string starting with $prefix.
2605
     *
2606
     * @param string ...$prefix <p>The string to append.</p>
2607
     *
2608
     * @psalm-mutation-free
2609
     *
2610
     * @return static
2611
     *                <p>Object with appended $prefix.</p>
2612
     *
2613
     * @noinspection PhpDocSignatureInspection
2614
     */
2615 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...
2616
    {
2617 8
        if (\count($prefix) <= 1) {
2618
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2619 6
            $prefix = $prefix[0];
2620
        } else {
2621
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2622 2
            $prefix = \implode('', $prefix);
2623
        }
2624
2625 8
        return static::create($prefix . $this->str, $this->encoding);
2626
    }
2627
2628
    /**
2629
     * Returns a new string starting with $prefix.
2630
     *
2631
     * @param CollectionStringy|static ...$prefix <p>The Stringy objects to append.</p>
2632
     *
2633
     * @psalm-param CollectionStringy<int,static>|static ...$prefix
2634
     *
2635
     * @psalm-mutation-free
2636
     *
2637
     * @return static
2638
     *                <p>Object with appended $prefix.</p>
2639
     */
2640 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...
2641
    {
2642 1
        $prefixStr = '';
2643 1
        foreach ($prefix as $prefixTmp) {
2644 1
            if ($prefixTmp instanceof CollectionStringy) {
2645 1
                $prefixStr .= $prefixTmp->implode('');
2646
            } else {
2647 1
                $prefixStr .= $prefixTmp->toString();
2648
            }
2649
        }
2650
2651 1
        return static::create($prefixStr . $this->str, $this->encoding);
2652
    }
2653
2654
    /**
2655
     * Replaces all occurrences of $pattern in $str by $replacement.
2656
     *
2657
     * @param string $pattern     <p>The regular expression pattern.</p>
2658
     * @param string $replacement <p>The string to replace with.</p>
2659
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2660
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2661
     *
2662
     * @psalm-mutation-free
2663
     *
2664
     * @return static
2665
     *                <p>Object with the result2ing $str after the replacements.</p>
2666
     */
2667 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2668
    {
2669 29
        return static::create(
2670 29
            $this->utf8::regex_replace(
2671 29
                $this->str,
2672 29
                $pattern,
2673 29
                $replacement,
2674 29
                $options,
2675 29
                $delimiter
2676
            ),
2677 29
            $this->encoding
2678
        );
2679
    }
2680
2681
    /**
2682
     * Remove html via "strip_tags()" from the string.
2683
     *
2684
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2685
     *                              not be stripped. Default: null
2686
     *                              </p>
2687
     *
2688
     * @psalm-mutation-free
2689
     *
2690
     * @return static
2691
     */
2692 12
    public function removeHtml(string $allowableTags = ''): self
2693
    {
2694 12
        return static::create(
2695 12
            $this->utf8::remove_html($this->str, $allowableTags),
2696 12
            $this->encoding
2697
        );
2698
    }
2699
2700
    /**
2701
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2702
     *
2703
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2704
     *
2705
     * @psalm-mutation-free
2706
     *
2707
     * @return static
2708
     */
2709 13
    public function removeHtmlBreak(string $replacement = ''): self
2710
    {
2711 13
        return static::create(
2712 13
            $this->utf8::remove_html_breaks($this->str, $replacement),
2713 13
            $this->encoding
2714
        );
2715
    }
2716
2717
    /**
2718
     * Returns a new string with the prefix $substring removed, if present.
2719
     *
2720
     * @param string $substring <p>The prefix to remove.</p>
2721
     *
2722
     * @psalm-mutation-free
2723
     *
2724
     * @return static
2725
     *                <p>Object having a $str without the prefix $substring.</p>
2726
     */
2727 36
    public function removeLeft(string $substring): self
2728
    {
2729 36
        return static::create(
2730 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2731 36
            $this->encoding
2732
        );
2733
    }
2734
2735
    /**
2736
     * Returns a new string with the suffix $substring removed, if present.
2737
     *
2738
     * @param string $substring <p>The suffix to remove.</p>
2739
     *
2740
     * @psalm-mutation-free
2741
     *
2742
     * @return static
2743
     *                <p>Object having a $str without the suffix $substring.</p>
2744
     */
2745 36
    public function removeRight(string $substring): self
2746
    {
2747 36
        return static::create(
2748 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2749 36
            $this->encoding
2750
        );
2751
    }
2752
2753
    /**
2754
     * Try to remove all XSS-attacks from the string.
2755
     *
2756
     * @psalm-mutation-free
2757
     *
2758
     * @return static
2759
     */
2760 12
    public function removeXss(): self
2761
    {
2762
        /**
2763
         * @var AntiXSS|null
2764
         *
2765
         * @psalm-suppress ImpureStaticVariable
2766
         */
2767 12
        static $antiXss = null;
2768
2769 12
        if ($antiXss === null) {
2770 1
            $antiXss = new AntiXSS();
2771
        }
2772
2773
        /**
2774
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2775
         */
2776 12
        $str = $antiXss->xss_clean($this->str);
2777
2778 12
        return static::create($str, $this->encoding);
2779
    }
2780
2781
    /**
2782
     * Returns a repeated string given a multiplier.
2783
     *
2784
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2785
     *
2786
     * @psalm-mutation-free
2787
     *
2788
     * @return static
2789
     *                <p>Object with a repeated str.</p>
2790
     */
2791 21
    public function repeat(int $multiplier): self
2792
    {
2793 21
        return static::create(
2794 21
            \str_repeat($this->str, $multiplier),
2795 21
            $this->encoding
2796
        );
2797
    }
2798
2799
    /**
2800
     * Replaces all occurrences of $search in $str by $replacement.
2801
     *
2802
     * @param string $search        <p>The needle to search for.</p>
2803
     * @param string $replacement   <p>The string to replace with.</p>
2804
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2805
     *
2806
     * @psalm-mutation-free
2807
     *
2808
     * @return static
2809
     *                <p>Object with the resulting $str after the replacements.</p>
2810
     */
2811 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2812
    {
2813 76
        if ($search === '' && $replacement === '') {
2814 16
            return static::create($this->str, $this->encoding);
2815
        }
2816
2817 60
        if ($this->str === '' && $search === '') {
2818 2
            return static::create($replacement, $this->encoding);
2819
        }
2820
2821 58
        if ($caseSensitive) {
2822 48
            return static::create(
2823 48
                $this->utf8::str_replace($search, $replacement, $this->str),
2824 48
                $this->encoding
2825
            );
2826
        }
2827
2828 10
        return static::create(
2829 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2830 10
            $this->encoding
2831
        );
2832
    }
2833
2834
    /**
2835
     * Replaces all occurrences of $search in $str by $replacement.
2836
     *
2837
     * @param string[]        $search        <p>The elements to search for.</p>
2838
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2839
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2840
     *
2841
     * @psalm-mutation-free
2842
     *
2843
     * @return static
2844
     *                <p>Object with the resulting $str after the replacements.</p>
2845
     */
2846 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2847
    {
2848 61
        if ($caseSensitive) {
2849 47
            return static::create(
2850 47
                $this->utf8::str_replace($search, $replacement, $this->str),
2851 47
                $this->encoding
2852
            );
2853
        }
2854
2855 14
        return static::create(
2856 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2857 14
            $this->encoding
2858
        );
2859
    }
2860
2861
    /**
2862
     * Replaces all occurrences of $search from the beginning of string with $replacement.
2863
     *
2864
     * @param string $search      <p>The string to search for.</p>
2865
     * @param string $replacement <p>The replacement.</p>
2866
     *
2867
     * @psalm-mutation-free
2868
     *
2869
     * @return static
2870
     *                <p>Object with the resulting $str after the replacements.</p>
2871
     */
2872 32
    public function replaceBeginning(string $search, string $replacement): self
2873
    {
2874 32
        return static::create(
2875 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
2876 32
            $this->encoding
2877
        );
2878
    }
2879
2880
    /**
2881
     * Replaces all occurrences of $search from the ending of string with $replacement.
2882
     *
2883
     * @param string $search      <p>The string to search for.</p>
2884
     * @param string $replacement <p>The replacement.</p>
2885
     *
2886
     * @psalm-mutation-free
2887
     *
2888
     * @return static
2889
     *                <p>Object with the resulting $str after the replacements.</p>
2890
     */
2891 32
    public function replaceEnding(string $search, string $replacement): self
2892
    {
2893 32
        return static::create(
2894 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
2895 32
            $this->encoding
2896
        );
2897
    }
2898
2899
    /**
2900
     * Replaces first occurrences of $search from the beginning of string with $replacement.
2901
     *
2902
     * @param string $search      <p>The string to search for.</p>
2903
     * @param string $replacement <p>The replacement.</p>
2904
     *
2905
     * @psalm-mutation-free
2906
     *
2907
     * @return static
2908
     *                <p>Object with the resulting $str after the replacements.</p>
2909
     */
2910 32
    public function replaceFirst(string $search, string $replacement): self
2911
    {
2912 32
        return static::create(
2913 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
2914 32
            $this->encoding
2915
        );
2916
    }
2917
2918
    /**
2919
     * Replaces last occurrences of $search from the ending of string with $replacement.
2920
     *
2921
     * @param string $search      <p>The string to search for.</p>
2922
     * @param string $replacement <p>The replacement.</p>
2923
     *
2924
     * @psalm-mutation-free
2925
     *
2926
     * @return static
2927
     *                <p>Object with the resulting $str after the replacements.</p>
2928
     */
2929 30
    public function replaceLast(string $search, string $replacement): self
2930
    {
2931 30
        return static::create(
2932 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
2933 30
            $this->encoding
2934
        );
2935
    }
2936
2937
    /**
2938
     * Returns a reversed string. A multibyte version of strrev().
2939
     *
2940
     * @psalm-mutation-free
2941
     *
2942
     * @return static
2943
     *                <p>Object with a reversed $str.</p>
2944
     */
2945 15
    public function reverse(): self
2946
    {
2947 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
2948
    }
2949
2950
    /**
2951
     * Truncates the string to a given length, while ensuring that it does not
2952
     * split words. If $substring is provided, and truncating occurs, the
2953
     * string is further truncated so that the substring may be appended without
2954
     * exceeding the desired length.
2955
     *
2956
     * @param int    $length                          <p>Desired length of the truncated string.</p>
2957
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
2958
     * @param bool   $ignoreDoNotSplitWordsForOneWord
2959
     *
2960
     * @psalm-mutation-free
2961
     *
2962
     * @return static
2963
     *                <p>Object with the resulting $str after truncating.</p>
2964
     */
2965 68
    public function safeTruncate(
2966
        int $length,
2967
        string $substring = '',
2968
        bool $ignoreDoNotSplitWordsForOneWord = true
2969
    ): self {
2970 68
        return static::create(
2971 68
            $this->utf8::str_truncate_safe(
2972 68
                $this->str,
2973 68
                $length,
2974 68
                $substring,
2975 68
                $this->encoding,
2976 68
                $ignoreDoNotSplitWordsForOneWord
2977
            ),
2978 68
            $this->encoding
2979
        );
2980
    }
2981
2982
    /**
2983
     * Set the internal character encoding.
2984
     *
2985
     * @param string $new_encoding <p>The desired character encoding.</p>
2986
     *
2987
     * @psalm-mutation-free
2988
     *
2989
     * @return static
2990
     */
2991 1
    public function setInternalEncoding(string $new_encoding): self
2992
    {
2993 1
        return new static($this->str, $new_encoding);
2994
    }
2995
2996
    /**
2997
     * Create a sha1 hash from the current string.
2998
     *
2999
     * @psalm-mutation-free
3000
     *
3001
     * @return static
3002
     */
3003 2
    public function sha1(): self
3004
    {
3005 2
        return static::create($this->hash('sha1'), $this->encoding);
3006
    }
3007
3008
    /**
3009
     * Create a sha256 hash from the current string.
3010
     *
3011
     * @psalm-mutation-free
3012
     *
3013
     * @return static
3014
     */
3015 2
    public function sha256(): self
3016
    {
3017 2
        return static::create($this->hash('sha256'), $this->encoding);
3018
    }
3019
3020
    /**
3021
     * Create a sha512 hash from the current string.
3022
     *
3023
     * @psalm-mutation-free
3024
     *
3025
     * @return static
3026
     */
3027 2
    public function sha512(): self
3028
    {
3029 2
        return static::create($this->hash('sha512'), $this->encoding);
3030
    }
3031
3032
    /**
3033
     * Shorten the string after $length, but also after the next word.
3034
     *
3035
     * @param int    $length   <p>The given length.</p>
3036
     * @param string $strAddOn [optional] <p>Default: '…'</p>
3037
     *
3038
     * @psalm-mutation-free
3039
     *
3040
     * @return static
3041
     */
3042 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
3043
    {
3044 8
        return static::create(
3045 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
3046 8
            $this->encoding
3047
        );
3048
    }
3049
3050
    /**
3051
     * A multibyte string shuffle function. It returns a string with its
3052
     * characters in random order.
3053
     *
3054
     * @psalm-mutation-free
3055
     *
3056
     * @return static
3057
     *                <p>Object with a shuffled $str.</p>
3058
     */
3059 9
    public function shuffle(): self
3060
    {
3061 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
3062
    }
3063
3064
    /**
3065
     * Calculate the similarity between two strings.
3066
     *
3067
     * @param string $str <p>The delimiting string.</p>
3068
     *
3069
     * @psalm-mutation-free
3070
     *
3071
     * @return float
3072
     */
3073 2
    public function similarity(string $str): float
3074
    {
3075 2
        \similar_text($this->str, $str, $percent);
3076
3077 2
        return $percent;
3078
    }
3079
3080
    /**
3081
     * Returns the substring beginning at $start, and up to, but not including
3082
     * the index specified by $end. If $end is omitted, the function extracts
3083
     * the remaining string. If $end is negative, it is computed from the end
3084
     * of the string.
3085
     *
3086
     * @param int $start <p>Initial index from which to begin extraction.</p>
3087
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
3088
     *
3089
     * @psalm-mutation-free
3090
     *
3091
     * @return static
3092
     *                <p>Object with its $str being the extracted substring.</p>
3093
     */
3094 50
    public function slice(int $start, int $end = null): self
3095
    {
3096 50
        return static::create(
3097 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
3098 50
            $this->encoding
3099
        );
3100
    }
3101
3102
    /**
3103
     * Converts the string into an URL slug. This includes replacing non-ASCII
3104
     * characters with their closest ASCII equivalents, removing remaining
3105
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3106
     * $separator. The separator defaults to a single dash, and the string
3107
     * is also converted to lowercase. The language of the source string can
3108
     * also be supplied for language-specific transliteration.
3109
     *
3110
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
3111
     * @param string                $language              [optional] <p>Language of the source string.</p>
3112
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
3113
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
3114
     *                                                     pound ".</p>
3115
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
3116
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
3117
     *                                                     chars.</p>
3118
     *
3119
     * @psalm-mutation-free
3120
     *
3121
     * @return static
3122
     *                <p>Object whose $str has been converted to an URL slug.</p>
3123
     *
3124
     * @noinspection PhpTooManyParametersInspection
3125
     */
3126 17
    public function slugify(
3127
        string $separator = '-',
3128
        string $language = 'en',
3129
        array $replacements = [],
3130
        bool $replace_extra_symbols = true,
3131
        bool $use_str_to_lower = true,
3132
        bool $use_transliterate = false
3133
    ): self {
3134 17
        return static::create(
3135 17
            $this->ascii::to_slugify(
3136 17
                $this->str,
3137 17
                $separator,
3138 17
                $language,
3139 17
                $replacements,
3140 17
                $replace_extra_symbols,
3141 17
                $use_str_to_lower,
3142 17
                $use_transliterate
3143
            ),
3144 17
            $this->encoding
3145
        );
3146
    }
3147
3148
    /**
3149
     * Convert the string to snake_case.
3150
     *
3151
     * @psalm-mutation-free
3152
     *
3153
     * @return static
3154
     */
3155 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...
3156
    {
3157 3
        $words = \array_map(
3158 3
            static function (self $word) {
3159 3
                return $word->toLowerCase();
3160 3
            },
3161 3
            $this->words('', true)
3162
        );
3163
3164 3
        return new static(\implode('_', $words), $this->encoding);
3165
    }
3166
3167
    /**
3168
     * Convert a string to e.g.: "snake_case"
3169
     *
3170
     * @psalm-mutation-free
3171
     *
3172
     * @return static
3173
     *                <p>Object with $str in snake_case.</p>
3174
     */
3175 40
    public function snakeize(): self
3176
    {
3177 40
        return static::create(
3178 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
3179 40
            $this->encoding
3180
        );
3181
    }
3182
3183
    /**
3184
     * Wrap the string after the first whitespace character after a given number
3185
     * of characters.
3186
     *
3187
     * @param int    $width <p>Number of characters at which to wrap.</p>
3188
     * @param string $break [optional] <p>Character used to break the string. | Default "\n"</p>
3189
     *
3190
     * @psalm-mutation-free
3191
     *
3192
     * @return static
3193
     */
3194 2
    public function softWrap(int $width, string $break = "\n"): self
3195
    {
3196 2
        return $this->lineWrapAfterWord($width, $break, false);
3197
    }
3198
3199
    /**
3200
     * Splits the string with the provided regular expression, returning an
3201
     * array of Stringy objects. An optional integer $limit will truncate the
3202
     * results.
3203
     *
3204
     * @param string $pattern <p>The regex with which to split the string.</p>
3205
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3206
     *                        limit</p>
3207
     *
3208
     * @psalm-mutation-free
3209
     *
3210
     * @return static[]
3211
     *                  <p>An array of Stringy objects.</p>
3212
     *
3213
     * @psalm-return array<int,static>
3214
     */
3215 51
    public function split(string $pattern, int $limit = null): array
3216
    {
3217 51
        if ($this->str === '') {
3218
            return [];
3219
        }
3220
3221 51
        if ($limit === null) {
3222 7
            $limit = -1;
3223
        }
3224
3225 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
3226
        /** @noinspection AlterInForeachInspection */
3227 51
        foreach ($array as $i => &$value) {
3228 45
            $value = static::create($value, $this->encoding);
3229
        }
3230
3231
        /** @noinspection PhpSillyAssignmentInspection */
3232
        /** @var static[] $array */
3233 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...
3234
3235 51
        return $array;
3236
    }
3237
3238
    /**
3239
     * Splits the string with the provided regular expression, returning an
3240
     * collection of Stringy objects. An optional integer $limit will truncate the
3241
     * results.
3242
     *
3243
     * @param string $pattern <p>The regex with which to split the string.</p>
3244
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3245
     *                        limit</p>
3246
     *
3247
     * @psalm-mutation-free
3248
     *
3249
     * @return CollectionStringy|static[]
3250
     *                                    <p>An collection of Stringy objects.</p>
3251
     *
3252
     * @psalm-return CollectionStringy<int,static>
3253
     */
3254 35
    public function splitCollection(string $pattern, int $limit = null): CollectionStringy
3255
    {
3256
        /**
3257
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3258
         */
3259 35
        return CollectionStringy::create(
3260 35
            $this->split($pattern, $limit)
3261
        );
3262
    }
3263
3264
    /**
3265
     * Returns true if the string begins with $substring, false otherwise. By
3266
     * default, the comparison is case-sensitive, but can be made insensitive
3267
     * by setting $caseSensitive to false.
3268
     *
3269
     * @param string $substring     <p>The substring to look for.</p>
3270
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3271
     *
3272
     * @psalm-mutation-free
3273
     *
3274
     * @return bool
3275
     *              <p>Whether or not $str starts with $substring.</p>
3276
     */
3277 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
3278
    {
3279 99
        if ($caseSensitive) {
3280 53
            return $this->utf8::str_starts_with($this->str, $substring);
3281
        }
3282
3283 46
        return $this->utf8::str_istarts_with($this->str, $substring);
3284
    }
3285
3286
    /**
3287
     * Returns true if the string begins with any of $substrings, false otherwise.
3288
     * By default the comparison is case-sensitive, but can be made insensitive by
3289
     * setting $caseSensitive to false.
3290
     *
3291
     * @param string[] $substrings    <p>Substrings to look for.</p>
3292
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3293
     *
3294
     * @psalm-mutation-free
3295
     *
3296
     * @return bool
3297
     *              <p>Whether or not $str starts with $substring.</p>
3298
     */
3299 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
3300
    {
3301 35
        if ($caseSensitive) {
3302 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
3303
        }
3304
3305 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
3306
    }
3307
3308
    /**
3309
     * Remove one or more strings from the string.
3310
     *
3311
     * @param string|string[] $search One or more strings to be removed
3312
     *
3313
     * @psalm-mutation-free
3314
     *
3315
     * @return static
3316
     */
3317 3
    public function strip($search): self
3318
    {
3319 3
        if (\is_array($search)) {
3320 1
            return $this->replaceAll($search, '');
3321
        }
3322
3323 2
        return $this->replace($search, '');
3324
    }
3325
3326
    /**
3327
     * Strip all whitespace characters. This includes tabs and newline characters,
3328
     * as well as multibyte whitespace such as the thin space and ideographic space.
3329
     *
3330
     * @psalm-mutation-free
3331
     *
3332
     * @return static
3333
     */
3334 36
    public function stripWhitespace(): self
3335
    {
3336 36
        return static::create(
3337 36
            $this->utf8::strip_whitespace($this->str),
3338 36
            $this->encoding
3339
        );
3340
    }
3341
3342
    /**
3343
     * Remove css media-queries.
3344
     *
3345
     * @psalm-mutation-free
3346
     *
3347
     * @return static
3348
     */
3349 2
    public function stripeCssMediaQueries(): self
3350
    {
3351 2
        return static::create(
3352 2
            $this->utf8::css_stripe_media_queries($this->str),
3353 2
            $this->encoding
3354
        );
3355
    }
3356
3357
    /**
3358
     * Remove empty html-tag.
3359
     *
3360
     * e.g.: <tag></tag>
3361
     *
3362
     * @psalm-mutation-free
3363
     *
3364
     * @return static
3365
     */
3366 2
    public function stripeEmptyHtmlTags(): self
3367
    {
3368 2
        return static::create(
3369 2
            $this->utf8::html_stripe_empty_tags($this->str),
3370 2
            $this->encoding
3371
        );
3372
    }
3373
3374
    /**
3375
     * Convert the string to StudlyCase.
3376
     *
3377
     * @psalm-mutation-free
3378
     *
3379
     * @return static
3380
     */
3381 6
    public function studlyCase(): self
3382
    {
3383 6
        $words = \array_map(
3384 6
            static function (self $word) {
3385 6
                return $word->substr(0, 1)
3386 6
                    ->toUpperCase()
3387 6
                    ->appendStringy($word->substr(1));
3388 6
            },
3389 6
            $this->words('', true)
3390
        );
3391
3392 6
        return new static(\implode('', $words), $this->encoding);
3393
    }
3394
3395
    /**
3396
     * Returns the substring beginning at $start with the specified $length.
3397
     * It differs from the $this->utf8::substr() function in that providing a $length of
3398
     * null will return the rest of the string, rather than an empty string.
3399
     *
3400
     * @param int $start  <p>Position of the first character to use.</p>
3401
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
3402
     *
3403
     * @psalm-mutation-free
3404
     *
3405
     * @return static
3406
     *                <p>Object with its $str being the substring.</p>
3407
     */
3408 40
    public function substr(int $start, int $length = null): self
3409
    {
3410 40
        return static::create(
3411 40
            $this->utf8::substr(
3412 40
                $this->str,
3413 40
                $start,
3414 40
                $length,
3415 40
                $this->encoding
3416
            ),
3417 40
            $this->encoding
3418
        );
3419
    }
3420
3421
    /**
3422
     * Return part of the string.
3423
     * Alias for substr()
3424
     *
3425
     * @param int $start  <p>Starting position of the substring.</p>
3426
     * @param int $length [optional] <p>Length of substring.</p>
3427
     *
3428
     * @psalm-mutation-free
3429
     *
3430
     * @return static
3431
     */
3432 3
    public function substring(int $start, int $length = null): self
3433
    {
3434 3
        if ($length === null) {
3435 2
            return $this->substr($start);
3436
        }
3437
3438 3
        return $this->substr($start, $length);
3439
    }
3440
3441
    /**
3442
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3443
     * If no match is found returns new empty Stringy object.
3444
     *
3445
     * @param string $needle       <p>The string to look for.</p>
3446
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3447
     *
3448
     * @psalm-mutation-free
3449
     *
3450
     * @return static
3451
     */
3452 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...
3453
    {
3454 4
        return static::create(
3455 4
            $this->utf8::str_substr_first(
3456 4
                $this->str,
3457 4
                $needle,
3458 4
                $beforeNeedle,
3459 4
                $this->encoding
3460
            ),
3461 4
            $this->encoding
3462
        );
3463
    }
3464
3465
    /**
3466
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3467
     * If no match is found returns new empty Stringy object.
3468
     *
3469
     * @param string $needle       <p>The string to look for.</p>
3470
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3471
     *
3472
     * @psalm-mutation-free
3473
     *
3474
     * @return static
3475
     */
3476 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...
3477
    {
3478 4
        return static::create(
3479 4
            $this->utf8::str_isubstr_first(
3480 4
                $this->str,
3481 4
                $needle,
3482 4
                $beforeNeedle,
3483 4
                $this->encoding
3484
            ),
3485 4
            $this->encoding
3486
        );
3487
    }
3488
3489
    /**
3490
     * Surrounds $str with the given substring.
3491
     *
3492
     * @param string $substring <p>The substring to add to both sides.</P>
3493
     *
3494
     * @psalm-mutation-free
3495
     *
3496
     * @return static
3497
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3498
     */
3499 15
    public function surround(string $substring): self
3500
    {
3501 15
        return static::create(
3502 15
            $substring . $this->str . $substring,
3503 15
            $this->encoding
3504
        );
3505
    }
3506
3507
    /**
3508
     * Returns a case swapped version of the string.
3509
     *
3510
     * @psalm-mutation-free
3511
     *
3512
     * @return static
3513
     *                <p>Object whose $str has each character's case swapped.</P>
3514
     */
3515 15
    public function swapCase(): self
3516
    {
3517 15
        return static::create(
3518 15
            $this->utf8::swapCase($this->str, $this->encoding),
3519 15
            $this->encoding
3520
        );
3521
    }
3522
3523
    /**
3524
     * Returns a string with smart quotes, ellipsis characters, and dashes from
3525
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
3526
     * equivalents.
3527
     *
3528
     * @psalm-mutation-free
3529
     *
3530
     * @return static
3531
     *                <p>Object whose $str has those characters removed.</p>
3532
     */
3533 12
    public function tidy(): self
3534
    {
3535 12
        return static::create(
3536 12
            $this->ascii::normalize_msword($this->str),
3537 12
            $this->encoding
3538
        );
3539
    }
3540
3541
    /**
3542
     * Returns a trimmed string with the first letter of each word capitalized.
3543
     * Also accepts an array, $ignore, allowing you to list words not to be
3544
     * capitalized.
3545
     *
3546
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
3547
     *                                               Default: null</p>
3548
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
3549
     *                                               separator === words.</p>
3550
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
3551
     *
3552
     * @psalm-mutation-free
3553
     *
3554
     * @return static
3555
     *                <p>Object with a titleized $str.</p>
3556
     */
3557 23
    public function titleize(
3558
        array $ignore = null,
3559
        string $word_define_chars = null,
3560
        string $language = null
3561
    ): self {
3562 23
        return static::create(
3563 23
            $this->utf8::str_titleize(
3564 23
                $this->str,
3565 23
                $ignore,
3566 23
                $this->encoding,
3567 23
                false,
3568 23
                $language,
3569 23
                false,
3570 23
                true,
3571 23
                $word_define_chars
3572
            ),
3573 23
            $this->encoding
3574
        );
3575
    }
3576
3577
    /**
3578
     * Returns a trimmed string in proper title case.
3579
     *
3580
     * Also accepts an array, $ignore, allowing you to list words not to be
3581
     * capitalized.
3582
     *
3583
     * Adapted from John Gruber's script.
3584
     *
3585
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
3586
     *
3587
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
3588
     *
3589
     * @psalm-mutation-free
3590
     *
3591
     * @return static
3592
     *                <p>Object with a titleized $str</p>
3593
     */
3594 70
    public function titleizeForHumans(array $ignore = []): self
3595
    {
3596 70
        return static::create(
3597 70
            $this->utf8::str_titleize_for_humans(
3598 70
                $this->str,
3599 70
                $ignore,
3600 70
                $this->encoding
3601
            ),
3602 70
            $this->encoding
3603
        );
3604
    }
3605
3606
    /**
3607
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3608
     * replaced with their closest ASCII counterparts, and the rest are removed
3609
     * by default. The language or locale of the source string can be supplied
3610
     * for language-specific transliteration in any of the following formats:
3611
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
3612
     * to "aeoeue" rather than "aou" as in other languages.
3613
     *
3614
     * @param string $language          [optional] <p>Language of the source string.</p>
3615
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
3616
     *                                  unsupported characters.</p>
3617
     *
3618
     * @psalm-mutation-free
3619
     *
3620
     * @return static
3621
     *                <p>Object whose $str contains only ASCII characters.</p>
3622
     */
3623 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
3624
    {
3625 23
        return static::create(
3626 23
            $this->ascii::to_ascii(
3627 23
                $this->str,
3628 23
                $language,
3629 23
                $removeUnsupported
3630
            ),
3631 23
            $this->encoding
3632
        );
3633
    }
3634
3635
    /**
3636
     * Returns a boolean representation of the given logical string value.
3637
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
3638
     * 'off', and 'no' will return false. In all instances, case is ignored.
3639
     * For other numeric strings, their sign will determine the return value.
3640
     * In addition, blank strings consisting of only whitespace will return
3641
     * false. For all other strings, the return value is a result of a
3642
     * boolean cast.
3643
     *
3644
     * @psalm-mutation-free
3645
     *
3646
     * @return bool
3647
     *              <p>A boolean value for the string.</p>
3648
     */
3649 45
    public function toBoolean(): bool
3650
    {
3651 45
        return $this->utf8::to_boolean($this->str);
3652
    }
3653
3654
    /**
3655
     * Converts all characters in the string to lowercase.
3656
     *
3657
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3658
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3659
     *
3660
     * @psalm-mutation-free
3661
     *
3662
     * @return static
3663
     *                <p>Object with all characters of $str being lowercase.</p>
3664
     */
3665 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...
3666
    {
3667 23
        return static::create(
3668 23
            $this->utf8::strtolower(
3669 23
                $this->str,
3670 23
                $this->encoding,
3671 23
                false,
3672 23
                $lang,
3673 23
                $tryToKeepStringLength
3674
            ),
3675 23
            $this->encoding
3676
        );
3677
    }
3678
3679
    /**
3680
     * Converts each tab in the string to some number of spaces, as defined by
3681
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
3682
     *
3683
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
3684
     *
3685
     * @psalm-mutation-free
3686
     *
3687
     * @return static
3688
     *                <p>Object whose $str has had tabs switched to spaces.</p>
3689
     */
3690 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...
3691
    {
3692 18
        if ($tabLength === 4) {
3693 9
            $tab = '    ';
3694 9
        } elseif ($tabLength === 2) {
3695 3
            $tab = '  ';
3696
        } else {
3697 6
            $tab = \str_repeat(' ', $tabLength);
3698
        }
3699
3700 18
        return static::create(
3701 18
            \str_replace("\t", $tab, $this->str),
3702 18
            $this->encoding
3703
        );
3704
    }
3705
3706
    /**
3707
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
3708
     * string.
3709
     *
3710
     * @psalm-mutation-free
3711
     *
3712
     * @return string
3713
     */
3714 2198
    public function toString(): string
3715
    {
3716 2198
        return (string) $this->str;
3717
    }
3718
3719
    /**
3720
     * Converts each occurrence of some consecutive number of spaces, as
3721
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
3722
     * are converted to a tab.
3723
     *
3724
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
3725
     *
3726
     * @psalm-mutation-free
3727
     *
3728
     * @return static
3729
     *                <p>Object whose $str has had spaces switched to tabs.</p>
3730
     */
3731 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...
3732
    {
3733 15
        if ($tabLength === 4) {
3734 9
            $tab = '    ';
3735 6
        } elseif ($tabLength === 2) {
3736 3
            $tab = '  ';
3737
        } else {
3738 3
            $tab = \str_repeat(' ', $tabLength);
3739
        }
3740
3741 15
        return static::create(
3742 15
            \str_replace($tab, "\t", $this->str),
3743 15
            $this->encoding
3744
        );
3745
    }
3746
3747
    /**
3748
     * Converts the first character of each word in the string to uppercase
3749
     * and all other chars to lowercase.
3750
     *
3751
     * @psalm-mutation-free
3752
     *
3753
     * @return static
3754
     *                <p>Object with all characters of $str being title-cased.</p>
3755
     */
3756 15
    public function toTitleCase(): self
3757
    {
3758 15
        return static::create(
3759 15
            $this->utf8::titlecase($this->str, $this->encoding),
3760 15
            $this->encoding
3761
        );
3762
    }
3763
3764
    /**
3765
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3766
     * replaced with their closest ASCII counterparts, and the rest are removed
3767
     * unless instructed otherwise.
3768
     *
3769
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
3770
     *                        performance | Default: false</p>
3771
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
3772
     *
3773
     * @psalm-mutation-free
3774
     *
3775
     * @return static
3776
     *                <p>Object whose $str contains only ASCII characters.</p>
3777
     */
3778 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
3779
    {
3780 34
        return static::create(
3781 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
3782 34
            $this->encoding
3783
        );
3784
    }
3785
3786
    /**
3787
     * Converts all characters in the string to uppercase.
3788
     *
3789
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3790
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3791
     *
3792
     * @psalm-mutation-free
3793
     *
3794
     * @return static
3795
     *                <p>Object with all characters of $str being uppercase.</p>
3796
     */
3797 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...
3798
    {
3799 26
        return static::create(
3800 26
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
3801 26
            $this->encoding
3802
        );
3803
    }
3804
3805
    /**
3806
     * Returns a string with whitespace removed from the start and end of the
3807
     * string. Supports the removal of unicode whitespace. Accepts an optional
3808
     * string of characters to strip instead of the defaults.
3809
     *
3810
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
3811
     *
3812
     * @psalm-mutation-free
3813
     *
3814
     * @return static
3815
     *                <p>Object with a trimmed $str.</p>
3816
     */
3817 36
    public function trim(string $chars = null): self
3818
    {
3819 36
        return static::create(
3820 36
            $this->utf8::trim($this->str, $chars),
3821 36
            $this->encoding
3822
        );
3823
    }
3824
3825
    /**
3826
     * Returns a string with whitespace removed from the start of the string.
3827
     * Supports the removal of unicode whitespace. Accepts an optional
3828
     * string of characters to strip instead of the defaults.
3829
     *
3830
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3831
     *
3832
     * @psalm-mutation-free
3833
     *
3834
     * @return static
3835
     *                <p>Object with a trimmed $str.</p>
3836
     */
3837 39
    public function trimLeft(string $chars = null): self
3838
    {
3839 39
        return static::create(
3840 39
            $this->utf8::ltrim($this->str, $chars),
3841 39
            $this->encoding
3842
        );
3843
    }
3844
3845
    /**
3846
     * Returns a string with whitespace removed from the end of the string.
3847
     * Supports the removal of unicode whitespace. Accepts an optional
3848
     * string of characters to strip instead of the defaults.
3849
     *
3850
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3851
     *
3852
     * @psalm-mutation-free
3853
     *
3854
     * @return static
3855
     *                <p>Object with a trimmed $str.</p>
3856
     */
3857 39
    public function trimRight(string $chars = null): self
3858
    {
3859 39
        return static::create(
3860 39
            $this->utf8::rtrim($this->str, $chars),
3861 39
            $this->encoding
3862
        );
3863
    }
3864
3865
    /**
3866
     * Truncates the string to a given length. If $substring is provided, and
3867
     * truncating occurs, the string is further truncated so that the substring
3868
     * may be appended without exceeding the desired length.
3869
     *
3870
     * @param int    $length    <p>Desired length of the truncated string.</p>
3871
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
3872
     *
3873
     * @psalm-mutation-free
3874
     *
3875
     * @return static
3876
     *                <p>Object with the resulting $str after truncating.</p>
3877
     */
3878 66
    public function truncate(int $length, string $substring = ''): self
3879
    {
3880 66
        return static::create(
3881 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
3882 66
            $this->encoding
3883
        );
3884
    }
3885
3886
    /**
3887
     * Returns a lowercase and trimmed string separated by underscores.
3888
     * Underscores are inserted before uppercase characters (with the exception
3889
     * of the first character of the string), and in place of spaces as well as
3890
     * dashes.
3891
     *
3892
     * @psalm-mutation-free
3893
     *
3894
     * @return static
3895
     *                <p>Object with an underscored $str.</p>
3896
     */
3897 48
    public function underscored(): self
3898
    {
3899 48
        return $this->delimit('_');
3900
    }
3901
3902
    /**
3903
     * Returns an UpperCamelCase version of the supplied string. It trims
3904
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
3905
     * and underscores, and removes spaces, dashes, underscores.
3906
     *
3907
     * @psalm-mutation-free
3908
     *
3909
     * @return static
3910
     *                <p>Object with $str in UpperCamelCase.</p>
3911
     */
3912 39
    public function upperCamelize(): self
3913
    {
3914 39
        return static::create(
3915 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
3916 39
            $this->encoding
3917
        );
3918
    }
3919
3920
    /**
3921
     * Converts the first character of the supplied string to upper case.
3922
     *
3923
     * @psalm-mutation-free
3924
     *
3925
     * @return static
3926
     *                <p>Object with the first character of $str being upper case.</p>
3927
     */
3928 18
    public function upperCaseFirst(): self
3929
    {
3930 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
3931
    }
3932
3933
    /**
3934
     * Simple url-decoding.
3935
     *
3936
     * e.g:
3937
     * 'test+test' => 'test test'
3938
     *
3939
     * @psalm-mutation-free
3940
     *
3941
     * @return static
3942
     */
3943 1
    public function urlDecode(): self
3944
    {
3945 1
        return static::create(\urldecode($this->str));
3946
    }
3947
3948
    /**
3949
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
3950
     *
3951
     * e.g:
3952
     * 'test+test'                     => 'test test'
3953
     * 'D&#252;sseldorf'               => 'Düsseldorf'
3954
     * 'D%FCsseldorf'                  => 'Düsseldorf'
3955
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
3956
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
3957
     * 'Düsseldorf'                   => 'Düsseldorf'
3958
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
3959
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
3960
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
3961
     *
3962
     * @psalm-mutation-free
3963
     *
3964
     * @return static
3965
     */
3966 1
    public function urlDecodeMulti(): self
3967
    {
3968 1
        return static::create($this->utf8::urldecode($this->str));
3969
    }
3970
3971
    /**
3972
     * Simple url-decoding.
3973
     *
3974
     * e.g:
3975
     * 'test+test' => 'test+test'
3976
     *
3977
     * @psalm-mutation-free
3978
     *
3979
     * @return static
3980
     */
3981 1
    public function urlDecodeRaw(): self
3982
    {
3983 1
        return static::create(\rawurldecode($this->str));
3984
    }
3985
3986
    /**
3987
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
3988
     *
3989
     * e.g:
3990
     * 'test+test'                     => 'test+test'
3991
     * 'D&#252;sseldorf'               => 'Düsseldorf'
3992
     * 'D%FCsseldorf'                  => 'Düsseldorf'
3993
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
3994
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
3995
     * 'Düsseldorf'                   => 'Düsseldorf'
3996
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
3997
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
3998
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
3999
     *
4000
     * @psalm-mutation-free
4001
     *
4002
     * @return static
4003
     */
4004 1
    public function urlDecodeRawMulti(): self
4005
    {
4006 1
        return static::create($this->utf8::rawurldecode($this->str));
4007
    }
4008
4009
    /**
4010
     * Simple url-encoding.
4011
     *
4012
     * e.g:
4013
     * 'test test' => 'test+test'
4014
     *
4015
     * @psalm-mutation-free
4016
     *
4017
     * @return static
4018
     */
4019 1
    public function urlEncode(): self
4020
    {
4021 1
        return static::create(\urlencode($this->str));
4022
    }
4023
4024
    /**
4025
     * Simple url-encoding.
4026
     *
4027
     * e.g:
4028
     * 'test test' => 'test%20test'
4029
     *
4030
     * @psalm-mutation-free
4031
     *
4032
     * @return static
4033
     */
4034 1
    public function urlEncodeRaw(): self
4035
    {
4036 1
        return static::create(\rawurlencode($this->str));
4037
    }
4038
4039
    /**
4040
     * Converts the string into an URL slug. This includes replacing non-ASCII
4041
     * characters with their closest ASCII equivalents, removing remaining
4042
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
4043
     * $separator. The separator defaults to a single dash, and the string
4044
     * is also converted to lowercase.
4045
     *
4046
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
4047
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
4048
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
4049
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
4050
     *
4051
     * @psalm-mutation-free
4052
     *
4053
     * @return static
4054
     *                <p>Object whose $str has been converted to an URL slug.</p>
4055
     *
4056
     * @psalm-suppress ImpureMethodCall :/
4057
     */
4058 32
    public function urlify(
4059
        string $separator = '-',
4060
        string $language = 'en',
4061
        array $replacements = [],
4062
        bool $strToLower = true
4063
    ): self {
4064
        // init
4065 32
        $str = $this->str;
4066
4067 32
        foreach ($replacements as $from => $to) {
4068 32
            $str = \str_replace($from, $to, $str);
4069
        }
4070
4071 32
        return static::create(
4072 32
            URLify::slug(
4073 32
                $str,
4074 32
                $language,
4075 32
                $separator,
4076 32
                $strToLower
4077
            ),
4078 32
            $this->encoding
4079
        );
4080
    }
4081
4082
    /**
4083
     * Converts the string into an valid UTF-8 string.
4084
     *
4085
     * @psalm-mutation-free
4086
     *
4087
     * @return static
4088
     */
4089 2
    public function utf8ify(): self
4090
    {
4091 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
4092
    }
4093
4094
    /**
4095
     * Convert a string into an array of words.
4096
     *
4097
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4098
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4099
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4100
     *
4101
     * @psalm-mutation-free
4102
     *
4103
     * @return static[]
4104
     *
4105
     * @psalm-return array<int,static>
4106
     */
4107 14
    public function words(
4108
        string $char_list = '',
4109
        bool $remove_empty_values = false,
4110
        int $remove_short_values = null
4111
    ): array {
4112 14
        if ($remove_short_values === null) {
4113 14
            $strings = $this->utf8::str_to_words(
4114 14
                $this->str,
4115 14
                $char_list,
4116 14
                $remove_empty_values
4117
            );
4118
        } else {
4119 2
            $strings = $this->utf8::str_to_words(
4120 2
                $this->str,
4121 2
                $char_list,
4122 2
                $remove_empty_values,
4123 2
                $remove_short_values
4124
            );
4125
        }
4126
4127
        /** @noinspection AlterInForeachInspection */
4128 14
        foreach ($strings as &$string) {
4129 14
            $string = static::create($string);
4130
        }
4131
4132
        /** @noinspection PhpSillyAssignmentInspection */
4133
        /** @var static[] $strings */
4134 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...
4135
4136 14
        return $strings;
4137
    }
4138
4139
    /**
4140
     * Convert a string into an collection of words.
4141
     *
4142
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4143
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4144
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4145
     *
4146
     * @psalm-mutation-free
4147
     *
4148
     * @return CollectionStringy|static[]
4149
     *                                    <p>An collection of Stringy objects.</p>
4150
     *
4151
     * @psalm-return CollectionStringy<int,static>
4152
     */
4153 2
    public function wordsCollection(
4154
        string $char_list = '',
4155
        bool $remove_empty_values = false,
4156
        int $remove_short_values = null
4157
    ): CollectionStringy {
4158
        /**
4159
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
4160
         */
4161 2
        return CollectionStringy::create(
4162 2
            $this->words(
4163 2
                $char_list,
4164 2
                $remove_empty_values,
4165 2
                $remove_short_values
4166
            )
4167
        );
4168
    }
4169
4170
    /**
4171
     * Surrounds $str with the given substring.
4172
     *
4173
     * @param string $substring <p>The substring to add to both sides.</P>
4174
     *
4175
     * @psalm-mutation-free
4176
     *
4177
     * @return static
4178
     *                <p>Object whose $str had the substring both prepended and appended.</p>
4179
     */
4180 10
    public function wrap(string $substring): self
4181
    {
4182 10
        return $this->surround($substring);
4183
    }
4184
4185
    /**
4186
     * Returns the replacements for the toAscii() method.
4187
     *
4188
     * @noinspection PhpUnused
4189
     *
4190
     * @psalm-mutation-free
4191
     *
4192
     * @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...
4193
     *                       <p>An array of replacements.</p>
4194
     *
4195
     * @deprecated   this is only here for backward-compatibly reasons
4196
     */
4197 1
    protected function charsArray(): array
4198
    {
4199 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
4200
    }
4201
4202
    /**
4203
     * Returns true if $str matches the supplied pattern, false otherwise.
4204
     *
4205
     * @param string $pattern <p>Regex pattern to match against.</p>
4206
     *
4207
     * @psalm-mutation-free
4208
     *
4209
     * @return bool
4210
     *              <p>Whether or not $str matches the pattern.</p>
4211
     */
4212 24
    protected function matchesPattern(string $pattern): bool
4213
    {
4214 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
4215
    }
4216
}
4217