Completed
Push — master ( 28cb02...b43893 )
by Lars
03:30 queued 11s
created

Stringy::isSerialized()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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

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

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

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

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

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

Loading history...
291
    {
292 7
        $suffixStr = '';
293 7
        foreach ($suffix as $suffixTmp) {
294 7
            if ($suffixTmp instanceof CollectionStringy) {
295 1
                $suffixStr .= $suffixTmp->implode('');
296
            } else {
297 7
                $suffixStr .= $suffixTmp->toString();
298
            }
299
        }
300
301 7
        return static::create($this->str . $suffixStr, $this->encoding);
302
    }
303
304
    /**
305
     * Append an unique identifier.
306
     *
307
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
308
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
309
     *
310
     * @return static
311
     *                <p>Object with appended unique identifier as md5-hash.</p>
312
     */
313 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
314
    {
315 2
        return $this->append(
316 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
317
        );
318
    }
319
320
    /**
321
     * Returns the character at $index, with indexes starting at 0.
322
     *
323
     * @param int $index <p>Position of the character.</p>
324
     *
325
     * @psalm-mutation-free
326
     *
327
     * @return static
328
     *                <p>The character at $index.</p>
329
     */
330 24
    public function at(int $index): self
331
    {
332 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
333
    }
334
335
    /**
336
     * Decode the base64 encoded string.
337
     *
338
     * @psalm-mutation-free
339
     *
340
     * @return self
341
     */
342 2
    public function base64Decode(): self
343
    {
344 2
        return static::create(
345 2
            \base64_decode($this->str, true),
346 2
            $this->encoding
347
        );
348
    }
349
350
    /**
351
     * Encode the string to base64.
352
     *
353
     * @psalm-mutation-free
354
     *
355
     * @return self
356
     */
357 2
    public function base64Encode(): self
358
    {
359 2
        return static::create(
360 2
            \base64_encode($this->str),
361 2
            $this->encoding
362
        );
363
    }
364
365
    /**
366
     * Creates a hash from the string using the CRYPT_BLOWFISH algorithm.
367
     *
368
     * WARNING: Using this algorithm, will result in the ```$this->str```
369
     *          being truncated to a maximum length of 72 characters.
370
     *
371
     * @param array<array-key, int|string> $options [optional] <p>An array of bcrypt hasing options.</p>
372
     *
373
     * @psalm-mutation-free
374
     *
375
     * @return static
376
     */
377 3
    public function bcrypt(array $options = []): self
378
    {
379 3
        return new static(
380 3
            \password_hash(
381 3
                $this->str,
382 3
                \PASSWORD_BCRYPT,
383 3
                $options
384
            ),
385 3
            $this->encoding
386
        );
387
    }
388
389
    /**
390
     * Return part of the string occurring before a specific string.
391
     *
392
     * @param string $string <p>The delimiting string.</p>
393
     *
394
     * @psalm-mutation-free
395
     *
396
     * @return static
397
     */
398 4
    public function before(string $string): self
399
    {
400 4
        $strArray = UTF8::str_split_pattern(
401 4
            $this->str,
402 4
            $string,
403 4
            1
404
        );
405
406 4
        return new static(
407 4
            $strArray[0] ?? '',
408 4
            $this->encoding
409
        );
410
    }
411
412
    /**
413
     * Gets the substring before the first occurrence of a separator.
414
     * If no match is found returns new empty Stringy object.
415
     *
416
     * @param string $separator
417
     *
418
     * @psalm-mutation-free
419
     *
420
     * @return static
421
     */
422 2
    public function beforeFirst(string $separator): self
423
    {
424 2
        return static::create(
425 2
            $this->utf8::str_substr_before_first_separator(
426 2
                $this->str,
427 2
                $separator,
428 2
                $this->encoding
429
            )
430
        );
431
    }
432
433
    /**
434
     * Gets the substring before the first occurrence of a separator.
435
     * If no match is found returns new empty Stringy object.
436
     *
437
     * @param string $separator
438
     *
439
     * @psalm-mutation-free
440
     *
441
     * @return static
442
     */
443 2
    public function beforeFirstIgnoreCase(string $separator): self
444
    {
445 2
        return static::create(
446 2
            $this->utf8::str_isubstr_before_first_separator(
447 2
                $this->str,
448 2
                $separator,
449 2
                $this->encoding
450
            )
451
        );
452
    }
453
454
    /**
455
     * Gets the substring before the last occurrence of a separator.
456
     * If no match is found returns new empty Stringy object.
457
     *
458
     * @param string $separator
459
     *
460
     * @psalm-mutation-free
461
     *
462
     * @return static
463
     */
464 2
    public function beforeLast(string $separator): self
465
    {
466 2
        return static::create(
467 2
            $this->utf8::str_substr_before_last_separator(
468 2
                $this->str,
469 2
                $separator,
470 2
                $this->encoding
471
            )
472
        );
473
    }
474
475
    /**
476
     * Gets the substring before the last occurrence of a separator.
477
     * If no match is found returns new empty Stringy object.
478
     *
479
     * @param string $separator
480
     *
481
     * @psalm-mutation-free
482
     *
483
     * @return static
484
     */
485 2
    public function beforeLastIgnoreCase(string $separator): self
486
    {
487 2
        return static::create(
488 2
            $this->utf8::str_isubstr_before_last_separator(
489 2
                $this->str,
490 2
                $separator,
491 2
                $this->encoding
492
            )
493
        );
494
    }
495
496
    /**
497
     * Returns the substring between $start and $end, if found, or an empty
498
     * string. An optional offset may be supplied from which to begin the
499
     * search for the start string.
500
     *
501
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
502
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
503
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
504
     *
505
     * @psalm-mutation-free
506
     *
507
     * @return static
508
     *                <p>Object whose $str is a substring between $start and $end.</p>
509
     */
510 48
    public function between(string $start, string $end, int $offset = null): self
511
    {
512
        /** @noinspection UnnecessaryCastingInspection */
513 48
        $str = $this->utf8::between(
514 48
            $this->str,
515 48
            $start,
516 48
            $end,
517 48
            (int) $offset,
518 48
            $this->encoding
519
        );
520
521 48
        return static::create($str, $this->encoding);
522
    }
523
524
    /**
525
     * Returns a camelCase version of the string. Trims surrounding spaces,
526
     * capitalizes letters following digits, spaces, dashes and underscores,
527
     * and removes spaces, dashes, as well as underscores.
528
     *
529
     * @psalm-mutation-free
530
     *
531
     * @return static
532
     *                <p>Object with $str in camelCase.</p>
533
     */
534 57
    public function camelize(): self
535
    {
536 57
        return static::create(
537 57
            $this->utf8::str_camelize($this->str, $this->encoding),
538 57
            $this->encoding
539
        );
540
    }
541
542
    /**
543
     * Returns the string with the first letter of each word capitalized,
544
     * except for when the word is a name which shouldn't be capitalized.
545
     *
546
     * @psalm-mutation-free
547
     *
548
     * @return static
549
     *                <p>Object with $str capitalized.</p>
550
     */
551 78
    public function capitalizePersonalName(): self
552
    {
553 78
        return static::create(
554 78
            $this->utf8::str_capitalize_name($this->str),
555 78
            $this->encoding
556
        );
557
    }
558
559
    /**
560
     * Returns an array consisting of the characters in the string.
561
     *
562
     * @psalm-mutation-free
563
     *
564
     * @return string[]
565
     *                  <p>An array of string chars.</p>
566
     */
567 14
    public function chars(): array
568
    {
569
        /** @var string[] */
570 14
        return $this->utf8::str_split($this->str);
571
    }
572
573
    /**
574
     * Splits the string into chunks of Stringy objects.
575
     *
576
     * @param int $length [optional] <p>Max character length of each array element.</p>
577
     *
578
     * @psalm-mutation-free
579
     *
580
     * @return static[]
581
     *                  <p>An array of Stringy objects.</p>
582
     *
583
     * @psalm-return array<int,static>
584
     */
585 13
    public function chunk(int $length = 1): array
586
    {
587 13
        if ($length < 1) {
588
            throw new \InvalidArgumentException('The chunk length must be greater than zero.');
589
        }
590
591 13
        if ($this->str === '') {
592 2
            return [];
593
        }
594
595 11
        $chunks = $this->utf8::str_split($this->str, $length);
596
597
        /** @noinspection AlterInForeachInspection */
598 11
        foreach ($chunks as $i => &$value) {
599 11
            $value = static::create($value, $this->encoding);
600
        }
601
602
        /** @noinspection PhpSillyAssignmentInspection */
603
        /** @var static[] $chunks */
604 11
        $chunks = $chunks;
0 ignored issues
show
Bug introduced by
Why assign $chunks to itself?

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

This assignement can be removed without consequences.

Loading history...
605
606 11
        return $chunks;
607
    }
608
609
    /**
610
     * Splits the string into chunks of Stringy objects collection.
611
     *
612
     * @param int $length [optional] <p>Max character length of each array element.</p>
613
     *
614
     * @psalm-mutation-free
615
     *
616
     * @return CollectionStringy|static[]
617
     *                                    <p>An collection of Stringy objects.</p>
618
     *
619
     * @psalm-return CollectionStringy<int,static>
620
     */
621 7
    public function chunkCollection(int $length = 1): CollectionStringy
622
    {
623
        /**
624
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
625
         */
626 7
        return CollectionStringy::create(
627 7
            $this->chunk($length)
628
        );
629
    }
630
631
    /**
632
     * Trims the string and replaces consecutive whitespace characters with a
633
     * single space. This includes tabs and newline characters, as well as
634
     * multibyte whitespace such as the thin space and ideographic space.
635
     *
636
     * @psalm-mutation-free
637
     *
638
     * @return static
639
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
640
     */
641 39
    public function collapseWhitespace(): self
642
    {
643 39
        return static::create(
644 39
            $this->utf8::collapse_whitespace($this->str),
645 39
            $this->encoding
646
        );
647
    }
648
649
    /**
650
     * Returns true if the string contains $needle, false otherwise. By default
651
     * the comparison is case-sensitive, but can be made insensitive by setting
652
     * $caseSensitive to false.
653
     *
654
     * @param string $needle        <p>Substring to look for.</p>
655
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
656
     *
657
     * @psalm-mutation-free
658
     *
659
     * @return bool
660
     *              <p>Whether or not $str contains $needle.</p>
661
     */
662 63
    public function contains(string $needle, bool $caseSensitive = true): bool
663
    {
664 63
        return $this->utf8::str_contains(
665 63
            $this->str,
666 63
            $needle,
667 63
            $caseSensitive
668
        );
669
    }
670
671
    /**
672
     * Returns true if the string contains all $needles, false otherwise. By
673
     * default the comparison is case-sensitive, but can be made insensitive by
674
     * setting $caseSensitive to false.
675
     *
676
     * @param string[] $needles       <p>SubStrings to look for.</p>
677
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
678
     *
679
     * @psalm-mutation-free
680
     *
681
     * @return bool
682
     *              <p>Whether or not $str contains $needle.</p>
683
     */
684 131
    public function containsAll(array $needles, bool $caseSensitive = true): bool
685
    {
686 131
        return $this->utf8::str_contains_all(
687 131
            $this->str,
688 131
            $needles,
689 131
            $caseSensitive
690
        );
691
    }
692
693
    /**
694
     * Returns true if the string contains any $needles, false otherwise. By
695
     * default the comparison is case-sensitive, but can be made insensitive by
696
     * setting $caseSensitive to false.
697
     *
698
     * @param string[] $needles       <p>SubStrings to look for.</p>
699
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
700
     *
701
     * @psalm-mutation-free
702
     *
703
     * @return bool
704
     *              <p>Whether or not $str contains $needle.</p>
705
     */
706 129
    public function containsAny(array $needles, bool $caseSensitive = true): bool
707
    {
708 129
        return $this->utf8::str_contains_any(
709 129
            $this->str,
710 129
            $needles,
711 129
            $caseSensitive
712
        );
713
    }
714
715
    /**
716
     * Returns the length of the string, implementing the countable interface.
717
     *
718
     * @psalm-mutation-free
719
     *
720
     * @return int
721
     *             <p>The number of characters in the string, given the encoding.</p>
722
     */
723 3
    public function count(): int
724
    {
725 3
        return $this->length();
726
    }
727
728
    /**
729
     * Returns the number of occurrences of $substring in the given string.
730
     * By default, the comparison is case-sensitive, but can be made insensitive
731
     * by setting $caseSensitive to false.
732
     *
733
     * @param string $substring     <p>The substring to search for.</p>
734
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
735
     *
736
     * @psalm-mutation-free
737
     *
738
     * @return int
739
     */
740 45
    public function countSubstr(string $substring, bool $caseSensitive = true): int
741
    {
742 45
        return $this->utf8::substr_count_simple(
743 45
            $this->str,
744 45
            $substring,
745 45
            $caseSensitive,
746 45
            $this->encoding
747
        );
748
    }
749
750
    /**
751
     * Calculates the crc32 polynomial of a string.
752
     *
753
     * @psalm-mutation-free
754
     *
755
     * @return int
756
     */
757 2
    public function crc32(): int
758
    {
759 2
        return \crc32($this->str);
760
    }
761
762
    /**
763
     * Creates a Stringy object and assigns both str and encoding properties
764
     * the supplied values. $str is cast to a string prior to assignment, and if
765
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
766
     * then returns the initialized object. Throws an InvalidArgumentException
767
     * if the first argument is an array or object without a __toString method.
768
     *
769
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
770
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
771
     *
772
     * @throws \InvalidArgumentException
773
     *                                   <p>if an array or object without a
774
     *                                   __toString method is passed as the first argument</p>
775
     *
776
     * @return static
777
     *                <p>A Stringy object.</p>
778
     * @psalm-pure
779
     */
780 3565
    public static function create($str = '', string $encoding = null): self
781
    {
782 3565
        return new static($str, $encoding);
783
    }
784
785
    /**
786
     * One-way string encryption (hashing).
787
     *
788
     * Hash the string using the standard Unix DES-based algorithm or an
789
     * alternative algorithm that may be available on the system.
790
     *
791
     * PS: if you need encrypt / decrypt, please use use ```static::encrypt($password)```
792
     *     and ```static::decrypt($password)```
793
     *
794
     * @param string $salt <p>A salt string to base the hashing on.</p>
795
     *
796
     * @psalm-mutation-free
797
     *
798
     * @return static
799
     */
