Completed
Push — master ( e5e98d...989391 )
by Lars
03:14
created

Stringy::substringOf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 7
Ratio 58.33 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 7
loc 12
ccs 8
cts 8
cp 1
crap 1
rs 9.8666
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 3
            function ($str) {
1072 3
                return new static($str, $this->encoding);
1073 3
            },
1074 3
            $strings
1075
        );
1076
1077
        /** @var static[] $strings */
1078
    }
1079
1080
    /**
1081
     * Split a string by a string.
1082
     *
1083
     * @param string $delimiter <p>The boundary string</p>
1084
     * @param int    $limit     [optional] <p>The maximum number of elements in the exploded
1085
     *                          collection.</p>
1086
     *
1087
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
1088
     *   element containing the rest of string.
1089
     *   - If the limit parameter is negative, all components except the last -limit are returned.
1090
     *   - If the limit parameter is zero, then this is treated as 1
1091
     *
1092
     * @psalm-mutation-free
1093
     *
1094
     * @return CollectionStringy|static[]
1095
     *                                    <p>An collection of Stringy objects.</p>
1096
     *
1097
     * @psalm-return CollectionStringy<int,static>
1098
     */
1099 1
    public function explodeCollection(string $delimiter, int $limit = \PHP_INT_MAX): CollectionStringy
1100
    {
1101
        /**
1102
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
1103
         */
1104 1
        return CollectionStringy::create(
1105 1
            $this->explode($delimiter, $limit)
1106
        );
1107
    }
1108
1109
    /**
1110
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
1111
     *
1112
     * @param string   $search
1113
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
1114
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
1115
     *
1116
     * @psalm-mutation-free
1117
     *
1118
     * @return static
1119
     */
1120 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
1121
    {
1122 2
        return static::create(
1123 2
            $this->utf8::extract_text(
1124 2
                $this->str,
1125 2
                $search,
1126 2
                $length,
1127 2
                $replacerForSkippedText,
1128 2
                $this->encoding
1129
            ),
1130 2
            $this->encoding
1131
        );
1132
    }
1133
1134
    /**
1135
     * Returns the first $n characters of the string.
1136
     *
1137
     * @param int $n <p>Number of characters to retrieve from the start.</p>
1138
     *
1139
     * @psalm-mutation-free
1140
     *
1141
     * @return static
1142
     *                <p>Object with its $str being the first $n chars.</p>
1143
     */
1144 37
    public function first(int $n): self
1145
    {
1146 37
        return static::create(
1147 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
1148 37
            $this->encoding
1149
        );
1150
    }
1151
1152
    /**
1153
     * Return a formatted string via sprintf + named parameters via array syntax.
1154
     *
1155
     * <p>
1156
     * <br>
1157
     * It will use "sprintf()" so you can use e.g.:
1158
     * <br>
1159
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
1160
     * <br>
1161
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
1162
     * <br>
1163
     * <br>
1164
     * But you can also use named parameter via array syntax e.g.:
1165
     * <br>
1166
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
1167
     * </p>
1168
     *
1169
     * @param mixed ...$args [optional]
1170
     *
1171
     * @psalm-mutation-free
1172
     *
1173
     * @return static
1174
     *                <p>A Stringy object produced according to the formatting string
1175
     *                format.</p>
1176
     */
1177 10
    public function format(...$args): self
1178
    {
1179
        // init
1180 10
        $str = $this->str;
1181
1182 10
        if (\strpos($this->str, '%:') !== false) {
1183 8
            $offset = null;
1184 8
            $replacement = null;
1185
            /** @noinspection AlterInForeachInspection */
1186 8
            foreach ($args as $key => &$arg) {
1187 8
                if (!\is_array($arg)) {
1188 4
                    continue;
1189
                }
1190
1191 8
                foreach ($arg as $name => $param) {
1192 8
                    $name = (string) $name;
1193
1194 8
                    if (\strpos($name, '%:') !== 0) {
1195 8
                        $nameTmp = '%:' . $name;
1196
                    } else {
1197
                        $nameTmp = $name;
1198
                    }
1199
1200 8
                    if ($offset === null) {
1201 8
                        $offset = \strpos($str, $nameTmp);
1202
                    } else {
1203 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
1204
                    }
1205 8
                    if ($offset === false) {
1206 4
                        continue;
1207
                    }
1208
1209 8
                    unset($arg[$name]);
1210
1211 8
                    $str = \substr_replace($str, $param, (int) $offset, \strlen($nameTmp));
1212
                }
1213
1214 8
                unset($args[$key]);
1215
            }
1216
        }
1217
1218 10
        $str = \str_replace('%:', '%%:', $str);
1219
1220 10
        return static::create(
1221 10
            \sprintf($str, ...$args),
1222 10
            $this->encoding
1223
        );
1224
    }
1225
1226
    /**
1227
     * Returns the encoding used by the Stringy object.
1228
     *
1229
     * @psalm-mutation-free
1230
     *
1231
     * @return string
1232
     *                <p>The current value of the $encoding property.</p>
1233
     */
1234 7
    public function getEncoding(): string
1235
    {
1236 7
        return $this->encoding;
1237
    }
1238
1239
    /**
1240
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
1241
     * interface. The ArrayIterator's constructor is passed an array of chars
1242
     * in the multibyte string. This enables the use of foreach with instances
1243
     * of Stringy\Stringy.
1244
     *
1245
     * @psalm-mutation-free
1246
     *
1247
     * @return \ArrayIterator
1248
     *                        <p>An iterator for the characters in the string.</p>
1249
     *
1250
     * @psalm-return \ArrayIterator<array-key,string>
1251
     */
1252 3
    public function getIterator(): \ArrayIterator
1253
    {
1254 3
        return new \ArrayIterator($this->chars());
1255
    }
1256
1257
    /**
1258
     * Wrap the string after an exact number of characters.
1259
     *
1260
     * @param int    $width <p>Number of characters at which to wrap.</p>
1261
     * @param string $break [optional] <p>Character used to break the string. | Default: "\n"</p>
1262
     *
1263
     * @psalm-mutation-free
1264
     *
1265
     * @return static
1266
     */
1267 2
    public function hardWrap($width, $break = "\n"): self
1268
    {
1269 2
        return $this->lineWrap($width, $break, false);
1270
    }
1271
1272
    /**
1273
     * Returns true if the string contains a lower case char, false otherwise.
1274
     *
1275
     * @psalm-mutation-free
1276
     *
1277
     * @return bool
1278
     *              <p>Whether or not the string contains a lower case character.</p>
1279
     */
1280 36
    public function hasLowerCase(): bool
1281
    {
1282 36
        return $this->utf8::has_lowercase($this->str);
1283
    }
1284
1285
    /**
1286
     * Returns true if the string contains an upper case char, false otherwise.
1287
     *
1288
     * @psalm-mutation-free
1289
     *
1290
     * @return bool
1291
     *              <p>Whether or not the string contains an upper case character.</p>
1292
     */
