Completed
Push — master ( ef1ee4...88e686 )
by Lars
01:47
created

Stringy::langSpecificCharsArray()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.0582

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 1
dl 0
loc 33
ccs 11
cts 13
cp 0.8462
crap 4.0582
rs 9.392
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stringy;
6
7
use voku\helper\AntiXSS;
8
use voku\helper\EmailCheck;
9
use voku\helper\URLify;
10
use voku\helper\UTF8;
11
12
/**
13
 * Class Stringy
14
 */
15
class Stringy implements \Countable, \IteratorAggregate, \ArrayAccess
16
{
17
    /**
18
     * An instance's string.
19
     *
20
     * @var string
21
     */
22
    protected $str;
23
24
    /**
25
     * The string's encoding, which should be one of the mbstring module's
26
     * supported encodings.
27
     *
28
     * @var string
29
     */
30
    protected $encoding;
31
32
    /**
33
     * @var UTF8
34
     */
35
    private $utf8;
36
37
    /**
38
     * Initializes a Stringy object and assigns both str and encoding properties
39
     * the supplied values. $str is cast to a string prior to assignment, and if
40
     * $encoding is not specified, it defaults to mb_internal_encoding(). Throws
41
     * an InvalidArgumentException if the first argument is an array or object
42
     * without a __toString method.
43
     *
44
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
45
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
46
     *
47
     * @throws \InvalidArgumentException
48
     *                                   <p>if an array or object without a
49
     *                                   __toString method is passed as the first argument</p>
50
     */
51 2171
    public function __construct($str = '', string $encoding = null)
52
    {
53 2171
        if (\is_array($str)) {
54 2
            throw new \InvalidArgumentException(
55 2
                'Passed value cannot be an array'
56
            );
57
        }
58
59
        if (
60 2169
            \is_object($str)
61
            &&
62 2169
            !\method_exists($str, '__toString')
63
        ) {
64 2
            throw new \InvalidArgumentException(
65 2
                'Passed object must have a __toString method'
66
            );
67
        }
68
69 2167
        $this->str = (string) $str;
70
71 2167
        static $UTF8 = null;
72 2167
        if ($UTF8 === null) {
73
            $UTF8 = new UTF8();
74
        }
75 2167
        $this->utf8 = $UTF8;
76
77 2167
        if ($encoding !== 'UTF-8') {
78 1416
            $this->encoding = $this->utf8::normalize_encoding($encoding, 'UTF-8');
79
        } else {
80 1645
            $this->encoding = $encoding;
81
        }
82 2167
    }
83
84
    /**
85
     * Returns the value in $str.
86
     *
87
     * @return string
88
     *                <p>The current value of the $str property.</p>
89
     */
90 978
    public function __toString()
91
    {
92 978
        return (string) $this->str;
93
    }
94
95
    /**
96
     * Gets the substring after the first occurrence of a separator.
97
     * If no match is found returns new empty Stringy object.
98
     *
99
     * @param string $separator
100
     *
101
     * @return static
102
     */
103 2
    public function afterFirst(string $separator): self
104
    {
105 2
        return static::create(
106 2
            $this->utf8::str_substr_after_first_separator(
107 2
                $this->str,
108 2
                $separator,
109 2
                $this->encoding
110
            )
111
        );
112
    }
113
114
    /**
115
     * Gets the substring after the first occurrence of a separator.
116
     * If no match is found returns new empty Stringy object.
117
     *
118
     * @param string $separator
119
     *
120
     * @return static
121
     */
122 1
    public function afterFirstIgnoreCase(string $separator): self
123
    {
124 1
        return static::create(
125 1
            $this->utf8::str_isubstr_after_first_separator(
126 1
                $this->str,
127 1
                $separator,
128 1
                $this->encoding
129
            )
130
        );
131
    }
132
133
    /**
134
     * Gets the substring after the last occurrence of a separator.
135
     * If no match is found returns new empty Stringy object.
136
     *
137
     * @param string $separator
138
     *
139
     * @return static
140
     */
141 1
    public function afterLast(string $separator): self
142
    {
143 1
        return static::create(
144 1
            $this->utf8::str_substr_after_last_separator(
145 1
                $this->str,
146 1
                $separator,
147 1
                $this->encoding
148
            )
149
        );
150
    }
151
152
    /**
153
     * Gets the substring after the last occurrence of a separator.
154
     * If no match is found returns new empty Stringy object.
155
     *
156
     * @param string $separator
157
     *
158
     * @return static
159
     */
160 1
    public function afterLastIgnoreCase(string $separator): self
161
    {
162 1
        return static::create(
163 1
            $this->utf8::str_isubstr_after_last_separator(
164 1
                $this->str,
165 1
                $separator,
166 1
                $this->encoding
167
            )
168
        );
169
    }
170
171
    /**
172
     * Returns a new string with $string appended.
173
     *
174
     * @param string $string <p>The string to append.</p>
175
     *
176
     * @return static
177
     *                <p>Object with appended $string.</p>
178
     */
179 7
    public function append(string $string): self
180
    {
181 7
        return static::create($this->str . $string, $this->encoding);
182
    }
183
184
    /**
185
     * Append an password (limited to chars that are good readable).
186
     *
187
     * @param int $length <p>Length of the random string.</p>
188
     *
189
     * @return static
190
     *                <p>Object with appended password.</p>
191
     */
192 1
    public function appendPassword(int $length): self
193
    {
194 1
        return $this->appendRandomString(
195 1
            $length,
196 1
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
197
        );
198
    }
199
200
    /**
201
     * Append an random string.
202
     *
203
     * @param int    $length        <p>Length of the random string.</p>
204
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
205
     *
206
     * @return static
207
     *                <p>Object with appended random string.</p>
208
     */
209 2
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
210
    {
211 2
        $str = $this->utf8::get_random_string($length, $possibleChars);
212
213 2
        return $this->append($str);
214
    }
215
216
    /**
217
     * Append an unique identifier.
218
     *
219
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
220
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
221
     *
222
     * @return static
223
     *                <p>Object with appended unique identifier as md5-hash.</p>
224
     */
225 1
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
226
    {
227 1
        return $this->append(
228 1
            $this->utf8::get_unique_string($entropyExtra, $md5)
229
        );
230
    }
231
232
    /**
233
     * Returns the character at $index, with indexes starting at 0.
234
     *
235
     * @param int $index <p>Position of the character.</p>
236
     *
237
     * @return static
238
     *                <p>The character at $index.</p>
239
     */
240 16
    public function at(int $index): self
241
    {
242 16
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
243
    }
244
245
    /**
246
     * Gets the substring before the first occurrence of a separator.
247
     * If no match is found returns new empty Stringy object.
248
     *
249
     * @param string $separator
250
     *
251
     * @return static
252
     */
253 1
    public function beforeFirst(string $separator): self
254
    {
255 1
        return static::create(
256 1
            $this->utf8::str_substr_before_first_separator(
257 1
                $this->str,
258 1
                $separator,
259 1
                $this->encoding
260
            )
261
        );
262
    }
263
264
    /**
265
     * Gets the substring before the first occurrence of a separator.
266
     * If no match is found returns new empty Stringy object.
267
     *
268
     * @param string $separator
269
     *
270
     * @return static
271
     */
272 1
    public function beforeFirstIgnoreCase(string $separator): self
273
    {
274 1
        return static::create(
275 1
            $this->utf8::str_isubstr_before_first_separator(
276 1
                $this->str,
277 1
                $separator,
278 1
                $this->encoding
279
            )
280
        );
281
    }
282
283
    /**
284
     * Gets the substring before the last occurrence of a separator.
285
     * If no match is found returns new empty Stringy object.
286
     *
287
     * @param string $separator
288
     *
289
     * @return static
290
     */
291 1
    public function beforeLast(string $separator): self
292
    {
293 1
        return static::create(
294 1
            $this->utf8::str_substr_before_last_separator(
295 1
                $this->str,
296 1
                $separator,
297 1
                $this->encoding
298
            )
299
        );
300
    }
301
302
    /**
303
     * Gets the substring before the last occurrence of a separator.
304
     * If no match is found returns new empty Stringy object.
305
     *
306
     * @param string $separator
307
     *
308
     * @return static
309
     */
310 1
    public function beforeLastIgnoreCase(string $separator): self
311
    {
312 1
        return static::create(
313 1
            $this->utf8::str_isubstr_before_last_separator(
314 1
                $this->str,
315 1
                $separator,
316 1
                $this->encoding
317
            )
318
        );
319
    }
320
321
    /**
322
     * Returns the substring between $start and $end, if found, or an empty
323
     * string. An optional offset may be supplied from which to begin the
324
     * search for the start string.
325
     *
326
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
327
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
328
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
329
     *
330
     * @return static
331
     *                <p>Object whose $str is a substring between $start and $end.</p>
332
     */
333 32
    public function between(string $start, string $end, int $offset = null): self
334
    {
335
        /** @noinspection UnnecessaryCastingInspection */
336 32
        $str = $this->utf8::between(
337 32
            $this->str,
338 32
            $start,
339 32
            $end,
340 32
            (int) $offset,
341 32
            $this->encoding
342
        );
343
344 32
        return static::create($str, $this->encoding);
345
    }
346
347
    /**
348
     * Returns a camelCase version of the string. Trims surrounding spaces,
349
     * capitalizes letters following digits, spaces, dashes and underscores,
350
     * and removes spaces, dashes, as well as underscores.
351
     *
352
     * @return static
353
     *                <p>Object with $str in camelCase.</p>
354
     */
355 38
    public function camelize(): self
356
    {
357 38
        return static::create(
358 38
            $this->utf8::str_camelize($this->str, $this->encoding),
359 38
            $this->encoding
360
        );
361
    }
362
363
    /**
364
     * Returns the string with the first letter of each word capitalized,
365
     * except for when the word is a name which shouldn't be capitalized.
366
     *
367
     * @return static
368
     *                <p>Object with $str capitalized.</p>
369
     */
370 39
    public function capitalizePersonalName(): self
371
    {
372 39
        return static::create(
373 39
            $this->utf8::str_capitalize_name($this->str),
374 39
            $this->encoding
375
        );
376
    }
377
378
    /**
379
     * Returns an array consisting of the characters in the string.
380
     *
381
     * @return array
382
     *               <p>An array of string chars.</p>
383
     */
384 8
    public function chars(): array
385
    {
386 8
        return $this->utf8::str_split($this->str);
387
    }
388
389
    /**
390
     * Trims the string and replaces consecutive whitespace characters with a
391
     * single space. This includes tabs and newline characters, as well as
392
     * multibyte whitespace such as the thin space and ideographic space.
393
     *
394
     * @return static
395
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
396
     */
397 26
    public function collapseWhitespace(): self
398
    {
399 26
        return static::create(
400 26
            $this->utf8::collapse_whitespace($this->str),
401 26
            $this->encoding
402
        );
403
    }
404
405
    /**
406
     * Returns true if the string contains $needle, false otherwise. By default
407
     * the comparison is case-sensitive, but can be made insensitive by setting
408
     * $caseSensitive to false.
409
     *
410
     * @param string $needle        <p>Substring to look for.</p>
411
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
412
     *
413
     * @return bool
414
     *              <p>Whether or not $str contains $needle.</p>
415
     */
416 42
    public function contains(string $needle, bool $caseSensitive = true): bool
417
    {
418 42
        return $this->utf8::str_contains(
419 42
            $this->str,
420 42
            $needle,
421 42
            $caseSensitive
422
        );
423
    }
424
425
    /**
426
     * Returns true if the string contains all $needles, false otherwise. By
427
     * default the comparison is case-sensitive, but can be made insensitive by
428
     * setting $caseSensitive to false.
429
     *
430
     * @param array $needles       <p>SubStrings to look for.</p>
431
     * @param bool  $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
432
     *
433
     * @return bool
434
     *              <p>Whether or not $str contains $needle.</p>
435
     */
436 87
    public function containsAll(array $needles, bool $caseSensitive = true): bool
437
    {
438 87
        return $this->utf8::str_contains_all(
439 87
            $this->str,
440 87
            $needles,
441 87
            $caseSensitive
442
        );
443
    }
444
445
    /**
446
     * Returns true if the string contains any $needles, false otherwise. By
447
     * default the comparison is case-sensitive, but can be made insensitive by
448
     * setting $caseSensitive to false.
449
     *
450
     * @param array $needles       <p>SubStrings to look for.</p>
451
     * @param bool  $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
452
     *
453
     * @return bool
454
     *              <p>Whether or not $str contains $needle.</p>
455
     */
456 86
    public function containsAny(array $needles, bool $caseSensitive = true): bool
457
    {
458 86
        return $this->utf8::str_contains_any(
459 86
            $this->str,
460 86
            $needles,
461 86
            $caseSensitive
462
        );
463
    }
464
465
    /**
466
     * Returns the length of the string, implementing the countable interface.
467
     *
468
     * @return int
469
     *             <p>The number of characters in the string, given the encoding.</p>
470
     */
471 2
    public function count(): int
472
    {
473 2
        return $this->length();
474
    }
475
476
    /**
477
     * Returns the number of occurrences of $substring in the given string.
478
     * By default, the comparison is case-sensitive, but can be made insensitive
479
     * by setting $caseSensitive to false.
480
     *
481
     * @param string $substring     <p>The substring to search for.</p>
482
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
483
     *
484
     * @return int
485
     */
486 30
    public function countSubstr(string $substring, bool $caseSensitive = true): int
487
    {
488 30
        return $this->utf8::substr_count_simple(
489 30
            $this->str,
490 30
            $substring,
491 30
            $caseSensitive,
492 30
            $this->encoding
493
        );
494
    }
495
496
    /**
497
     * Creates a Stringy object and assigns both str and encoding properties
498
     * the supplied values. $str is cast to a string prior to assignment, and if
499
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
500
     * then returns the initialized object. Throws an InvalidArgumentException
501
     * if the first argument is an array or object without a __toString method.
502
     *
503
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
504
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
505
     *
506
     * @throws \InvalidArgumentException
507
     *                                   <p>if an array or object without a
508
     *                                   __toString method is passed as the first argument</p>
509
     *
510
     * @return static
511
     *                <p>A Stringy object.</p>
512
     */
513 2151
    public static function create($str = '', string $encoding = null): self
514
    {
515 2151
        return new static($str, $encoding);
516
    }
517
518
    /**
519
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
520
     * inserted before uppercase characters (with the exception of the first
521
     * character of the string), and in place of spaces as well as underscores.
522
     *
523
     * @return static
524
     *                <p>Object with a dasherized $str</p>
525
     */
526 38
    public function dasherize(): self
527
    {
528 38
        return static::create(
529 38
            $this->utf8::str_dasherize($this->str),
530 38
            $this->encoding
531
        );
532
    }
533
534
    /**
535
     * Returns a lowercase and trimmed string separated by the given delimiter.
536
     * Delimiters are inserted before uppercase characters (with the exception
537
     * of the first character of the string), and in place of spaces, dashes,
538
     * and underscores. Alpha delimiters are not converted to lowercase.
539
     *
540
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
541
     *
542
     * @return static
543
     *                <p>Object with a delimited $str.</p>
544
     */
545 60
    public function delimit(string $delimiter): self
546
    {
547 60
        return static::create(
548 60
            $this->utf8::str_delimit($this->str, $delimiter),
549 60
            $this->encoding
550
        );
551
    }
552
553
    /**
554
     * Returns true if the string ends with $substring, false otherwise. By
555
     * default, the comparison is case-sensitive, but can be made insensitive
556
     * by setting $caseSensitive to false.
557
     *
558
     * @param string $substring     <p>The substring to look for.</p>
559
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
560
     *
561
     * @return bool
562
     *              <p>Whether or not $str ends with $substring.</p>
563
     */
564 55
    public function endsWith(string $substring, bool $caseSensitive = true): bool
565
    {
566 55
        if ($caseSensitive) {
567 30
            return $this->utf8::str_ends_with($this->str, $substring);
568
        }
569
570 25
        return $this->utf8::str_iends_with($this->str, $substring);
571
    }
572
573
    /**
574
     * Returns true if the string ends with any of $substrings, false otherwise.
575
     * By default, the comparison is case-sensitive, but can be made insensitive
576
     * by setting $caseSensitive to false.
577
     *
578
     * @param string[] $substrings    <p>Substrings to look for.</p>
579
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
580
     *
581
     * @return bool
582
     *              <p>Whether or not $str ends with $substring.</p>
583
     */
584 22
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
585
    {
586 22
        if ($caseSensitive) {
587 14
            return $this->utf8::str_ends_with_any($this->str, $substrings);
588
        }
589
590 8
        return $this->utf8::str_iends_with_any($this->str, $substrings);
591
    }
592
593
    /**
594
     * Ensures that the string begins with $substring. If it doesn't, it's
595
     * prepended.
596
     *
597
     * @param string $substring <p>The substring to add if not present.</p>
598
     *
599
     * @return static
600
     *                <p>Object with its $str prefixed by the $substring.</p>
601
     */
602 20
    public function ensureLeft(string $substring): self
603
    {
604 20
        return static::create(
605 20
            $this->utf8::str_ensure_left($this->str, $substring),
606 20
            $this->encoding
607
        );
608
    }
609
610
    /**
611
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
612
     *
613
     * @param string $substring <p>The substring to add if not present.</p>
614
     *
615
     * @return static
616
     *                <p>Object with its $str suffixed by the $substring.</p>
617
     */
618 20
    public function ensureRight(string $substring): self
619
    {
620 20
        return static::create(
621 20
            $this->utf8::str_ensure_right($this->str, $substring),
622 20
            $this->encoding
623
        );
624
    }
625
626
    /**
627
     * Create a escape html version of the string via "$this->utf8::htmlspecialchars()".
628
     *
629
     * @return static
630
     */
631 6
    public function escape(): self
632
    {
633 6
        return static::create(
634 6
            $this->utf8::htmlspecialchars(
635 6
                $this->str,
636 6
                \ENT_QUOTES | \ENT_SUBSTITUTE,
637 6
                $this->encoding
638
            ),
639 6
            $this->encoding
640
        );
641
    }
642
643
    /**
644
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
645
     *
646
     * @param string   $search
647
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
648
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
649
     *
650
     * @return static
651
     */
652 1
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
653
    {
654 1
        return static::create(
655 1
            $this->utf8::extract_text(
656 1
                $this->str,
657 1
                $search,
658 1
                $length,
659 1
                $replacerForSkippedText,
660 1
                $this->encoding
661
            ),
662 1
            $this->encoding
663
        );
664
    }
665
666
    /**
667
     * Returns the first $n characters of the string.
668
     *
669
     * @param int $n <p>Number of characters to retrieve from the start.</p>
670
     *
671
     * @return static
672
     *                <p>Object with its $str being the first $n chars.</p>
673
     */
674 25
    public function first(int $n): self
675
    {
676 25
        return static::create(
677 25
            $this->utf8::first_char($this->str, $n, $this->encoding),
678 25
            $this->encoding
679
        );
680
    }
681
682
    /**
683
     * Returns the encoding used by the Stringy object.
684
     *
685
     * @return string
686
     *                <p>The current value of the $encoding property.</p>
687
     */
688 5
    public function getEncoding(): string
689
    {
690 5
        return $this->encoding;
691
    }
692
693
    /**
694
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
695
     * interface. The ArrayIterator's constructor is passed an array of chars
696
     * in the multibyte string. This enables the use of foreach with instances
697
     * of Stringy\Stringy.
698
     *
699
     * @return \ArrayIterator
700
     *                        <p>An iterator for the characters in the string.</p>
701
     */
702 2
    public function getIterator(): \ArrayIterator
703
    {
704 2
        return new \ArrayIterator($this->chars());
705
    }
706
707
    /**
708
     * Returns true if the string contains a lower case char, false otherwise.
709
     *
710
     * @return bool
711
     *              <p>Whether or not the string contains a lower case character.</p>
712
     */
713 24
    public function hasLowerCase(): bool
714
    {
715 24
        return $this->utf8::has_lowercase($this->str);
716
    }
717
718
    /**
719
     * Returns true if the string contains an upper case char, false otherwise.
720
     *
721
     * @return bool
722
     *              <p>Whether or not the string contains an upper case character.</p>
723
     */
724 24
    public function hasUpperCase(): bool
725
    {
726 24
        return $this->utf8::has_uppercase($this->str);
727
    }
728
729
    /**
730
     * Convert all HTML entities to their applicable characters.
731
     *
732
     * @param int $flags [optional] <p>
733
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
734
     *                   which document type to use. The default is ENT_COMPAT.
735
     *                   <table>
736
     *                   Available <i>flags</i> constants
737
     *                   <tr valign="top">
738
     *                   <td>Constant Name</td>
739
     *                   <td>Description</td>
740
     *                   </tr>
741
     *                   <tr valign="top">
742
     *                   <td><b>ENT_COMPAT</b></td>
743
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
744
     *                   </tr>
745
     *                   <tr valign="top">
746
     *                   <td><b>ENT_QUOTES</b></td>
747
     *                   <td>Will convert both double and single quotes.</td>
748
     *                   </tr>
749
     *                   <tr valign="top">
750
     *                   <td><b>ENT_NOQUOTES</b></td>
751
     *                   <td>Will leave both double and single quotes unconverted.</td>
752
     *                   </tr>
753
     *                   <tr valign="top">
754
     *                   <td><b>ENT_HTML401</b></td>
755
     *                   <td>
756
     *                   Handle code as HTML 4.01.
757
     *                   </td>
758
     *                   </tr>
759
     *                   <tr valign="top">
760
     *                   <td><b>ENT_XML1</b></td>
761
     *                   <td>
762
     *                   Handle code as XML 1.
763
     *                   </td>
764
     *                   </tr>
765
     *                   <tr valign="top">
766
     *                   <td><b>ENT_XHTML</b></td>
767
     *                   <td>
768
     *                   Handle code as XHTML.
769
     *                   </td>
770
     *                   </tr>
771
     *                   <tr valign="top">
772
     *                   <td><b>ENT_HTML5</b></td>
773
     *                   <td>
774
     *                   Handle code as HTML 5.
775
     *                   </td>
776
     *                   </tr>
777
     *                   </table>
778
     *                   </p>
779
     *
780
     * @return static
781
     *                <p>Object with the resulting $str after being html decoded.</p>
782
     */
783 10 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...
784
    {
785 10
        return static::create(
786 10
            $this->utf8::html_entity_decode(
787 10
                $this->str,
788 10
                $flags,
789 10
                $this->encoding
790
            ),
791 10
            $this->encoding
792
        );
793
    }
794
795
    /**
796
     * Convert all applicable characters to HTML entities.
797
     *
798
     * @param int $flags [optional] <p>
799
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
800
     *                   which document type to use. The default is ENT_COMPAT.
801
     *                   <table>
802
     *                   Available <i>flags</i> constants
803
     *                   <tr valign="top">
804
     *                   <td>Constant Name</td>
805
     *                   <td>Description</td>
806
     *                   </tr>
807
     *                   <tr valign="top">
808
     *                   <td><b>ENT_COMPAT</b></td>
809
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
810
     *                   </tr>
811
     *                   <tr valign="top">
812
     *                   <td><b>ENT_QUOTES</b></td>
813
     *                   <td>Will convert both double and single quotes.</td>
814
     *                   </tr>
815
     *                   <tr valign="top">
816
     *                   <td><b>ENT_NOQUOTES</b></td>
817
     *                   <td>Will leave both double and single quotes unconverted.</td>
818
     *                   </tr>
819
     *                   <tr valign="top">
820
     *                   <td><b>ENT_HTML401</b></td>
821
     *                   <td>
822
     *                   Handle code as HTML 4.01.
823
     *                   </td>
824
     *                   </tr>
825
     *                   <tr valign="top">
826
     *                   <td><b>ENT_XML1</b></td>
827
     *                   <td>
828
     *                   Handle code as XML 1.
829
     *                   </td>
830
     *                   </tr>
831
     *                   <tr valign="top">
832
     *                   <td><b>ENT_XHTML</b></td>
833
     *                   <td>
834
     *                   Handle code as XHTML.
835
     *                   </td>
836
     *                   </tr>
837
     *                   <tr valign="top">
838
     *                   <td><b>ENT_HTML5</b></td>
839
     *                   <td>
840
     *                   Handle code as HTML 5.
841
     *                   </td>
842
     *                   </tr>
843
     *                   </table>
844
     *                   </p>
845
     *
846
     * @return static
847
     *                <p>Object with the resulting $str after being html encoded.</p>
848
     */
849 10 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...
850
    {
851 10
        return static::create(
852 10
            $this->utf8::htmlentities(
853 10
                $this->str,
854 10
                $flags,
855 10
                $this->encoding
856
            ),
857 10
            $this->encoding
858
        );
859
    }
860
861
    /**
862
     * Capitalizes the first word of the string, replaces underscores with
863
     * spaces, and strips '_id'.
864
     *
865
     * @return static
866
     *                <p>Object with a humanized $str.</p>
867
     */
868 6
    public function humanize(): self
869
    {
870 6
        return static::create(
871 6
            $this->utf8::str_humanize($this->str),
872 6
            $this->encoding
873
        );
874
    }
875
876
    /**
877
     * Returns the index of the first occurrence of $needle in the string,
878
     * and false if not found. Accepts an optional offset from which to begin
879
     * the search.
880
     *
881
     * @param string $needle <p>Substring to look for.</p>
882
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
883
     *
884
     * @return false|int
885
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
886
     */
887 20
    public function indexOf(string $needle, int $offset = 0)
888
    {
889 20
        return $this->utf8::strpos(
890 20
            $this->str,
891 20
            $needle,
892 20
            $offset,
893 20
            $this->encoding
894
        );
895
    }
896
897
    /**
898
     * Returns the index of the first occurrence of $needle in the string,
899
     * and false if not found. Accepts an optional offset from which to begin
900
     * the search.
901
     *
902
     * @param string $needle <p>Substring to look for.</p>
903
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
904
     *
905
     * @return false|int
906
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
907
     */
908
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
909
    {
910
        return $this->utf8::stripos(
911
            $this->str,
912
            $needle,
913
            $offset,
914
            $this->encoding
915
        );
916
    }
917
918
    /**
919
     * Returns the index of the last occurrence of $needle in the string,
920
     * and false if not found. Accepts an optional offset from which to begin
921
     * the search. Offsets may be negative to count from the last character
922
     * in the string.
923
     *
924
     * @param string $needle <p>Substring to look for.</p>
925
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
926
     *
927
     * @return false|int
928
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
929
     */
930 20
    public function indexOfLast(string $needle, int $offset = 0)
931
    {
932 20
        return $this->utf8::strrpos(
933 20
            $this->str,
934 20
            $needle,
935 20
            $offset,
936 20
            $this->encoding
937
        );
938
    }
939
940
    /**
941
     * Returns the index of the last occurrence of $needle in the string,
942
     * and false if not found. Accepts an optional offset from which to begin
943
     * the search. Offsets may be negative to count from the last character
944
     * in the string.
945
     *
946
     * @param string $needle <p>Substring to look for.</p>
947
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
948
     *
949
     * @return false|int
950
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
951
     */
952
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
953
    {
954
        return $this->utf8::strripos(
955
            $this->str,
956
            $needle,
957
            $offset,
958
            $this->encoding
959
        );
960
    }
961
962
    /**
963
     * Inserts $substring into the string at the $index provided.
964
     *
965
     * @param string $substring <p>String to be inserted.</p>
966
     * @param int    $index     <p>The index at which to insert the substring.</p>
967
     *
968
     * @return static
969
     *                <p>Object with the resulting $str after the insertion.</p>
970
     */
971 16
    public function insert(string $substring, int $index): self
972
    {
973 16
        return static::create(
974 16
            $this->utf8::str_insert(
975 16
                $this->str,
976 16
                $substring,
977 16
                $index,
978 16
                $this->encoding
979
            ),
980 16
            $this->encoding
981
        );
982
    }
983
984
    /**
985
     * Returns true if the string contains the $pattern, otherwise false.
986
     *
987
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
988
     * expression wildcards.
989
     *
990
     * @credit Originally from Laravel, thanks Taylor.
991
     *
992
     * @param string $pattern <p>The string or pattern to match against.</p>
993
     *
994
     * @return bool
995
     *              <p>Whether or not we match the provided pattern.</p>
996
     */
997 13
    public function is(string $pattern): bool
998
    {
999 13
        if ($this->toString() === $pattern) {
1000 1
            return true;
1001
        }
1002
1003 12
        $quotedPattern = \preg_quote($pattern, '/');
1004 12
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1005
1006 12
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1007
    }
1008
1009
    /**
1010
     * Returns true if the string contains only alphabetic chars, false otherwise.
1011
     *
1012
     * @return bool
1013
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1014
     */
1015 20
    public function isAlpha(): bool
1016
    {
1017 20
        return $this->utf8::is_alpha($this->str);
1018
    }
1019
1020
    /**
1021
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1022
     *
1023
     * @return bool
1024
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1025
     */
1026 26
    public function isAlphanumeric(): bool
1027
    {
1028 26
        return $this->utf8::is_alphanumeric($this->str);
1029
    }
1030
1031
    /**
1032
     * Returns true if the string is base64 encoded, false otherwise.
1033
     *
1034
     * @param bool $emptyStringIsValid
1035
     *
1036
     * @return bool
1037
     *              <p>Whether or not $str is base64 encoded.</p>
1038
     */
1039 14
    public function isBase64($emptyStringIsValid = true): bool
1040
    {
1041 14
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
1042
    }
1043
1044
    /**
1045
     * Returns true if the string contains only whitespace chars, false otherwise.
1046
     *
1047
     * @return bool
1048
     *              <p>Whether or not $str contains only whitespace characters.</p>
1049
     */
1050 30
    public function isBlank(): bool
1051
    {
1052 30
        return $this->utf8::is_blank($this->str);
1053
    }
1054
1055
    /**
1056
     * Returns true if the string contains a valid E-Mail address, false otherwise.
1057
     *
1058
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
1059
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
1060
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
1061
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
1062
     *
1063
     * @return bool
1064
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
1065
     */
1066 1
    public function isEmail(bool $useExampleDomainCheck = false, bool $useTypoInDomainCheck = false, bool $useTemporaryDomainCheck = false, bool $useDnsCheck = false): bool
1067
    {
1068 1
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
1069
    }
1070
1071
    /**
1072
     * Determine whether the string is considered to be empty.
1073
     *
1074
     * A variable is considered empty if it does not exist or if its value equals FALSE.
1075
     * empty() does not generate a warning if the variable does not exist.
1076
     *
1077
     * @return bool
1078
     *              <p>Whether or not $str is empty().</p>
1079
     */
1080
    public function isEmpty(): bool
1081
    {
1082
        return $this->utf8::is_empty($this->str);
1083
    }
1084
1085
    /**
1086
     * Returns true if the string contains only hexadecimal chars, false otherwise.
1087
     *
1088
     * @return bool
1089
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
1090
     */
1091 26
    public function isHexadecimal(): bool
1092
    {
1093 26
        return $this->utf8::is_hexadecimal($this->str);
1094
    }
1095
1096
    /**
1097
     * Returns true if the string contains HTML-Tags, false otherwise.
1098
     *
1099
     * @return bool
1100
     *              <p>Whether or not $str contains HTML-Tags.</p>
1101
     */
1102 1
    public function isHtml(): bool
1103
    {
1104 1
        return $this->utf8::is_html($this->str);
1105
    }
1106
1107
    /**
1108
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
1109
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
1110
     * in that an empty string is not considered valid JSON.
1111
     *
1112
     * @param bool $onlyArrayOrObjectResultsAreValid
1113
     *
1114
     * @return bool
1115
     *              <p>Whether or not $str is JSON.</p>
1116
     */
1117 40
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
1118
    {
1119 40
        return $this->utf8::is_json($this->str, $onlyArrayOrObjectResultsAreValid);
1120
    }
1121
1122
    /**
1123
     * Returns true if the string contains only lower case chars, false otherwise.
1124
     *
1125
     * @return bool
1126
     *              <p>Whether or not $str contains only lower case characters.</p>
1127
     */
1128 16
    public function isLowerCase(): bool
1129
    {
1130 16
        return $this->utf8::is_lowercase($this->str);
1131
    }
1132
1133
    /**
1134
     * Returns true if the string is serialized, false otherwise.
1135
     *
1136
     * @return bool
1137
     *              <p>Whether or not $str is serialized.</p>
1138
     */
1139 14
    public function isSerialized(): bool
1140
    {
1141 14
        return $this->utf8::is_serialized($this->str);
1142
    }
1143
1144
    /**
1145
     * Returns true if the string contains only lower case chars, false
1146
     * otherwise.
1147
     *
1148
     * @return bool
1149
     *              <p>Whether or not $str contains only lower case characters.</p>
1150
     */
1151 16
    public function isUpperCase(): bool
1152
    {
1153 16
        return $this->utf8::is_uppercase($this->str);
1154
    }
1155
1156
    /**
1157
     * Returns the last $n characters of the string.
1158
     *
1159
     * @param int $n <p>Number of characters to retrieve from the end.</p>
1160
     *
1161
     * @return static
1162
     *                <p>Object with its $str being the last $n chars.</p>
1163
     */
1164 24
    public function last(int $n): self
1165
    {
1166 24
        return static::create(
1167 24
            $this->utf8::str_last_char(
1168 24
                $this->str,
1169 24
                $n,
1170 24
                $this->encoding
1171
            ),
1172 24
            $this->encoding
1173
        );
1174
    }
1175
1176
    /**
1177
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1178
     * If no match is found returns new empty Stringy object.
1179
     *
1180
     * @param string $needle       <p>The string to look for.</p>
1181
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1182
     *
1183
     * @return static
1184
     */
1185 2 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...
1186
    {
1187 2
        return static::create(
1188 2
            $this->utf8::str_substr_last(
1189 2
                $this->str,
1190 2
                $needle,
1191 2
                $beforeNeedle,
1192 2
                $this->encoding
1193
            ),
1194 2
            $this->encoding
1195
        );
1196
    }
1197
1198
    /**
1199
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1200
     * If no match is found returns new empty Stringy object.
1201
     *
1202
     * @param string $needle       <p>The string to look for.</p>
1203
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1204
     *
1205
     * @return static
1206
     */
1207 1 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...
1208
    {
1209 1
        return static::create(
1210 1
            $this->utf8::str_isubstr_last(
1211 1
                $this->str,
1212 1
                $needle,
1213 1
                $beforeNeedle,
1214 1
                $this->encoding
1215
            ),
1216 1
            $this->encoding
1217
        );
1218
    }
1219
1220
    /**
1221
     * Returns the length of the string.
1222
     *
1223
     * @return int
1224
     *             <p>The number of characters in $str given the encoding.</p>
1225
     */
1226 11
    public function length(): int
1227
    {
1228 11
        return (int) $this->utf8::strlen($this->str, $this->encoding);
1229
    }
1230
1231
    /**
1232
     * Line-Wrap the string after $limit, but also after the next word.
1233
     *
1234
     * @param int $limit
1235
     *
1236
     * @return static
1237
     */
1238 1
    public function lineWrapAfterWord(int $limit): self
1239
    {
1240 1
        return static::create(
1241 1
            $this->utf8::wordwrap_per_line($this->str, $limit),
1242 1
            $this->encoding
1243
        );
1244
    }
1245
1246
    /**
1247
     * Splits on newlines and carriage returns, returning an array of Stringy
1248
     * objects corresponding to the lines in the string.
1249
     *
1250
     * @return static[]
1251
     *                  <p>An array of Stringy objects.</p>
1252
     */
1253 32
    public function lines(): array
1254
    {
1255 32
        $array = $this->utf8::str_to_lines($this->str);
1256 32
        foreach ($array as $i => &$value) {
1257 32
            $value = static::create($value, $this->encoding);
1258
        }
1259
1260 32
        return $array;
1261
    }
1262
1263
    /**
1264
     * Returns the longest common prefix between the string and $otherStr.
1265
     *
1266
     * @param string $otherStr <p>Second string for comparison.</p>
1267
     *
1268
     * @return static
1269
     *                <p>Object with its $str being the longest common prefix.</p>
1270
     */
1271 20
    public function longestCommonPrefix(string $otherStr): self
1272
    {
1273 20
        return static::create(
1274 20
            $this->utf8::str_longest_common_prefix(
1275 20
                $this->str,
1276 20
                $otherStr,
1277 20
                $this->encoding
1278
            ),
1279 20
            $this->encoding
1280
        );
1281
    }
1282
1283
    /**
1284
     * Returns the longest common substring between the string and $otherStr.
1285
     * In the case of ties, it returns that which occurs first.
1286
     *
1287
     * @param string $otherStr <p>Second string for comparison.</p>
1288
     *
1289
     * @return static
1290
     *                <p>Object with its $str being the longest common substring.</p>
1291
     */
1292 20
    public function longestCommonSubstring(string $otherStr): self
1293
    {
1294 20
        return static::create(
1295 20
            $this->utf8::str_longest_common_substring(
1296 20
                $this->str,
1297 20
                $otherStr,
1298 20
                $this->encoding
1299
            ),
1300 20
            $this->encoding
1301
        );
1302
    }
1303
1304
    /**
1305
     * Returns the longest common suffix between the string and $otherStr.
1306
     *
1307
     * @param string $otherStr <p>Second string for comparison.</p>
1308
     *
1309
     * @return static
1310
     *                <p>Object with its $str being the longest common suffix.</p>
1311
     */
1312 20
    public function longestCommonSuffix(string $otherStr): self
1313
    {
1314 20
        return static::create(
1315 20
            $this->utf8::str_longest_common_suffix(
1316 20
                $this->str,
1317 20
                $otherStr,
1318 20
                $this->encoding
1319
            ),
1320 20
            $this->encoding
1321
        );
1322
    }
1323
1324
    /**
1325
     * Converts the first character of the string to lower case.
1326
     *
1327
     * @return static
1328
     *                <p>Object with the first character of $str being lower case.</p>
1329
     */
1330 10
    public function lowerCaseFirst(): self
1331
    {
1332 10
        return static::create(
1333 10
            $this->utf8::lcfirst($this->str, $this->encoding),
1334 10
            $this->encoding
1335
        );
1336
    }
1337
1338
    /**
1339
     * Returns whether or not a character exists at an index. Offsets may be
1340
     * negative to count from the last character in the string. Implements
1341
     * part of the ArrayAccess interface.
1342
     *
1343
     * @param int $offset <p>The index to check.</p>
1344
     *
1345
     * @return bool
1346
     *              <p>Whether or not the index exists.</p>
1347
     */
1348 12
    public function offsetExists($offset): bool
1349
    {
1350 12
        return $this->utf8::str_offset_exists(
1351 12
            $this->str,
1352 12
            $offset,
1353 12
            $this->encoding
1354
        );
1355
    }
1356
1357
    /**
1358
     * Returns the character at the given index. Offsets may be negative to
1359
     * count from the last character in the string. Implements part of the
1360
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
1361
     * does not exist.
1362
     *
1363
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
1364
     *
1365
     *@throws \OutOfBoundsException
1366
     *                               <p>If the positive or negative offset does not exist.</p>
1367
     *
1368
     * @return string
1369
     *                <p>The character at the specified index.</p>
1370
     */
1371 4
    public function offsetGet($offset): string
1372
    {
1373 4
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
1374
    }
1375
1376
    /**
1377
     * Implements part of the ArrayAccess interface, but throws an exception
1378
     * when called. This maintains the immutability of Stringy objects.
1379
     *
1380
     * @param int   $offset <p>The index of the character.</p>
1381
     * @param mixed $value  <p>Value to set.</p>
1382
     *
1383
     * @throws \Exception
1384
     *                    <p>When called.</p>
1385
     */
1386 2
    public function offsetSet($offset, $value)
1387
    {
1388
        // Stringy is immutable, cannot directly set char
1389
        /** @noinspection ThrowRawExceptionInspection */
1390 2
        throw new \Exception('Stringy object is immutable, cannot modify char');
1391
    }
1392
1393
    /**
1394
     * Implements part of the ArrayAccess interface, but throws an exception
1395
     * when called. This maintains the immutability of Stringy objects.
1396
     *
1397
     * @param int $offset <p>The index of the character.</p>
1398
     *
1399
     * @throws \Exception
1400
     *                    <p>When called.</p>
1401
     */
1402 2
    public function offsetUnset($offset)
1403
    {
1404
        // Don't allow directly modifying the string
1405
        /** @noinspection ThrowRawExceptionInspection */
1406 2
        throw new \Exception('Stringy object is immutable, cannot unset char');
1407
    }
1408
1409
    /**
1410
     * Pads the string to a given length with $padStr. If length is less than
1411
     * or equal to the length of the string, no padding takes places. The
1412
     * default string used for padding is a space, and the default type (one of
1413
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
1414
     * if $padType isn't one of those 3 values.
1415
     *
1416
     * @param int    $length  <p>Desired string length after padding.</p>
1417
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1418
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
1419
     *
1420
     * @throws \InvalidArgumentException
1421
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
1422
     *
1423
     * @return static
1424
     *                <p>Object with a padded $str.</p>
1425
     */
1426 26
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
1427
    {
1428 26
        return static::create(
1429 26
            $this->utf8::str_pad(
1430 26
                $this->str,
1431 26
                $length,
1432 26
                $padStr,
1433 26
                $padType,
1434 26
                $this->encoding
1435
            )
1436
        );
1437
    }
1438
1439
    /**
1440
     * Returns a new string of a given length such that both sides of the
1441
     * string are padded. Alias for pad() with a $padType of 'both'.
1442
     *
1443
     * @param int    $length <p>Desired string length after padding.</p>
1444
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1445
     *
1446
     * @return static
1447
     *                <p>String with padding applied.</p>
1448
     */
1449 22
    public function padBoth(int $length, string $padStr = ' '): self
1450
    {
1451 22
        return static::create(
1452 22
            $this->utf8::str_pad_both(
1453 22
                $this->str,
1454 22
                $length,
1455 22
                $padStr,
1456 22
                $this->encoding
1457
            )
1458
        );
1459
    }
1460
1461
    /**
1462
     * Returns a new string of a given length such that the beginning of the
1463
     * string is padded. Alias for pad() with a $padType of 'left'.
1464
     *
1465
     * @param int    $length <p>Desired string length after padding.</p>
1466
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1467
     *
1468
     * @return static
1469
     *                <p>String with left padding.</p>
1470
     */
1471 14
    public function padLeft(int $length, string $padStr = ' '): self
1472
    {
1473 14
        return static::create(
1474 14
            $this->utf8::str_pad_left(
1475 14
                $this->str,
1476 14
                $length,
1477 14
                $padStr,
1478 14
                $this->encoding
1479
            )
1480
        );
1481
    }
1482
1483
    /**
1484
     * Returns a new string of a given length such that the end of the string
1485
     * is padded. Alias for pad() with a $padType of 'right'.
1486
     *
1487
     * @param int    $length <p>Desired string length after padding.</p>
1488
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
1489
     *
1490
     * @return static
1491
     *                <p>String with right padding.</p>
1492
     */
1493 14
    public function padRight(int $length, string $padStr = ' '): self
1494
    {
1495 14
        return static::create(
1496 14
            $this->utf8::str_pad_right(
1497 14
                $this->str,
1498 14
                $length,
1499 14
                $padStr,
1500 14
                $this->encoding
1501
            )
1502
        );
1503
    }
1504
1505
    /**
1506
     * Returns a new string starting with $string.
1507
     *
1508
     * @param string $string <p>The string to append.</p>
1509
     *
1510
     * @return static
1511
     *                <p>Object with appended $string.</p>
1512
     */
1513 4
    public function prepend(string $string): self
1514
    {
1515 4
        return static::create($string . $this->str, $this->encoding);
1516
    }
1517
1518
    /**
1519
     * Replaces all occurrences of $pattern in $str by $replacement.
1520
     *
1521
     * @param string $pattern     <p>The regular expression pattern.</p>
1522
     * @param string $replacement <p>The string to replace with.</p>
1523
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
1524
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
1525
     *
1526
     * @return static
1527
     *                <p>Object with the result2ing $str after the replacements.</p>
1528
     */
1529 19
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
1530
    {
1531 19
        return static::create(
1532 19
            $this->utf8::regex_replace(
1533 19
                $this->str,
1534 19
                $pattern,
1535 19
                $replacement,
1536 19
                $options,
1537 19
                $delimiter
1538
            ),
1539 19
            $this->encoding
1540
        );
1541
    }
1542
1543
    /**
1544
     * Remove html via "strip_tags()" from the string.
1545
     *
1546
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
1547
     *                              not be stripped. Default: null
1548
     *                              </p>
1549
     *
1550
     * @return static
1551
     */
1552 6
    public function removeHtml(string $allowableTags = null): self
1553
    {
1554 6
        return static::create(
1555 6
            $this->utf8::remove_html($this->str, $allowableTags . ''),
1556 6
            $this->encoding
1557
        );
1558
    }
1559
1560
    /**
1561
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
1562
     *
1563
     * @param string $replacement [optional] <p>Default is a empty string.</p>
1564
     *
1565
     * @return static
1566
     */
1567 6
    public function removeHtmlBreak(string $replacement = ''): self
1568
    {
1569 6
        return static::create(
1570 6
            $this->utf8::remove_html_breaks($this->str, $replacement),
1571 6
            $this->encoding
1572
        );
1573
    }
1574
1575
    /**
1576
     * Returns a new string with the prefix $substring removed, if present.
1577
     *
1578
     * @param string $substring <p>The prefix to remove.</p>
1579
     *
1580
     * @return static
1581
     *                <p>Object having a $str without the prefix $substring.</p>
1582
     */
1583 24
    public function removeLeft(string $substring): self
1584
    {
1585 24
        return static::create(
1586 24
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
1587 24
            $this->encoding
1588
        );
1589
    }
1590
1591
    /**
1592
     * Returns a new string with the suffix $substring removed, if present.
1593
     *
1594
     * @param string $substring <p>The suffix to remove.</p>
1595
     *
1596
     * @return static
1597
     *                <p>Object having a $str without the suffix $substring.</p>
1598
     */
1599 24
    public function removeRight(string $substring): self
1600
    {
1601 24
        return static::create(
1602 24
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
1603 24
            $this->encoding
1604
        );
1605
    }
1606
1607
    /**
1608
     * Try to remove all XSS-attacks from the string.
1609
     *
1610
     * @return static
1611
     */
1612 6
    public function removeXss(): self
1613
    {
1614 6
        static $antiXss = null;
1615
1616 6
        if ($antiXss === null) {
1617 1
            $antiXss = new AntiXSS();
1618
        }
1619
1620 6
        $str = $antiXss->xss_clean($this->str);
1621
1622 6
        return static::create($str, $this->encoding);
1623
    }
1624
1625
    /**
1626
     * Returns a repeated string given a multiplier.
1627
     *
1628
     * @param int $multiplier <p>The number of times to repeat the string.</p>
1629
     *
1630
     * @return static
1631
     *                <p>Object with a repeated str.</p>
1632
     */
1633 14
    public function repeat(int $multiplier): self
1634
    {
1635 14
        return static::create(
1636 14
            \str_repeat($this->str, $multiplier),
1637 14
            $this->encoding
1638
        );
1639
    }
1640
1641
    /**
1642
     * Replaces all occurrences of $search in $str by $replacement.
1643
     *
1644
     * @param string $search        <p>The needle to search for.</p>
1645
     * @param string $replacement   <p>The string to replace with.</p>
1646
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1647
     *
1648
     * @return static
1649
     *                <p>Object with the resulting $str after the replacements.</p>
1650
     */
1651 45
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
1652
    {
1653 45
        if ($search === '' && $replacement === '') {
1654 10
            return static::create($this->str, $this->encoding);
1655
        }
1656
1657 35
        if ($this->str === '' && $search === '') {
1658 2
            return static::create($replacement, $this->encoding);
1659
        }
1660
1661 33
        if ($caseSensitive) {
1662 28
            return static::create(
1663 28
                $this->utf8::str_replace($search, $replacement, $this->str),
1664 28
                $this->encoding
1665
            );
1666
        }
1667
1668 5
        return static::create(
1669 5
            $this->utf8::str_ireplace($search, $replacement, $this->str),
1670 5
            $this->encoding
1671
        );
1672
    }
1673
1674
    /**
1675
     * Replaces all occurrences of $search in $str by $replacement.
1676
     *
1677
     * @param array        $search        <p>The elements to search for.</p>
1678
     * @param array|string $replacement   <p>The string to replace with.</p>
1679
     * @param bool         $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1680
     *
1681
     * @return static
1682
     *                <p>Object with the resulting $str after the replacements.</p>
1683
     */
1684 30
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
1685
    {
1686 30
        if ($caseSensitive) {
1687 23
            return static::create(
1688 23
                $this->utf8::str_replace($search, $replacement, $this->str),
1689 23
                $this->encoding
1690
            );
1691
        }
1692
1693 7
        return static::create(
1694 7
            $this->utf8::str_ireplace($search, $replacement, $this->str),
1695 7
            $this->encoding
1696
        );
1697
    }
1698
1699
    /**
1700
     * Replaces first occurrences of $search from the beginning of string with $replacement.
1701
     *
1702
     * @param string $search      <p>The string to search for.</p>
1703
     * @param string $replacement <p>The replacement.</p>
1704
     *
1705
     * @return static
1706
     *                <p>Object with the resulting $str after the replacements.</p>
1707
     */
1708 16
    public function replaceFirst(string $search, string $replacement): self
1709
    {
1710 16
        return static::create(
1711 16
            $this->utf8::str_replace_first($search, $replacement, $this->str),
1712 16
            $this->encoding
1713
        );
1714
    }
1715
1716
    /**
1717
     * Replaces last occurrences of $search from the ending of string with $replacement.
1718
     *
1719
     * @param string $search      <p>The string to search for.</p>
1720
     * @param string $replacement <p>The replacement.</p>
1721
     *
1722
     * @return static
1723
     *                <p>Object with the resulting $str after the replacements.</p>
1724
     */
1725 15
    public function replaceLast(string $search, string $replacement): self
1726
    {
1727 15
        return static::create(
1728 15
            $this->utf8::str_replace_last($search, $replacement, $this->str),
1729 15
            $this->encoding
1730
        );
1731
    }
1732
1733
    /**
1734
     * Replaces all occurrences of $search from the beginning of string with $replacement.
1735
     *
1736
     * @param string $search      <p>The string to search for.</p>
1737
     * @param string $replacement <p>The replacement.</p>
1738
     *
1739
     * @return static
1740
     *                <p>Object with the resulting $str after the replacements.</p>
1741
     */
1742 16
    public function replaceBeginning(string $search, string $replacement): self
1743
    {
1744 16
        return static::create(
1745 16
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
1746 16
            $this->encoding
1747
        );
1748
    }
1749
1750
    /**
1751
     * Replaces all occurrences of $search from the ending of string with $replacement.
1752
     *
1753
     * @param string $search      <p>The string to search for.</p>
1754
     * @param string $replacement <p>The replacement.</p>
1755
     *
1756
     * @return static
1757
     *                <p>Object with the resulting $str after the replacements.</p>
1758
     */
1759 16
    public function replaceEnding(string $search, string $replacement): self
1760
    {
1761 16
        return static::create(
1762 16
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
1763 16
            $this->encoding
1764
        );
1765
    }
1766
1767
    /**
1768
     * Returns a reversed string. A multibyte version of strrev().
1769
     *
1770
     * @return static
1771
     *                <p>Object with a reversed $str.</p>
1772
     */
1773 10
    public function reverse(): self
1774
    {
1775 10
        return static::create($this->utf8::strrev($this->str), $this->encoding);
1776
    }
1777
1778
    /**
1779
     * Truncates the string to a given length, while ensuring that it does not
1780
     * split words. If $substring is provided, and truncating occurs, the
1781
     * string is further truncated so that the substring may be appended without
1782
     * exceeding the desired length.
1783
     *
1784
     * @param int    $length                          <p>Desired length of the truncated string.</p>
1785
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
1786
     * @param bool   $ignoreDoNotSplitWordsForOneWord
1787
     *
1788
     * @return static
1789
     *                <p>Object with the resulting $str after truncating.</p>
1790
     */
1791 45
    public function safeTruncate(int $length, string $substring = '', bool $ignoreDoNotSplitWordsForOneWord = true): self
1792
    {
1793 45
        return static::create(
1794 45
            $this->utf8::str_truncate_safe(
1795 45
                $this->str,
1796 45
                $length,
1797 45
                $substring,
1798 45
                $this->encoding,
1799 45
                $ignoreDoNotSplitWordsForOneWord
1800
            ),
1801 45
            $this->encoding
1802
        );
1803
    }
1804
1805
    /**
1806
     * Shorten the string after $length, but also after the next word.
1807
     *
1808
     * @param int    $length
1809
     * @param string $strAddOn [optional] <p>Default: '…'</p>
1810
     *
1811
     * @return static
1812
     */
1813 4
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
1814
    {
1815 4
        return static::create(
1816 4
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
1817 4
            $this->encoding
1818
        );
1819
    }
1820
1821
    /**
1822
     * A multibyte string shuffle function. It returns a string with its
1823
     * characters in random order.
1824
     *
1825
     * @return static
1826
     *                <p>Object with a shuffled $str.</p>
1827
     */
1828 6
    public function shuffle(): self
1829
    {
1830 6
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
1831
    }
1832
1833
    /**
1834
     * Returns the substring beginning at $start, and up to, but not including
1835
     * the index specified by $end. If $end is omitted, the function extracts
1836
     * the remaining string. If $end is negative, it is computed from the end
1837
     * of the string.
1838
     *
1839
     * @param int $start <p>Initial index from which to begin extraction.</p>
1840
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
1841
     *
1842
     * @return static
1843
     *                <p>Object with its $str being the extracted substring.</p>
1844
     */
1845 34
    public function slice(int $start, int $end = null): self
1846
    {
1847 34
        return static::create(
1848 34
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
1849 34
            $this->encoding
1850
        );
1851
    }
1852
1853
    /**
1854
     * Converts the string into an URL slug. This includes replacing non-ASCII
1855
     * characters with their closest ASCII equivalents, removing remaining
1856
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
1857
     * $replacement. The replacement defaults to a single dash, and the string
1858
     * is also converted to lowercase. The language of the source string can
1859
     * also be supplied for language-specific transliteration.
1860
     *
1861
     * @param string $replacement The string used to replace whitespace
1862
     * @param string $language    Language of the source string
1863
     *
1864
     * @return static Object whose $str has been converted to an URL slug
1865
     */
1866 16
    public function slugify(string $replacement = '-', string $language = 'en'): self
1867
    {
1868 16
        $stringy = self::create($this->str);
1869
1870 16
        $langSpecific = self::langSpecificCharsArray($language);
1871 16
        if (!empty($langSpecific)) {
1872
            $stringy->str = \str_replace($langSpecific[0], $langSpecific[1], $stringy->str);
1873
        }
1874
1875 16
        foreach ($this->charsArray() as $key => $value) {
1876 16
            $stringy->str = \str_replace($value, $key, $stringy->str);
1877
        }
1878 16
        $stringy->str = \str_replace('@', $replacement, $stringy->str);
1879
1880 16
        $stringy->str = (string) \preg_replace(
1881 16
            '/[^a-zA-Z\\d\\s\\-_' . \preg_quote($replacement, '/') . ']/u',
1882 16
            '',
1883 16
            $stringy->str
1884
        );
1885 16
        $stringy->str = (string) \preg_replace("/^['\\s']+|['\\s']+\$/", '', \strtolower($stringy->str));
1886 16
        $stringy->str = (string) \preg_replace('/\\B([A-Z])/', '/-\\1/', $stringy->str);
1887 16
        $stringy->str = (string) \preg_replace('/[-_\\s]+/', $replacement, $stringy->str);
1888
1889 16
        $l = \strlen($replacement);
1890 16 View Code Duplication
        if (\strpos($stringy->str, $replacement) === 0) {
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...
1891 1
            $stringy->str = (string) \substr($stringy->str, $l);
1892
        }
1893
1894 16 View Code Duplication
        if (\substr($stringy->str, -$l) === $replacement) {
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...
1895 1
            $stringy->str = (string) \substr($stringy->str, 0, \strlen($stringy->str) - $l);
1896
        }
1897
1898 16
        return static::create($stringy->str, $this->encoding);
1899
    }
1900
1901
    /**
1902
     * Converts the string into an URL slug. This includes replacing non-ASCII
1903
     * characters with their closest ASCII equivalents, removing remaining
1904
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
1905
     * $replacement. The replacement defaults to a single dash, and the string
1906
     * is also converted to lowercase.
1907
     *
1908
     * @param string $replacement [optional] <p>The string used to replace whitespace. Default: '-'</p>
1909
     * @param string $language    [optional] <p>The language for the url. Default: 'de'</p>
1910
     * @param bool   $strToLower  [optional] <p>string to lower. Default: true</p>
1911
     *
1912
     * @return static
1913
     *                <p>Object whose $str has been converted to an URL slug.</p>
1914
     */
1915 15
    public function urlify(string $replacement = '-', string $language = 'de', bool $strToLower = true): self
1916
    {
1917 15
        return static::create(
1918 15
            URLify::slug($this->str, $language, $replacement, $strToLower),
1919 15
            $this->encoding
1920
        );
1921
    }
1922
1923
    /**
1924
     * Convert a string to e.g.: "snake_case"
1925
     *
1926
     * @return static
1927
     *                <p>Object with $str in snake_case.</p>
1928
     */
1929 20
    public function snakeize(): self
1930
    {
1931 20
        return static::create(
1932 20
            $this->utf8::str_snakeize($this->str, $this->encoding),
1933 20
            $this->encoding
1934
        );
1935
    }
1936
1937
    /**
1938
     * Splits the string with the provided regular expression, returning an
1939
     * array of Stringy objects. An optional integer $limit will truncate the
1940
     * results.
1941
     *
1942
     * @param string $pattern <p>The regex with which to split the string.</p>
1943
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no limit</p>
1944
     *
1945
     * @return static[]
1946
     *                  <p>An array of Stringy objects.</p>
1947
     */
1948 35
    public function split(string $pattern, int $limit = null): array
1949
    {
1950 35
        if ($limit === null) {
1951 7
            $limit = -1;
1952
        }
1953
1954 35
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
1955 35
        foreach ($array as $i => &$value) {
1956 31
            $value = static::create($value, $this->encoding);
1957
        }
1958
1959 35
        return $array;
1960
    }
1961
1962
    /**
1963
     * Returns true if the string begins with $substring, false otherwise. By
1964
     * default, the comparison is case-sensitive, but can be made insensitive
1965
     * by setting $caseSensitive to false.
1966
     *
1967
     * @param string $substring     <p>The substring to look for.</p>
1968
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1969
     *
1970
     * @return bool
1971
     *              <p>Whether or not $str starts with $substring.</p>
1972
     */
1973 55
    public function startsWith(string $substring, bool $caseSensitive = true): bool
1974
    {
1975 55
        if ($caseSensitive) {
1976 30
            return $this->utf8::str_starts_with($this->str, $substring);
1977
        }
1978
1979 25
        return $this->utf8::str_istarts_with($this->str, $substring);
1980
    }
1981
1982
    /**
1983
     * Returns true if the string begins with any of $substrings, false otherwise.
1984
     * By default the comparison is case-sensitive, but can be made insensitive by
1985
     * setting $caseSensitive to false.
1986
     *
1987
     * @param array $substrings    <p>Substrings to look for.</p>
1988
     * @param bool  $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1989
     *
1990
     * @return bool
1991
     *              <p>Whether or not $str starts with $substring.</p>
1992
     */
1993 23
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
1994
    {
1995 23
        if ($caseSensitive) {
1996 15
            return $this->utf8::str_starts_with_any($this->str, $substrings);
1997
        }
1998
1999 8
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
2000
    }
2001
2002
    /**
2003
     * Strip all whitespace characters. This includes tabs and newline characters,
2004
     * as well as multibyte whitespace such as the thin space and ideographic space.
2005
     *
2006
     * @return static
2007
     */
2008 24
    public function stripWhitespace(): self
2009
    {
2010 24
        return static::create(
2011 24
            $this->utf8::strip_whitespace($this->str),
2012 24
            $this->encoding
2013
        );
2014
    }
2015
2016
    /**
2017
     * Remove css media-queries.
2018
     *
2019
     * @return static
2020
     */
2021 1
    public function stripeCssMediaQueries(): self
2022
    {
2023 1
        return static::create(
2024 1
            $this->utf8::css_stripe_media_queries($this->str),
2025 1
            $this->encoding
2026
        );
2027
    }
2028
2029
    /**
2030
     * Remove empty html-tag.
2031
     *
2032
     * e.g.: <tag></tag>
2033
     *
2034
     * @return static
2035
     */
2036 1
    public function stripeEmptyHtmlTags(): self
2037
    {
2038 1
        return static::create(
2039 1
            $this->utf8::html_stripe_empty_tags($this->str),
2040 1
            $this->encoding
2041
        );
2042
    }
2043
2044
    /**
2045
     * Returns the substring beginning at $start with the specified $length.
2046
     * It differs from the $this->utf8::substr() function in that providing a $length of
2047
     * null will return the rest of the string, rather than an empty string.
2048
     *
2049
     * @param int $start  <p>Position of the first character to use.</p>
2050
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
2051
     *
2052
     * @return static
2053
     *                <p>Object with its $str being the substring.</p>
2054
     */
2055 18
    public function substr(int $start, int $length = null): self
2056
    {
2057 18
        return static::create(
2058 18
            $this->utf8::substr(
2059 18
                $this->str,
2060 18
                $start,
2061 18
                $length,
2062 18
                $this->encoding
2063
            ),
2064 18
            $this->encoding
2065
        );
2066
    }
2067
2068
    /**
2069
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
2070
     * If no match is found returns new empty Stringy object.
2071
     *
2072
     * @param string $needle       <p>The string to look for.</p>
2073
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2074
     *
2075
     * @return static
2076
     */
2077 2 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...
2078
    {
2079 2
        return static::create(
2080 2
            $this->utf8::str_substr_first(
2081 2
                $this->str,
2082 2
                $needle,
2083 2
                $beforeNeedle,
2084 2
                $this->encoding
2085
            ),
2086 2
            $this->encoding
2087
        );
2088
    }
2089
2090
    /**
2091
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
2092
     * If no match is found returns new empty Stringy object.
2093
     *
2094
     * @param string $needle       <p>The string to look for.</p>
2095
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
2096
     *
2097
     * @return static
2098
     */
2099 2 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...
2100
    {
2101 2
        return static::create(
2102 2
            $this->utf8::str_isubstr_first(
2103 2
                $this->str,
2104 2
                $needle,
2105 2
                $beforeNeedle,
2106 2
                $this->encoding
2107
            ),
2108 2
            $this->encoding
2109
        );
2110
    }
2111
2112
    /**
2113
     * Surrounds $str with the given substring.
2114
     *
2115
     * @param string $substring <p>The substring to add to both sides.</P>
2116
     *
2117
     * @return static
2118
     *                <p>Object whose $str had the substring both prepended and appended.</p>
2119
     */
2120 10
    public function surround(string $substring): self
2121
    {
2122 10
        return static::create(
2123 10
            $substring . $this->str . $substring,
2124 10
            $this->encoding
2125
        );
2126
    }
2127
2128
    /**
2129
     * Returns a case swapped version of the string.
2130
     *
2131
     * @return static
2132
     *                <p>Object whose $str has each character's case swapped.</P>
2133
     */
2134 10
    public function swapCase(): self
2135
    {
2136 10
        return static::create(
2137 10
            $this->utf8::swapCase($this->str, $this->encoding),
2138 10
            $this->encoding
2139
        );
2140
    }
2141
2142
    /**
2143
     * Returns a string with smart quotes, ellipsis characters, and dashes from
2144
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
2145
     * equivalents.
2146
     *
2147
     * @return static
2148
     *                <p>Object whose $str has those characters removed.</p>
2149
     */
2150 8
    public function tidy(): self
2151
    {
2152 8
        return static::create(
2153 8
            $this->utf8::normalize_msword($this->str),
2154 8
            $this->encoding
2155
        );
2156
    }
2157
2158
    /**
2159
     * Returns a trimmed string with the first letter of each word capitalized.
2160
     * Also accepts an array, $ignore, allowing you to list words not to be
2161
     * capitalized.
2162
     *
2163
     * @param array|string[]|null $ignore [optional] <p>An array of words not to capitalize or null. Default: null</p>
2164
     *
2165
     * @return static
2166
     *                <p>Object with a titleized $str.</p>
2167
     */
2168 10
    public function titleize(array $ignore = null): self
2169
    {
2170 10
        return static::create(
2171 10
            $this->utf8::str_titleize($this->str, $ignore, $this->encoding),
2172 10
            $this->encoding
2173
        );
2174
    }
2175
2176
    /**
2177
     * Returns a trimmed string in proper title case.
2178
     *
2179
     * Also accepts an array, $ignore, allowing you to list words not to be
2180
     * capitalized.
2181
     *
2182
     * Adapted from John Gruber's script.
2183
     *
2184
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
2185
     *
2186
     * @param array $ignore <p>An array of words not to capitalize.</p>
2187
     *
2188
     * @return static
2189
     *                <p>Object with a titleized $str</p>
2190
     */
2191 35
    public function titleizeForHumans(array $ignore = []): self
2192
    {
2193 35
        return static::create(
2194 35
            $this->utf8::str_titleize_for_humans($this->str, $ignore, $this->encoding),
2195 35
            $this->encoding
2196
        );
2197
    }
2198
2199
    /**
2200
     * Returns an ASCII version of the string. A set of non-ASCII characters are
2201
     * replaced with their closest ASCII counterparts, and the rest are removed
2202
     * unless instructed otherwise.
2203
     *
2204
     * @param bool $strict [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad performance |
2205
     *                     Default: false</p>
2206
     *
2207
     * @return static
2208
     *                <p>Object whose $str contains only ASCII characters.</p>
2209
     */
2210 16
    public function toTransliterate(bool $strict = false): self
2211
    {
2212 16
        return static::create(
2213 16
            $this->utf8::to_ascii($this->str, '?', $strict),
2214 16
            $this->encoding
2215
        );
2216
    }
2217
2218
    /**
2219
     * Returns an ASCII version of the string. A set of non-ASCII characters are
2220
     * replaced with their closest ASCII counterparts, and the rest are removed
2221
     * by default. The language or locale of the source string can be supplied
2222
     * for language-specific transliteration in any of the following formats:
2223
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
2224
     * to "aeoeue" rather than "aou" as in other languages.
2225
     *
2226
     * @param string $language          Language of the source string
2227
     * @param bool   $removeUnsupported Whether or not to remove the
2228
     *                                  unsupported characters
2229
     *
2230
     * @return static
2231
     *                <p>Object whose $str contains only ASCII characters.</p>
2232
     */
2233 21
    public function toAscii(string $language = 'en', bool $removeUnsupported = true)
2234
    {
2235
        // init
2236 21
        $str = $this->str;
2237
2238 21
        $langSpecific = self::langSpecificCharsArray($language);
2239 21
        if (!empty($langSpecific)) {
2240 2
            $str = \str_replace($langSpecific[0], $langSpecific[1], $str);
2241
        }
2242
2243 21
        foreach ($this->charsArray() as $key => $value) {
2244 21
            $str = \str_replace($value, $key, $str);
2245
        }
2246
2247 21
        if ($removeUnsupported) {
2248
            /** @noinspection NotOptimalRegularExpressionsInspection */
2249 20
            $str = \preg_replace('/[^\\x20-\\x7E]/u', '', $str);
2250
        }
2251
2252 21
        return static::create($str, $this->encoding);
2253
    }
2254
2255
    /**
2256
     * Returns a boolean representation of the given logical string value.
2257
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
2258
     * 'off', and 'no' will return false. In all instances, case is ignored.
2259
     * For other numeric strings, their sign will determine the return value.
2260
     * In addition, blank strings consisting of only whitespace will return
2261
     * false. For all other strings, the return value is a result of a
2262
     * boolean cast.
2263
     *
2264
     * @return bool
2265
     *              <p>A boolean value for the string.</p>
2266
     */
2267 30
    public function toBoolean(): bool
2268
    {
2269 30
        return $this->utf8::to_boolean($this->str);
2270
    }
2271
2272
    /**
2273
     * Converts all characters in the string to lowercase.
2274
     *
2275
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
2276
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
2277
     *
2278
     * @return static
2279
     *                <p>Object with all characters of $str being lowercase.</p>
2280
     */
2281 12 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...
2282
    {
2283 12
        return static::create(
2284 12
            $this->utf8::strtolower(
2285 12
                $this->str,
2286 12
                $this->encoding,
2287 12
                false,
2288 12
                $lang,
2289 12
                $tryToKeepStringLength
2290
            ),
2291 12
            $this->encoding
2292
        );
2293
    }
2294
2295
    /**
2296
     * Converts each tab in the string to some number of spaces, as defined by
2297
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
2298
     *
2299
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
2300
     *
2301
     * @return static
2302
     *                <p>Object whose $str has had tabs switched to spaces.</p>
2303
     */
2304 12 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...
2305
    {
2306 12
        if ($tabLength === 4) {
2307 6
            $tab = '    ';
2308 6
        } elseif ($tabLength === 2) {
2309 2
            $tab = '  ';
2310
        } else {
2311 4
            $tab = \str_repeat(' ', $tabLength);
2312
        }
2313
2314 12
        return static::create(
2315 12
            \str_replace("\t", $tab, $this->str),
2316 12
            $this->encoding
2317
        );
2318
    }
2319
2320
    /**
2321
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
2322
     * string.
2323
     *
2324
     * @return string
2325
     */
2326 1071
    public function toString(): string
2327
    {
2328 1071
        return (string) $this->str;
2329
    }
2330
2331
    /**
2332
     * Converts each occurrence of some consecutive number of spaces, as
2333
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
2334
     * are converted to a tab.
2335
     *
2336
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
2337
     *
2338
     * @return static
2339
     *                <p>Object whose $str has had spaces switched to tabs.</p>
2340
     */
2341 10 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...
2342
    {
2343 10
        if ($tabLength === 4) {
2344 6
            $tab = '    ';
2345 4
        } elseif ($tabLength === 2) {
2346 2
            $tab = '  ';
2347
        } else {
2348 2
            $tab = \str_repeat(' ', $tabLength);
2349
        }
2350
2351 10
        return static::create(
2352 10
            \str_replace($tab, "\t", $this->str),
2353 10
            $this->encoding
2354
        );
2355
    }
2356
2357
    /**
2358
     * Converts the first character of each word in the string to uppercase
2359
     * and all other chars to lowercase.
2360
     *
2361
     * @return static
2362
     *                <p>Object with all characters of $str being title-cased.</p>
2363
     */
2364 10
    public function toTitleCase(): self
2365
    {
2366 10
        return static::create(
2367 10
            $this->utf8::titlecase($this->str, $this->encoding),
2368 10
            $this->encoding
2369
        );
2370
    }
2371
2372
    /**
2373
     * Converts all characters in the string to uppercase.
2374
     *
2375
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
2376
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
2377
     *
2378
     * @return static
2379
     *                <p>Object with all characters of $str being uppercase.</p>
2380
     */
2381 10 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...
2382
    {
2383 10
        return static::create(
2384 10
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
2385 10
            $this->encoding
2386
        );
2387
    }
2388
2389
    /**
2390
     * Returns a string with whitespace removed from the start and end of the
2391
     * string. Supports the removal of unicode whitespace. Accepts an optional
2392
     * string of characters to strip instead of the defaults.
2393
     *
2394
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
2395
     *
2396
     * @return static
2397
     *                <p>Object with a trimmed $str.</p>
2398
     */
2399 24
    public function trim(string $chars = null): self
2400
    {
2401 24
        return static::create(
2402 24
            $this->utf8::trim($this->str, $chars),
2403 24
            $this->encoding
2404
        );
2405
    }
2406
2407
    /**
2408
     * Returns a string with whitespace removed from the start of the string.
2409
     * Supports the removal of unicode whitespace. Accepts an optional
2410
     * string of characters to strip instead of the defaults.
2411
     *
2412
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
2413
     *
2414
     * @return static
2415
     *                <p>Object with a trimmed $str.</p>
2416
     */
2417 26
    public function trimLeft(string $chars = null): self
2418
    {
2419 26
        return static::create(
2420 26
            $this->utf8::ltrim($this->str, $chars),
2421 26
            $this->encoding
2422
        );
2423
    }
2424
2425
    /**
2426
     * Returns a string with whitespace removed from the end of the string.
2427
     * Supports the removal of unicode whitespace. Accepts an optional
2428
     * string of characters to strip instead of the defaults.
2429
     *
2430
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
2431
     *
2432
     * @return static
2433
     *                <p>Object with a trimmed $str.</p>
2434
     */
2435 26
    public function trimRight(string $chars = null): self
2436
    {
2437 26
        return static::create(
2438 26
            $this->utf8::rtrim($this->str, $chars),
2439 26
            $this->encoding
2440
        );
2441
    }
2442
2443
    /**
2444
     * Truncates the string to a given length. If $substring is provided, and
2445
     * truncating occurs, the string is further truncated so that the substring
2446
     * may be appended without exceeding the desired length.
2447
     *
2448
     * @param int    $length    <p>Desired length of the truncated string.</p>
2449
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
2450
     *
2451
     * @return static
2452
     *                <p>Object with the resulting $str after truncating.</p>
2453
     */
2454 44
    public function truncate(int $length, string $substring = ''): self
2455
    {
2456 44
        return static::create(
2457 44
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
2458 44
            $this->encoding
2459
        );
2460
    }
2461
2462
    /**
2463
     * Returns a lowercase and trimmed string separated by underscores.
2464
     * Underscores are inserted before uppercase characters (with the exception
2465
     * of the first character of the string), and in place of spaces as well as
2466
     * dashes.
2467
     *
2468
     * @return static
2469
     *                <p>Object with an underscored $str.</p>
2470
     */
2471 32
    public function underscored(): self
2472
    {
2473 32
        return $this->delimit('_');
2474
    }
2475
2476
    /**
2477
     * Returns an UpperCamelCase version of the supplied string. It trims
2478
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
2479
     * and underscores, and removes spaces, dashes, underscores.
2480
     *
2481
     * @return static
2482
     *                <p>Object with $str in UpperCamelCase.</p>
2483
     */
2484 26
    public function upperCamelize(): self
2485
    {
2486 26
        return static::create(
2487 26
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
2488 26
            $this->encoding
2489
        );
2490
    }
2491
2492
    /**
2493
     * Converts the first character of the supplied string to upper case.
2494
     *
2495
     * @return static
2496
     *                <p>Object with the first character of $str being upper case.</p>
2497
     */
2498 12
    public function upperCaseFirst(): self
2499
    {
2500 12
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
2501
    }
2502
2503
    /**
2504
     * Converts the string into an valid UTF-8 string.
2505
     *
2506
     * @return static
2507
     */
2508 1
    public function utf8ify(): self
2509
    {
2510 1
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
2511
    }
2512
2513
    /**
2514
     * Returns the replacements for the toAscii() method.
2515
     *
2516
     * @return array
2517
     *               <p>An array of replacements.</p>
2518
     */
2519 37
    protected function charsArray(): array
2520
    {
2521 37
        static $charsArray;
2522
2523 37
        if (isset($charsArray)) {
2524 36
            return $charsArray;
2525
        }
2526
2527
        return $charsArray = [
2528 1
            '0' => ['°', '₀', '۰', '0'],
2529
            '1' => ['¹', '₁', '۱', '1'],
2530
            '2' => ['²', '₂', '۲', '2'],
2531
            '3' => ['³', '₃', '۳', '3'],
2532
            '4' => ['⁴', '₄', '۴', '٤', '4'],
2533
            '5' => ['⁵', '₅', '۵', '٥', '5'],
2534
            '6' => ['⁶', '₆', '۶', '٦', '6'],
2535
            '7' => ['⁷', '₇', '۷', '7'],
2536
            '8' => ['⁸', '₈', '۸', '8'],
2537
            '9' => ['⁹', '₉', '۹', '9'],
2538
            'a' => [
2539
                'à',
2540
                'á',
2541
                'ả',
2542
                'ã',
2543
                'ạ',
2544
                'ă',
2545
                'ắ',
2546
                'ằ',
2547
                'ẳ',
2548
                'ẵ',
2549
                'ặ',
2550
                'â',
2551
                'ấ',
2552
                'ầ',
2553
                'ẩ',
2554
                'ẫ',
2555
                'ậ',
2556
                'ā',
2557
                'ą',
2558
                'å',
2559
                'α',
2560
                'ά',
2561
                'ἀ',
2562
                'ἁ',
2563
                'ἂ',
2564
                'ἃ',
2565
                'ἄ',
2566
                'ἅ',
2567
                'ἆ',
2568
                'ἇ',
2569
                'ᾀ',
2570
                'ᾁ',
2571
                'ᾂ',
2572
                'ᾃ',
2573
                'ᾄ',
2574
                'ᾅ',
2575
                'ᾆ',
2576
                'ᾇ',
2577
                'ὰ',
2578
                'ά',
2579
                'ᾰ',
2580
                'ᾱ',
2581
                'ᾲ',
2582
                'ᾳ',
2583
                'ᾴ',
2584
                'ᾶ',
2585
                'ᾷ',
2586
                'а',
2587
                'أ',
2588
                'အ',
2589
                'ာ',
2590
                'ါ',
2591
                'ǻ',
2592
                'ǎ',
2593
                'ª',
2594
                'ა',
2595
                'अ',
2596
                'ا',
2597
                'a',
2598
                'ä',
2599
            ],
2600
            'b' => ['б', 'β', 'ب', 'ဗ', 'ბ', 'b'],
2601
            'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ', 'c'],
2602
            'd' => [
2603
                'ď',
2604
                'ð',
2605
                'đ',
2606
                'ƌ',
2607
                'ȡ',
2608
                'ɖ',
2609
                'ɗ',
2610
                'ᵭ',
2611
                'ᶁ',
2612
                'ᶑ',
2613
                'д',
2614
                'δ',
2615
                'د',
2616
                'ض',
2617
                'ဍ',
2618
                'ဒ',
2619
                'დ',
2620
                'd',
2621
            ],
2622
            'e' => [
2623
                'é',
2624
                'è',
2625
                'ẻ',
2626
                'ẽ',
2627
                'ẹ',
2628
                'ê',
2629
                'ế',
2630
                'ề',
2631
                'ể',
2632
                'ễ',
2633
                'ệ',
2634
                'ë',
2635
                'ē',
2636
                'ę',
2637
                'ě',
2638
                'ĕ',
2639
                'ė',
2640
                'ε',
2641
                'έ',
2642
                'ἐ',
2643
                'ἑ',
2644
                'ἒ',
2645
                'ἓ',
2646
                'ἔ',
2647
                'ἕ',
2648
                'ὲ',
2649
                'έ',
2650
                'е',
2651
                'ё',
2652
                'э',
2653
                'є',
2654
                'ə',
2655
                'ဧ',
2656
                'ေ',
2657
                'ဲ',
2658
                'ე',
2659
                'ए',
2660
                'إ',
2661
                'ئ',
2662
                'e',
2663
            ],
2664
            'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ', 'f'],
2665
            'g' => [
2666
                'ĝ',
2667
                'ğ',
2668
                'ġ',
2669
                'ģ',
2670
                'г',
2671
                'ґ',
2672
                'γ',
2673
                'ဂ',
2674
                'გ',
2675
                'گ',
2676
                'g',
2677
            ],
2678
            'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ', 'h'],