800 3
    public function crypt(string $salt): self
801
    {
802 3
        return new static(
803 3
            \crypt(
804 3
                $this->str,
805 3
                $salt
806
            ),
807 3
            $this->encoding
808
        );
809
    }
810
811
    /**
812
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
813
     * inserted before uppercase characters (with the exception of the first
814
     * character of the string), and in place of spaces as well as underscores.
815
     *
816
     * @psalm-mutation-free
817
     *
818
     * @return static
819
     *                <p>Object with a dasherized $str</p>
820
     */
821 57
    public function dasherize(): self
822
    {
823 57
        return static::create(
824 57
            $this->utf8::str_dasherize($this->str),
825 57
            $this->encoding
826
        );
827
    }
828
829
    /**
830
     * Decrypt the string.
831
     *
832
     * @param string $password The key for decrypting
833
     *
834
     * @psalm-mutation-free
835
     *
836
     * @return static
837
     */
838 5
    public function decrypt(string $password): self
839
    {
840
        /**
841
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff
842
         */
843 5
        return new static(
844 5
            Crypto::decryptWithPassword($this->str, $password),
845 3
            $this->encoding
846
        );
847
    }
848
849
    /**
850
     * Returns a lowercase and trimmed string separated by the given delimiter.
851
     * Delimiters are inserted before uppercase characters (with the exception
852
     * of the first character of the string), and in place of spaces, dashes,
853
     * and underscores. Alpha delimiters are not converted to lowercase.
854
     *
855
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
856
     *
857
     * @psalm-mutation-free
858
     *
859
     * @return static
860
     *                <p>Object with a delimited $str.</p>
861
     */
862 90
    public function delimit(string $delimiter): self
863
    {
864 90
        return static::create(
865 90
            $this->utf8::str_delimit($this->str, $delimiter),
866 90
            $this->encoding
867
        );
868
    }
869
870
    /**
871
     * Encode the given string into the given $encoding + set the internal character encoding
872
     *
873
     * @param string $new_encoding         <p>The desired character encoding.</p>
874
     * @param bool   $auto_detect_encoding [optional] <p>Auto-detect the current string-encoding</p>
875
     *
876
     * @psalm-mutation-free
877
     *
878
     * @return static
879
     */
880 2
    public function encode(string $new_encoding, bool $auto_detect_encoding = false): self
881
    {
882 2
        if ($auto_detect_encoding) {
883 1
            $str = $this->utf8::encode(
884 1
                $new_encoding,
885 1
                $this->str
886
            );
887
        } else {
888 1
            $str = $this->utf8::encode(
889 1
                $new_encoding,
890 1
                $this->str,
891 1
                false,
892 1
                $this->encoding
893
            );
894
        }
895
896 2
        return new static($str, $new_encoding);
897
    }
898
899
    /**
900
     * Encrypt the string.
901
     *
902
     * @param string $password <p>The key for encrypting</p>
903
     *
904
     * @psalm-mutation-free
905
     *
906
     * @return static
907
     */
908 4
    public function encrypt(string $password): self
909
    {
910
        /**
911
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff
912
         */
913 4
        return new static(
914 4
            Crypto::encryptWithPassword($this->str, $password),
915 4
            $this->encoding
916
        );
917
    }
918
919
    /**
920
     * Returns true if the string ends with $substring, false otherwise. By
921
     * default, the comparison is case-sensitive, but can be made insensitive
922
     * by setting $caseSensitive to false.
923
     *
924
     * @param string $substring     <p>The substring to look for.</p>
925
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
926
     *
927
     * @psalm-mutation-free
928
     *
929
     * @return bool
930
     *              <p>Whether or not $str ends with $substring.</p>
931
     */
932 97
    public function endsWith(string $substring, bool $caseSensitive = true): bool
933
    {
934 97
        if ($caseSensitive) {
935 53
            return $this->utf8::str_ends_with($this->str, $substring);
936
        }
937
938 44
        return $this->utf8::str_iends_with($this->str, $substring);
939
    }
940
941
    /**
942
     * Returns true if the string ends with any of $substrings, false otherwise.
943
     * By default, the comparison is case-sensitive, but can be made insensitive
944
     * by setting $caseSensitive to false.
945
     *
946
     * @param string[] $substrings    <p>Substrings to look for.</p>
947
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
948
     *
949
     * @psalm-mutation-free
950
     *
951
     * @return bool
952
     *              <p>Whether or not $str ends with $substring.</p>
953
     */
954 33
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
955
    {
956 33
        if ($caseSensitive) {
957 21
            return $this->utf8::str_ends_with_any($this->str, $substrings);
958
        }
959
960 12
        return $this->utf8::str_iends_with_any($this->str, $substrings);
961
    }
962
963
    /**
964
     * Ensures that the string begins with $substring. If it doesn't, it's
965
     * prepended.
966
     *
967
     * @param string $substring <p>The substring to add if not present.</p>
968
     *
969
     * @psalm-mutation-free
970
     *
971
     * @return static
972
     *                <p>Object with its $str prefixed by the $substring.</p>
973
     */
974 30
    public function ensureLeft(string $substring): self
975
    {
976 30
        return static::create(
977 30
            $this->utf8::str_ensure_left($this->str, $substring),
978 30
            $this->encoding
979
        );
980
    }
981
982
    /**
983
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
984
     *
985
     * @param string $substring <p>The substring to add if not present.</p>
986
     *
987
     * @psalm-mutation-free
988
     *
989
     * @return static
990
     *                <p>Object with its $str suffixed by the $substring.</p>
991
     */
992 30
    public function ensureRight(string $substring): self
993
    {
994 30
        return static::create(
995 30
            $this->utf8::str_ensure_right($this->str, $substring),
996 30
            $this->encoding
997
        );
998
    }
999
1000
    /**
1001
     * Create a escape html version of the string via "htmlspecialchars()".
1002
     *
1003
     * @psalm-mutation-free
1004
     *
1005
     * @return static
1006
     */
1007 12
    public function escape(): self
1008
    {
1009 12
        return static::create(
1010 12
            $this->utf8::htmlspecialchars(
1011 12
                $this->str,
1012 12
                \ENT_QUOTES | \ENT_SUBSTITUTE,
1013 12
                $this->encoding
1014
            ),
1015 12
            $this->encoding
1016
        );
1017
    }
1018
1019
    /**
1020
     * Split a string by a string.
1021
     *
1022
     * @param string $delimiter <p>The boundary string</p>
1023
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1024
     *                          collection.</p>
1025
     *
1026
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1027
     *   element containing the rest of string.
1028
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1029
     *   - If the limit parameter is zero, then this is treated as 1
1030
     *
1031
     * @psalm-mutation-free
1032
     *
1033
     * @return array<int,static>
1034
     */
1035 3
    public function explode(string $delimiter, int $limit = \PHP_INT_MAX): array
1036
    {
1037 3
        if ($this->str === '') {
1038
            return [];
1039
        }
1040
1041 3
        $strings = \explode($delimiter, $this->str, $limit);
1042 3
        if ($strings === false) {
1043
            $strings = [];
1044
        }
1045
1046 3
        $strings = \array_map(
1047
            function ($str) {
1048 3
                return new static($str, $this->encoding);
1049 3
            },
1050 3
            $strings
1051
        );
1052
1053
        /** @var static[] $strings */
1054 3
        return $strings;
1055
    }
1056
1057
    /**
1058
     * Split a string by a string.
1059
     *
1060
     * @param string $delimiter <p>The boundary string</p>
1061
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1062
     *                          collection.</p>
1063
     *
1064
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1065
     *   element containing the rest of string.
1066
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1067
     *   - If the limit parameter is zero, then this is treated as 1
1068
     *
1069
     * @psalm-mutation-free
1070
     *
1071
     * @return CollectionStringy|static[]
1072
     *                                    <p>An collection of Stringy objects.</p>
1073
     *
1074
     * @psalm-return CollectionStringy<int,static>
1075
     */
1076 1
    public function explodeCollection(string $delimiter, int $limit = \PHP_INT_MAX): CollectionStringy
1077
    {
1078
        /**
1079
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
1080
         */
1081 1
        return CollectionStringy::create(
1082 1
            $this->explode($delimiter, $limit)
1083
        );
1084
    }
1085
1086
    /**
1087
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
1088
     *
1089
     * @param string   $search
1090
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
1091
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
1092
     *
1093
     * @psalm-mutation-free
1094
     *
1095
     * @return static
1096
     */
1097 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
1098
    {
1099 2
        return static::create(
1100 2
            $this->utf8::extract_text(
1101 2
                $this->str,
1102 2
                $search,
1103 2
                $length,
1104 2
                $replacerForSkippedText,
1105 2
                $this->encoding
1106
            ),
1107 2
            $this->encoding
1108
        );
1109
    }
1110
1111
    /**
1112
     * Returns the first $n characters of the string.
1113
     *
1114
     * @param int $n <p>Number of characters to retrieve from the start.</p>
1115
     *
1116
     * @psalm-mutation-free
1117
     *
1118
     * @return static
1119
     *                <p>Object with its $str being the first $n chars.</p>
1120
     */
1121 37
    public function first(int $n): self
1122
    {
1123 37
        return static::create(
1124 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
1125 37
            $this->encoding
1126
        );
1127
    }
1128
1129
    /**
1130
     * Return a formatted string via sprintf + named parameters via array syntax.
1131
     *
1132
     * <p>
1133
     * <br>
1134
     * It will use "sprintf()" so you can use e.g.:
1135
     * <br>
1136
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
1137
     * <br>
1138
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
1139
     * <br>
1140
     * <br>
1141
     * But you can also use named parameter via array syntax e.g.:
1142
     * <br>
1143
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
1144
     * </p>
1145
     *
1146
     * @param mixed ...$args [optional]
1147
     *
1148
     * @psalm-mutation-free
1149
     *
1150
     * @return static
1151
     *                <p>A Stringy object produced according to the formatting string
1152
     *                format.</p>
1153
     */
1154 10
    public function format(...$args): self
1155
    {
1156
        // init
1157 10
        $str = $this->str;
1158
1159 10
        if (\strpos($this->str, '%:') !== false) {
1160 8
            $offset = null;
1161 8
            $replacement = null;
1162
            /** @noinspection AlterInForeachInspection */
1163 8
            foreach ($args as $key => &$arg) {
1164 8
                if (!\is_array($arg)) {
1165 4
                    continue;
1166
                }
1167
1168 8
                foreach ($arg as $name => $param) {
1169 8
                    $name = (string) $name;
1170
1171 8
                    if (\strpos($name, '%:') !== 0) {
1172 8
                        $nameTmp = '%:' . $name;
1173
                    } else {
1174
                        $nameTmp = $name;
1175
                    }
1176
1177 8
                    if ($offset === null) {
1178 8
                        $offset = \strpos($str, $nameTmp);
1179
                    } else {
1180 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
1181
                    }
1182 8
                    if ($offset === false) {
1183 4
                        continue;
1184
                    }
1185
1186 8
                    unset($arg[$name]);
1187
1188 8
                    $str = \substr_replace($str, $param, (int) $offset, \strlen($nameTmp));
1189
                }
1190
1191 8
                unset($args[$key]);
1192
            }
1193
        }
1194
1195 10
        $str = \str_replace('%:', '%%:', $str);
1196
1197 10
        return static::create(
1198 10
            \sprintf($str, ...$args),
1199 10
            $this->encoding
1200
        );
1201
    }
1202
1203
    /**
1204
     * Returns the encoding used by the Stringy object.
1205
     *
1206
     * @psalm-mutation-free
1207
     *
1208
     * @return string
1209
     *                <p>The current value of the $encoding property.</p>
1210
     */
1211 7
    public function getEncoding(): string
1212
    {
1213 7
        return $this->encoding;
1214
    }
1215
1216
    /**
1217
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
1218
     * interface. The ArrayIterator's constructor is passed an array of chars
1219
     * in the multibyte string. This enables the use of foreach with instances
1220
     * of Stringy\Stringy.
1221
     *
1222
     * @psalm-mutation-free
1223
     *
1224
     * @return \ArrayIterator
1225
     *                        <p>An iterator for the characters in the string.</p>
1226
     *
1227
     * @psalm-return \ArrayIterator<array-key,string>
1228
     */
1229 3
    public function getIterator(): \ArrayIterator
1230
    {
1231 3
        return new \ArrayIterator($this->chars());
1232
    }
1233
1234
    /**
1235
     * Wrap the string after an exact number of characters.
1236
     *
1237
     * @param int    $width <p>Number of characters at which to wrap.</p>
1238
     * @param string $break [optional] <p>Character used to break the string. | Default: "\n"</p>
1239
     *
1240
     * @psalm-mutation-free
1241
     *
1242
     * @return static
1243
     */
1244 2
    public function hardWrap($width, $break = "\n"): self
1245
    {
1246 2
        return $this->lineWrap($width, $break, false);
1247
    }
1248
1249
    /**
1250
     * Returns true if the string contains a lower case char, false otherwise.
1251
     *
1252
     * @psalm-mutation-free
1253
     *
1254
     * @return bool
1255
     *              <p>Whether or not the string contains a lower case character.</p>
1256
     */
1257 36
    public function hasLowerCase(): bool
1258
    {
1259 36
        return $this->utf8::has_lowercase($this->str);
1260
    }
1261
1262
    /**
1263
     * Returns true if the string contains an upper case char, false otherwise.
1264
     *
1265
     * @psalm-mutation-free
1266
     *
1267
     * @return bool
1268
     *              <p>Whether or not the string contains an upper case character.</p>
1269
     */
1270 36
    public function hasUpperCase(): bool
1271
    {
1272 36
        return $this->utf8::has_uppercase($this->str);
1273
    }
1274
1275
    /**
1276
     * Generate a hash value (message digest)
1277
     *
1278
     * @see https://php.net/manual/en/function.hash.php
1279
     *
1280
     * @param string $algorithm
1281
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
1282
     *
1283
     * @psalm-mutation-free
1284
     *
1285
     * @return static
1286
     */
1287 8
    public function hash($algorithm): self
1288
    {
1289 8
        return static::create(\hash($algorithm, $this->str), $this->encoding);
1290
    }
1291
1292
    /**
1293
     * Decode the string from hex.
1294
     *
1295
     * @psalm-mutation-free
1296
     *
1297
     * @return static
1298
     */
1299 2
    public function hexDecode(): self