1293 36
    public function hasUpperCase(): bool
1294
    {
1295 36
        return $this->utf8::has_uppercase($this->str);
1296
    }
1297
1298
    /**
1299
     * Generate a hash value (message digest)
1300
     *
1301
     * @see https://php.net/manual/en/function.hash.php
1302
     *
1303
     * @param string $algorithm
1304
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
1305
     *
1306
     * @psalm-mutation-free
1307
     *
1308
     * @return static
1309
     */
1310 8
    public function hash($algorithm): self
1311
    {
1312 8
        return static::create(\hash($algorithm, $this->str), $this->encoding);
1313
    }
1314
1315
    /**
1316
     * Decode the string from hex.
1317
     *
1318
     * @psalm-mutation-free
1319
     *
1320
     * @return static
1321
     */
1322 2
    public function hexDecode(): self
1323
    {
1324 2
        $string = \preg_replace_callback(
1325 2
            '/\\\\x([0-9A-Fa-f]+)/',
1326 2
            function (array $matched) {
1327 2
                return (string) $this->utf8::hex_to_chr($matched[1]);
1328 2
            },
1329 2
            $this->str
1330
        );
1331
1332 2
        return static::create(
1333 2
            $string,
1334 2
            $this->encoding
1335
        );
1336
    }
1337
1338
    /**
1339
     * Encode string to hex.
1340
     *
1341
     * @psalm-mutation-free
1342
     *
1343
     * @return static
1344
     */
1345 2
    public function hexEncode(): self
1346
    {
1347 2
        $string = \array_reduce(
1348 2
            $this->chars(),
1349 2
            function (string $str, string $char) {
1350 2
                return $str . $this->utf8::chr_to_hex($char);
1351 2
            },
1352 2
            ''
1353
        );
1354
1355 2
        return static::create(
1356 2
            $string,
1357 2
            $this->encoding
1358
        );
1359
    }
1360
1361
    /**
1362
     * Convert all HTML entities to their applicable characters.
1363
     *
1364
     * @param int $flags [optional] <p>
1365
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1366
     *                   which document type to use. The default is ENT_COMPAT.
1367
     *                   <table>
1368
     *                   Available <i>flags</i> constants
1369
     *                   <tr valign="top">
1370
     *                   <td>Constant Name</td>
1371
     *                   <td>Description</td>
1372
     *                   </tr>
1373
     *                   <tr valign="top">
1374
     *                   <td><b>ENT_COMPAT</b></td>
1375
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1376
     *                   </tr>
1377
     *                   <tr valign="top">
1378
     *                   <td><b>ENT_QUOTES</b></td>
1379
     *                   <td>Will convert both double and single quotes.</td>
1380
     *                   </tr>
1381
     *                   <tr valign="top">
1382
     *                   <td><b>ENT_NOQUOTES</b></td>
1383
     *                   <td>Will leave both double and single quotes unconverted.</td>
1384
     *                   </tr>
1385
     *                   <tr valign="top">
1386
     *                   <td><b>ENT_HTML401</b></td>
1387
     *                   <td>
1388
     *                   Handle code as HTML 4.01.
1389
     *                   </td>
1390
     *                   </tr>
1391
     *                   <tr valign="top">
1392
     *                   <td><b>ENT_XML1</b></td>
1393
     *                   <td>
1394
     *                   Handle code as XML 1.
1395
     *                   </td>
1396
     *                   </tr>
1397
     *                   <tr valign="top">
1398
     *                   <td><b>ENT_XHTML</b></td>
1399
     *                   <td>
1400
     *                   Handle code as XHTML.
1401
     *                   </td>
1402
     *                   </tr>
1403
     *                   <tr valign="top">
1404
     *                   <td><b>ENT_HTML5</b></td>
1405
     *                   <td>
1406
     *                   Handle code as HTML 5.
1407
     *                   </td>
1408
     *                   </tr>
1409
     *                   </table>
1410
     *                   </p>
1411
     *
1412
     * @psalm-mutation-free
1413
     *
1414
     * @return static
1415
     *                <p>Object with the resulting $str after being html decoded.</p>
1416
     */
1417 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...
1418
    {
1419 15
        return static::create(
1420 15
            $this->utf8::html_entity_decode(
1421 15
                $this->str,
1422 15
                $flags,
1423 15
                $this->encoding
1424
            ),
1425 15
            $this->encoding
1426
        );
1427
    }
1428
1429
    /**
1430
     * Convert all applicable characters to HTML entities.
1431
     *
1432
     * @param int $flags [optional] <p>
1433
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1434
     *                   which document type to use. The default is ENT_COMPAT.
1435
     *                   <table>
1436
     *                   Available <i>flags</i> constants
1437
     *                   <tr valign="top">
1438
     *                   <td>Constant Name</td>
1439
     *                   <td>Description</td>
1440
     *                   </tr>
1441
     *                   <tr valign="top">
1442
     *                   <td><b>ENT_COMPAT</b></td>
1443
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1444
     *                   </tr>
1445
     *                   <tr valign="top">
1446
     *                   <td><b>ENT_QUOTES</b></td>
1447
     *                   <td>Will convert both double and single quotes.</td>
1448
     *                   </tr>
1449
     *                   <tr valign="top">
1450
     *                   <td><b>ENT_NOQUOTES</b></td>
1451
     *                   <td>Will leave both double and single quotes unconverted.</td>
1452
     *                   </tr>
1453
     *                   <tr valign="top">
1454
     *                   <td><b>ENT_HTML401</b></td>
1455
     *                   <td>
1456
     *                   Handle code as HTML 4.01.
1457
     *                   </td>
1458
     *                   </tr>
1459
     *                   <tr valign="top">
1460
     *                   <td><b>ENT_XML1</b></td>
1461
     *                   <td>
1462
     *                   Handle code as XML 1.
1463
     *                   </td>
1464
     *                   </tr>
1465
     *                   <tr valign="top">
1466
     *                   <td><b>ENT_XHTML</b></td>
1467
     *                   <td>
1468
     *                   Handle code as XHTML.
1469
     *                   </td>
1470
     *                   </tr>
1471
     *                   <tr valign="top">
1472
     *                   <td><b>ENT_HTML5</b></td>
1473
     *                   <td>
1474
     *                   Handle code as HTML 5.
1475
     *                   </td>
1476
     *                   </tr>
1477
     *                   </table>
1478
     *                   </p>
1479
     *
1480
     * @psalm-mutation-free
1481
     *
1482
     * @return static
1483
     *                <p>Object with the resulting $str after being html encoded.</p>
1484
     */