2679
            'i' => [
2680
                'í',
2681
                'ì',
2682
                'ỉ',
2683
                'ĩ',
2684
                'ị',
2685
                'î',
2686
                'ï',
2687
                'ī',
2688
                'ĭ',
2689
                'į',
2690
                'ı',
2691
                'ι',
2692
                'ί',
2693
                'ϊ',
2694
                'ΐ',
2695
                'ἰ',
2696
                'ἱ',
2697
                'ἲ',
2698
                'ἳ',
2699
                'ἴ',
2700
                'ἵ',
2701
                'ἶ',
2702
                'ἷ',
2703
                'ὶ',
2704
                'ί',
2705
                'ῐ',
2706
                'ῑ',
2707
                'ῒ',
2708
                'ΐ',
2709
                'ῖ',
2710
                'ῗ',
2711
                'і',
2712
                'ї',
2713
                'и',
2714
                'ဣ',
2715
                'ိ',
2716
                'ီ',
2717
                'ည်',
2718
                'ǐ',
2719
                'ი',
2720
                'इ',
2721
                'ی',
2722
                'i',
2723
            ],
2724
            'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج', 'j'],
2725
            'k' => [
2726
                'ķ',
2727
                'ĸ',
2728
                'к',
2729
                'κ',
2730
                'Ķ',
2731
                'ق',
2732
                'ك',
2733
                'က',
2734
                'კ',
2735
                'ქ',
2736
                'ک',
2737
                'k',
2738
            ],
