Completed
Push — master ( a6ab86...860738 )
by Lars
02:03
created

Stringy::titleizeForHumans()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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