1485 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...
1486
    {
1487 15
        return static::create(
1488 15
            $this->utf8::htmlentities(
1489 15
                $this->str,
1490 15
                $flags,
1491 15
                $this->encoding
1492
            ),
1493 15
            $this->encoding
1494
        );
1495
    }
1496
1497
    /**
1498
     * Capitalizes the first word of the string, replaces underscores with
1499
     * spaces, and strips '_id'.
1500
     *
1501
     * @psalm-mutation-free
1502
     *
1503
     * @return static
1504
     *                <p>Object with a humanized $str.</p>
1505
     */
1506 9
    public function humanize(): self
1507
    {
1508 9
        return static::create(
1509 9
            $this->utf8::str_humanize($this->str),
1510 9
            $this->encoding
1511
        );
1512
    }
1513
1514
    /**
1515
     * Determine if the current string exists in another string. By
1516
     * default, the comparison is case-sensitive, but can be made insensitive
1517
     * by setting $caseSensitive to false.
1518
     *
1519
     * @param string $str           <p>The string to compare against.</p>
1520
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1521
     *
1522
     * @psalm-mutation-free
1523
     *
1524
     * @return bool
1525
     */
1526 3
    public function in(string $str, bool $caseSensitive = true): bool
1527
    {
1528 3
        if ($caseSensitive) {
1529 2
            return \strpos($str, $this->str) !== false;
1530
        }
1531
1532 1
        return \stripos($str, $this->str) !== false;
1533
    }
1534
1535
    /**
1536
     * Returns the index of the first occurrence of $needle in the string,
1537
     * and false if not found. Accepts an optional offset from which to begin
1538
     * the search.
1539
     *
1540
     * @param string $needle <p>Substring to look for.</p>
1541
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1542
     *
1543
     * @psalm-mutation-free
1544
     *
1545
     * @return false|int
1546
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1547
     */
1548 31
    public function indexOf(string $needle, int $offset = 0)
1549
    {
1550 31
        return $this->utf8::strpos(
1551 31
            $this->str,
1552 31
            $needle,
1553 31
            $offset,
1554 31
            $this->encoding
1555
        );
1556
    }
1557
1558
    /**
1559
     * Returns the index of the first occurrence of $needle in the string,
1560
     * and false if not found. Accepts an optional offset from which to begin
1561
     * the search.
1562
     *
1563
     * @param string $needle <p>Substring to look for.</p>
1564
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1565
     *
1566
     * @psalm-mutation-free
1567
     *
1568
     * @return false|int
1569
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1570
     */
1571 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1572
    {
1573 20
        return $this->utf8::stripos(
1574 20
            $this->str,
1575 20
            $needle,
1576 20
            $offset,
1577 20
            $this->encoding
1578
        );
1579
    }
1580
1581
    /**
1582
     * Returns the index of the last occurrence of $needle in the string,
1583
     * and false if not found. Accepts an optional offset from which to begin
1584
     * the search. Offsets may be negative to count from the last character
1585
     * in the string.
1586
     *
1587
     * @param string $needle <p>Substring to look for.</p>
1588
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1589
     *
1590
     * @psalm-mutation-free
1591
     *
1592
     * @return false|int
1593
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1594
     */
1595 31
    public function indexOfLast(string $needle, int $offset = 0)
1596
    {
1597 31
        return $this->utf8::strrpos(
1598 31
            $this->str,
1599 31
            $needle,
1600 31
            $offset,
1601 31
            $this->encoding
1602
        );
1603
    }
1604
1605
    /**
1606
     * Returns the index of the last occurrence of $needle in the string,
1607
     * and false if not found. Accepts an optional offset from which to begin
1608
     * the search. Offsets may be negative to count from the last character
1609
     * in the string.
1610
     *
1611
     * @param string $needle <p>Substring to look for.</p>
1612
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1613
     *
1614
     * @psalm-mutation-free
1615
     *
1616
     * @return false|int
1617
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1618
     */
1619 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1620
    {
1621 20
        return $this->utf8::strripos(
1622 20
            $this->str,
1623 20
            $needle,
1624 20
            $offset,
1625 20
            $this->encoding
1626
        );
1627
    }
1628
1629
    /**
1630
     * Inserts $substring into the string at the $index provided.
1631
     *
1632
     * @param string $substring <p>String to be inserted.</p>
1633
     * @param int    $index     <p>The index at which to insert the substring.</p>
1634
     *
1635
     * @psalm-mutation-free
1636
     *
1637
     * @return static
1638
     *                <p>Object with the resulting $str after the insertion.</p>
1639
     */
1640 24
    public function insert(string $substring, int $index): self
1641
    {
1642 24
        return static::create(
1643 24
            $this->utf8::str_insert(
1644 24
                $this->str,
1645 24
                $substring,
1646 24
                $index,
1647 24
                $this->encoding
1648
            ),
1649 24
            $this->encoding
1650
        );
1651
    }
1652
1653
    /**
1654
     * Returns true if the string contains the $pattern, otherwise false.
1655
     *
1656
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1657
     * expression wildcards.
1658
     *
1659
     * @credit Originally from Laravel, thanks Taylor.
1660
     *
1661
     * @param string $pattern <p>The string or pattern to match against.</p>
1662
     *
1663
     * @psalm-mutation-free
1664
     *
1665
     * @return bool
1666
     *              <p>Whether or not we match the provided pattern.</p>
1667
     */
1668 26
    public function is(string $pattern): bool
1669
    {
1670 26
        if ($this->toString() === $pattern) {
1671 2
            return true;
1672
        }
1673
1674 24
        $quotedPattern = \preg_quote($pattern, '/');
1675 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1676
1677 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1678
    }
1679
1680
    /**
1681
     * Returns true if the string contains only alphabetic chars, false otherwise.
1682
     *
1683
     * @psalm-mutation-free
1684
     *
1685
     * @return bool
1686
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1687
     */
1688 30
    public function isAlpha(): bool
1689
    {
1690 30
        return $this->utf8::is_alpha($this->str);
1691
    }
1692
1693
    /**
1694
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1695
     *
1696
     * @psalm-mutation-free
1697
     *
1698
     * @return bool
1699
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1700
     */
1701 39
    public function isAlphanumeric(): bool
1702
    {
1703 39
        return $this->utf8::is_alphanumeric($this->str);
1704
    }
1705
1706
    /**
1707
     * Returns true if the string is base64 encoded, false otherwise.
1708
     *
1709
     * @param bool $emptyStringIsValid
1710
     *
1711
     * @psalm-mutation-free
1712
     *
1713
     * @return bool
1714
     *              <p>Whether or not $str is base64 encoded.</p>
1715
     */
1716 21
    public function isBase64($emptyStringIsValid = true): bool
1717
    {
1718 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
1719
    }
1720
1721
    /**
1722
     * Returns true if the string contains only whitespace chars, false otherwise.
1723
     *
1724
     * @psalm-mutation-free
1725
     *
1726
     * @return bool
1727
     *              <p>Whether or not $str contains only whitespace characters.</p>
1728
     */
