Completed
Push — master ( 989391...d3a134 )
by Lars
01:53
created

Stringy::explode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

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