1300
    {
1301 2
        $string = \preg_replace_callback(
1302 2
            '/\\\\x([0-9A-Fa-f]+)/',
1303
            function (array $matched) {
1304 2
                return (string) $this->utf8::hex_to_chr($matched[1]);
1305 2
            },
1306 2
            $this->str
1307
        );
1308
1309 2
        return static::create(
1310 2
            $string,
1311 2
            $this->encoding
1312
        );
1313
    }
1314
1315
    /**
1316
     * Encode string to hex.
1317
     *
1318
     * @psalm-mutation-free
1319
     *
1320
     * @return static
1321
     */
1322 2
    public function hexEncode(): self
1323
    {
1324 2
        $string = \array_reduce(
1325 2
            $this->chars(),
1326
            function (string $str, string $char) {
1327 2
                return $str . $this->utf8::chr_to_hex($char);
1328 2
            },
1329 2
            ''
1330
        );
1331
1332 2
        return static::create(
1333 2
            $string,
1334 2
            $this->encoding
1335
        );
1336
    }
1337
1338
    /**
1339
     * Convert all HTML entities to their applicable characters.
1340
     *
1341
     * @param int $flags [optional] <p>
1342
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1343
     *                   which document type to use. The default is ENT_COMPAT.
1344
     *                   <table>
1345
     *                   Available <i>flags</i> constants
1346
     *                   <tr valign="top">
1347
     *                   <td>Constant Name</td>
1348
     *                   <td>Description</td>
1349
     *                   </tr>
1350
     *                   <tr valign="top">
1351
     *                   <td><b>ENT_COMPAT</b></td>
1352
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1353
     *                   </tr>
1354
     *                   <tr valign="top">
1355
     *                   <td><b>ENT_QUOTES</b></td>
1356
     *                   <td>Will convert both double and single quotes.</td>
1357
     *                   </tr>
1358
     *                   <tr valign="top">
1359
     *                   <td><b>ENT_NOQUOTES</b></td>
1360
     *                   <td>Will leave both double and single quotes unconverted.</td>
1361
     *                   </tr>
1362
     *                   <tr valign="top">
1363
     *                   <td><b>ENT_HTML401</b></td>
1364
     *                   <td>
1365
     *                   Handle code as HTML 4.01.
1366
     *                   </td>
1367
     *                   </tr>
1368
     *                   <tr valign="top">
1369
     *                   <td><b>ENT_XML1</b></td>
1370
     *                   <td>
1371
     *                   Handle code as XML 1.
1372
     *                   </td>
1373
     *                   </tr>
1374
     *                   <tr valign="top">
1375
     *                   <td><b>ENT_XHTML</b></td>
1376
     *                   <td>
1377
     *                   Handle code as XHTML.
1378
     *                   </td>
1379
     *                   </tr>
1380
     *                   <tr valign="top">
1381
     *                   <td><b>ENT_HTML5</b></td>
1382
     *                   <td>
1383
     *                   Handle code as HTML 5.
1384
     *                   </td>
1385
     *                   </tr>
1386
     *                   </table>
1387
     *                   </p>
1388
     *
1389
     * @psalm-mutation-free
1390
     *
1391
     * @return static
1392
     *                <p>Object with the resulting $str after being html decoded.</p>
1393
     */
1394 15 View Code Duplication
    public function htmlDecode(int $flags = \ENT_COMPAT): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1395
    {
1396 15
        return static::create(
1397 15
            $this->utf8::html_entity_decode(
1398 15
                $this->str,
1399 15
                $flags,
1400 15
                $this->encoding
1401
            ),
1402 15
            $this->encoding
1403
        );
1404
    }
1405
1406
    /**
1407
     * Convert all applicable characters to HTML entities.
1408
     *
1409
     * @param int $flags [optional] <p>
1410
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1411
     *                   which document type to use. The default is ENT_COMPAT.
1412
     *                   <table>
1413
     *                   Available <i>flags</i> constants
1414
     *                   <tr valign="top">
1415
     *                   <td>Constant Name</td>
1416
     *                   <td>Description</td>
1417
     *                   </tr>
1418
     *                   <tr valign="top">
1419
     *                   <td><b>ENT_COMPAT</b></td>
1420
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1421
     *                   </tr>
1422
     *                   <tr valign="top">
1423
     *                   <td><b>ENT_QUOTES</b></td>
1424
     *                   <td>Will convert both double and single quotes.</td>
1425
     *                   </tr>
1426
     *                   <tr valign="top">
1427
     *                   <td><b>ENT_NOQUOTES</b></td>
1428
     *                   <td>Will leave both double and single quotes unconverted.</td>
1429
     *                   </tr>
1430
     *                   <tr valign="top">
1431
     *                   <td><b>ENT_HTML401</b></td>
1432
     *                   <td>
1433
     *                   Handle code as HTML 4.01.
1434
     *                   </td>
1435
     *                   </tr>
1436
     *                   <tr valign="top">
1437
     *                   <td><b>ENT_XML1</b></td>
1438
     *                   <td>
1439
     *                   Handle code as XML 1.
1440
     *                   </td>
1441
     *                   </tr>
1442
     *                   <tr valign="top">
1443
     *                   <td><b>ENT_XHTML</b></td>
1444
     *                   <td>
1445
     *                   Handle code as XHTML.
1446
     *                   </td>
1447
     *                   </tr>
1448
     *                   <tr valign="top">
1449
     *                   <td><b>ENT_HTML5</b></td>
1450
     *                   <td>
1451
     *                   Handle code as HTML 5.
1452
     *                   </td>
1453
     *                   </tr>
1454
     *                   </table>
1455
     *                   </p>
1456
     *
1457
     * @psalm-mutation-free
1458
     *
1459
     * @return static
1460
     *                <p>Object with the resulting $str after being html encoded.</p>
1461
     */
1462 15 View Code Duplication
    public function htmlEncode(int $flags = \ENT_COMPAT): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1463
    {
1464 15
        return static::create(
1465 15
            $this->utf8::htmlentities(
1466 15
                $this->str,
1467 15
                $flags,
1468 15
                $this->encoding
1469
            ),
1470 15
            $this->encoding
1471
        );
1472
    }
1473
1474
    /**
1475
     * Capitalizes the first word of the string, replaces underscores with
1476
     * spaces, and strips '_id'.
1477
     *
1478
     * @psalm-mutation-free
1479
     *
1480
     * @return static
1481
     *                <p>Object with a humanized $str.</p>
1482
     */
1483 9
    public function humanize(): self
1484
    {
1485 9
        return static::create(
1486 9
            $this->utf8::str_humanize($this->str),
1487 9
            $this->encoding
1488
        );
1489
    }
1490
1491
    /**
1492
     * Determine if the current string exists in another string. By
1493
     * default, the comparison is case-sensitive, but can be made insensitive
1494
     * by setting $caseSensitive to false.
1495
     *
1496
     * @param string $str           <p>The string to compare against.</p>
1497
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1498
     *
1499
     * @psalm-mutation-free
1500
     *
1501
     * @return bool
1502
     */
1503 3
    public function in(string $str, bool $caseSensitive = true): bool
1504
    {
1505 3
        if ($caseSensitive) {
1506 2
            return \strpos($str, $this->str) !== false;
1507
        }
1508
1509 1
        return \stripos($str, $this->str) !== false;
1510
    }
1511
1512
    /**
1513
     * Returns the index of the first occurrence of $needle in the string,
1514
     * and false if not found. Accepts an optional offset from which to begin
1515
     * the search.
1516
     *
1517
     * @param string $needle <p>Substring to look for.</p>
1518
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1519
     *
1520
     * @psalm-mutation-free
1521
     *
1522
     * @return false|int
1523
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1524
     */
1525 31
    public function indexOf(string $needle, int $offset = 0)
1526
    {
1527 31
        return $this->utf8::strpos(
1528 31
            $this->str,
1529 31
            $needle,
1530 31
            $offset,
1531 31
            $this->encoding
1532
        );
1533
    }
1534
1535
    /**
1536
     * Returns the index of the first occurrence of $needle in the string,
1537
     * and false if not found. Accepts an optional offset from which to begin
1538
     * the search.
1539
     *
1540
     * @param string $needle <p>Substring to look for.</p>
1541
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1542
     *
1543
     * @psalm-mutation-free
1544
     *
1545
     * @return false|int
1546
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1547
     */
1548 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1549
    {
1550 20
        return $this->utf8::stripos(
1551 20
            $this->str,
1552 20
            $needle,
1553 20
            $offset,
1554 20
            $this->encoding
1555
        );
1556
    }
1557
1558
    /**
1559
     * Returns the index of the last occurrence of $needle in the string,
1560
     * and false if not found. Accepts an optional offset from which to begin
1561
     * the search. Offsets may be negative to count from the last character
1562
     * in the string.
1563
     *
1564
     * @param string $needle <p>Substring to look for.</p>
1565
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1566
     *
1567
     * @psalm-mutation-free
1568
     *
1569
     * @return false|int
1570
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1571
     */
1572 31
    public function indexOfLast(string $needle, int $offset = 0)
1573
    {
1574 31
        return $this->utf8::strrpos(
1575 31
            $this->str,
1576 31
            $needle,
1577 31
            $offset,
1578 31
            $this->encoding
1579
        );
1580
    }
1581
1582
    /**
1583
     * Returns the index of the last occurrence of $needle in the string,
1584
     * and false if not found. Accepts an optional offset from which to begin
1585
     * the search. Offsets may be negative to count from the last character
1586
     * in the string.
1587
     *
1588
     * @param string $needle <p>Substring to look for.</p>
1589
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1590
     *
1591
     * @psalm-mutation-free
1592
     *
1593
     * @return false|int
1594
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1595
     */
1596 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1597
    {
1598 20
        return $this->utf8::strripos(
1599 20
            $this->str,
1600 20
            $needle,
1601 20
            $offset,
1602 20
            $this->encoding
1603
        );
1604
    }
1605
1606
    /**
1607
     * Inserts $substring into the string at the $index provided.
1608
     *
1609
     * @param string $substring <p>String to be inserted.</p>
1610
     * @param int    $index     <p>The index at which to insert the substring.</p>
1611
     *
1612
     * @psalm-mutation-free
1613
     *
1614
     * @return static
1615
     *                <p>Object with the resulting $str after the insertion.</p>
1616
     */
1617 24
    public function insert(string $substring, int $index): self
1618
    {
1619 24
        return static::create(
1620 24
            $this->utf8::str_insert(
1621 24
                $this->str,
1622 24
                $substring,
1623 24
                $index,
1624 24
                $this->encoding
1625
            ),
1626 24
            $this->encoding
1627
        );
1628
    }
1629
1630
    /**
1631
     * Returns true if the string contains the $pattern, otherwise false.
1632
     *
1633
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1634
     * expression wildcards.
1635
     *
1636
     * @credit Originally from Laravel, thanks Taylor.
1637
     *
1638
     * @param string $pattern <p>The string or pattern to match against.</p>
1639
     *
1640
     * @psalm-mutation-free
1641
     *
1642
     * @return bool
1643
     *              <p>Whether or not we match the provided pattern.</p>
1644
     */
1645 26
    public function is(string $pattern): bool
1646
    {
1647 26
        if ($this->toString() === $pattern) {
1648 2
            return true;
1649
        }
1650
1651 24
        $quotedPattern = \preg_quote($pattern, '/');
1652 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1653
1654 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1655
    }
1656
1657
    /**
1658
     * Returns true if the string contains only alphabetic chars, false otherwise.
1659
     *
1660
     * @psalm-mutation-free
1661
     *
1662
     * @return bool
1663
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1664
     */
1665 30
    public function isAlpha(): bool
1666
    {
1667 30
        return $this->utf8::is_alpha($this->str);
1668
    }
1669
1670
    /**
1671
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1672
     *
1673
     * @psalm-mutation-free
1674
     *
1675
     * @return bool
1676
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1677
     */
1678 39
    public function isAlphanumeric(): bool
1679
    {
1680 39
        return $this->utf8::is_alphanumeric($this->str);
1681
    }
1682
1683
    /**
1684
     * Returns true if the string is base64 encoded, false otherwise.
1685
     *
1686
     * @param bool $emptyStringIsValid
1687
     *
1688
     * @psalm-mutation-free
1689
     *
1690
     * @return bool
1691
     *              <p>Whether or not $str is base64 encoded.</p>
1692
     */
1693 21
    public function isBase64($emptyStringIsValid = true): bool
1694
    {
1695 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
1696
    }
1697
1698
    /**
1699
     * Returns true if the string contains only whitespace chars, false otherwise.
1700
     *
1701
     * @psalm-mutation-free
1702
     *
1703
     * @return bool
1704
     *              <p>Whether or not $str contains only whitespace characters.</p>
1705
     */
1706 45
    public function isBlank(): bool
1707
    {
1708 45
        return $this->utf8::is_blank($this->str);
1709
    }
1710
1711
    /**
1712
     * Returns true if the string contains a valid E-Mail address, false otherwise.
1713
     *
1714
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
1715
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
1716
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
1717
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
1718
     *
1719
     * @psalm-mutation-free
1720
     *
1721
     * @return bool
1722
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
1723
     */
1724 2
    public function isEmail(
1725
        bool $useExampleDomainCheck = false,
1726
        bool $useTypoInDomainCheck = false,
1727
        bool $useTemporaryDomainCheck = false,
1728
        bool $useDnsCheck = false
1729
    ): bool {
1730
        /**
1731
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
1732
         */
1733 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
1734
    }
1735
1736
    /**
1737
     * Determine whether the string is considered to be empty.
1738
     *
1739
     * A variable is considered empty if it does not exist or if its value equals FALSE.
1740
     *
1741
     * @psalm-mutation-free
1742
     *
1743
     * @return bool
1744
     *              <p>Whether or not $str is empty().</p>
1745
     */
1746 10
    public function isEmpty(): bool
1747
    {
1748 10
        return $this->utf8::is_empty($this->str);
1749
    }
1750
1751
    /**
1752
     * Determine whether the string is equals to $str.
1753
     * Alias for isEqualsCaseSensitive()
1754
     *
1755
     * @param string|Stringy ...$str
1756
     *
1757
     * @psalm-mutation-free
1758
     *
1759
     * @return bool
1760
     */
1761 13
    public function isEquals(...$str): bool
1762
    {
1763 13
        return $this->isEqualsCaseSensitive(...$str);
1764
    }