1729 45
    public function isBlank(): bool
1730
    {
1731 45
        return $this->utf8::is_blank($this->str);
1732
    }
1733
1734
    /**
1735
     * Returns true if the string contains a valid E-Mail address, false otherwise.
1736
     *
1737
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
1738
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
1739
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
1740
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
1741
     *
1742
     * @psalm-mutation-free
1743
     *
1744
     * @return bool
1745
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
1746
     */
1747 2
    public function isEmail(
1748
        bool $useExampleDomainCheck = false,
1749
        bool $useTypoInDomainCheck = false,
1750
        bool $useTemporaryDomainCheck = false,
1751
        bool $useDnsCheck = false
1752
    ): bool {
1753
        /**
1754
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
1755
         */
1756 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
1757
    }
1758
1759
    /**
1760
     * Determine whether the string is considered to be empty.
1761
     *
1762
     * A variable is considered empty if it does not exist or if its value equals FALSE.
1763
     *
1764
     * @psalm-mutation-free
1765
     *
1766
     * @return bool
1767
     *              <p>Whether or not $str is empty().</p>
1768
     */
1769 10
    public function isEmpty(): bool
1770
    {
1771 10
        return $this->utf8::is_empty($this->str);
1772
    }
1773
1774
    /**
1775
     * Determine whether the string is equals to $str.
1776
     * Alias for isEqualsCaseSensitive()
1777
     *
1778
     * @param string|Stringy ...$str
1779
     *
1780
     * @psalm-mutation-free
1781
     *
1782
     * @return bool
1783
     */
1784 13
    public function isEquals(...$str): bool
1785
    {
1786 13
        return $this->isEqualsCaseSensitive(...$str);
1787
    }
1788
1789
    /**
1790
     * Determine whether the string is equals to $str.
1791
     *
1792
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1793
     *
1794
     * @psalm-mutation-free
1795
     *
1796
     * @return bool
1797
     *              <p>Whether or not $str is equals.</p>
1798
     */
1799 3
    public function isEqualsCaseInsensitive(...$str): bool
1800
    {
1801 3
        $strUpper = $this->toUpperCase()->str;
1802
1803 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...
1804
            /**
1805
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1806
             */
1807 3
            if ($strTmp instanceof self) {
1808
                if ($strUpper !== $strTmp->toUpperCase()->str) {
1809
                    return false;
1810
                }
1811 3
            } elseif (\is_scalar($strTmp)) {
1812 3
                if ($strUpper !== $this->utf8::strtoupper((string) $strTmp, $this->encoding)) {
1813 3
                    return false;
1814
                }
1815
            } else {
1816 3
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1817
            }
1818
        }
1819
1820 3
        return true;
1821
    }
1822
1823
    /**
1824
     * Determine whether the string is equals to $str.
1825
     *
1826
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1827
     *
1828
     * @psalm-mutation-free
1829
     *
1830
     * @return bool
1831
     *              <p>Whether or not $str is equals.</p>
1832
     */
1833 14
    public function isEqualsCaseSensitive(...$str): bool
1834
    {
1835 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...
1836
            /**
1837
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1838
             */
1839 14
            if ($strTmp instanceof self) {
1840 2
                if ($this->str !== $strTmp->str) {
1841 2
                    return false;
1842
                }
1843 12
            } elseif (\is_scalar($strTmp)) {
1844 12
                if ($this->str !== (string) $strTmp) {
1845 12
                    return false;
1846
                }
1847
            } else {
1848 3
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1849
            }
1850
        }
1851
1852 3
        return true;
1853
    }
1854
1855
    /**
1856
     * Returns true if the string contains only hexadecimal chars, false otherwise.
1857
     *
1858
     * @psalm-mutation-free
1859
     *
1860
     * @return bool
1861
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
1862
     */
1863 39
    public function isHexadecimal(): bool
1864
    {
1865 39
        return $this->utf8::is_hexadecimal($this->str);
1866
    }
1867
1868
    /**
1869
     * Returns true if the string contains HTML-Tags, false otherwise.
1870
     *
1871
     * @psalm-mutation-free
1872
     *
1873
     * @return bool
1874
     *              <p>Whether or not $str contains HTML-Tags.</p>
1875
     */
1876 2
    public function isHtml(): bool
1877
    {
1878 2
        return $this->utf8::is_html($this->str);
1879
    }
1880
1881
    /**
1882
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
1883
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
1884
     * in that an empty string is not considered valid JSON.
1885
     *
1886
     * @param bool $onlyArrayOrObjectResultsAreValid
1887
     *
1888
     * @psalm-mutation-free
1889
     *
1890
     * @return bool
1891
     *              <p>Whether or not $str is JSON.</p>
1892
     */
1893 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
1894
    {
1895
        /**
1896
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to vendor stuff?
1897
         */
1898 60
        return $this->utf8::is_json(
1899 60
            $this->str,
1900 60
            $onlyArrayOrObjectResultsAreValid
1901
        );
1902
    }
1903
1904
    /**
1905
     * Returns true if the string contains only lower case chars, false otherwise.
1906
     *
1907
     * @psalm-mutation-free
1908
     *
1909
     * @return bool
1910
     *              <p>Whether or not $str contains only lower case characters.</p>
1911
     */
1912 24
    public function isLowerCase(): bool
1913
    {
1914 24
        return $this->utf8::is_lowercase($this->str);
1915
    }
1916
1917
    /**
1918
     * Determine whether the string is considered to be NOT empty.
1919
     *
1920
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
1921
     *
1922
     * @psalm-mutation-free
1923
     *
1924
     * @return bool
1925
     *              <p>Whether or not $str is empty().</p>
1926
     */
1927 10
    public function isNotEmpty(): bool
1928
    {
1929 10
        return !$this->utf8::is_empty($this->str);
1930
    }
1931
1932
    /**
1933
     * Determine if the string is composed of numeric characters.
1934
     *
1935
     * @psalm-mutation-free
1936
     *
1937
     * @return bool
1938
     */
1939 4
    public function isNumeric(): bool
1940
    {
1941 4
        return \is_numeric($this->str);
1942
    }
1943
1944
    /**
1945
     * Determine if the string is composed of printable (non-invisible) characters.
1946
     *
1947
     * @psalm-mutation-free
1948
     *
1949
     * @return bool
1950
     */
1951 3
    public function isPrintable(): bool
1952
    {
1953 3
        return $this->utf8::is_printable($this->str);
1954
    }
1955
1956
    /**
1957
     * Determine if the string is composed of punctuation characters.
1958
     *
1959
     * @psalm-mutation-free
1960
     *
1961
     * @return bool
1962
     */
1963 3
    public function isPunctuation(): bool
1964
    {
1965 3
        return $this->utf8::is_punctuation($this->str);
1966
    }