2739
            'l' => [
2740
                'ł',
2741
                'ľ',
2742
                'ĺ',
2743
                'ļ',
2744
                'ŀ',
2745
                'л',
2746
                'λ',
2747
                'ل',
2748
                'လ',
2749
                'ლ',
2750
                'l',
2751
            ],
2752
            'm' => ['м', 'μ', 'م', 'မ', 'მ', 'm'],
2753
            'n' => [
2754
                'ñ',
2755
                'ń',
2756
                'ň',
2757
                'ņ',
2758
                'ʼn',
2759
                'ŋ',
2760
                'ν',
2761
                'н',
2762
                'ن',
2763
                'န',
2764
                'ნ',
2765
                'n',
2766
            ],
2767
            'o' => [
2768
                'ó',
2769
                'ò',
2770
                'ỏ',
2771
                'õ',
2772
                'ọ',
2773
                'ô',
2774
                'ố',
2775
                'ồ',
2776
                'ổ',
2777
                'ỗ',
2778
                'ộ',
2779
                'ơ',
2780
                'ớ',
2781
                'ờ',
2782
                'ở',
2783
                'ỡ',
2784
                'ợ',
2785
                'ø',
2786
                'ō',
2787
                'ő',
2788
                'ŏ',
2789
                'ο',
2790
                'ὀ',
2791
                'ὁ',
2792
                'ὂ',
2793
                'ὃ',
2794
                'ὄ',
2795
                'ὅ',
2796
                'ὸ',
2797
                'ό',
2798
                'о',
2799
                'و',
2800
                'θ',
2801
                'ို',
2802
                'ǒ',
2803
                'ǿ',
2804
                'º',
2805
                'ო',
2806
                'ओ',
2807
                'o',
2808
                'ö',
2809
            ],