1765
1766
    /**
1767
     * Determine whether the string is equals to $str.
1768
     *
1769
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1770
     *
1771
     * @psalm-mutation-free
1772
     *
1773
     * @return bool
1774
     *              <p>Whether or not $str is equals.</p>
1775
     */
1776 3
    public function isEqualsCaseInsensitive(...$str): bool
1777
    {
1778 3
        $strUpper = $this->toUpperCase()->str;
1779
1780 3 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1781
            /**
1782
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1783
             */
1784 3
            if ($strTmp instanceof self) {
1785
                if ($strUpper !== $strTmp->toUpperCase()) {
1786
                    return false;
1787
                }
1788 3
            } elseif (\is_scalar($strTmp)) {
1789 3
                if ($strUpper !== $this->utf8::strtoupper((string) $strTmp, $this->encoding)) {
1790 3
                    return false;
1791
                }
1792
            } else {
1793 3
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1794
            }
1795
        }
1796
1797 3
        return true;
1798
    }
1799
1800
    /**
1801
     * Determine whether the string is equals to $str.
1802
     *
1803
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1804
     *
1805
     * @psalm-mutation-free
1806
     *
1807
     * @return bool
1808
     *              <p>Whether or not $str is equals.</p>
1809
     */
1810 14
    public function isEqualsCaseSensitive(...$str): bool
1811
    {
1812 14 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1813
            /**
1814
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1815
             */
1816 14
            if ($strTmp instanceof self) {
1817 2
                if ($this->str !== $strTmp->str) {
1818 2
                    return false;
1819
                }
1820 12
            } elseif (\is_scalar($strTmp)) {
1821 12
                if ($this->str !== (string) $strTmp) {
1822 12
                    return false;
1823
                }
1824
            } else {
1825 3
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1826
            }
1827
        }
1828
1829 3
        return true;
1830
    }
1831
1832
    /**
1833
     * Returns true if the string contains only hexadecimal chars, false otherwise.
1834
     *
1835
     * @psalm-mutation-free
1836
     *
1837
     * @return bool
1838
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
1839
     */
1840 39
    public function isHexadecimal(): bool
1841
    {
1842 39
        return $this->utf8::is_hexadecimal($this->str);
1843
    }
1844
1845
    /**
1846
     * Returns true if the string contains HTML-Tags, false otherwise.
1847
     *
1848
     * @psalm-mutation-free
1849
     *
1850
     * @return bool
1851
     *              <p>Whether or not $str contains HTML-Tags.</p>
1852
     */
1853 2
    public function isHtml(): bool
1854
    {
1855 2
        return $this->utf8::is_html($this->str);
1856
    }
1857
1858
    /**
1859
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
1860
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
1861
     * in that an empty string is not considered valid JSON.
1862
     *
1863
     * @param bool $onlyArrayOrObjectResultsAreValid
1864
     *
1865
     * @psalm-mutation-free
1866
     *
1867
     * @return bool
1868
     *              <p>Whether or not $str is JSON.</p>
1869
     */
1870 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
1871
    {
1872
        /**
1873
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff?
1874
         */
1875 60
        return $this->utf8::is_json(
1876 60
            $this->str,
1877 60
            $onlyArrayOrObjectResultsAreValid
1878
        );
1879
    }
1880
1881
    /**
1882
     * Returns true if the string contains only lower case chars, false otherwise.
1883
     *
1884
     * @psalm-mutation-free
1885
     *
1886
     * @return bool
1887
     *              <p>Whether or not $str contains only lower case characters.</p>
1888
     */
1889 24
    public function isLowerCase(): bool
1890
    {
1891 24
        return $this->utf8::is_lowercase($this->str);
1892
    }
1893
1894
    /**
1895
     * Determine whether the string is considered to be NOT empty.
1896
     *
1897
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
1898
     *
1899
     * @psalm-mutation-free
1900
     *
1901
     * @return bool
1902
     *              <p>Whether or not $str is empty().</p>
1903
     */
1904 10
    public function isNotEmpty(): bool
1905
    {
1906 10
        return !$this->utf8::is_empty($this->str);
1907
    }
1908
1909
    /**
1910
     * Determine if the string is composed of numeric characters.
1911
     *
1912
     * @psalm-mutation-free
1913
     *
1914
     * @return bool
1915
     */
1916 4
    public function isNumeric(): bool
1917
    {
1918 4
        return \is_numeric($this->str);
1919
    }
1920
1921
    /**
1922
     * Determine if the string is composed of printable (non-invisible) characters.
1923
     *
1924
     * @psalm-mutation-free
1925
     *
1926
     * @return bool
1927
     */
1928 3
    public function isPrintable(): bool
1929
    {
1930 3
        return $this->utf8::is_printable($this->str);
1931
    }
1932
1933
    /**
1934
     * Determine if the string is composed of punctuation characters.
1935
     *
1936
     * @psalm-mutation-free
1937
     *
1938
     * @return bool
1939
     */
1940 3
    public function isPunctuation(): bool
1941
    {
1942 3
        return $this->utf8::is_punctuation($this->str);
1943
    }
1944
1945
    /**
1946
     * Returns true if the string is serialized, false otherwise.
1947
     *
1948
     * @psalm-mutation-free
1949
     *
1950
     * @return bool
1951
     *              <p>Whether or not $str is serialized.</p>
1952
     */
1953 21
    public function isSerialized(): bool
1954
    {
1955 21
        return $this->utf8::is_serialized($this->str);
1956
    }
1957
1958
    /**
1959
     * Check if two strings are similar.
1960
     *
1961
     * @param string $str                     <p>The string to compare against.</p>
1962
     * @param float  $minPercentForSimilarity [optional] <p>The percentage of needed similarity. | Default: 80%</p>
1963
     *
1964
     * @psalm-mutation-free
1965
     *
1966
     * @return bool
1967
     */
1968 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
1969
    {
1970 2
        return $this->similarity($str) >= $minPercentForSimilarity;
1971
    }
1972
1973
    /**
1974
     * Returns true if the string contains only lower case chars, false
1975
     * otherwise.
1976
     *
1977
     * @psalm-mutation-free
1978
     *
1979
     * @return bool
1980
     *              <p>Whether or not $str contains only lower case characters.</p>
1981
     */
1982 24
    public function isUpperCase(): bool
1983
    {
1984 24
        return $this->utf8::is_uppercase($this->str);
1985
    }
1986
1987
    /**
1988
     * Returns true if the string contains only whitespace chars, false otherwise.
1989
     *
1990
     * @psalm-mutation-free
1991
     *
1992
     * @return bool
1993
     *              <p>Whether or not $str contains only whitespace characters.</p>
1994
     */
1995 30
    public function isWhitespace(): bool
1996
    {
1997 30
        return $this->isBlank();
1998
    }
1999
2000
    /**
2001
     * Returns value which can be serialized by json_encode().
2002
     *
2003
     * @noinspection ReturnTypeCanBeDeclaredInspection
2004
     *
2005
     * @psalm-mutation-free
2006
     *
2007
     * @return string The current value of the $str property
2008
     */
2009 2
    public function jsonSerialize()
2010
    {
2011 2
        return (string) $this;
2012
    }
2013
2014
    /**
2015
     * Convert the string to kebab-case.
2016
     *
2017
     * @psalm-mutation-free
2018
     *
2019
     * @return static
2020
     */
2021 3 View Code Duplication
    public function kebabCase(): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2022
    {
2023 3
        $words = \array_map(
2024
            static function (self $word) {
2025 3
                return $word->toLowerCase();
2026 3
            },
2027 3
            $this->words('', true)
2028
        );
2029
2030 3
        return new static(\implode('-', $words), $this->encoding);
2031
    }
2032
2033
    /**
2034
     * Returns the last $n characters of the string.
2035
     *
2036
     * @param int $n <p>Number of characters to retrieve from the end.</p>
2037
     *
2038
     * @psalm-mutation-free
2039
     *
2040
     * @return static
2041
     *                <p>Object with its $str being the last $n chars.</p>
2042
     */
2043 36
    public function last(int $n): self
2044
    {
2045 36
        return static::create(
2046 36
            $this->utf8::str_last_char(
2047 36
                $this->str,
2048 36
                $n,
2049 36
                $this->encoding
2050
            ),
2051 36
            $this->encoding
2052
        );
2053
    }
2054
2055
    /**
2056
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2057
     * If no match is found returns new empty Stringy object.
2058
     *
2059
     * @param string $needle       <p>The string to look for.</p>
2060
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2061
     *
2062
     * @psalm-mutation-free
2063
     *
2064
     * @return static
2065
     */