1967
1968
    /**
1969
     * Returns true if the string is serialized, false otherwise.
1970
     *
1971
     * @psalm-mutation-free
1972
     *
1973
     * @return bool
1974
     *              <p>Whether or not $str is serialized.</p>
1975
     */
1976 21
    public function isSerialized(): bool
1977
    {
1978 21
        return $this->utf8::is_serialized($this->str);
1979
    }
1980
1981
    /**
1982
     * Check if two strings are similar.
1983
     *
1984
     * @param string $str                     <p>The string to compare against.</p>
1985
     * @param float  $minPercentForSimilarity [optional] <p>The percentage of needed similarity. | Default: 80%</p>
1986
     *
1987
     * @psalm-mutation-free
1988
     *
1989
     * @return bool
1990
     */
1991 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
1992
    {
1993 2
        return $this->similarity($str) >= $minPercentForSimilarity;
1994
    }
1995
1996
    /**
1997
     * Returns true if the string contains only lower case chars, false
1998
     * otherwise.
1999
     *
2000
     * @psalm-mutation-free
2001
     *
2002
     * @return bool
2003
     *              <p>Whether or not $str contains only lower case characters.</p>
2004
     */
2005 24
    public function isUpperCase(): bool
2006
    {
2007 24
        return $this->utf8::is_uppercase($this->str);
2008
    }
2009
2010
    /**
2011
     * Returns true if the string contains only whitespace chars, false otherwise.
2012
     *
2013
     * @psalm-mutation-free
2014
     *
2015
     * @return bool
2016
     *              <p>Whether or not $str contains only whitespace characters.</p>
2017
     */
2018 30
    public function isWhitespace(): bool
2019
    {
2020 30
        return $this->isBlank();
2021
    }
2022
2023
    /**
2024
     * Returns value which can be serialized by json_encode().
2025
     *
2026
     * @noinspection ReturnTypeCanBeDeclaredInspection
2027
     *
2028
     * @psalm-mutation-free
2029
     *
2030
     * @return string The current value of the $str property
2031
     */
2032 2
    public function jsonSerialize()
2033
    {
2034 2
        return (string) $this;
2035
    }
2036
2037
    /**
2038
     * Convert the string to kebab-case.
2039
     *
2040
     * @psalm-mutation-free
2041
     *
2042
     * @return static
2043
     */
2044 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...
2045
    {
2046 3
        $words = \array_map(
2047 3
            static function (self $word) {
2048 3
                return $word->toLowerCase();
2049 3
            },
2050 3
            $this->words('', true)
2051
        );
2052
2053 3
        return new static(\implode('-', $words), $this->encoding);
2054
    }
2055
2056
    /**
2057
     * Returns the last $n characters of the string.
2058
     *
2059
     * @param int $n <p>Number of characters to retrieve from the end.</p>
2060
     *
2061
     * @psalm-mutation-free
2062
     *
2063
     * @return static
2064
     *                <p>Object with its $str being the last $n chars.</p>
2065
     */
2066 36
    public function last(int $n): self
2067
    {
2068 36
        return static::create(
2069 36
            $this->utf8::str_last_char(
2070 36
                $this->str,
2071 36
                $n,
2072 36
                $this->encoding
2073
            ),
2074 36
            $this->encoding
2075
        );
2076
    }
2077
2078
    /**
2079
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2080
     * If no match is found returns new empty Stringy object.
2081
     *
2082
     * @param string $needle       <p>The string to look for.</p>
2083
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2084
     *
2085
     * @psalm-mutation-free
2086
     *
2087
     * @return static
2088
     */
2089 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...
2090
    {
2091 4
        return static::create(
2092 4
            $this->utf8::str_substr_last(
2093 4
                $this->str,
2094 4
                $needle,
2095 4
                $beforeNeedle,
2096 4
                $this->encoding
2097
            ),
2098 4
            $this->encoding
2099
        );
2100
    }
2101
2102
    /**
2103
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
2104
     * If no match is found returns new empty Stringy object.
2105
     *
2106
     * @param string $needle       <p>The string to look for.</p>
2107
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2108
     *
2109
     * @psalm-mutation-free
2110
     *
2111
     * @return static
2112
     */
2113 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...
2114
    {
2115 2
        return static::create(
2116 2
            $this->utf8::str_isubstr_last(
2117 2
                $this->str,
2118 2
                $needle,
2119 2
                $beforeNeedle,
2120 2
                $this->encoding
2121
            ),
2122 2
            $this->encoding
2123
        );
2124
    }
2125
2126
    /**
2127
     * Returns the length of the string.
2128
     *
2129
     * @psalm-mutation-free
2130
     *
2131
     * @return int
2132
     *             <p>The number of characters in $str given the encoding.</p>
2133
     */
2134 17
    public function length(): int
2135
    {
2136 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
2137
    }
2138
2139
    /**
2140
     * Line-Wrap the string after $limit, but also after the next word.
2141
     *
2142
     * @param int         $limit           [optional] <p>The column width.</p>
2143
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2144
     * @param bool        $add_final_break [optional] <p>
2145
     *                                     If this flag is true, then the method will add a $break at the end
2146
     *                                     of the result string.
2147
     *                                     </p>
2148
     * @param string|null $delimiter       [optional] <p>
2149
     *                                     You can change the default behavior, where we split the string by newline.
2150
     *                                     </p>
2151
     *
2152
     * @psalm-mutation-free
2153
     *
2154
     * @return static
2155
     */
2156 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...
2157
        int $limit,
2158
        string $break = "\n",
2159
        bool $add_final_break = true,
2160
        string $delimiter = null
2161
    ): self {
2162 3
        return static::create(
2163 3
            $this->utf8::wordwrap_per_line(
2164 3
                $this->str,
2165 3
                $limit,
2166 3
                $break,
2167 3
                true,
2168 3
                $add_final_break,
2169 3
                $delimiter
2170
            ),
2171 3
            $this->encoding
2172
        );
2173
    }
2174
2175
    /**
2176
     * Line-Wrap the string after $limit, but also after the next word.
2177
     *
2178
     * @param int         $limit           [optional] <p>The column width.</p>
2179
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
2180
     * @param bool        $add_final_break [optional] <p>
2181
     *                                     If this flag is true, then the method will add a $break at the end
2182
     *                                     of the result string.
2183
     *                                     </p>
2184
     * @param string|null $delimiter       [optional] <p>
2185
     *                                     You can change the default behavior, where we split the string by newline.
2186
     *                                     </p>
2187
     *
2188
     * @psalm-mutation-free
2189
     *
2190
     * @return static
2191
     */
2192 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...
2193
        int $limit,
2194
        string $break = "\n",
2195
        bool $add_final_break = true,
2196
        string $delimiter = null