2810
            'p' => ['п', 'π', 'ပ', 'პ', 'پ', 'p'],
2811
            'q' => ['ყ', 'q'],
2812
            'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ', 'r'],
2813
            's' => [
2814
                'ś',
2815
                'š',
2816
                'ş',
2817
                'с',
2818
                'σ',
2819
                'ș',
2820
                'ς',
2821
                'س',
2822
                'ص',
2823
                'စ',
2824
                'ſ',
2825
                'ს',
2826
                's',
2827
            ],
2828
            't' => [
2829
                'ť',
2830
                'ţ',
2831
                'т',
2832
                'τ',
2833
                'ț',
2834
                'ت',
2835
                'ط',
2836
                'ဋ',
2837
                'တ',
2838
                'ŧ',
2839
                'თ',
2840
                'ტ',
2841
                't',
2842
            ],
2843
            'u' => [
2844
                'ú',
2845
                'ù',
2846
                'ủ',
2847
                'ũ',
2848
                'ụ',
2849
                'ư',
2850
                'ứ',
2851
                'ừ',
2852
                'ử',
2853
                'ữ',
2854
                'ự',
2855
                'û',
2856
                'ū',
2857
                'ů',
2858
                'ű',
2859
                'ŭ',
2860
                'ų',
2861
                'µ',
2862
                'у',
2863
                'ဉ',
2864
                'ု',
2865
                'ူ',
2866
                'ǔ',
2867
                'ǖ',
2868
                'ǘ',
2869
                'ǚ',
2870
                'ǜ',
2871
                'უ',
2872
                'उ',
2873
                'u',
2874
                'ў',
2875
                'ü',
2876
            ],