2066 4 View Code Duplication
    public function lastSubstringOf(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2067
    {
2068 4
        return static::create(
2069 4
            $this->utf8::str_substr_last(
2070 4
                $this->str,
2071 4
                $needle,
2072 4
                $beforeNeedle,
2073 4
                $this->encoding
2074
            ),
2075 4
            $this->encoding
2076
        );
2077
    }
2078
2079
    /**
2080
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2081
     * If no match is found returns new empty Stringy object.
2082
     *
2083
     * @param string $needle       <p>The string to look for.</p>
2084
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2085
     *
2086
     * @psalm-mutation-free
2087
     *
2088
     * @return static
2089
     */
2090 2 View Code Duplication
    public function lastSubstringOfIgnoreCase(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2091
    {
2092 2
        return static::create(
2093 2
            $this->utf8::str_isubstr_last(
2094 2
                $this->str,
2095 2
                $needle,
2096 2
                $beforeNeedle,
2097 2
                $this->encoding
2098
            ),
2099 2
            $this->encoding
2100
        );
2101
    }
2102
2103
    /**
2104
     * Returns the length of the string.
2105
     *
2106
     * @psalm-mutation-free
2107
     *
2108
     * @return int
2109
     *             <p>The number of characters in $str given the encoding.</p>
2110
     */
2111 17
    public function length(): int
2112
    {
2113 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
2114
    }
2115
2116
    /**
2117
     * Line-Wrap the string after $limit, but also after the next word.
2118
     *
2119
     * @param int         $limit           [optional] <p>The column width.</p>
2120
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2121
     * @param bool        $add_final_break [optional] <p>
2122
     *                                     If this flag is true, then the method will add a $break at the end
2123
     *                                     of the result string.
2124
     *                                     </p>
2125
     * @param string|null $delimiter       [optional] <p>
2126
     *                                     You can change the default behavior, where we split the string by newline.
2127
     *                                     </p>
2128
     *
2129
     * @psalm-mutation-free
2130
     *
2131
     * @return static
2132
     */
2133 3 View Code Duplication
    public function lineWrap(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2134
        int $limit,
2135
        string $break = "\n",
2136
        bool $add_final_break = true,
2137
        string $delimiter = null
2138
    ): self {
2139 3
        return static::create(
2140 3
            $this->utf8::wordwrap_per_line(
2141 3
                $this->str,
2142 3
                $limit,
2143 3
                $break,
2144 3
                true,
2145 3
                $add_final_break,
2146 3
                $delimiter
2147
            ),
2148 3
            $this->encoding
2149
        );
2150
    }
2151
2152
    /**
2153
     * Line-Wrap the string after $limit, but also after the next word.
2154
     *
2155
     * @param int         $limit           [optional] <p>The column width.</p>
2156
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2157
     * @param bool        $add_final_break [optional] <p>
2158
     *                                     If this flag is true, then the method will add a $break at the end
2159
     *                                     of the result string.
2160
     *                                     </p>
2161
     * @param string|null $delimiter       [optional] <p>
2162
     *                                     You can change the default behavior, where we split the string by newline.
2163
     *                                     </p>
2164
     *
2165
     * @psalm-mutation-free
2166
     *
2167
     * @return static
2168
     */
2169 4 View Code Duplication
    public function lineWrapAfterWord(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2170
        int $limit,
2171
        string $break = "\n",
2172
        bool $add_final_break = true,
2173
        string $delimiter = null
2174
    ): self {
2175 4
        return static::create(
2176 4
            $this->utf8::wordwrap_per_line(
2177 4
                $this->str,
2178 4
                $limit,
2179 4
                $break,
2180 4
                false,
2181 4
                $add_final_break,
2182 4
                $delimiter
2183
            ),
2184 4
            $this->encoding
2185
        );
2186
    }
2187
2188
    /**
2189
     * Splits on newlines and carriage returns, returning an array of Stringy
2190
     * objects corresponding to the lines in the string.
2191
     *
2192
     * @psalm-mutation-free
2193
     *
2194
     * @return static[]
2195
     *                  <p>An array of Stringy objects.</p>
2196
     *
2197
     * @psalm-return array<int,static>
2198
     */
2199 51
    public function lines(): array
2200
    {
2201 51
        if ($this->str === '') {
2202 3
            return [static::create('')];
2203
        }
2204
2205 48
        $strings = $this->utf8::str_to_lines($this->str);
2206
        /** @noinspection AlterInForeachInspection */
2207 48
        foreach ($strings as &$str) {
2208 48
            $str = static::create($str, $this->encoding);
2209
        }
2210
2211
        /** @noinspection PhpSillyAssignmentInspection */
2212
        /** @var static[] $strings */
2213 48
        $strings = $strings;
0 ignored issues
show
Bug introduced by
Why assign $strings to itself?

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

This assignement can be removed without consequences.

Loading history...
2214
2215 48
        return $strings;
2216
    }
2217
2218
    /**
2219
     * Splits on newlines and carriage returns, returning an array of Stringy
2220
     * objects corresponding to the lines in the string.
2221
     *
2222
     * @psalm-mutation-free
2223
     *
2224
     * @return CollectionStringy|static[]
2225
     *                                    <p>An collection of Stringy objects.</p>
2226
     *
2227
     * @psalm-return CollectionStringy<int,static>
2228
     */
2229 34
    public function linesCollection(): CollectionStringy
2230
    {
2231
        /**
2232
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2233
         */
2234 34
        return CollectionStringy::create(
2235 34
            $this->lines()
2236
        );
2237
    }
2238
2239
    /**
2240
     * Returns the longest common prefix between the string and $otherStr.
2241
     *
2242
     * @param string $otherStr <p>Second string for comparison.</p>
2243
     *
2244
     * @psalm-mutation-free
2245
     *
2246
     * @return static
2247
     *                <p>Object with its $str being the longest common prefix.</p>
2248
     */
2249 30
    public function longestCommonPrefix(string $otherStr): self
2250
    {
2251 30
        return static::create(
2252 30
            $this->utf8::str_longest_common_prefix(
2253 30
                $this->str,
2254 30
                $otherStr,
2255 30
                $this->encoding
2256
            ),
2257 30
            $this->encoding
2258
        );
2259
    }
2260
2261
    /**
2262
     * Returns the longest common substring between the string and $otherStr.
2263
     * In the case of ties, it returns that which occurs first.
2264
     *
2265
     * @param string $otherStr <p>Second string for comparison.</p>
2266
     *
2267
     * @psalm-mutation-free
2268
     *
2269
     * @return static
2270
     *                <p>Object with its $str being the longest common substring.</p>
2271
     */
2272 30
    public function longestCommonSubstring(string $otherStr): self
2273
    {
2274 30
        return static::create(
2275 30
            $this->utf8::str_longest_common_substring(
2276 30
                $this->str,
2277 30
                $otherStr,
2278 30
                $this->encoding
2279
            ),
2280 30
            $this->encoding
2281
        );
2282
    }
2283
2284
    /**
2285
     * Returns the longest common suffix between the string and $otherStr.
2286
     *
2287
     * @param string $otherStr <p>Second string for comparison.</p>
2288
     *
2289
     * @psalm-mutation-free
2290
     *
2291
     * @return static
2292
     *                <p>Object with its $str being the longest common suffix.</p>
2293
     */
2294 30
    public function longestCommonSuffix(string $otherStr): self
2295
    {
2296 30
        return static::create(
2297 30
            $this->utf8::str_longest_common_suffix(
2298 30
                $this->str,
2299 30
                $otherStr,
2300 30
                $this->encoding
2301
            ),
2302 30
            $this->encoding
2303
        );
2304
    }
2305
2306
    /**
2307
     * Converts the first character of the string to lower case.
2308
     *
2309
     * @psalm-mutation-free
2310
     *
2311
     * @return static
2312
     *                <p>Object with the first character of $str being lower case.</p>
2313
     */
2314 15
    public function lowerCaseFirst(): self
2315
    {
2316 15
        return static::create(
2317 15
            $this->utf8::lcfirst($this->str, $this->encoding),
2318 15
            $this->encoding
2319
        );
2320
    }
2321
2322
    /**
2323
     * Determine if the string matches another string regardless of case.
2324
     * Alias for isEqualsCaseInsensitive()
2325
     *
2326
     * @psalm-mutation-free
2327
     *
2328
     * @param string|Stringy ...$str
2329
     *                               <p>The string to compare against.</p>
2330
     *
2331
     * @psalm-mutation-free
2332
     *
2333
     * @return bool
2334
     */
2335 3
    public function matchCaseInsensitive(...$str): bool
2336
    {
2337 3
        return $this->isEqualsCaseInsensitive(...$str);
2338
    }
2339
2340
    /**
2341
     * Determine if the string matches another string.
2342
     * Alias for isEqualsCaseSensitive()
2343
     *
2344
     * @psalm-mutation-free
2345
     *
2346
     * @param string|Stringy ...$str
2347
     *                               <p>The string to compare against.</p>
2348
     *
2349
     * @psalm-mutation-free
2350
     *
2351
     * @return bool
2352
     */
2353 7
    public function matchCaseSensitive(...$str): bool
2354
    {
2355 7
        return $this->isEqualsCaseSensitive(...$str);
2356
    }
2357
2358
    /**
2359
     * Create a md5 hash from the current string.
2360
     *
2361
     * @psalm-mutation-free
2362
     *
2363
     * @return static
2364
     */
2365 2
    public function md5(): self
2366
    {
2367 2
        return static::create($this->hash('md5'), $this->encoding);
2368
    }
2369
2370
    /**
2371
     * Replace all breaks [<br> | \r\n | \r | \n | ...] into "<br>".
2372
     *
2373
     * @return static
2374
     */
2375 1
    public function newLineToHtmlBreak(): self
2376
    {
2377 1
        return $this->removeHtmlBreak('<br>');
2378
    }
2379
2380
    /**
2381
     * Get every nth character of the string.
2382
     *
2383
     * @param int $step   <p>The number of characters to step.</p>
2384
     * @param int $offset [optional] <p>The string offset to start at.</p>
2385
     *
2386
     * @psalm-mutation-free
2387
     *
2388
     * @return static
2389
     */
2390 4
    public function nth(int $step, int $offset = 0): self
2391
    {
2392 4
        $length = $step - 1;
2393 4
        $substring = $this->substr($offset)->toString();
2394
2395 4
        if ($substring === '') {
2396
            return new static('', $this->encoding);
2397
        }
2398
2399 4
        \preg_match_all(
2400 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2401 4
            $substring,
2402 4
            $matches
2403
        );
2404
2405 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2406
    }
2407
2408
    /**
2409
     * Returns whether or not a character exists at an index. Offsets may be
2410
     * negative to count from the last character in the string. Implements
2411
     * part of the ArrayAccess interface.
2412
     *
2413
     * @param int $offset <p>The index to check.</p>
2414
     *
2415
     * @psalm-mutation-free
2416
     *
2417
     * @return bool
2418
     *              <p>Whether or not the index exists.</p>
2419
     */
2420 18
    public function offsetExists($offset): bool
2421
    {
2422 18
        return $this->utf8::str_offset_exists(
2423 18
            $this->str,
2424 18
            $offset,
2425 18
            $this->encoding
2426
        );
2427
    }
2428
2429
    /**
2430
     * Returns the character at the given index. Offsets may be negative to
2431
     * count from the last character in the string. Implements part of the
2432
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2433
     * does not exist.
2434
     *
2435
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2436
     *
2437
     * @throws \OutOfBoundsException
2438
     *                               <p>If the positive or negative offset does not exist.</p>
2439
     *
2440
     * @return string
2441
     *                <p>The character at the specified index.</p>
2442
     *
2443
     * @psalm-mutation-free
2444
     */
2445 6
    public function offsetGet($offset): string
2446
    {
2447 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2448
    }
2449
2450
    /**
2451
     * Implements part of the ArrayAccess interface, but throws an exception
2452
     * when called. This maintains the immutability of Stringy objects.
2453
     *
2454
     * @param int   $offset <p>The index of the character.</p>
2455
     * @param mixed $value  <p>Value to set.</p>
2456
     *
2457
     * @throws \Exception
2458
     *                    <p>When called.</p>
2459
     *
2460
     * @return void
2461
     */
2462 3
    public function offsetSet($offset, $value)
2463
    {
2464
        // Stringy is immutable, cannot directly set char
2465
        /** @noinspection ThrowRawExceptionInspection */
2466 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
2467
    }
2468
2469
    /**
2470
     * Implements part of the ArrayAccess interface, but throws an exception
2471
     * when called. This maintains the immutability of Stringy objects.
2472
     *
2473
     * @param int $offset <p>The index of the character.</p>
2474
     *
2475
     * @throws \Exception
2476
     *                    <p>When called.</p>
2477
     *
2478
     * @return void
2479
     */
2480 3
    public function offsetUnset($offset)
2481
    {
2482
        // Don't allow directly modifying the string
2483
        /** @noinspection ThrowRawExceptionInspection */
2484 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
2485
    }
2486
2487
    /**
2488
     * Pads the string to a given length with $padStr. If length is less than
2489
     * or equal to the length of the string, no padding takes places. The
2490
     * default string used for padding is a space, and the default type (one of
2491
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
2492
     * if $padType isn't one of those 3 values.
2493
     *
2494
     * @param int    $length  <p>Desired string length after padding.</p>
2495
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2496
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
2497
     *
2498
     * @throws \InvalidArgumentException
2499
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
2500
     *
2501
     * @return static
2502
     *                <p>Object with a padded $str.</p>
2503
     *
2504
     * @psalm-mutation-free
2505
     */
2506 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
2507
    {
2508 39
        return static::create(
2509 39
            $this->utf8::str_pad(
2510 39
                $this->str,
2511 39
                $length,
2512 39
                $padStr,
2513 39
                $padType,
2514 39
                $this->encoding
2515
            )
2516
        );
2517
    }
2518
2519
    /**
2520
     * Returns a new string of a given length such that both sides of the
2521
     * string are padded. Alias for pad() with a $padType of 'both'.
2522
     *
2523
     * @param int    $length <p>Desired string length after padding.</p>
2524
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2525
     *
2526
     * @psalm-mutation-free
2527
     *
2528
     * @return static
2529
     *                <p>String with padding applied.</p>
2530
     */
2531 33
    public function padBoth(int $length, string $padStr = ' '): self
2532
    {
2533 33
        return static::create(
2534 33
            $this->utf8::str_pad_both(
2535 33
                $this->str,
2536 33
                $length,
2537 33
                $padStr,
2538 33
                $this->encoding
2539
            )
2540
        );
2541
    }
2542
2543
    /**
2544
     * Returns a new string of a given length such that the beginning of the
2545
     * string is padded. Alias for pad() with a $padType of 'left'.
2546
     *
2547
     * @param int    $length <p>Desired string length after padding.</p>
2548
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2549
     *
2550
     * @psalm-mutation-free
2551
     *
2552
     * @return static
2553
     *                <p>String with left padding.</p>
2554
     */
2555 21
    public function padLeft(int $length, string $padStr = ' '): self
2556
    {
2557 21
        return static::create(
2558 21
            $this->utf8::str_pad_left(
2559 21
                $this->str,
2560 21
                $length,
2561 21
                $padStr,
2562 21
                $this->encoding
2563
            )
2564
        );
2565
    }
2566
2567
    /**
2568
     * Returns a new string of a given length such that the end of the string
2569
     * is padded. Alias for pad() with a $padType of 'right'.
2570
     *
2571
     * @param int    $length <p>Desired string length after padding.</p>
2572
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2573
     *
2574
     * @psalm-mutation-free
2575
     *
2576
     * @return static
2577
     *                <p>String with right padding.</p>
2578
     */
2579 21
    public function padRight(int $length, string $padStr = ' '): self
2580
    {
2581 21
        return static::create(
2582 21
            $this->utf8::str_pad_right(
2583 21
                $this->str,
2584 21
                $length,
2585 21
                $padStr,
2586 21
                $this->encoding
2587
            )
2588
        );
2589
    }
2590
2591
    /**
2592
     * Convert the string to PascalCase.
2593
     * Alias for studlyCase()
2594
     *
2595
     * @psalm-mutation-free
2596
     *
2597
     * @return static
2598
     */
2599 3
    public function pascalCase(): self
2600
    {
2601 3
        return $this->studlyCase();
2602
    }
2603
2604
    /**
2605
     * Returns a new string starting with $prefix.
2606
     *
2607
     * @param string ...$prefix <p>The string to append.</p>
2608
     *
2609
     * @psalm-mutation-free
2610
     *
2611
     * @return static
2612
     *                <p>Object with appended $prefix.</p>
2613
     *
2614
     * @noinspection PhpDocSignatureInspection
2615
     */
2616 8 View Code Duplication
    public function prepend(string ...$prefix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2617
    {
2618 8
        if (\count($prefix) <= 1) {
2619
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2620 6
            $prefix = $prefix[0];
2621
        } else {
2622
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2623 2
            $prefix = \implode('', $prefix);
2624
        }
2625
2626 8
        return static::create($prefix . $this->str, $this->encoding);
2627
    }
2628
2629
    /**
2630
     * Returns a new string starting with $prefix.
2631
     *
2632
     * @param CollectionStringy|static ...$prefix <p>The Stringy objects to append.</p>
2633
     *
2634
     * @psalm-param CollectionStringy<int,static>|static ...$prefix
2635
     *
2636
     * @psalm-mutation-free
2637
     *
2638
     * @return static
2639
     *                <p>Object with appended $prefix.</p>
2640
     */
2641 1 View Code Duplication
    public function prependStringy(...$prefix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2642
    {
2643 1
        $prefixStr = '';
2644 1
        foreach ($prefix as $prefixTmp) {
2645 1
            if ($prefixTmp instanceof CollectionStringy) {
2646 1
                $prefixStr .= $prefixTmp->implode('');
2647
            } else {
2648 1
                $prefixStr .= $prefixTmp->toString();
2649
            }
2650
        }
2651
2652 1
        return static::create($prefixStr . $this->str, $this->encoding);
2653
    }
2654
2655
    /**
2656
     * Replaces all occurrences of $pattern in $str by $replacement.
2657
     *
2658
     * @param string $pattern     <p>The regular expression pattern.</p>
2659
     * @param string $replacement <p>The string to replace with.</p>
2660
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2661
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2662
     *
2663
     * @psalm-mutation-free
2664
     *
2665
     * @return static
2666
     *                <p>Object with the result2ing $str after the replacements.</p>
2667
     */
2668 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2669
    {
2670 29
        return static::create(
2671 29
            $this->utf8::regex_replace(
2672 29
                $this->str,
2673 29
                $pattern,
2674 29
                $replacement,
2675 29
                $options,
2676 29
                $delimiter
2677
            ),
2678 29
            $this->encoding
2679
        );
2680
    }
2681
2682
    /**
2683
     * Remove html via "strip_tags()" from the string.
2684
     *
2685
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2686
     *                              not be stripped. Default: null
2687
     *                              </p>
2688
     *
2689
     * @psalm-mutation-free
2690
     *
2691
     * @return static
2692
     */
2693 12
    public function removeHtml(string $allowableTags = ''): self
2694
    {
2695 12
        return static::create(
2696 12
            $this->utf8::remove_html($this->str, $allowableTags),
2697 12
            $this->encoding
2698
        );
2699
    }
2700
2701
    /**
2702
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2703
     *
2704
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2705
     *
2706
     * @psalm-mutation-free
2707
     *
2708
     * @return static
2709
     */
2710 13
    public function removeHtmlBreak(string $replacement = ''): self
2711
    {
2712 13
        return static::create(
2713 13
            $this->utf8::remove_html_breaks($this->str, $replacement),
2714 13
            $this->encoding
2715
        );
2716
    }
2717
2718
    /**
2719
     * Returns a new string with the prefix $substring removed, if present.
2720
     *
2721
     * @param string $substring <p>The prefix to remove.</p>
2722
     *
2723
     * @psalm-mutation-free
2724
     *
2725
     * @return static
2726
     *                <p>Object having a $str without the prefix $substring.</p>
2727
     */
2728 36
    public function removeLeft(string $substring): self
2729
    {
2730 36
        return static::create(
2731 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2732 36
            $this->encoding
2733
        );
2734
    }
2735
2736
    /**
2737
     * Returns a new string with the suffix $substring removed, if present.
2738
     *
2739
     * @param string $substring <p>The suffix to remove.</p>
2740
     *
2741
     * @psalm-mutation-free
2742
     *
2743
     * @return static
2744
     *                <p>Object having a $str without the suffix $substring.</p>
2745
     */
2746 36
    public function removeRight(string $substring): self
2747
    {
2748 36
        return static::create(
2749 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2750 36
            $this->encoding
2751
        );
2752
    }
2753
2754
    /**
2755
     * Try to remove all XSS-attacks from the string.
2756
     *
2757
     * @psalm-mutation-free
2758
     *
2759
     * @return static
2760
     */
2761 12
    public function removeXss(): self
2762
    {
2763
        /**
2764
         * @var AntiXSS|null
2765
         *
2766
         * @psalm-suppress ImpureStaticVariable
2767
         */
2768 12
        static $antiXss = null;
2769
2770 12
        if ($antiXss === null) {
2771 1
            $antiXss = new AntiXSS();
2772
        }
2773
2774
        /**
2775
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2776
         */
2777 12
        $str = $antiXss->xss_clean($this->str);
2778
2779 12
        return static::create($str, $this->encoding);
2780
    }
2781
2782
    /**
2783
     * Returns a repeated string given a multiplier.
2784
     *
2785
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2786
     *
2787
     * @psalm-mutation-free
2788
     *
2789
     * @return static
2790
     *                <p>Object with a repeated str.</p>
2791
     */
2792 21
    public function repeat(int $multiplier): self
2793
    {
2794 21
        return static::create(
2795 21
            \str_repeat($this->str, $multiplier),
2796 21
            $this->encoding
2797
        );
2798
    }
2799
2800
    /**
2801
     * Replaces all occurrences of $search in $str by $replacement.
2802
     *
2803
     * @param string $search        <p>The needle to search for.</p>
2804
     * @param string $replacement   <p>The string to replace with.</p>
2805
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2806
     *
2807
     * @psalm-mutation-free
2808
     *
2809
     * @return static
2810
     *                <p>Object with the resulting $str after the replacements.</p>
2811
     */
2812 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2813
    {
2814 76
        if ($search === '' && $replacement === '') {
2815 16
            return static::create($this->str, $this->encoding);
2816
        }
2817
2818 60
        if ($this->str === '' && $search === '') {
2819 2
            return static::create($replacement, $this->encoding);
2820
        }
2821
2822 58
        if ($caseSensitive) {
2823 48
            return static::create(
2824 48
                $this->utf8::str_replace($search, $replacement, $this->str),
2825 48
                $this->encoding
2826
            );
2827
        }
2828
2829 10
        return static::create(
2830 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2831 10
            $this->encoding
2832
        );
2833
    }
2834
2835
    /**
2836
     * Replaces all occurrences of $search in $str by $replacement.
2837
     *
2838
     * @param string[]        $search        <p>The elements to search for.</p>
2839
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2840
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2841
     *
2842
     * @psalm-mutation-free
2843
     *
2844
     * @return static
2845
     *                <p>Object with the resulting $str after the replacements.</p>
2846
     */
2847 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2848
    {
2849 61
        if ($caseSensitive) {
2850 47
            return static::create(
2851 47
                $this->utf8::str_replace($search, $replacement, $this->str),
2852 47
                $this->encoding
2853
            );
2854
        }
2855
2856 14
        return static::create(
2857 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2858 14
            $this->encoding
2859
        );
2860
    }
2861
2862
    /**
2863
     * Replaces all occurrences of $search from the beginning of string with $replacement.
2864
     *
2865
     * @param string $search      <p>The string to search for.</p>
2866
     * @param string $replacement <p>The replacement.</p>
2867
     *
2868
     * @psalm-mutation-free
2869
     *
2870
     * @return static
2871
     *                <p>Object with the resulting $str after the replacements.</p>
2872
     */
2873 32
    public function replaceBeginning(string $search, string $replacement): self
2874
    {
2875 32
        return static::create(
2876 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
2877 32
            $this->encoding
2878
        );
2879
    }
2880
2881
    /**
2882
     * Replaces all occurrences of $search from the ending of string with $replacement.
2883
     *
2884
     * @param string $search      <p>The string to search for.</p>
2885
     * @param string $replacement <p>The replacement.</p>
2886
     *
2887
     * @psalm-mutation-free
2888
     *
2889
     * @return static
2890
     *                <p>Object with the resulting $str after the replacements.</p>
2891
     */
2892 32
    public function replaceEnding(string $search, string $replacement): self
2893
    {
2894 32
        return static::create(
2895 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
2896 32
            $this->encoding
2897
        );
2898
    }
2899
2900
    /**
2901
     * Replaces first occurrences of $search from the beginning of string with $replacement.
2902
     *
2903
     * @param string $search      <p>The string to search for.</p>
2904
     * @param string $replacement <p>The replacement.</p>
2905
     *
2906
     * @psalm-mutation-free
2907
     *
2908
     * @return static
2909
     *                <p>Object with the resulting $str after the replacements.</p>
2910
     */
2911 32
    public function replaceFirst(string $search, string $replacement): self
2912
    {
2913 32
        return static::create(
2914 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
2915 32
            $this->encoding
2916
        );
2917
    }
2918
2919
    /**
2920
     * Replaces last occurrences of $search from the ending of string with $replacement.
2921
     *
2922
     * @param string $search      <p>The string to search for.</p>
2923
     * @param string $replacement <p>The replacement.</p>
2924
     *
2925
     * @psalm-mutation-free
2926
     *
2927
     * @return static
2928
     *                <p>Object with the resulting $str after the replacements.</p>
2929
     */
2930 30
    public function replaceLast(string $search, string $replacement): self
2931
    {
2932 30
        return static::create(
2933 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
2934 30
            $this->encoding
2935
        );
2936
    }
2937
2938
    /**
2939
     * Returns a reversed string. A multibyte version of strrev().
2940
     *
2941
     * @psalm-mutation-free
2942
     *
2943
     * @return static
2944
     *                <p>Object with a reversed $str.</p>
2945
     */
2946 15
    public function reverse(): self
2947
    {
2948 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
2949
    }
2950
2951
    /**
2952
     * Truncates the string to a given length, while ensuring that it does not
2953
     * split words. If $substring is provided, and truncating occurs, the
2954
     * string is further truncated so that the substring may be appended without
2955
     * exceeding the desired length.
2956
     *
2957
     * @param int    $length                          <p>Desired length of the truncated string.</p>
2958
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
2959
     * @param bool   $ignoreDoNotSplitWordsForOneWord
2960
     *
2961
     * @psalm-mutation-free
2962
     *
2963
     * @return static
2964
     *                <p>Object with the resulting $str after truncating.</p>
2965
     */
2966 68
    public function safeTruncate(
2967
        int $length,
2968
        string $substring = '',
2969
        bool $ignoreDoNotSplitWordsForOneWord = true
2970
    ): self {
2971 68
        return static::create(
2972 68
            $this->utf8::str_truncate_safe(
2973 68
                $this->str,
2974 68
                $length,
2975 68
                $substring,
2976 68
                $this->encoding,
2977 68
                $ignoreDoNotSplitWordsForOneWord
2978
            ),
2979 68
            $this->encoding
2980
        );
2981
    }
2982
2983
    /**
2984
     * Set the internal character encoding.
2985
     *
2986
     * @param string $new_encoding <p>The desired character encoding.</p>
2987
     *
2988
     * @psalm-mutation-free
2989
     *
2990
     * @return static
2991
     */
2992 1
    public function setInternalEncoding(string $new_encoding): self
2993
    {
2994 1
        return new static($this->str, $new_encoding);
2995
    }
2996
2997
    /**
2998
     * Create a sha1 hash from the current string.
2999
     *
3000
     * @psalm-mutation-free
3001
     *
3002
     * @return static
3003
     */
3004 2
    public function sha1(): self
3005
    {
3006 2
        return static::create($this->hash('sha1'), $this->encoding);
3007
    }
3008
3009
    /**
3010
     * Create a sha256 hash from the current string.
3011
     *
3012
     * @psalm-mutation-free
3013
     *
3014
     * @return static
3015
     */
3016 2
    public function sha256(): self
3017
    {
3018 2
        return static::create($this->hash('sha256'), $this->encoding);
3019
    }
3020
3021
    /**
3022
     * Create a sha512 hash from the current string.
3023
     *
3024
     * @psalm-mutation-free
3025
     *
3026
     * @return static
3027
     */
3028 2
    public function sha512(): self
3029
    {
3030 2
        return static::create($this->hash('sha512'), $this->encoding);
3031
    }
3032
3033
    /**
3034
     * Shorten the string after $length, but also after the next word.
3035
     *
3036
     * @param int    $length   <p>The given length.</p>
3037
     * @param string $strAddOn [optional] <p>Default: '…'</p>
3038
     *
3039
     * @psalm-mutation-free
3040
     *
3041
     * @return static
3042
     */
3043 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
3044
    {
3045 8
        return static::create(
3046 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
3047 8
            $this->encoding
3048
        );
3049
    }
3050
3051
    /**
3052
     * A multibyte string shuffle function. It returns a string with its
3053
     * characters in random order.
3054
     *
3055
     * @psalm-mutation-free
3056
     *
3057
     * @return static
3058
     *                <p>Object with a shuffled $str.</p>
3059
     */
3060 9
    public function shuffle(): self
3061
    {
3062 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
3063
    }
3064
3065
    /**
3066
     * Calculate the similarity between two strings.
3067
     *
3068
     * @param string $str <p>The delimiting string.</p>
3069
     *
3070
     * @psalm-mutation-free
3071
     *
3072
     * @return float
3073
     */
3074 2
    public function similarity(string $str): float
3075
    {
3076 2
        \similar_text($this->str, $str, $percent);
3077
3078 2
        return $percent;
3079
    }
3080
3081
    /**
3082
     * Returns the substring beginning at $start, and up to, but not including
3083
     * the index specified by $end. If $end is omitted, the function extracts
3084
     * the remaining string. If $end is negative, it is computed from the end
3085
     * of the string.
3086
     *
3087
     * @param int $start <p>Initial index from which to begin extraction.</p>
3088
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
3089
     *
3090
     * @psalm-mutation-free
3091
     *
3092
     * @return static
3093
     *                <p>Object with its $str being the extracted substring.</p>
3094
     */
3095 50
    public function slice(int $start, int $end = null): self
3096
    {
3097 50
        return static::create(
3098 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
3099 50
            $this->encoding
3100
        );
3101
    }
3102
3103
    /**
3104
     * Converts the string into an URL slug. This includes replacing non-ASCII
3105
     * characters with their closest ASCII equivalents, removing remaining
3106
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3107
     * $separator. The separator defaults to a single dash, and the string
3108
     * is also converted to lowercase. The language of the source string can
3109
     * also be supplied for language-specific transliteration.
3110
     *
3111
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
3112
     * @param string                $language              [optional] <p>Language of the source string.</p>
3113
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
3114
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
3115
     *                                                     pound ".</p>
3116
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
3117
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
3118
     *                                                     chars.</p>
3119
     *
3120
     * @psalm-mutation-free
3121
     *
3122
     * @return static
3123
     *                <p>Object whose $str has been converted to an URL slug.</p>
3124
     *
3125
     * @noinspection PhpTooManyParametersInspection
3126
     */
3127 17
    public function slugify(
3128
        string $separator = '-',
3129
        string $language = 'en',
3130
        array $replacements = [],
3131
        bool $replace_extra_symbols = true,
3132
        bool $use_str_to_lower = true,
3133
        bool $use_transliterate = false
3134
    ): self {
3135 17
        return static::create(
3136 17
            $this->ascii::to_slugify(
3137 17
                $this->str,
3138 17
                $separator,
3139 17
                $language,
3140 17
                $replacements,
3141 17
                $replace_extra_symbols,
3142 17
                $use_str_to_lower,
3143 17
                $use_transliterate
3144
            ),
3145 17
            $this->encoding
3146
        );
3147
    }
3148
3149
    /**
3150
     * Convert the string to snake_case.
3151
     *
3152
     * @psalm-mutation-free
3153
     *
3154
     * @return static
3155
     */
3156 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...
3157
    {
3158 3
        $words = \array_map(
3159
            static function (self $word) {
3160 3
                return $word->toLowerCase();
3161 3
            },
3162 3
            $this->words('', true)
3163
        );
3164
3165 3
        return new static(\implode('_', $words), $this->encoding);
3166
    }
3167
3168
    /**
3169
     * Convert a string to e.g.: "snake_case"
3170
     *
3171
     * @psalm-mutation-free
3172
     *
3173
     * @return static
3174
     *                <p>Object with $str in snake_case.</p>
3175
     */
3176 40
    public function snakeize(): self
3177
    {
3178 40
        return static::create(
3179 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
3180 40
            $this->encoding
3181
        );
3182
    }
3183
3184
    /**
3185
     * Wrap the string after the first whitespace character after a given number
3186
     * of characters.
3187
     *
3188
     * @param int    $width <p>Number of characters at which to wrap.</p>
3189
     * @param string $break [optional] <p>Character used to break the string. | Default "\n"</p>
3190
     *
3191
     * @psalm-mutation-free
3192
     *
3193
     * @return static
3194
     */
3195 2
    public function softWrap(int $width, string $break = "\n"): self
3196
    {
3197 2
        return $this->lineWrapAfterWord($width, $break, false);
3198
    }
3199
3200
    /**
3201
     * Splits the string with the provided regular expression, returning an
3202
     * array of Stringy objects. An optional integer $limit will truncate the
3203
     * results.
3204
     *
3205
     * @param string $pattern <p>The regex with which to split the string.</p>
3206
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3207
     *                        limit</p>
3208
     *
3209
     * @psalm-mutation-free
3210
     *
3211
     * @return static[]
3212
     *                  <p>An array of Stringy objects.</p>
3213
     *
3214
     * @psalm-return array<int,static>
3215
     */
3216 51
    public function split(string $pattern, int $limit = null): array
3217
    {
3218 51
        if ($this->str === '') {
3219
            return [];
3220
        }
3221
3222 51
        if ($limit === null) {
3223 7
            $limit = -1;
3224
        }
3225
3226 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
3227
        /** @noinspection AlterInForeachInspection */
3228 51
        foreach ($array as $i => &$value) {
3229 45
            $value = static::create($value, $this->encoding);
3230
        }
3231
3232
        /** @noinspection PhpSillyAssignmentInspection */
3233
        /** @var static[] $array */
3234 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...
3235
3236 51
        return $array;
3237
    }
3238
3239
    /**
3240
     * Splits the string with the provided regular expression, returning an
3241
     * collection of Stringy objects. An optional integer $limit will truncate the
3242
     * results.
3243
     *
3244
     * @param string $pattern <p>The regex with which to split the string.</p>
3245
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no
3246
     *                        limit</p>
3247
     *
3248
     * @psalm-mutation-free
3249
     *
3250
     * @return CollectionStringy|static[]
3251
     *                                    <p>An collection of Stringy objects.</p>
3252
     *
3253
     * @psalm-return CollectionStringy<int,static>
3254
     */
3255 35
    public function splitCollection(string $pattern, int $limit = null): CollectionStringy
3256
    {
3257
        /**
3258
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3259
         */
3260 35
        return CollectionStringy::create(
3261 35
            $this->split($pattern, $limit)
3262
        );
3263
    }
3264
3265
    /**
3266
     * Returns true if the string begins with $substring, false otherwise. By
3267
     * default, the comparison is case-sensitive, but can be made insensitive
3268
     * by setting $caseSensitive to false.
3269
     *
3270
     * @param string $substring     <p>The substring to look for.</p>
3271
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3272
     *
3273
     * @psalm-mutation-free
3274
     *
3275
     * @return bool
3276
     *              <p>Whether or not $str starts with $substring.</p>
3277
     */
3278 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
3279
    {
3280 99
        if ($caseSensitive) {
3281 53
            return $this->utf8::str_starts_with($this->str, $substring);
3282
        }
3283
3284 46
        return $this->utf8::str_istarts_with($this->str, $substring);
3285
    }
3286
3287
    /**
3288
     * Returns true if the string begins with any of $substrings, false otherwise.
3289
     * By default the comparison is case-sensitive, but can be made insensitive by
3290
     * setting $caseSensitive to false.
3291
     *
3292
     * @param string[] $substrings    <p>Substrings to look for.</p>
3293
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
3294
     *
3295
     * @psalm-mutation-free
3296
     *
3297
     * @return bool
3298
     *              <p>Whether or not $str starts with $substring.</p>
3299
     */
3300 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
3301
    {
3302 35
        if ($caseSensitive) {
3303 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
3304
        }
3305
3306 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
3307
    }
3308
3309
    /**
3310
     * Remove one or more strings from the string.
3311
     *
3312
     * @param string|string[] $search One or more strings to be removed
3313
     *
3314
     * @psalm-mutation-free
3315
     *
3316
     * @return static
3317
     */
3318 3
    public function strip($search): self
3319
    {
3320 3
        if (\is_array($search)) {
3321 1
            return $this->replaceAll($search, '');
3322
        }
3323
3324 2
        return $this->replace($search, '');
3325
    }
3326
3327
    /**
3328
     * Strip all whitespace characters. This includes tabs and newline characters,
3329
     * as well as multibyte whitespace such as the thin space and ideographic space.
3330
     *
3331
     * @psalm-mutation-free
3332
     *
3333
     * @return static
3334
     */
3335 36
    public function stripWhitespace(): self
3336
    {
3337 36
        return static::create(
3338 36
            $this->utf8::strip_whitespace($this->str),
3339 36
            $this->encoding
3340
        );
3341
    }
3342
3343
    /**
3344
     * Remove css media-queries.
3345
     *
3346
     * @psalm-mutation-free
3347
     *
3348
     * @return static
3349
     */
3350 2
    public function stripeCssMediaQueries(): self
3351
    {
3352 2
        return static::create(
3353 2
            $this->utf8::css_stripe_media_queries($this->str),
3354 2
            $this->encoding
3355
        );
3356
    }
3357
3358
    /**
3359
     * Remove empty html-tag.
3360
     *
3361
     * e.g.: <tag></tag>
3362
     *
3363
     * @psalm-mutation-free
3364
     *
3365
     * @return static
3366
     */
3367 2
    public function stripeEmptyHtmlTags(): self
3368
    {
3369 2
        return static::create(
3370 2
            $this->utf8::html_stripe_empty_tags($this->str),
3371 2
            $this->encoding
3372
        );
3373
    }
3374
3375
    /**
3376
     * Convert the string to StudlyCase.
3377
     *
3378
     * @psalm-mutation-free
3379
     *
3380
     * @return static
3381
     */
3382 6
    public function studlyCase(): self
3383
    {
3384 6
        $words = \array_map(
3385
            static function (self $word) {
3386 6
                return $word->substr(0, 1)
3387 6
                    ->toUpperCase()
3388 6
                    ->appendStringy($word->substr(1));
3389 6
            },
3390 6
            $this->words('', true)
3391
        );
3392
3393 6
        return new static(\implode('', $words), $this->encoding);
3394
    }
3395
3396
    /**
3397
     * Returns the substring beginning at $start with the specified $length.
3398
     * It differs from the $this->utf8::substr() function in that providing a $length of
3399
     * null will return the rest of the string, rather than an empty string.
3400
     *
3401
     * @param int $start  <p>Position of the first character to use.</p>
3402
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
3403
     *
3404
     * @psalm-mutation-free
3405
     *
3406
     * @return static
3407
     *                <p>Object with its $str being the substring.</p>
3408
     */
3409 40
    public function substr(int $start, int $length = null): self
3410
    {
3411 40
        return static::create(
3412 40
            $this->utf8::substr(
3413 40
                $this->str,
3414 40
                $start,
3415 40
                $length,
3416 40
                $this->encoding
3417
            ),
3418 40
            $this->encoding
3419
        );
3420
    }
3421
3422
    /**
3423
     * Return part of the string.
3424
     * Alias for substr()
3425
     *
3426
     * @param int $start  <p>Starting position of the substring.</p>
3427
     * @param int $length [optional] <p>Length of substring.</p>
3428
     *
3429
     * @psalm-mutation-free
3430
     *
3431
     * @return static
3432
     */
3433 3
    public function substring(int $start, int $length = null): self
3434
    {
3435 3
        if ($length === null) {
3436 2
            return $this->substr($start);
3437
        }
3438
3439 3
        return $this->substr($start, $length);
3440
    }
3441
3442
    /**
3443
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3444
     * If no match is found returns new empty Stringy object.
3445
     *
3446
     * @param string $needle       <p>The string to look for.</p>
3447
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3448
     *
3449
     * @psalm-mutation-free
3450
     *
3451
     * @return static
3452
     */
3453 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...
3454
    {
3455 4
        return static::create(
3456 4
            $this->utf8::str_substr_first(
3457 4
                $this->str,
3458 4
                $needle,
3459 4
                $beforeNeedle,
3460 4
                $this->encoding
3461
            ),
3462 4
            $this->encoding
3463
        );
3464
    }
3465
3466
    /**
3467
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3468
     * If no match is found returns new empty Stringy object.
3469
     *
3470
     * @param string $needle       <p>The string to look for.</p>
3471
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3472
     *
3473
     * @psalm-mutation-free
3474
     *
3475
     * @return static
3476
     */
3477 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...
3478
    {
3479 4
        return static::create(
3480 4
            $this->utf8::str_isubstr_first(
3481 4
                $this->str,
3482 4
                $needle,
3483 4
                $beforeNeedle,
3484 4
                $this->encoding
3485
            ),
3486 4
            $this->encoding
3487
        );
3488
    }
3489
3490
    /**
3491
     * Surrounds $str with the given substring.
3492
     *
3493
     * @param string $substring <p>The substring to add to both sides.</P>
3494
     *
3495
     * @psalm-mutation-free
3496
     *
3497
     * @return static
3498
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3499
     */
3500 15
    public function surround(string $substring): self
3501
    {
3502 15
        return static::create(
3503 15
            $substring . $this->str . $substring,
3504 15
            $this->encoding
3505
        );
3506
    }
3507
3508
    /**
3509
     * Returns a case swapped version of the string.
3510
     *
3511
     * @psalm-mutation-free
3512
     *
3513
     * @return static
3514
     *                <p>Object whose $str has each character's case swapped.</P>
3515
     */
3516 15
    public function swapCase(): self
3517
    {
3518 15
        return static::create(
3519 15
            $this->utf8::swapCase($this->str, $this->encoding),
3520 15
            $this->encoding
3521
        );
3522
    }
3523
3524
    /**
3525
     * Returns a string with smart quotes, ellipsis characters, and dashes from
3526
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
3527
     * equivalents.
3528
     *
3529
     * @psalm-mutation-free
3530
     *
3531
     * @return static
3532
     *                <p>Object whose $str has those characters removed.</p>
3533
     */
3534 12
    public function tidy(): self
3535
    {
3536 12
        return static::create(
3537 12
            $this->ascii::normalize_msword($this->str),
3538 12
            $this->encoding
3539
        );
3540
    }
3541
3542
    /**
3543
     * Returns a trimmed string with the first letter of each word capitalized.
3544
     * Also accepts an array, $ignore, allowing you to list words not to be
3545
     * capitalized.
3546
     *
3547
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
3548
     *                                               Default: null</p>
3549
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
3550
     *                                               separator === words.</p>
3551
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
3552
     *
3553
     * @psalm-mutation-free
3554
     *
3555
     * @return static
3556
     *                <p>Object with a titleized $str.</p>
3557
     */
3558 23
    public function titleize(
3559
        array $ignore = null,
3560
        string $word_define_chars = null,
3561
        string $language = null
3562
    ): self {
3563 23
        return static::create(
3564 23
            $this->utf8::str_titleize(
3565 23
                $this->str,
3566 23
                $ignore,
3567 23
                $this->encoding,
3568 23
                false,
3569 23
                $language,
3570 23
                false,
3571 23
                true,
3572 23
                $word_define_chars
3573
            ),
3574 23
            $this->encoding
3575
        );
3576
    }
3577
3578
    /**
3579
     * Returns a trimmed string in proper title case.
3580
     *
3581
     * Also accepts an array, $ignore, allowing you to list words not to be
3582
     * capitalized.
3583
     *
3584
     * Adapted from John Gruber's script.
3585
     *
3586
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
3587
     *
3588
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
3589
     *
3590
     * @psalm-mutation-free
3591
     *
3592
     * @return static
3593
     *                <p>Object with a titleized $str</p>
3594
     */
3595 70
    public function titleizeForHumans(array $ignore = []): self
3596
    {
3597 70
        return static::create(
3598 70
            $this->utf8::str_titleize_for_humans(
3599 70
                $this->str,
3600 70
                $ignore,
3601 70
                $this->encoding
3602
            ),
3603 70
            $this->encoding
3604
        );
3605
    }
3606
3607
    /**
3608
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3609
     * replaced with their closest ASCII counterparts, and the rest are removed
3610
     * by default. The language or locale of the source string can be supplied
3611
     * for language-specific transliteration in any of the following formats:
3612
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
3613
     * to "aeoeue" rather than "aou" as in other languages.
3614
     *
3615
     * @param string $language          [optional] <p>Language of the source string.</p>
3616
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
3617
     *                                  unsupported characters.</p>
3618
     *
3619
     * @psalm-mutation-free
3620
     *
3621
     * @return static
3622
     *                <p>Object whose $str contains only ASCII characters.</p>
3623
     */
3624 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
3625
    {
3626 23
        return static::create(
3627 23
            $this->ascii::to_ascii(
3628 23
                $this->str,
3629 23
                $language,
3630 23
                $removeUnsupported
3631
            ),
3632 23
            $this->encoding
3633
        );
3634
    }
3635
3636
    /**
3637
     * Returns a boolean representation of the given logical string value.
3638
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
3639
     * 'off', and 'no' will return false. In all instances, case is ignored.
3640
     * For other numeric strings, their sign will determine the return value.
3641
     * In addition, blank strings consisting of only whitespace will return
3642
     * false. For all other strings, the return value is a result of a
3643
     * boolean cast.
3644
     *
3645
     * @psalm-mutation-free
3646
     *
3647
     * @return bool
3648
     *              <p>A boolean value for the string.</p>
3649
     */
3650 45
    public function toBoolean(): bool
3651
    {
3652 45
        return $this->utf8::to_boolean($this->str);
3653
    }
3654
3655
    /**
3656
     * Converts all characters in the string to lowercase.
3657
     *
3658
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3659
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3660
     *
3661
     * @psalm-mutation-free
3662
     *
3663
     * @return static
3664
     *                <p>Object with all characters of $str being lowercase.</p>
3665
     */
3666 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...
3667
    {
3668 23
        return static::create(
3669 23
            $this->utf8::strtolower(
3670 23
                $this->str,
3671 23
                $this->encoding,
3672 23
                false,
3673 23
                $lang,
3674 23
                $tryToKeepStringLength
3675
            ),
3676 23
            $this->encoding
3677
        );
3678
    }
3679
3680
    /**
3681
     * Converts each tab in the string to some number of spaces, as defined by
3682
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
3683
     *
3684
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
3685
     *
3686
     * @psalm-mutation-free
3687
     *
3688
     * @return static
3689
     *                <p>Object whose $str has had tabs switched to spaces.</p>
3690
     */
3691 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...
3692
    {
3693 18
        if ($tabLength === 4) {
3694 9
            $tab = '    ';
3695 9
        } elseif ($tabLength === 2) {
3696 3
            $tab = '  ';
3697
        } else {
3698 6
            $tab = \str_repeat(' ', $tabLength);
3699
        }
3700
3701 18
        return static::create(
3702 18
            \str_replace("\t", $tab, $this->str),
3703 18
            $this->encoding
3704
        );
3705
    }
3706
3707
    /**
3708
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
3709
     * string.
3710
     *
3711
     * @psalm-mutation-free
3712
     *
3713
     * @return string
3714
     */
3715 2198
    public function toString(): string
3716
    {
3717 2198
        return (string) $this->str;
3718
    }
3719
3720
    /**
3721
     * Converts each occurrence of some consecutive number of spaces, as
3722
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
3723
     * are converted to a tab.
3724
     *
3725
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
3726
     *
3727
     * @psalm-mutation-free
3728
     *
3729
     * @return static
3730
     *                <p>Object whose $str has had spaces switched to tabs.</p>
3731
     */
3732 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...
3733
    {
3734 15
        if ($tabLength === 4) {
3735 9
            $tab = '    ';
3736 6
        } elseif ($tabLength === 2) {
3737 3
            $tab = '  ';
3738
        } else {
3739 3
            $tab = \str_repeat(' ', $tabLength);
3740
        }
3741
3742 15
        return static::create(
3743 15
            \str_replace($tab, "\t", $this->str),
3744 15
            $this->encoding
3745
        );
3746
    }
3747
3748
    /**
3749
     * Converts the first character of each word in the string to uppercase
3750
     * and all other chars to lowercase.
3751
     *
3752
     * @psalm-mutation-free
3753
     *
3754
     * @return static
3755
     *                <p>Object with all characters of $str being title-cased.</p>
3756
     */
3757 15
    public function toTitleCase(): self
3758
    {
3759 15
        return static::create(
3760 15
            $this->utf8::titlecase($this->str, $this->encoding),
3761 15
            $this->encoding
3762
        );
3763
    }
3764
3765
    /**
3766
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3767
     * replaced with their closest ASCII counterparts, and the rest are removed
3768
     * unless instructed otherwise.
3769
     *
3770
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
3771
     *                        performance | Default: false</p>
3772
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
3773
     *
3774
     * @psalm-mutation-free
3775
     *
3776
     * @return static
3777
     *                <p>Object whose $str contains only ASCII characters.</p>
3778
     */
3779 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
3780
    {
3781 34
        return static::create(
3782 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
3783 34
            $this->encoding
3784
        );
3785
    }
3786
3787
    /**
3788
     * Converts all characters in the string to uppercase.
3789
     *
3790
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3791
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3792
     *
3793
     * @psalm-mutation-free
3794
     *
3795
     * @return static
3796
     *                <p>Object with all characters of $str being uppercase.</p>
3797
     */
3798 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...
3799
    {
3800 26
        return static::create(
3801 26
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
3802 26
            $this->encoding
3803
        );
3804
    }
3805
3806
    /**
3807
     * Returns a string with whitespace removed from the start and end of the
3808
     * string. Supports the removal of unicode whitespace. Accepts an optional
3809
     * string of characters to strip instead of the defaults.
3810
     *
3811
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
3812
     *
3813
     * @psalm-mutation-free
3814
     *
3815
     * @return static
3816
     *                <p>Object with a trimmed $str.</p>
3817
     */
3818 36
    public function trim(string $chars = null): self
3819
    {
3820 36
        return static::create(
3821 36
            $this->utf8::trim($this->str, $chars),
3822 36
            $this->encoding
3823
        );
3824
    }
3825
3826
    /**
3827
     * Returns a string with whitespace removed from the start of the string.
3828
     * Supports the removal of unicode whitespace. Accepts an optional
3829
     * string of characters to strip instead of the defaults.
3830
     *
3831
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3832
     *
3833
     * @psalm-mutation-free
3834
     *
3835
     * @return static
3836
     *                <p>Object with a trimmed $str.</p>
3837
     */
3838 39
    public function trimLeft(string $chars = null): self
3839
    {
3840 39
        return static::create(
3841 39
            $this->utf8::ltrim($this->str, $chars),
3842 39
            $this->encoding
3843
        );
3844
    }
3845
3846
    /**
3847
     * Returns a string with whitespace removed from the end of the string.
3848
     * Supports the removal of unicode whitespace. Accepts an optional
3849
     * string of characters to strip instead of the defaults.
3850
     *
3851
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3852
     *
3853
     * @psalm-mutation-free
3854
     *
3855
     * @return static
3856
     *                <p>Object with a trimmed $str.</p>
3857
     */
3858 39
    public function trimRight(string $chars = null): self
3859
    {
3860 39
        return static::create(
3861 39
            $this->utf8::rtrim($this->str, $chars),
3862 39
            $this->encoding
3863
        );
3864
    }
3865
3866
    /**
3867
     * Truncates the string to a given length. If $substring is provided, and
3868
     * truncating occurs, the string is further truncated so that the substring
3869
     * may be appended without exceeding the desired length.
3870
     *
3871
     * @param int    $length    <p>Desired length of the truncated string.</p>
3872
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
3873
     *
3874
     * @psalm-mutation-free
3875
     *
3876
     * @return static
3877
     *                <p>Object with the resulting $str after truncating.</p>
3878
     */
3879 66
    public function truncate(int $length, string $substring = ''): self
3880
    {
3881 66
        return static::create(
3882 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
3883 66
            $this->encoding
3884
        );
3885
    }
3886
3887
    /**
3888
     * Returns a lowercase and trimmed string separated by underscores.
3889
     * Underscores are inserted before uppercase characters (with the exception
3890
     * of the first character of the string), and in place of spaces as well as
3891
     * dashes.
3892
     *
3893
     * @psalm-mutation-free
3894
     *
3895
     * @return static
3896
     *                <p>Object with an underscored $str.</p>
3897
     */
3898 48
    public function underscored(): self
3899
    {
3900 48
        return $this->delimit('_');
3901
    }
3902
3903
    /**
3904
     * Returns an UpperCamelCase version of the supplied string. It trims
3905
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
3906
     * and underscores, and removes spaces, dashes, underscores.
3907
     *
3908
     * @psalm-mutation-free
3909
     *
3910
     * @return static
3911
     *                <p>Object with $str in UpperCamelCase.</p>
3912
     */
3913 39
    public function upperCamelize(): self
3914
    {
3915 39
        return static::create(
3916 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
3917 39
            $this->encoding
3918
        );
3919
    }
3920
3921
    /**
3922
     * Converts the first character of the supplied string to upper case.
3923
     *
3924
     * @psalm-mutation-free
3925
     *
3926
     * @return static
3927
     *                <p>Object with the first character of $str being upper case.</p>
3928
     */
3929 18
    public function upperCaseFirst(): self
3930
    {
3931 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
3932
    }
3933
3934
    /**
3935
     * Simple url-decoding.
3936
     *
3937
     * e.g:
3938
     * 'test+test' => 'test test'
3939
     *
3940
     * @psalm-mutation-free
3941
     *
3942
     * @return static
3943
     */
3944 1
    public function urlDecode(): self
3945
    {
3946 1
        return static::create(\urldecode($this->str));
3947
    }
3948
3949
    /**
3950
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
3951
     *
3952
     * e.g:
3953
     * 'test+test'                     => 'test test'
3954
     * 'D&#252;sseldorf'               => 'Düsseldorf'
3955
     * 'D%FCsseldorf'                  => 'Düsseldorf'
3956
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
3957
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
3958
     * 'Düsseldorf'                   => 'Düsseldorf'
3959
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
3960
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
3961
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
3962
     *
3963
     * @psalm-mutation-free
3964
     *
3965
     * @return static
3966
     */
3967 1
    public function urlDecodeMulti(): self
3968
    {
3969 1
        return static::create($this->utf8::urldecode($this->str));
3970
    }
3971
3972
    /**
3973
     * Simple url-decoding.
3974
     *
3975
     * e.g:
3976
     * 'test+test' => 'test+test'
3977
     *
3978
     * @psalm-mutation-free
3979
     *
3980
     * @return static
3981
     */
3982 1
    public function urlDecodeRaw(): self
3983
    {
3984 1
        return static::create(\rawurldecode($this->str));
3985
    }
3986
3987
    /**
3988
     * Multi url-decoding + decode HTML entity + fix urlencoded-win1252-chars.
3989
     *
3990
     * e.g:
3991
     * 'test+test'                     => 'test+test'
3992
     * 'D&#252;sseldorf'               => 'Düsseldorf'
3993
     * 'D%FCsseldorf'                  => 'Düsseldorf'
3994
     * 'D&#xFC;sseldorf'               => 'Düsseldorf'
3995
     * 'D%26%23xFC%3Bsseldorf'         => 'Düsseldorf'
3996
     * 'Düsseldorf'                   => 'Düsseldorf'
3997
     * 'D%C3%BCsseldorf'               => 'Düsseldorf'
3998
     * 'D%C3%83%C2%BCsseldorf'         => 'Düsseldorf'
3999
     * 'D%25C3%2583%25C2%25BCsseldorf' => 'Düsseldorf'
4000
     *
4001
     * @psalm-mutation-free
4002
     *
4003
     * @return static
4004
     */
4005 1
    public function urlDecodeRawMulti(): self
4006
    {
4007 1
        return static::create($this->utf8::rawurldecode($this->str));
4008
    }
4009
4010
    /**
4011
     * Simple url-encoding.
4012
     *
4013
     * e.g:
4014
     * 'test test' => 'test+test'
4015
     *
4016
     * @psalm-mutation-free
4017
     *
4018
     * @return static
4019
     */
4020 1
    public function urlEncode(): self
4021
    {
4022 1
        return static::create(\urlencode($this->str));
4023
    }
4024
4025
    /**
4026
     * Simple url-encoding.
4027
     *
4028
     * e.g:
4029
     * 'test test' => 'test%20test'
4030
     *
4031
     * @psalm-mutation-free
4032
     *
4033
     * @return static
4034
     */
4035 1
    public function urlEncodeRaw(): self
4036
    {
4037 1
        return static::create(\rawurlencode($this->str));
4038
    }
4039
4040
    /**
4041
     * Converts the string into an URL slug. This includes replacing non-ASCII
4042
     * characters with their closest ASCII equivalents, removing remaining
4043
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
4044
     * $separator. The separator defaults to a single dash, and the string
4045
     * is also converted to lowercase.
4046
     *
4047
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
4048
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
4049
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
4050
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
4051
     *
4052
     * @psalm-mutation-free
4053
     *
4054
     * @return static
4055
     *                <p>Object whose $str has been converted to an URL slug.</p>
4056
     *
4057
     * @psalm-suppress ImpureMethodCall :/
4058
     */
4059 32
    public function urlify(
4060
        string $separator = '-',
4061
        string $language = 'en',
4062
        array $replacements = [],
4063
        bool $strToLower = true
4064
    ): self {
4065
        // init
4066 32
        $str = $this->str;
4067
4068 32
        foreach ($replacements as $from => $to) {
4069 32
            $str = \str_replace($from, $to, $str);
4070
        }
4071
4072 32
        return static::create(
4073 32
            URLify::slug(
4074 32
                $str,
4075 32
                $language,
4076 32
                $separator,
4077 32
                $strToLower
4078
            ),
4079 32
            $this->encoding
4080
        );
4081
    }
4082
4083
    /**
4084
     * Converts the string into an valid UTF-8 string.
4085
     *
4086
     * @psalm-mutation-free
4087
     *
4088
     * @return static
4089
     */
4090 2
    public function utf8ify(): self
4091
    {
4092 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
4093
    }
4094
4095
    /**
4096
     * Convert a string into an array of words.
4097
     *
4098
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4099
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4100
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4101
     *
4102
     * @psalm-mutation-free
4103
     *
4104
     * @return static[]
4105
     *
4106
     * @psalm-return array<int,static>
4107
     */
4108 14
    public function words(
4109
        string $char_list = '',
4110
        bool $remove_empty_values = false,
4111
        int $remove_short_values = null
4112
    ): array {
4113 14
        if ($remove_short_values === null) {
4114 14
            $strings = $this->utf8::str_to_words(
4115 14
                $this->str,
4116 14
                $char_list,
4117 14
                $remove_empty_values
4118
            );
4119
        } else {
4120 2
            $strings = $this->utf8::str_to_words(
4121 2
                $this->str,
4122 2
                $char_list,
4123 2
                $remove_empty_values,
4124 2
                $remove_short_values
4125
            );
4126
        }
4127
4128
        /** @noinspection AlterInForeachInspection */
4129 14
        foreach ($strings as &$string) {
4130 14
            $string = static::create($string);
4131
        }
4132
4133
        /** @noinspection PhpSillyAssignmentInspection */
4134
        /** @var static[] $strings */
4135 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...
4136
4137 14
        return $strings;
4138
    }
4139
4140
    /**
4141
     * Convert a string into an collection of words.
4142
     *
4143
     * @param string   $char_list           [optional] <p>Additional chars for the definition of "words".</p>
4144
     * @param bool     $remove_empty_values [optional] <p>Remove empty values.</p>
4145
     * @param int|null $remove_short_values [optional] <p>The min. string length or null to disable</p>
4146
     *
4147
     * @psalm-mutation-free
4148
     *
4149
     * @return CollectionStringy|static[]
4150
     *                                    <p>An collection of Stringy objects.</p>
4151
     *
4152
     * @psalm-return CollectionStringy<int,static>
4153
     */
4154 2
    public function wordsCollection(
4155
        string $char_list = '',
4156
        bool $remove_empty_values = false,
4157
        int $remove_short_values = null
4158
    ): CollectionStringy {
4159
        /**
4160
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
4161
         */
4162 2
        return CollectionStringy::create(
4163 2
            $this->words(
4164 2
                $char_list,
4165 2
                $remove_empty_values,
4166 2
                $remove_short_values
4167
            )
4168
        );
4169
    }
4170
4171
    /**
4172
     * Surrounds $str with the given substring.
4173
     *
4174
     * @param string $substring <p>The substring to add to both sides.</P>
4175
     *
4176
     * @psalm-mutation-free
4177
     *
4178
     * @return static
4179
     *                <p>Object whose $str had the substring both prepended and appended.</p>
4180
     */
4181 10
    public function wrap(string $substring): self
4182
    {
4183 10
        return $this->surround($substring);
4184
    }
4185
4186
    /**
4187
     * Returns the replacements for the toAscii() method.
4188
     *
4189
     * @noinspection PhpUnused
4190
     *
4191
     * @psalm-mutation-free
4192
     *
4193
     * @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...
4194
     *                       <p>An array of replacements.</p>
4195
     *
4196
     * @deprecated   this is only here for backward-compatibly reasons
4197
     */
4198 1
    protected function charsArray(): array
4199
    {
4200 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
4201
    }
4202
4203
    /**
4204
     * Returns true if $str matches the supplied pattern, false otherwise.
4205
     *
4206
     * @param string $pattern <p>Regex pattern to match against.</p>
4207
     *
4208
     * @psalm-mutation-free
4209
     *
4210
     * @return bool
4211
     *              <p>Whether or not $str matches the pattern.</p>
4212
     */
4213 24
    protected function matchesPattern(string $pattern): bool
4214
    {
4215 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
4216
    }
4217
}
4218