2197
    ): self {
2198 4
        return static::create(
2199 4
            $this->utf8::wordwrap_per_line(
2200 4
                $this->str,
2201 4
                $limit,
2202 4
                $break,
2203 4
                false,
2204 4
                $add_final_break,
2205 4
                $delimiter
2206
            ),
2207 4
            $this->encoding
2208
        );
2209
    }
2210
2211
    /**
2212
     * Splits on newlines and carriage returns, returning an array of Stringy
2213
     * objects corresponding to the lines in the string.
2214
     *
2215
     * @psalm-mutation-free
2216
     *
2217
     * @return static[]
2218
     *                  <p>An array of Stringy objects.</p>
2219
     *
2220
     * @psalm-return array<int,static>
2221
     */
2222 51
    public function lines(): array
2223
    {
2224 51
        if ($this->str === '') {
2225 3
            return [static::create('')];
2226
        }
2227
2228 48
        $strings = $this->utf8::str_to_lines($this->str);
2229
        /** @noinspection AlterInForeachInspection */
2230 48
        foreach ($strings as &$str) {
2231 48
            $str = static::create($str, $this->encoding);
2232
        }
2233
2234
        /** @noinspection PhpSillyAssignmentInspection */
2235
        /** @var static[] $strings */
2236 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...
2237
2238 48
        return $strings;
2239
    }
2240
2241
    /**
2242
     * Splits on newlines and carriage returns, returning an array of Stringy
2243
     * objects corresponding to the lines in the string.
2244
     *
2245
     * @psalm-mutation-free
2246
     *
2247
     * @return CollectionStringy|static[]
2248
     *                                    <p>An collection of Stringy objects.</p>
2249
     *
2250
     * @psalm-return CollectionStringy<int,static>
2251
     */
2252 34
    public function linesCollection(): CollectionStringy
2253
    {
2254
        /**
2255
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2256
         */
2257 34
        return CollectionStringy::create(
2258 34
            $this->lines()
2259
        );
2260
    }
2261
2262
    /**
2263
     * Returns the longest common prefix between the string and $otherStr.
2264
     *
2265
     * @param string $otherStr <p>Second string for comparison.</p>
2266
     *
2267
     * @psalm-mutation-free
2268
     *
2269
     * @return static
2270
     *                <p>Object with its $str being the longest common prefix.</p>
2271
     */
2272 30
    public function longestCommonPrefix(string $otherStr): self
2273
    {
2274 30
        return static::create(
2275 30
            $this->utf8::str_longest_common_prefix(
2276 30
                $this->str,
2277 30
                $otherStr,
2278 30
                $this->encoding
2279
            ),
2280 30
            $this->encoding
2281
        );
2282
    }
2283
2284
    /**
2285
     * Returns the longest common substring between the string and $otherStr.
2286
     * In the case of ties, it returns that which occurs first.
2287
     *
2288
     * @param string $otherStr <p>Second string for comparison.</p>
2289
     *
2290
     * @psalm-mutation-free
2291
     *
2292
     * @return static
2293
     *                <p>Object with its $str being the longest common substring.</p>
2294
     */
2295 30
    public function longestCommonSubstring(string $otherStr): self
2296
    {
2297 30
        return static::create(
2298 30
            $this->utf8::str_longest_common_substring(
2299 30
                $this->str,
2300 30
                $otherStr,
2301 30
                $this->encoding
2302
            ),
2303 30
            $this->encoding
2304
        );
2305
    }
2306
2307
    /**
2308
     * Returns the longest common suffix between the string and $otherStr.
2309
     *
2310
     * @param string $otherStr <p>Second string for comparison.</p>
2311
     *
2312
     * @psalm-mutation-free
2313
     *
2314
     * @return static
2315
     *                <p>Object with its $str being the longest common suffix.</p>
2316
     */
2317 30
    public function longestCommonSuffix(string $otherStr): self
2318
    {
2319 30
        return static::create(
2320 30
            $this->utf8::str_longest_common_suffix(
2321 30
                $this->str,
2322 30
                $otherStr,
2323 30
                $this->encoding
2324
            ),
2325 30
            $this->encoding
2326
        );
2327
    }
2328
2329
    /**
2330
     * Converts the first character of the string to lower case.
2331
     *
2332
     * @psalm-mutation-free
2333
     *
2334
     * @return static
2335
     *                <p>Object with the first character of $str being lower case.</p>
2336
     */
2337 15
    public function lowerCaseFirst(): self
2338
    {
2339 15
        return static::create(
2340 15
            $this->utf8::lcfirst($this->str, $this->encoding),
2341 15
            $this->encoding
2342
        );
2343
    }
2344
2345
    /**
2346
     * Determine if the string matches another string regardless of case.
2347
     * Alias for isEqualsCaseInsensitive()
2348
     *
2349
     * @psalm-mutation-free
2350
     *
2351
     * @param string|Stringy ...$str
2352
     *                               <p>The string to compare against.</p>
2353
     *
2354
     * @psalm-mutation-free
2355
     *
2356
     * @return bool
2357
     */
2358 3
    public function matchCaseInsensitive(...$str): bool
2359
    {
2360 3
        return $this->isEqualsCaseInsensitive(...$str);
2361
    }
2362
2363
    /**
2364
     * Determine if the string matches another string.
2365
     * Alias for isEqualsCaseSensitive()
2366
     *
2367
     * @psalm-mutation-free
2368
     *
2369
     * @param string|Stringy ...$str
2370
     *                               <p>The string to compare against.</p>
2371
     *
2372
     * @psalm-mutation-free
2373
     *
2374
     * @return bool
2375
     */
2376 7
    public function matchCaseSensitive(...$str): bool
2377
    {
2378 7
        return $this->isEqualsCaseSensitive(...$str);
2379
    }
2380
2381
    /**
2382
     * Create a md5 hash from the current string.
2383
     *
2384
     * @psalm-mutation-free
2385
     *
2386
     * @return static
2387
     */
2388 2
    public function md5(): self
2389
    {
2390 2
        return static::create($this->hash('md5'), $this->encoding);
2391
    }
2392
2393
    /**
2394
     * Replace all breaks [<br> | \r\n | \r | \n | ...] into "<br>".
2395
     *
2396
     * @return static
2397
     */
2398 1
    public function newLineToHtmlBreak(): self
2399
    {
2400 1
        return $this->removeHtmlBreak('<br>');
2401
    }
2402
2403
    /**
2404
     * Get every nth character of the string.
2405
     *
2406
     * @param int $step   <p>The number of characters to step.</p>
2407
     * @param int $offset [optional] <p>The string offset to start at.</p>
2408
     *
2409
     * @psalm-mutation-free
2410
     *
2411
     * @return static
2412
     */
2413 4
    public function nth(int $step, int $offset = 0): self