2877
            'v' => ['в', 'ვ', 'ϐ', 'v'],
2878
            'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ', 'w'],
2879
            'x' => ['χ', 'ξ', 'x'],
2880
            'y' => [
2881
                'ý',
2882
                'ỳ',
2883
                'ỷ',
2884
                'ỹ',
2885
                'ỵ',
2886
                'ÿ',
2887
                'ŷ',
2888
                'й',
2889
                'ы',
2890
                'υ',
2891
                'ϋ',
2892
                'ύ',
2893
                'ΰ',
2894
                'ي',
2895
                'ယ',
2896
                'y',
2897
            ],
2898
            'z'    => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ', 'z'],
2899
            'aa'   => ['ع', 'आ', 'آ'],
2900
            'ae'   => ['æ', 'ǽ'],
2901
            'ai'   => ['ऐ'],
2902
            'ch'   => ['ч', 'ჩ', 'ჭ', 'چ'],
2903
            'dj'   => ['ђ', 'đ'],
2904
            'dz'   => ['џ', 'ძ'],
2905
            'ei'   => ['ऍ'],
2906
            'gh'   => ['غ', 'ღ'],
2907
            'ii'   => ['ई'],
2908
            'ij'   => ['ij'],
2909
            'kh'   => ['х', 'خ', 'ხ'],
2910
            'lj'   => ['љ'],
2911
            'nj'   => ['њ'],
2912
            'oe'   => ['œ', 'ؤ'],
2913
            'oi'   => ['ऑ'],
2914
            'oii'  => ['ऒ'],
2915
            'ps'   => ['ψ'],
2916
            'sh'   => ['ш', 'შ', 'ش'],
2917
            'shch' => ['щ'],
2918
            'ss'   => ['ß'],
2919
            'sx'   => ['ŝ'],
2920
            'th'   => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
2921
            'ts'   => ['ц', 'ც', 'წ'],
2922
            'uu'   => ['ऊ'],
2923
            'ya'   => ['я'],
2924
            'yu'   => ['ю'],
2925
            'zh'   => ['ж', 'ჟ', 'ژ'],
2926
            '(c)'  => ['©'],
2927
            'A'    => [
2928
                'Á',
2929
                'À',
2930
                'Ả',
2931
                'Ã',
2932
                'Ạ',
2933
                'Ă',
2934
                'Ắ',
2935
                'Ằ',
2936
                'Ẳ',
2937
                'Ẵ',
2938
                'Ặ',
2939
                'Â',
2940
                'Ấ',
2941
                'Ầ',
2942
                'Ẩ',
2943
                'Ẫ',
2944
                'Ậ',
2945
                'Å',
2946
                'Ā',
2947
                'Ą',
2948
                'Α',
2949
                'Ά',
2950
                'Ἀ',
2951
                'Ἁ',
2952
                'Ἂ',
2953
                'Ἃ',
2954
                'Ἄ',
2955
                'Ἅ',
2956
                'Ἆ',
2957
                'Ἇ',
2958
                'ᾈ',
2959
                'ᾉ',
2960
                'ᾊ',
2961
                'ᾋ',
2962
                'ᾌ',
2963
                'ᾍ',
2964
                'ᾎ',
2965
                'ᾏ',
2966
                'Ᾰ',
2967
                'Ᾱ',
2968
                'Ὰ',
2969
                'Ά',
2970
                'ᾼ',
2971
                'А',
2972
                'Ǻ',
2973
                'Ǎ',
2974
                'A',
2975
                'Ä',
2976
            ],