2414
    {
2415 4
        $length = $step - 1;
2416 4
        $substring = $this->substr($offset)->toString();
2417
2418 4
        if ($substring === '') {
2419
            return new static('', $this->encoding);
2420
        }
2421
2422 4
        \preg_match_all(
2423 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2424 4
            $substring,
2425 4
            $matches
2426
        );
2427
2428 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2429
    }
2430
2431
    /**
2432
     * Returns whether or not a character exists at an index. Offsets may be
2433
     * negative to count from the last character in the string. Implements
2434
     * part of the ArrayAccess interface.
2435
     *
2436
     * @param int $offset <p>The index to check.</p>
2437
     *
2438
     * @psalm-mutation-free
2439
     *
2440
     * @return bool
2441
     *              <p>Whether or not the index exists.</p>
2442
     */
2443 18
    public function offsetExists($offset): bool
2444
    {
2445 18
        return $this->utf8::str_offset_exists(
2446 18
            $this->str,
2447 18
            $offset,
2448 18
            $this->encoding
2449
        );
2450
    }
2451
2452
    /**
2453
     * Returns the character at the given index. Offsets may be negative to
2454
     * count from the last character in the string. Implements part of the
2455
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2456
     * does not exist.
2457
     *
2458
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2459
     *
2460
     * @throws \OutOfBoundsException
2461
     *                               <p>If the positive or negative offset does not exist.</p>
2462
     *
2463
     * @return string
2464
     *                <p>The character at the specified index.</p>
2465
     *
2466
     * @psalm-mutation-free
2467
     */
2468 6
    public function offsetGet($offset): string
2469
    {
2470 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2471
    }
2472
2473
    /**
2474
     * Implements part of the ArrayAccess interface, but throws an exception
2475
     * when called. This maintains the immutability of Stringy objects.
2476
     *
2477
     * @param int   $offset <p>The index of the character.</p>
2478
     * @param mixed $value  <p>Value to set.</p>
2479
     *
2480
     * @throws \Exception
2481
     *                    <p>When called.</p>
2482
     *
2483
     * @return void
2484
     */
2485 3
    public function offsetSet($offset, $value)
2486
    {
2487
        // Stringy is immutable, cannot directly set char
2488
        /** @noinspection ThrowRawExceptionInspection */
2489 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
2490
    }
2491
2492
    /**
2493
     * Implements part of the ArrayAccess interface, but throws an exception
2494
     * when called. This maintains the immutability of Stringy objects.
2495
     *
2496
     * @param int $offset <p>The index of the character.</p>
2497
     *
2498
     * @throws \Exception
2499
     *                    <p>When called.</p>
2500
     *
2501
     * @return void
2502
     */
2503 3
    public function offsetUnset($offset)
2504
    {
2505
        // Don't allow directly modifying the string
2506
        /** @noinspection ThrowRawExceptionInspection */
2507 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
2508
    }
2509
2510
    /**
2511
     * Pads the string to a given length with $padStr. If length is less than
2512
     * or equal to the length of the string, no padding takes places. The
2513
     * default string used for padding is a space, and the default type (one of
2514
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
2515
     * if $padType isn't one of those 3 values.
2516
     *
2517
     * @param int    $length  <p>Desired string length after padding.</p>
2518
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2519
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
2520
     *
2521
     * @throws \InvalidArgumentException
2522
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
2523
     *
2524
     * @return static
2525
     *                <p>Object with a padded $str.</p>
2526
     *
2527
     * @psalm-mutation-free
2528
     */
2529 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
2530
    {
2531 39
        return static::create(
2532 39
            $this->utf8::str_pad(
2533 39
                $this->str,
2534 39
                $length,
2535 39
                $padStr,
2536 39
                $padType,
2537 39
                $this->encoding
2538
            )
2539
        );
2540
    }
2541
2542
    /**
2543
     * Returns a new string of a given length such that both sides of the
2544
     * string are padded. Alias for pad() with a $padType of 'both'.
2545
     *
2546
     * @param int    $length <p>Desired string length after padding.</p>
2547
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2548
     *
2549
     * @psalm-mutation-free
2550
     *
2551
     * @return static
2552
     *                <p>String with padding applied.</p>
2553
     */
2554 33
    public function padBoth(int $length, string $padStr = ' '): self
2555
    {
2556 33
        return static::create(
2557 33
            $this->utf8::str_pad_both(
2558 33
                $this->str,
2559 33
                $length,
2560 33
                $padStr,
2561 33
                $this->encoding
2562
            )
2563
        );
2564
    }
2565
2566
    /**
2567
     * Returns a new string of a given length such that the beginning of the
2568
     * string is padded. Alias for pad() with a $padType of 'left'.
2569
     *
2570
     * @param int    $length <p>Desired string length after padding.</p>
2571
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2572
     *
2573
     * @psalm-mutation-free
2574
     *
2575
     * @return static
2576
     *                <p>String with left padding.</p>
2577
     */
2578 21
    public function padLeft(int $length, string $padStr = ' '): self
2579
    {
2580 21
        return static::create(
2581 21
            $this->utf8::str_pad_left(
2582 21
                $this->str,
2583 21
                $length,
2584 21
                $padStr,
2585 21
                $this->encoding
2586
            )
2587
        );
2588
    }
2589
2590
    /**
2591
     * Returns a new string of a given length such that the end of the string
2592
     * is padded. Alias for pad() with a $padType of 'right'.
2593
     *
2594
     * @param int    $length <p>Desired string length after padding.</p>
2595
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2596
     *
2597
     * @psalm-mutation-free
2598
     *
2599
     * @return static
2600
     *                <p>String with right padding.</p>
2601
     */
2602 21
    public function padRight(int $length, string $padStr = ' '): self
2603
    {
2604 21
        return static::create(
2605 21
            $this->utf8::str_pad_right(
2606 21
                $this->str,
2607 21
                $length,
2608 21
                $padStr,
2609 21
                $this->encoding
2610
            )
2611
        );
2612
    }
2613
2614
    /**
2615
     * Convert the string to PascalCase.
2616
     * Alias for studlyCase()
2617
     *
2618
     * @psalm-mutation-free
2619
     *
2620
     * @return static
2621
     */
2622 3
    public function pascalCase(): self
2623
    {
2624 3
        return $this->studlyCase();
2625
    }
2626
2627
    /**
2628
     * Returns a new string starting with $prefix.
2629
     *
2630
     * @param string ...$prefix <p>The string to append.</p>
2631
     *
2632
     * @psalm-mutation-free
2633
     *
2634
     * @return static
2635
     *                <p>Object with appended $prefix.</p>
2636
     */
2637 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...
2638
    {
2639 8
        if (\count($prefix) <= 1) {
2640
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2641 6
            $prefix = $prefix[0];
2642
        } else {
2643
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2644 2
            $prefix = \implode('', $prefix);
2645
        }
2646
2647 8
        return static::create($prefix . $this->str, $this->encoding);
2648
    }