2977
            'B' => ['Б', 'Β', 'ब', 'B'],
2978
            'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ', 'C'],
2979
            'D' => [
2980
                'Ď',
2981
                'Ð',
2982
                'Đ',
2983
                'Ɖ',
2984
                'Ɗ',
2985
                'Ƌ',
2986
                'ᴅ',
2987
                'ᴆ',
2988
                'Д',
2989
                'Δ',
2990
                'D',
2991
            ],
2992
            'E' => [
2993
                'É',
2994
                'È',
2995
                'Ẻ',
2996
                'Ẽ',
2997
                'Ẹ',
2998
                'Ê',
2999
                'Ế',
3000
                'Ề',
3001
                'Ể',
3002
                'Ễ',
3003
                'Ệ',
3004
                'Ë',
3005
                'Ē',
3006
                'Ę',
3007
                'Ě',
3008
                'Ĕ',
3009
                'Ė',
3010
                'Ε',
3011
                'Έ',
3012
                'Ἐ',
3013
                'Ἑ',
3014
                'Ἒ',
3015
                'Ἓ',
3016
                'Ἔ',
3017
                'Ἕ',
3018
                'Έ',
3019
                'Ὲ',
3020
                'Е',
3021
                'Ё',
3022
                'Э',
3023
                'Є',
3024
                'Ə',
3025
                'E',
3026
            ],