2649
2650
    /**
2651
     * Returns a new string starting with $prefix.
2652
     *
2653
     * @param CollectionStringy|static ...$prefix <p>The Stringy objects to append.</p>
2654
     *
2655
     * @psalm-param CollectionStringy<int,static>|static ...$prefix
2656
     *
2657
     * @psalm-mutation-free
2658
     *
2659
     * @return static
2660
     *                <p>Object with appended $prefix.</p>
2661
     */
2662 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...
2663
    {
2664 1
        $prefixStr = '';
2665 1
        foreach ($prefix as $prefixTmp) {
2666 1
            if ($prefixTmp instanceof CollectionStringy) {
2667 1
                $prefixStr .= $prefixTmp->implode('');
2668
            } else {
2669 1
                $prefixStr .= $prefixTmp->toString();
2670
            }
2671
        }
2672
2673 1
        return static::create($prefixStr . $this->str, $this->encoding);
2674
    }
2675
2676
    /**
2677
     * Replaces all occurrences of $pattern in $str by $replacement.
2678
     *
2679
     * @param string $pattern     <p>The regular expression pattern.</p>
2680
     * @param string $replacement <p>The string to replace with.</p>
2681
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2682
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2683
     *
2684
     * @psalm-mutation-free
2685
     *
2686
     * @return static
2687
     *                <p>Object with the result2ing $str after the replacements.</p>
2688
     */
2689 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2690
    {
2691 29
        return static::create(
2692 29
            $this->utf8::regex_replace(
2693 29
                $this->str,
2694 29
                $pattern,
2695 29
                $replacement,
2696 29
                $options,
2697 29
                $delimiter
2698
            ),
2699 29
            $this->encoding
2700
        );
2701
    }
2702
2703
    /**
2704
     * Remove html via "strip_tags()" from the string.
2705
     *
2706
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2707
     *                              not be stripped. Default: null
2708
     *                              </p>
2709
     *
2710
     * @psalm-mutation-free
2711
     *
2712
     * @return static
2713
     */
2714 12
    public function removeHtml(string $allowableTags = ''): self
2715
    {
2716 12
        return static::create(
2717 12
            $this->utf8::remove_html($this->str, $allowableTags),
2718 12
            $this->encoding
2719
        );
2720
    }
2721
2722
    /**
2723
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2724
     *
2725
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2726
     *
2727
     * @psalm-mutation-free
2728
     *
2729
     * @return static
2730
     */
2731 13
    public function removeHtmlBreak(string $replacement = ''): self
2732
    {
2733 13
        return static::create(
2734 13
            $this->utf8::remove_html_breaks($this->str, $replacement),
2735 13
            $this->encoding
2736
        );
2737
    }
2738
2739
    /**
2740
     * Returns a new string with the prefix $substring removed, if present.
2741
     *
2742
     * @param string $substring <p>The prefix to remove.</p>
2743
     *
2744
     * @psalm-mutation-free
2745
     *
2746
     * @return static
2747
     *                <p>Object having a $str without the prefix $substring.</p>
2748
     */
2749 36
    public function removeLeft(string $substring): self
2750
    {
2751 36
        return static::create(
2752 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2753 36
            $this->encoding
2754
        );
2755
    }
2756
2757
    /**
2758
     * Returns a new string with the suffix $substring removed, if present.
2759
     *
2760
     * @param string $substring <p>The suffix to remove.</p>
2761
     *
2762
     * @psalm-mutation-free
2763
     *
2764
     * @return static
2765
     *                <p>Object having a $str without the suffix $substring.</p>
2766
     */
2767 36
    public function removeRight(string $substring): self
2768
    {
2769 36
        return static::create(
2770 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2771 36
            $this->encoding
2772
        );
2773
    }
2774
2775
    /**
2776
     * Try to remove all XSS-attacks from the string.
2777
     *
2778
     * @psalm-mutation-free
2779
     *
2780
     * @return static
2781
     */
2782 12
    public function removeXss(): self
2783
    {
2784
        /**
2785
         * @var AntiXSS|null
2786
         *
2787
         * @psalm-suppress ImpureStaticVariable
2788
         */
2789 12
        static $antiXss = null;
2790
2791 12
        if ($antiXss === null) {
2792 1
            $antiXss = new AntiXSS();
2793
        }
2794
2795
        /**
2796
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2797
         */
2798 12
        $str = $antiXss->xss_clean($this->str);
2799
2800 12
        return static::create($str, $this->encoding);
2801
    }
2802
2803
    /**
2804
     * Returns a repeated string given a multiplier.
2805
     *
2806
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2807
     *
2808
     * @psalm-mutation-free
2809
     *
2810
     * @return static
2811
     *                <p>Object with a repeated str.</p>
2812
     */
2813 21
    public function repeat(int $multiplier): self
2814
    {
2815 21
        return static::create(
2816 21
            \str_repeat($this->str, $multiplier),
2817 21
            $this->encoding
2818
        );
2819
    }
2820
2821
    /**
2822
     * Replaces all occurrences of $search in $str by $replacement.
2823
     *
2824
     * @param string $search        <p>The needle to search for.</p>
2825
     * @param string $replacement   <p>The string to replace with.</p>
2826
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2827
     *
2828
     * @psalm-mutation-free
2829
     *
2830
     * @return static
2831
     *                <p>Object with the resulting $str after the replacements.</p>
2832
     */
2833 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2834
    {
2835 76
        if ($search === '' && $replacement === '') {
2836 16
            return static::create($this->str, $this->encoding);
2837
        }
2838
2839 60
        if ($this->str === '' && $search === '') {
2840 2
            return static::create($replacement, $this->encoding);
2841
        }
2842
2843 58
        if ($caseSensitive) {
2844 48
            return static::create(
2845 48
                $this->utf8::str_replace($search, $replacement, $this->str),
0 ignored issues
show
Deprecated Code introduced by
The method voku\helper\UTF8::str_replace() has been deprecated with message: please use \str_replace() instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
2846 48
                $this->encoding
2847
            );
2848
        }
2849
2850 10
        return static::create(
2851 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2852 10
            $this->encoding
2853
        );
2854
    }
2855
2856
    /**
2857
     * Replaces all occurrences of $search in $str by $replacement.
2858
     *
2859
     * @param string[]        $search        <p>The elements to search for.</p>
2860
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2861
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2862
     *
2863
     * @psalm-mutation-free
2864
     *
2865
     * @return static
2866
     *                <p>Object with the resulting $str after the replacements.</p>
2867
     */
2868 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2869
    {
2870 61
        if ($caseSensitive) {
2871 47
            return static::create(
2872 47
                $this->utf8::str_replace($search, $replacement, $this->str),
0 ignored issues
show
Deprecated Code introduced by
The method voku\helper\UTF8::str_replace() has been deprecated with message: please use \str_replace() instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

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