3027
            'F' => ['Ф', 'Φ', 'F'],
3028
            'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ', 'G'],
3029
            'H' => ['Η', 'Ή', 'Ħ', 'H'],
3030
            'I' => [
3031
                'Í',
3032
                'Ì',
3033
                'Ỉ',
3034
                'Ĩ',
3035
                'Ị',
3036
                'Î',
3037
                'Ï',
3038
                'Ī',
3039
                'Ĭ',
3040
                'Į',
3041
                'İ',
3042
                'Ι',
3043
                'Ί',
3044
                'Ϊ',
3045
                'Ἰ',
3046
                'Ἱ',
3047
                'Ἳ',
3048
                'Ἴ',
3049
                'Ἵ',
3050
                'Ἶ',
3051
                'Ἷ',
3052
                'Ῐ',
3053
                'Ῑ',
3054
                'Ὶ',
3055
                'Ί',
3056
                'И',
3057
                'І',
3058
                'Ї',
3059
                'Ǐ',
3060
                'ϒ',
3061
                'I',
3062
            ],
3063
            'J' => ['J'],
3064
            'K' => ['К', 'Κ', 'K'],
3065
            'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल', 'L'],
3066
            'M' => ['М', 'Μ', 'M'],
3067
            'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν', 'N'],
3068
            'O' => [
3069
                'Ó',
3070
                'Ò',
3071
                'Ỏ',
3072
                'Õ',
3073
                'Ọ',
3074
                'Ô',
3075
                'Ố',
3076
                'Ồ',
3077
                'Ổ',
3078
                'Ỗ',
3079
                'Ộ',
3080
                'Ơ',
3081
                'Ớ',
3082
                'Ờ',
3083
                'Ở',
3084
                'Ỡ',
3085
                'Ợ',
3086
                'Ø',
3087
                'Ō',
3088
                'Ő',
3089
                'Ŏ',
3090
                'Ο',
3091
                'Ό',
3092
                'Ὀ',
3093
                'Ὁ',
3094
                'Ὂ',
3095
                'Ὃ',
3096
                'Ὄ',
3097
                'Ὅ',
3098
                'Ὸ',
3099
                'Ό',
3100
                'О',
3101
                'Θ',
3102
                'Ө',
3103
                'Ǒ',
3104
                'Ǿ',
3105
                'O',
3106
                'Ö',
3107
            ],
3108
            'P' => ['П', 'Π', 'P'],
3109
            'Q' => ['Q'],
3110
            'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ', 'R'],
3111
            'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ', 'S'],
3112
            'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ', 'T'],
3113
            'U' => [
3114
                'Ú',
3115
                'Ù',
3116
                'Ủ',
3117
                'Ũ',
3118
                'Ụ',
3119
                'Ư',
3120
                'Ứ',
3121
                'Ừ',
3122
                'Ử',
3123
                'Ữ',
3124
                'Ự',
3125
                'Û',
3126
                'Ū',
3127
                'Ů',
3128
                'Ű',
3129
                'Ŭ',
3130
                'Ų',
3131
                'У',
3132
                'Ǔ',
3133
                'Ǖ',
3134
                'Ǘ',
3135
                'Ǚ',
3136
                'Ǜ',
3137
                'U',
3138
                'Ў',
3139
                'Ü',
3140
            ],
3141
            'V' => ['В', 'V'],
3142
            'W' => ['Ω', 'Ώ', 'Ŵ', 'W'],
3143
            'X' => ['Χ', 'Ξ', 'X'],
3144
            'Y' => [
3145
                'Ý',
3146
                'Ỳ',
3147
                'Ỷ',
3148
                'Ỹ',
3149
                'Ỵ',
3150
                'Ÿ',
3151
                'Ῠ',
3152
                'Ῡ',
3153
                'Ὺ',
3154
                'Ύ',
3155
                'Ы',
3156
                'Й',
3157
                'Υ',
3158
                'Ϋ',
3159
                'Ŷ',
3160
                'Y',
3161
            ],
3162
            'Z'    => ['Ź', 'Ž', 'Ż', 'З', 'Ζ', 'Z'],
3163
            'AE'   => ['Æ', 'Ǽ'],
3164
            'Ch'   => ['Ч'],
3165
            'Dj'   => ['Ђ'],
3166
            'Dz'   => ['Џ'],
3167
            'Gx'   => ['Ĝ'],
3168
            'Hx'   => ['Ĥ'],
3169
            'Ij'   => ['IJ'],
3170
            'Jx'   => ['Ĵ'],
3171
            'Kh'   => ['Х'],
3172
            'Lj'   => ['Љ'],
3173
            'Nj'   => ['Њ'],
3174
            'Oe'   => ['Œ'],
3175
            'Ps'   => ['Ψ'],
3176
            'Sh'   => ['Ш'],
3177
            'Shch' => ['Щ'],
3178
            'Ss'   => ['ẞ'],
3179
            'Th'   => ['Þ'],
3180
            'Ts'   => ['Ц'],
3181
            'Ya'   => ['Я'],
3182
            'Yu'   => ['Ю'],
3183
            'Zh'   => ['Ж'],
3184
            ' '    => [
3185
                "\xC2\xA0",
3186
                "\xE2\x80\x80",
3187
                "\xE2\x80\x81",
3188
                "\xE2\x80\x82",
3189
                "\xE2\x80\x83",
3190
                "\xE2\x80\x84",
3191
                "\xE2\x80\x85",
3192
                "\xE2\x80\x86",
3193
                "\xE2\x80\x87",
3194
                "\xE2\x80\x88",
3195
                "\xE2\x80\x89",
3196
                "\xE2\x80\x8A",
3197
                "\xE2\x80\xAF",
3198
                "\xE2\x81\x9F",
3199
                "\xE3\x80\x80",
3200
                "\xEF\xBE\xA0",
3201
            ],
3202
        ];
3203
    }
3204
3205
    /**
3206
     * Returns true if $str matches the supplied pattern, false otherwise.
3207
     *
3208
     * @param string $pattern <p>Regex pattern to match against.</p>
3209
     *
3210
     * @return bool
3211
     *              <p>Whether or not $str matches the pattern.</p>
3212
     */
3213 12
    protected function matchesPattern(string $pattern): bool
3214
    {
3215 12
        return $this->utf8::str_matches_pattern($this->str, $pattern);
3216
    }
3217
3218
    /**
3219
     * Returns language-specific replacements for the toAscii() method.
3220
     * For example, German will map 'ä' to 'ae', while other languages
3221
     * will simply return 'a'.
3222
     *
3223
     * @param string $language Language of the source string
3224
     *
3225
     * @return array an array of replacements
3226
     */
3227 37
    protected static function langSpecificCharsArray(string $language = 'en'): array
3228
    {
3229 37
        $split = \preg_split('/[-_]/', $language);
3230 37
        if ($split === false) {
3231
            return [];
3232
        }
3233
3234 37
        if (!isset($split[0])) {
3235
            return [];
3236
        }
3237
3238 37
        $language = \strtolower($split[0]);
3239 37
        static $charsArray = [];
3240
3241 37
        if (isset($charsArray[$language])) {
3242 35
            return $charsArray[$language];
3243
        }
3244
3245
        $languageSpecific = [
3246 2
            'de' => [
3247
                ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'],
3248
                ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'],
3249
            ],
3250
            'bg' => [
3251
                ['х', 'Х', 'щ', 'Щ', 'ъ', 'Ъ', 'ь', 'Ь'],
3252
                ['h', 'H', 'sht', 'SHT', 'a', 'А', 'y', 'Y'],
3253
            ],
3254
        ];
3255
3256 2
        $charsArray[$language] = $languageSpecific[$language] ?? [];
3257
3258 2
        return $charsArray[$language];
3259
    }
3260
}
3261