Completed
Push — master ( 4912e4...42172e )
by Lars
01:35
created

Stringy   F

Complexity

Total Complexity 218

Size/Duplication

Total Lines 3616
Duplicated Lines 5.2 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 98.81%

Importance

Changes 0
Metric Value
dl 188
loc 3616
ccs 827
cts 837
cp 0.9881
rs 0.8
c 0
b 0
f 0
wmc 218
lcom 1
cbo 6

165 Methods

Rating   Name   Duplication   Size   Complexity  
A afterFirstIgnoreCase() 0 10 1
B __construct() 0 38 7
A __toString() 0 4 1
A afterFirst() 0 10 1
A afterLast() 0 10 1
A afterLastIgnoreCase() 0 10 1
A append() 12 12 2
A appendPassword() 0 7 1
A appendRandomString() 0 6 1
A appendUniqueIdentifier() 0 6 1
A at() 0 4 1
A base64Decode() 0 7 1
A base64Encode() 0 7 1
A beforeFirst() 0 10 1
A beforeFirstIgnoreCase() 0 10 1
A beforeLast() 0 10 1
A beforeLastIgnoreCase() 0 10 1
A between() 0 13 1
A camelize() 0 7 1
A capitalizePersonalName() 0 7 1
A chars() 0 4 1
A chunk() 0 23 4
A collapseWhitespace() 0 7 1
A contains() 0 8 1
A containsAll() 0 8 1
A containsAny() 0 8 1
A count() 0 4 1
A countSubstr() 0 9 1
A crc32() 0 4 1
A create() 0 4 1
A dasherize() 0 7 1
A delimit() 0 7 1
A endsWith() 0 8 2
A endsWithAny() 0 8 2
A ensureLeft() 0 7 1
A ensureRight() 0 7 1
A escape() 0 11 1
A explode() 0 19 2
A extractText() 0 13 1
A first() 0 7 1
B format() 0 48 8
A getEncoding() 0 4 1
A getIterator() 0 4 1
A hardWrap() 0 4 1
A hasLowerCase() 0 4 1
A hasUpperCase() 0 4 1
A hash() 0 4 1
A hexDecode() 0 15 1
A hexEncode() 0 15 1
A htmlDecode() 11 11 1
A htmlEncode() 11 11 1
A humanize() 0 7 1
A in() 0 8 2
A indexOf() 0 9 1
A indexOfIgnoreCase() 0 9 1
A indexOfLast() 0 9 1
A indexOfLastIgnoreCase() 0 9 1
A insert() 0 12 1
A is() 0 11 2
A isAlpha() 0 4 1
A isAlphanumeric() 0 4 1
A isBase64() 0 4 1
A isBlank() 0 4 1
A isEmail() 0 11 1
A isEmpty() 0 4 1
A isEquals() 0 4 1
B isEqualsCaseInsensitive() 16 23 6
B isEqualsCaseSensitive() 16 21 6
A isHexadecimal() 0 4 1
A isHtml() 0 4 1
A isJson() 0 7 1
A isLowerCase() 0 4 1
A isNotEmpty() 0 4 1
A isSerialized() 0 4 1
A isSimilar() 0 4 1
A isUpperCase() 0 4 1
A isWhitespace() 0 4 1
A jsonSerialize() 0 4 1
A last() 0 11 1
A lastSubstringOf() 7 12 1
A lastSubstringOfIgnoreCase() 7 12 1
A length() 0 4 1
A lineWrap() 18 18 1
A lineWrapAfterWord() 18 18 1
A lines() 0 17 2
A longestCommonPrefix() 0 11 1
A longestCommonSubstring() 0 11 1
A longestCommonSuffix() 0 11 1
A lowerCaseFirst() 0 7 1
A matchCaseInsensitive() 0 4 1
A matchCaseSensitive() 0 4 1
A md5() 0 4 1
A nth() 0 17 2
A before() 0 13 1
A after() 0 14 1
A offsetExists() 0 8 1
A offsetGet() 0 4 1
A offsetSet() 0 6 1
A offsetUnset() 0 6 1
A pad() 0 12 1
A padBoth() 0 11 1
A padLeft() 0 11 1
A padRight() 0 11 1
A prepend() 12 12 2
A regexReplace() 0 13 1
A removeHtml() 0 7 1
A removeHtmlBreak() 0 7 1
A removeLeft() 0 7 1
A removeRight() 0 7 1
A removeXss() 0 20 2
A repeat() 0 7 1
B replace() 0 22 6
A replaceAll() 0 14 2
A replaceBeginning() 0 7 1
A replaceEnding() 0 7 1
A replaceFirst() 0 7 1
A replaceLast() 0 7 1
A reverse() 0 4 1
A safeTruncate() 0 16 1
A sha1() 0 4 1
A sha256() 0 4 1
A sha512() 0 4 1
A shortenAfterWord() 0 7 1
A shuffle() 0 4 1
A similarity() 0 6 1
A slice() 0 7 1
A slugify() 0 21 1
A snakeize() 0 7 1
A softWrap() 0 4 1
A split() 0 21 3
A startsWith() 0 8 2
A startsWithAny() 0 8 2
A strip() 0 8 2
A stripWhitespace() 0 7 1
A stripeCssMediaQueries() 0 7 1
A stripeEmptyHtmlTags() 0 7 1
A substr() 0 12 1
A substringOf() 7 12 1
A substringOfIgnoreCase() 7 12 1
A surround() 0 7 1
A swapCase() 0 7 1
A tidy() 0 7 1
A titleize() 0 19 1
A titleizeForHumans() 0 11 1
A toAscii() 0 11 1
A toBoolean() 0 4 1
A toLowerCase() 9 13 1
A toSpaces() 15 15 3
A toString() 0 4 1
A toTabs() 15 15 3
A toTitleCase() 0 7 1
A toTransliterate() 0 7 1
A toUpperCase() 7 7 1
A trim() 0 7 1
A trimLeft() 0 7 1
A trimRight() 0 7 1
A truncate() 0 7 1
A underscored() 0 4 1
A upperCamelize() 0 7 1
A upperCaseFirst() 0 4 1
A urlify() 0 23 2
A utf8ify() 0 4 1
A words() 0 17 1
A wrap() 0 4 1
A matchesPattern() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Stringy often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Stringy, and based on these observations, apply Extract Interface, too.

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

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

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

Loading history...
209
    {
210 14
        if (\count($suffix) <= 1) {
211
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
212 13
            $suffix = $suffix[0];
213
        } else {
214
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
215 1
            $suffix = \implode('', $suffix);
216
        }
217
218 14
        return static::create($this->str . $suffix, $this->encoding);
219
    }
220
221
    /**
222
     * Append an password (limited to chars that are good readable).
223
     *
224
     * @param int $length <p>Length of the random string.</p>
225
     *
226
     * @return static
227
     *                <p>Object with appended password.</p>
228
     */
229 2
    public function appendPassword(int $length): self
230
    {
231 2
        return $this->appendRandomString(
232 2
            $length,
233 2
            '2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ!?_#'
234
        );
235
    }
236
237
    /**
238
     * Append an random string.
239
     *
240
     * @param int    $length        <p>Length of the random string.</p>
241
     * @param string $possibleChars [optional] <p>Characters string for the random selection.</p>
242
     *
243
     * @return static
244
     *                <p>Object with appended random string.</p>
245
     */
246 4
    public function appendRandomString(int $length, string $possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'): self
247
    {
248 4
        $str = $this->utf8::get_random_string($length, $possibleChars);
249
250 4
        return $this->append($str);
251
    }
252
253
    /**
254
     * Append an unique identifier.
255
     *
256
     * @param int|string $entropyExtra [optional] <p>Extra entropy via a string or int value.</p>
257
     * @param bool       $md5          [optional] <p>Return the unique identifier as md5-hash? Default: true</p>
258
     *
259
     * @return static
260
     *                <p>Object with appended unique identifier as md5-hash.</p>
261
     */
262 2
    public function appendUniqueIdentifier($entropyExtra = '', bool $md5 = true): self
263
    {
264 2
        return $this->append(
265 2
            $this->utf8::get_unique_string($entropyExtra, $md5)
266
        );
267
    }
268
269
    /**
270
     * Returns the character at $index, with indexes starting at 0.
271
     *
272
     * @param int $index <p>Position of the character.</p>
273
     *
274
     * @psalm-mutation-free
275
     *
276
     * @return static
277
     *                <p>The character at $index.</p>
278
     */
279 24
    public function at(int $index): self
280
    {
281 24
        return static::create($this->utf8::char_at($this->str, $index), $this->encoding);
282
    }
283
284
    /**
285
     * Decode the base64 encoded string.
286
     *
287
     * @psalm-mutation-free
288
     *
289
     * @return self
290
     */
291 2
    public function base64Decode(): self
292
    {
293 2
        return static::create(
294 2
            \base64_decode($this->str, true),
295 2
            $this->encoding
296
        );
297
    }
298
299
    /**
300
     * Encode the string to base64.
301
     *
302
     * @psalm-mutation-free
303
     *
304
     * @return self
305
     */
306 2
    public function base64Encode(): self
307
    {
308 2
        return static::create(
309 2
            \base64_encode($this->str),
310 2
            $this->encoding
311
        );
312
    }
313
314
    /**
315
     * Gets the substring before the first occurrence of a separator.
316
     * If no match is found returns new empty Stringy object.
317
     *
318
     * @param string $separator
319
     *
320
     * @psalm-mutation-free
321
     *
322
     * @return static
323
     */
324 2
    public function beforeFirst(string $separator): self
325
    {
326 2
        return static::create(
327 2
            $this->utf8::str_substr_before_first_separator(
328 2
                $this->str,
329 2
                $separator,
330 2
                $this->encoding
331
            )
332
        );
333
    }
334
335
    /**
336
     * Gets the substring before the first occurrence of a separator.
337
     * If no match is found returns new empty Stringy object.
338
     *
339
     * @param string $separator
340
     *
341
     * @psalm-mutation-free
342
     *
343
     * @return static
344
     */
345 2
    public function beforeFirstIgnoreCase(string $separator): self
346
    {
347 2
        return static::create(
348 2
            $this->utf8::str_isubstr_before_first_separator(
349 2
                $this->str,
350 2
                $separator,
351 2
                $this->encoding
352
            )
353
        );
354
    }
355
356
    /**
357
     * Gets the substring before the last occurrence of a separator.
358
     * If no match is found returns new empty Stringy object.
359
     *
360
     * @param string $separator
361
     *
362
     * @psalm-mutation-free
363
     *
364
     * @return static
365
     */
366 2
    public function beforeLast(string $separator): self
367
    {
368 2
        return static::create(
369 2
            $this->utf8::str_substr_before_last_separator(
370 2
                $this->str,
371 2
                $separator,
372 2
                $this->encoding
373
            )
374
        );
375
    }
376
377
    /**
378
     * Gets the substring before the last occurrence of a separator.
379
     * If no match is found returns new empty Stringy object.
380
     *
381
     * @param string $separator
382
     *
383
     * @psalm-mutation-free
384
     *
385
     * @return static
386
     */
387 2
    public function beforeLastIgnoreCase(string $separator): self
388
    {
389 2
        return static::create(
390 2
            $this->utf8::str_isubstr_before_last_separator(
391 2
                $this->str,
392 2
                $separator,
393 2
                $this->encoding
394
            )
395
        );
396
    }
397
398
    /**
399
     * Returns the substring between $start and $end, if found, or an empty
400
     * string. An optional offset may be supplied from which to begin the
401
     * search for the start string.
402
     *
403
     * @param string $start  <p>Delimiter marking the start of the substring.</p>
404
     * @param string $end    <p>Delimiter marking the end of the substring.</p>
405
     * @param int    $offset [optional] <p>Index from which to begin the search. Default: 0</p>
406
     *
407
     * @psalm-mutation-free
408
     *
409
     * @return static
410
     *                <p>Object whose $str is a substring between $start and $end.</p>
411
     */
412 48
    public function between(string $start, string $end, int $offset = null): self
413
    {
414
        /** @noinspection UnnecessaryCastingInspection */
415 48
        $str = $this->utf8::between(
416 48
            $this->str,
417 48
            $start,
418 48
            $end,
419 48
            (int) $offset,
420 48
            $this->encoding
421
        );
422
423 48
        return static::create($str, $this->encoding);
424
    }
425
426
    /**
427
     * Returns a camelCase version of the string. Trims surrounding spaces,
428
     * capitalizes letters following digits, spaces, dashes and underscores,
429
     * and removes spaces, dashes, as well as underscores.
430
     *
431
     * @psalm-mutation-free
432
     *
433
     * @return static
434
     *                <p>Object with $str in camelCase.</p>
435
     */
436 57
    public function camelize(): self
437
    {
438 57
        return static::create(
439 57
            $this->utf8::str_camelize($this->str, $this->encoding),
440 57
            $this->encoding
441
        );
442
    }
443
444
    /**
445
     * Returns the string with the first letter of each word capitalized,
446
     * except for when the word is a name which shouldn't be capitalized.
447
     *
448
     * @psalm-mutation-free
449
     *
450
     * @return static
451
     *                <p>Object with $str capitalized.</p>
452
     */
453 78
    public function capitalizePersonalName(): self
454
    {
455 78
        return static::create(
456 78
            $this->utf8::str_capitalize_name($this->str),
457 78
            $this->encoding
458
        );
459
    }
460
461
    /**
462
     * Returns an array consisting of the characters in the string.
463
     *
464
     * @psalm-mutation-free
465
     *
466
     * @return string[]
467
     *                  <p>An array of string chars.</p>
468
     */
469 14
    public function chars(): array
470
    {
471 14
        return $this->utf8::str_split($this->str);
472
    }
473
474
    /**
475
     * Splits the string into chunks of Stringy objects.
476
     *
477
     * @param int $length
478
     *
479
     * @psalm-mutation-free
480
     *
481
     * @return CollectionStringy|static[]
482
     *                                    <p>An collection of Stringy objects.</p>
483
     *
484
     * @psalm-return CollectionStringy<int,static>
485
     */
486 13
    public function chunk(int $length = 1): CollectionStringy
487
    {
488 13
        if ($length < 1) {
489
            throw new \InvalidArgumentException('The chunk length must be greater than zero.');
490
        }
491
492 13
        if ($this->str === '') {
493
            /**
494
             * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
495
             */
496 2
            return CollectionStringy::create([]);
497
        }
498
499 11
        $chunks = $this->utf8::str_split($this->str, $length);
500 11
        foreach ($chunks as $i => &$value) {
501 11
            $value = static::create($value, $this->encoding);
502
        }
503
504
        /**
505
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
506
         */
507 11
        return CollectionStringy::create($chunks);
508
    }
509
510
    /**
511
     * Trims the string and replaces consecutive whitespace characters with a
512
     * single space. This includes tabs and newline characters, as well as
513
     * multibyte whitespace such as the thin space and ideographic space.
514
     *
515
     * @psalm-mutation-free
516
     *
517
     * @return static
518
     *                <p>Object with a trimmed $str and condensed whitespace.</p>
519
     */
520 39
    public function collapseWhitespace(): self
521
    {
522 39
        return static::create(
523 39
            $this->utf8::collapse_whitespace($this->str),
524 39
            $this->encoding
525
        );
526
    }
527
528
    /**
529
     * Returns true if the string contains $needle, false otherwise. By default
530
     * the comparison is case-sensitive, but can be made insensitive by setting
531
     * $caseSensitive to false.
532
     *
533
     * @param string $needle        <p>Substring to look for.</p>
534
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
535
     *
536
     * @psalm-mutation-free
537
     *
538
     * @return bool
539
     *              <p>Whether or not $str contains $needle.</p>
540
     */
541 63
    public function contains(string $needle, bool $caseSensitive = true): bool
542
    {
543 63
        return $this->utf8::str_contains(
544 63
            $this->str,
545 63
            $needle,
546 63
            $caseSensitive
547
        );
548
    }
549
550
    /**
551
     * Returns true if the string contains all $needles, false otherwise. By
552
     * default the comparison is case-sensitive, but can be made insensitive by
553
     * setting $caseSensitive to false.
554
     *
555
     * @param string[] $needles       <p>SubStrings to look for.</p>
556
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
557
     *
558
     * @psalm-mutation-free
559
     *
560
     * @return bool
561
     *              <p>Whether or not $str contains $needle.</p>
562
     */
563 131
    public function containsAll(array $needles, bool $caseSensitive = true): bool
564
    {
565 131
        return $this->utf8::str_contains_all(
566 131
            $this->str,
567 131
            $needles,
568 131
            $caseSensitive
569
        );
570
    }
571
572
    /**
573
     * Returns true if the string contains any $needles, false otherwise. By
574
     * default the comparison is case-sensitive, but can be made insensitive by
575
     * setting $caseSensitive to false.
576
     *
577
     * @param string[] $needles       <p>SubStrings to look for.</p>
578
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
579
     *
580
     * @psalm-mutation-free
581
     *
582
     * @return bool
583
     *              <p>Whether or not $str contains $needle.</p>
584
     */
585 129
    public function containsAny(array $needles, bool $caseSensitive = true): bool
586
    {
587 129
        return $this->utf8::str_contains_any(
588 129
            $this->str,
589 129
            $needles,
590 129
            $caseSensitive
591
        );
592
    }
593
594
    /**
595
     * Returns the length of the string, implementing the countable interface.
596
     *
597
     * @psalm-mutation-free
598
     *
599
     * @return int
600
     *             <p>The number of characters in the string, given the encoding.</p>
601
     */
602 3
    public function count(): int
603
    {
604 3
        return $this->length();
605
    }
606
607
    /**
608
     * Returns the number of occurrences of $substring in the given string.
609
     * By default, the comparison is case-sensitive, but can be made insensitive
610
     * by setting $caseSensitive to false.
611
     *
612
     * @param string $substring     <p>The substring to search for.</p>
613
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
614
     *
615
     * @psalm-mutation-free
616
     *
617
     * @return int
618
     */
619 45
    public function countSubstr(string $substring, bool $caseSensitive = true): int
620
    {
621 45
        return $this->utf8::substr_count_simple(
622 45
            $this->str,
623 45
            $substring,
624 45
            $caseSensitive,
625 45
            $this->encoding
626
        );
627
    }
628
629
    /**
630
     * Calculates the crc32 polynomial of a string.
631
     *
632
     * @psalm-mutation-free
633
     *
634
     * @return int
635
     */
636 2
    public function crc32(): int
637
    {
638 2
        return \crc32($this->str);
639
    }
640
641
    /**
642
     * Creates a Stringy object and assigns both str and encoding properties
643
     * the supplied values. $str is cast to a string prior to assignment, and if
644
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
645
     * then returns the initialized object. Throws an InvalidArgumentException
646
     * if the first argument is an array or object without a __toString method.
647
     *
648
     * @param mixed  $str      [optional] <p>Value to modify, after being cast to string. Default: ''</p>
649
     * @param string $encoding [optional] <p>The character encoding. Fallback: 'UTF-8'</p>
650
     *
651
     * @throws \InvalidArgumentException
652
     *                                   <p>if an array or object without a
653
     *                                   __toString method is passed as the first argument</p>
654
     * @psalm-pure
655
     *
656
     * @return static
657
     *                <p>A Stringy object.</p>
658
     */
659 3541
    public static function create($str = '', string $encoding = null): self
660
    {
661 3541
        return new static($str, $encoding);
662
    }
663
664
    /**
665
     * Returns a lowercase and trimmed string separated by dashes. Dashes are
666
     * inserted before uppercase characters (with the exception of the first
667
     * character of the string), and in place of spaces as well as underscores.
668
     *
669
     * @psalm-mutation-free
670
     *
671
     * @return static
672
     *                <p>Object with a dasherized $str</p>
673
     */
674 57
    public function dasherize(): self
675
    {
676 57
        return static::create(
677 57
            $this->utf8::str_dasherize($this->str),
678 57
            $this->encoding
679
        );
680
    }
681
682
    /**
683
     * Returns a lowercase and trimmed string separated by the given delimiter.
684
     * Delimiters are inserted before uppercase characters (with the exception
685
     * of the first character of the string), and in place of spaces, dashes,
686
     * and underscores. Alpha delimiters are not converted to lowercase.
687
     *
688
     * @param string $delimiter <p>Sequence used to separate parts of the string.</p>
689
     *
690
     * @psalm-mutation-free
691
     *
692
     * @return static
693
     *                <p>Object with a delimited $str.</p>
694
     */
695 90
    public function delimit(string $delimiter): self
696
    {
697 90
        return static::create(
698 90
            $this->utf8::str_delimit($this->str, $delimiter),
699 90
            $this->encoding
700
        );
701
    }
702
703
    /**
704
     * Returns true if the string ends with $substring, false otherwise. By
705
     * default, the comparison is case-sensitive, but can be made insensitive
706
     * by setting $caseSensitive to false.
707
     *
708
     * @param string $substring     <p>The substring to look for.</p>
709
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
710
     *
711
     * @psalm-mutation-free
712
     *
713
     * @return bool
714
     *              <p>Whether or not $str ends with $substring.</p>
715
     */
716 97
    public function endsWith(string $substring, bool $caseSensitive = true): bool
717
    {
718 97
        if ($caseSensitive) {
719 53
            return $this->utf8::str_ends_with($this->str, $substring);
720
        }
721
722 44
        return $this->utf8::str_iends_with($this->str, $substring);
723
    }
724
725
    /**
726
     * Returns true if the string ends with any of $substrings, false otherwise.
727
     * By default, the comparison is case-sensitive, but can be made insensitive
728
     * by setting $caseSensitive to false.
729
     *
730
     * @param string[] $substrings    <p>Substrings to look for.</p>
731
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
732
     *
733
     * @psalm-mutation-free
734
     *
735
     * @return bool
736
     *              <p>Whether or not $str ends with $substring.</p>
737
     */
738 33
    public function endsWithAny(array $substrings, bool $caseSensitive = true): bool
739
    {
740 33
        if ($caseSensitive) {
741 21
            return $this->utf8::str_ends_with_any($this->str, $substrings);
742
        }
743
744 12
        return $this->utf8::str_iends_with_any($this->str, $substrings);
745
    }
746
747
    /**
748
     * Ensures that the string begins with $substring. If it doesn't, it's
749
     * prepended.
750
     *
751
     * @param string $substring <p>The substring to add if not present.</p>
752
     *
753
     * @psalm-mutation-free
754
     *
755
     * @return static
756
     *                <p>Object with its $str prefixed by the $substring.</p>
757
     */
758 30
    public function ensureLeft(string $substring): self
759
    {
760 30
        return static::create(
761 30
            $this->utf8::str_ensure_left($this->str, $substring),
762 30
            $this->encoding
763
        );
764
    }
765
766
    /**
767
     * Ensures that the string ends with $substring. If it doesn't, it's appended.
768
     *
769
     * @param string $substring <p>The substring to add if not present.</p>
770
     *
771
     * @psalm-mutation-free
772
     *
773
     * @return static
774
     *                <p>Object with its $str suffixed by the $substring.</p>
775
     */
776 30
    public function ensureRight(string $substring): self
777
    {
778 30
        return static::create(
779 30
            $this->utf8::str_ensure_right($this->str, $substring),
780 30
            $this->encoding
781
        );
782
    }
783
784
    /**
785
     * Create a escape html version of the string via "htmlspecialchars()".
786
     *
787
     * @psalm-mutation-free
788
     *
789
     * @return static
790
     */
791 12
    public function escape(): self
792
    {
793 12
        return static::create(
794 12
            $this->utf8::htmlspecialchars(
795 12
                $this->str,
796 12
                \ENT_QUOTES | \ENT_SUBSTITUTE,
797 12
                $this->encoding
798
            ),
799 12
            $this->encoding
800
        );
801
    }
802
803
    /**
804
     * Split a string by a string.
805
     *
806
     * @param string $delimiter The boundary string
807
     * @param int    $limit     the maximum number of elements in the exploded collection.
808
     *
809
     *   - If limit is set and positive, the returned collection will contain a maximum of limit elements with the last
810
     *   element containing the rest of string.
811
     *   - If the limit parameter is negative, all components except the last -limit are returned.
812
     *   - If the limit parameter is zero, then this is treated as 1
813
     *
814
     * @psalm-mutation-free
815
     *
816
     * @return CollectionStringy<int,static>
0 ignored issues
show
Documentation introduced by
The doc-type CollectionStringy<int,static> could not be parsed: Expected "|" or "end of type", but got "<" at position 17. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
817
     */
818 3
    public function explode(string $delimiter, int $limit = \PHP_INT_MAX): CollectionStringy
819
    {
820 3
        $data = \explode($delimiter, $this->str, $limit);
821 3
        if ($data === false) {
822
            $data = [];
823
        }
824
825 3
        $data = \array_map(
826
            function ($str) {
827 3
                return new static($str, $this->encoding);
828 3
            },
829 3
            $data
830
        );
831
832
        /**
833
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
834
         */
835 3
        return CollectionStringy::create($data);
836
    }
837
838
    /**
839
     * Create an extract from a sentence, so if the search-string was found, it try to centered in the output.
840
     *
841
     * @param string   $search
842
     * @param int|null $length                 [optional] <p>Default: null === text->length / 2</p>
843
     * @param string   $replacerForSkippedText [optional] <p>Default: …</p>
844
     *
845
     * @psalm-mutation-free
846
     *
847
     * @return static
848
     */
849 2
    public function extractText(string $search = '', int $length = null, string $replacerForSkippedText = '…'): self
850
    {
851 2
        return static::create(
852 2
            $this->utf8::extract_text(
853 2
                $this->str,
854 2
                $search,
855 2
                $length,
856 2
                $replacerForSkippedText,
857 2
                $this->encoding
858
            ),
859 2
            $this->encoding
860
        );
861
    }
862
863
    /**
864
     * Returns the first $n characters of the string.
865
     *
866
     * @param int $n <p>Number of characters to retrieve from the start.</p>
867
     *
868
     * @psalm-mutation-free
869
     *
870
     * @return static
871
     *                <p>Object with its $str being the first $n chars.</p>
872
     */
873 37
    public function first(int $n): self
874
    {
875 37
        return static::create(
876 37
            $this->utf8::first_char($this->str, $n, $this->encoding),
877 37
            $this->encoding
878
        );
879
    }
880
881
    /**
882
     * Return a formatted string via sprintf + named parameters via array syntax.
883
     *
884
     * <p>
885
     * <br>
886
     * It will use "sprintf()" so you can use e.g.:
887
     * <br>
888
     * <br><pre>s('There are %d monkeys in the %s')->format(5, 'tree');</pre>
889
     * <br>
890
     * <br><pre>s('There are %2$d monkeys in the %1$s')->format('tree', 5);</pre>
891
     * <br>
892
     * <br>
893
     * But you can also use named parameter via array syntax e.g.:
894
     * <br>
895
     * <br><pre>s('There are %:count monkeys in the %:location')->format(['count' => 5, 'location' => 'tree');</pre>
896
     * </p>
897
     *
898
     * @param mixed ...$args [optional]
899
     *
900
     * @psalm-mutation-free
901
     *
902
     * @return static
903
     *                <p>A Stringy object produced according to the formatting string
904
     *                format.</p>
905
     */
906 10
    public function format(...$args): self
907
    {
908
        // init
909 10
        $str = $this->str;
910
911 10
        if (\strpos($this->str, '%:') !== false) {
912 8
            $offset = null;
913 8
            $replacement = null;
914
            /** @noinspection AlterInForeachInspection */
915 8
            foreach ($args as $key => &$arg) {
916 8
                if (!\is_array($arg)) {
917 4
                    continue;
918
                }
919
920 8
                foreach ($arg as $name => $param) {
921 8
                    $name = (string) $name;
922
923 8
                    if (\strpos($name, '%:') !== 0) {
924 8
                        $nameTmp = '%:' . $name;
925
                    } else {
926
                        $nameTmp = $name;
927
                    }
928
929 8
                    if ($offset === null) {
930 8
                        $offset = \strpos($str, $nameTmp);
931
                    } else {
932 6
                        $offset = \strpos($str, $nameTmp, (int) $offset + \strlen((string) $replacement));
933
                    }
934 8
                    if ($offset === false) {
935 4
                        continue;
936
                    }
937
938 8
                    unset($arg[$name]);
939
940 8
                    $str = \substr_replace($str, $param, (int) $offset, \strlen($nameTmp));
941
                }
942
943 8
                unset($args[$key]);
944
            }
945
        }
946
947 10
        $str = \str_replace('%:', '%%:', $str);
948
949 10
        return static::create(
950 10
            \sprintf($str, ...$args),
951 10
            $this->encoding
952
        );
953
    }
954
955
    /**
956
     * Returns the encoding used by the Stringy object.
957
     *
958
     * @psalm-mutation-free
959
     *
960
     * @return string
961
     *                <p>The current value of the $encoding property.</p>
962
     */
963 7
    public function getEncoding(): string
964
    {
965 7
        return $this->encoding;
966
    }
967
968
    /**
969
     * Returns a new ArrayIterator, thus implementing the IteratorAggregate
970
     * interface. The ArrayIterator's constructor is passed an array of chars
971
     * in the multibyte string. This enables the use of foreach with instances
972
     * of Stringy\Stringy.
973
     *
974
     * @psalm-mutation-free
975
     *
976
     * @return \ArrayIterator
977
     *                        <p>An iterator for the characters in the string.</p>
978
     *
979
     * @psalm-return \ArrayIterator<array-key,string>
980
     */
981 3
    public function getIterator(): \ArrayIterator
982
    {
983 3
        return new \ArrayIterator($this->chars());
984
    }
985
986
    /**
987
     * Wrap the string after an exact number of characters.
988
     *
989
     * @param int    $width Number of characters at which to wrap
990
     * @param string $break Character used to break the string
991
     *
992
     * @psalm-mutation-free
993
     *
994
     * @return static
995
     */
996 2
    public function hardWrap($width, $break = "\n"): self
997
    {
998 2
        return $this->lineWrap($width, $break, false);
999
    }
1000
1001
    /**
1002
     * Returns true if the string contains a lower case char, false otherwise.
1003
     *
1004
     * @psalm-mutation-free
1005
     *
1006
     * @return bool
1007
     *              <p>Whether or not the string contains a lower case character.</p>
1008
     */
1009 36
    public function hasLowerCase(): bool
1010
    {
1011 36
        return $this->utf8::has_lowercase($this->str);
1012
    }
1013
1014
    /**
1015
     * Returns true if the string contains an upper case char, false otherwise.
1016
     *
1017
     * @psalm-mutation-free
1018
     *
1019
     * @return bool
1020
     *              <p>Whether or not the string contains an upper case character.</p>
1021
     */
1022 36
    public function hasUpperCase(): bool
1023
    {
1024 36
        return $this->utf8::has_uppercase($this->str);
1025
    }
1026
1027
    /**
1028
     * Generate a hash value (message digest)
1029
     *
1030
     * @see https://php.net/manual/en/function.hash.php
1031
     *
1032
     * @param string $algorithm
1033
     *                          <p>Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)</p>
1034
     *
1035
     * @psalm-mutation-free
1036
     *
1037
     * @return static
1038
     */
1039 8
    public function hash($algorithm): self
1040
    {
1041 8
        return static::create(\hash($algorithm, $this->str), $this->encoding);
1042
    }
1043
1044
    /**
1045
     * Decode the string from hex.
1046
     *
1047
     * @psalm-mutation-free
1048
     *
1049
     * @return static
1050
     */
1051 2
    public function hexDecode(): self
1052
    {
1053 2
        $string = \preg_replace_callback(
1054 2
            '/\\\\x([0-9A-Fa-f]+)/',
1055
            function (array $matched) {
1056 2
                return (string) $this->utf8::hex_to_chr($matched[1]);
1057 2
            },
1058 2
            $this->str
1059
        );
1060
1061 2
        return static::create(
1062 2
            $string,
1063 2
            $this->encoding
1064
        );
1065
    }
1066
1067
    /**
1068
     * Encode string to hex.
1069
     *
1070
     * @psalm-mutation-free
1071
     *
1072
     * @return static
1073
     */
1074 2
    public function hexEncode(): self
1075
    {
1076 2
        $string = \array_reduce(
1077 2
            $this->chars(),
1078
            function (string $str, string $char) {
1079 2
                return $str . $this->utf8::chr_to_hex($char);
1080 2
            },
1081 2
            ''
1082
        );
1083
1084 2
        return static::create(
1085 2
            $string,
1086 2
            $this->encoding
1087
        );
1088
    }
1089
1090
    /**
1091
     * Convert all HTML entities to their applicable characters.
1092
     *
1093
     * @param int $flags [optional] <p>
1094
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1095
     *                   which document type to use. The default is ENT_COMPAT.
1096
     *                   <table>
1097
     *                   Available <i>flags</i> constants
1098
     *                   <tr valign="top">
1099
     *                   <td>Constant Name</td>
1100
     *                   <td>Description</td>
1101
     *                   </tr>
1102
     *                   <tr valign="top">
1103
     *                   <td><b>ENT_COMPAT</b></td>
1104
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1105
     *                   </tr>
1106
     *                   <tr valign="top">
1107
     *                   <td><b>ENT_QUOTES</b></td>
1108
     *                   <td>Will convert both double and single quotes.</td>
1109
     *                   </tr>
1110
     *                   <tr valign="top">
1111
     *                   <td><b>ENT_NOQUOTES</b></td>
1112
     *                   <td>Will leave both double and single quotes unconverted.</td>
1113
     *                   </tr>
1114
     *                   <tr valign="top">
1115
     *                   <td><b>ENT_HTML401</b></td>
1116
     *                   <td>
1117
     *                   Handle code as HTML 4.01.
1118
     *                   </td>
1119
     *                   </tr>
1120
     *                   <tr valign="top">
1121
     *                   <td><b>ENT_XML1</b></td>
1122
     *                   <td>
1123
     *                   Handle code as XML 1.
1124
     *                   </td>
1125
     *                   </tr>
1126
     *                   <tr valign="top">
1127
     *                   <td><b>ENT_XHTML</b></td>
1128
     *                   <td>
1129
     *                   Handle code as XHTML.
1130
     *                   </td>
1131
     *                   </tr>
1132
     *                   <tr valign="top">
1133
     *                   <td><b>ENT_HTML5</b></td>
1134
     *                   <td>
1135
     *                   Handle code as HTML 5.
1136
     *                   </td>
1137
     *                   </tr>
1138
     *                   </table>
1139
     *                   </p>
1140
     *
1141
     * @psalm-mutation-free
1142
     *
1143
     * @return static
1144
     *                <p>Object with the resulting $str after being html decoded.</p>
1145
     */
1146 15 View Code Duplication
    public function htmlDecode(int $flags = \ENT_COMPAT): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1147
    {
1148 15
        return static::create(
1149 15
            $this->utf8::html_entity_decode(
1150 15
                $this->str,
1151 15
                $flags,
1152 15
                $this->encoding
1153
            ),
1154 15
            $this->encoding
1155
        );
1156
    }
1157
1158
    /**
1159
     * Convert all applicable characters to HTML entities.
1160
     *
1161
     * @param int $flags [optional] <p>
1162
     *                   A bitmask of one or more of the following flags, which specify how to handle quotes and
1163
     *                   which document type to use. The default is ENT_COMPAT.
1164
     *                   <table>
1165
     *                   Available <i>flags</i> constants
1166
     *                   <tr valign="top">
1167
     *                   <td>Constant Name</td>
1168
     *                   <td>Description</td>
1169
     *                   </tr>
1170
     *                   <tr valign="top">
1171
     *                   <td><b>ENT_COMPAT</b></td>
1172
     *                   <td>Will convert double-quotes and leave single-quotes alone.</td>
1173
     *                   </tr>
1174
     *                   <tr valign="top">
1175
     *                   <td><b>ENT_QUOTES</b></td>
1176
     *                   <td>Will convert both double and single quotes.</td>
1177
     *                   </tr>
1178
     *                   <tr valign="top">
1179
     *                   <td><b>ENT_NOQUOTES</b></td>
1180
     *                   <td>Will leave both double and single quotes unconverted.</td>
1181
     *                   </tr>
1182
     *                   <tr valign="top">
1183
     *                   <td><b>ENT_HTML401</b></td>
1184
     *                   <td>
1185
     *                   Handle code as HTML 4.01.
1186
     *                   </td>
1187
     *                   </tr>
1188
     *                   <tr valign="top">
1189
     *                   <td><b>ENT_XML1</b></td>
1190
     *                   <td>
1191
     *                   Handle code as XML 1.
1192
     *                   </td>
1193
     *                   </tr>
1194
     *                   <tr valign="top">
1195
     *                   <td><b>ENT_XHTML</b></td>
1196
     *                   <td>
1197
     *                   Handle code as XHTML.
1198
     *                   </td>
1199
     *                   </tr>
1200
     *                   <tr valign="top">
1201
     *                   <td><b>ENT_HTML5</b></td>
1202
     *                   <td>
1203
     *                   Handle code as HTML 5.
1204
     *                   </td>
1205
     *                   </tr>
1206
     *                   </table>
1207
     *                   </p>
1208
     *
1209
     * @psalm-mutation-free
1210
     *
1211
     * @return static
1212
     *                <p>Object with the resulting $str after being html encoded.</p>
1213
     */
1214 15 View Code Duplication
    public function htmlEncode(int $flags = \ENT_COMPAT): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1215
    {
1216 15
        return static::create(
1217 15
            $this->utf8::htmlentities(
1218 15
                $this->str,
1219 15
                $flags,
1220 15
                $this->encoding
1221
            ),
1222 15
            $this->encoding
1223
        );
1224
    }
1225
1226
    /**
1227
     * Capitalizes the first word of the string, replaces underscores with
1228
     * spaces, and strips '_id'.
1229
     *
1230
     * @psalm-mutation-free
1231
     *
1232
     * @return static
1233
     *                <p>Object with a humanized $str.</p>
1234
     */
1235 9
    public function humanize(): self
1236
    {
1237 9
        return static::create(
1238 9
            $this->utf8::str_humanize($this->str),
1239 9
            $this->encoding
1240
        );
1241
    }
1242
1243
    /**
1244
     * Determine if the current string exists in another string. By
1245
     * default, the comparison is case-sensitive, but can be made insensitive
1246
     * by setting $caseSensitive to false.
1247
     *
1248
     * @param string $str           <p>The string to compare against.</p>
1249
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
1250
     *
1251
     * @psalm-mutation-free
1252
     *
1253
     * @return bool
1254
     */
1255 3
    public function in(string $str, bool $caseSensitive = true): bool
1256
    {
1257 3
        if ($caseSensitive) {
1258 2
            return \strpos($str, $this->str) !== false;
1259
        }
1260
1261 1
        return \stripos($str, $this->str) !== false;
1262
    }
1263
1264
    /**
1265
     * Returns the index of the first occurrence of $needle in the string,
1266
     * and false if not found. Accepts an optional offset from which to begin
1267
     * the search.
1268
     *
1269
     * @param string $needle <p>Substring to look for.</p>
1270
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1271
     *
1272
     * @psalm-mutation-free
1273
     *
1274
     * @return false|int
1275
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1276
     */
1277 31
    public function indexOf(string $needle, int $offset = 0)
1278
    {
1279 31
        return $this->utf8::strpos(
1280 31
            $this->str,
1281 31
            $needle,
1282 31
            $offset,
1283 31
            $this->encoding
1284
        );
1285
    }
1286
1287
    /**
1288
     * Returns the index of the first occurrence of $needle in the string,
1289
     * and false if not found. Accepts an optional offset from which to begin
1290
     * the search.
1291
     *
1292
     * @param string $needle <p>Substring to look for.</p>
1293
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1294
     *
1295
     * @psalm-mutation-free
1296
     *
1297
     * @return false|int
1298
     *                   <p>The occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1299
     */
1300 20
    public function indexOfIgnoreCase(string $needle, int $offset = 0)
1301
    {
1302 20
        return $this->utf8::stripos(
1303 20
            $this->str,
1304 20
            $needle,
1305 20
            $offset,
1306 20
            $this->encoding
1307
        );
1308
    }
1309
1310
    /**
1311
     * Returns the index of the last occurrence of $needle in the string,
1312
     * and false if not found. Accepts an optional offset from which to begin
1313
     * the search. Offsets may be negative to count from the last character
1314
     * in the string.
1315
     *
1316
     * @param string $needle <p>Substring to look for.</p>
1317
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1318
     *
1319
     * @psalm-mutation-free
1320
     *
1321
     * @return false|int
1322
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1323
     */
1324 31
    public function indexOfLast(string $needle, int $offset = 0)
1325
    {
1326 31
        return $this->utf8::strrpos(
1327 31
            $this->str,
1328 31
            $needle,
1329 31
            $offset,
1330 31
            $this->encoding
1331
        );
1332
    }
1333
1334
    /**
1335
     * Returns the index of the last occurrence of $needle in the string,
1336
     * and false if not found. Accepts an optional offset from which to begin
1337
     * the search. Offsets may be negative to count from the last character
1338
     * in the string.
1339
     *
1340
     * @param string $needle <p>Substring to look for.</p>
1341
     * @param int    $offset [optional] <p>Offset from which to search. Default: 0</p>
1342
     *
1343
     * @psalm-mutation-free
1344
     *
1345
     * @return false|int
1346
     *                   <p>The last occurrence's <strong>index</strong> if found, otherwise <strong>false</strong>.</p>
1347
     */
1348 20
    public function indexOfLastIgnoreCase(string $needle, int $offset = 0)
1349
    {
1350 20
        return $this->utf8::strripos(
1351 20
            $this->str,
1352 20
            $needle,
1353 20
            $offset,
1354 20
            $this->encoding
1355
        );
1356
    }
1357
1358
    /**
1359
     * Inserts $substring into the string at the $index provided.
1360
     *
1361
     * @param string $substring <p>String to be inserted.</p>
1362
     * @param int    $index     <p>The index at which to insert the substring.</p>
1363
     *
1364
     * @psalm-mutation-free
1365
     *
1366
     * @return static
1367
     *                <p>Object with the resulting $str after the insertion.</p>
1368
     */
1369 24
    public function insert(string $substring, int $index): self
1370
    {
1371 24
        return static::create(
1372 24
            $this->utf8::str_insert(
1373 24
                $this->str,
1374 24
                $substring,
1375 24
                $index,
1376 24
                $this->encoding
1377
            ),
1378 24
            $this->encoding
1379
        );
1380
    }
1381
1382
    /**
1383
     * Returns true if the string contains the $pattern, otherwise false.
1384
     *
1385
     * WARNING: Asterisks ("*") are translated into (".*") zero-or-more regular
1386
     * expression wildcards.
1387
     *
1388
     * @credit Originally from Laravel, thanks Taylor.
1389
     *
1390
     * @param string $pattern <p>The string or pattern to match against.</p>
1391
     *
1392
     * @psalm-mutation-free
1393
     *
1394
     * @return bool
1395
     *              <p>Whether or not we match the provided pattern.</p>
1396
     */
1397 26
    public function is(string $pattern): bool
1398
    {
1399 26
        if ($this->toString() === $pattern) {
1400 2
            return true;
1401
        }
1402
1403 24
        $quotedPattern = \preg_quote($pattern, '/');
1404 24
        $replaceWildCards = \str_replace('\*', '.*', $quotedPattern);
1405
1406 24
        return $this->matchesPattern('^' . $replaceWildCards . '\z');
1407
    }
1408
1409
    /**
1410
     * Returns true if the string contains only alphabetic chars, false otherwise.
1411
     *
1412
     * @psalm-mutation-free
1413
     *
1414
     * @return bool
1415
     *              <p>Whether or not $str contains only alphabetic chars.</p>
1416
     */
1417 30
    public function isAlpha(): bool
1418
    {
1419 30
        return $this->utf8::is_alpha($this->str);
1420
    }
1421
1422
    /**
1423
     * Returns true if the string contains only alphabetic and numeric chars, false otherwise.
1424
     *
1425
     * @psalm-mutation-free
1426
     *
1427
     * @return bool
1428
     *              <p>Whether or not $str contains only alphanumeric chars.</p>
1429
     */
1430 39
    public function isAlphanumeric(): bool
1431
    {
1432 39
        return $this->utf8::is_alphanumeric($this->str);
1433
    }
1434
1435
    /**
1436
     * Returns true if the string is base64 encoded, false otherwise.
1437
     *
1438
     * @param bool $emptyStringIsValid
1439
     *
1440
     * @psalm-mutation-free
1441
     *
1442
     * @return bool
1443
     *              <p>Whether or not $str is base64 encoded.</p>
1444
     */
1445 21
    public function isBase64($emptyStringIsValid = true): bool
1446
    {
1447 21
        return $this->utf8::is_base64($this->str, $emptyStringIsValid);
1448
    }
1449
1450
    /**
1451
     * Returns true if the string contains only whitespace chars, false otherwise.
1452
     *
1453
     * @psalm-mutation-free
1454
     *
1455
     * @return bool
1456
     *              <p>Whether or not $str contains only whitespace characters.</p>
1457
     */
1458 45
    public function isBlank(): bool
1459
    {
1460 45
        return $this->utf8::is_blank($this->str);
1461
    }
1462
1463
    /**
1464
     * Returns true if the string contains a valid E-Mail address, false otherwise.
1465
     *
1466
     * @param bool $useExampleDomainCheck   [optional] <p>Default: false</p>
1467
     * @param bool $useTypoInDomainCheck    [optional] <p>Default: false</p>
1468
     * @param bool $useTemporaryDomainCheck [optional] <p>Default: false</p>
1469
     * @param bool $useDnsCheck             [optional] <p>Default: false</p>
1470
     *
1471
     * @psalm-mutation-free
1472
     *
1473
     * @return bool
1474
     *              <p>Whether or not $str contains a valid E-Mail address.</p>
1475
     */
1476 2
    public function isEmail(
1477
        bool $useExampleDomainCheck = false,
1478
        bool $useTypoInDomainCheck = false,
1479
        bool $useTemporaryDomainCheck = false,
1480
        bool $useDnsCheck = false
1481
    ): bool {
1482
        /**
1483
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the email-check class
1484
         */
1485 2
        return EmailCheck::isValid($this->str, $useExampleDomainCheck, $useTypoInDomainCheck, $useTemporaryDomainCheck, $useDnsCheck);
1486
    }
1487
1488
    /**
1489
     * Determine whether the string is considered to be empty.
1490
     *
1491
     * A variable is considered empty if it does not exist or if its value equals FALSE.
1492
     *
1493
     * @psalm-mutation-free
1494
     *
1495
     * @return bool
1496
     *              <p>Whether or not $str is empty().</p>
1497
     */
1498 10
    public function isEmpty(): bool
1499
    {
1500 10
        return $this->utf8::is_empty($this->str);
1501
    }
1502
1503
    /**
1504
     * Determine whether the string is equals to $str.
1505
     * Alias for isEqualsCaseSensitive()
1506
     *
1507
     * @param string|Stringy ...$str
1508
     *
1509
     * @psalm-mutation-free
1510
     *
1511
     * @return bool
1512
     */
1513 13
    public function isEquals(...$str): bool
1514
    {
1515 13
        return $this->isEqualsCaseSensitive(...$str);
1516
    }
1517
1518
    /**
1519
     * Determine whether the string is equals to $str.
1520
     *
1521
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1522
     *
1523
     * @psalm-mutation-free
1524
     *
1525
     * @return bool
1526
     *              <p>Whether or not $str is equals.</p>
1527
     */
1528 3
    public function isEqualsCaseInsensitive(...$str): bool
1529
    {
1530 3
        $strUpper = $this->toUpperCase()->str;
1531
1532 3 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1533
            /**
1534
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1535
             */
1536 3
            if ($strTmp instanceof self) {
1537
                if ($strUpper !== $strTmp->toUpperCase()) {
1538
                    return false;
1539
                }
1540 3
            } elseif (\is_scalar($strTmp)) {
1541 3
                if ($strUpper !== $this->utf8::strtoupper((string) $strTmp, $this->encoding)) {
1542 3
                    return false;
1543
                }
1544
            } else {
1545
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1546
            }
1547
        }
1548
1549 3
        return true;
1550
    }
1551
1552
    /**
1553
     * Determine whether the string is equals to $str.
1554
     *
1555
     * @param float|int|string|Stringy ...$str <p>The string to compare.</p>
1556
     *
1557
     * @psalm-mutation-free
1558
     *
1559
     * @return bool
1560
     *              <p>Whether or not $str is equals.</p>
1561
     */
1562 14
    public function isEqualsCaseSensitive(...$str): bool
1563
    {
1564 14 View Code Duplication
        foreach ($str as $strTmp) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1565
            /**
1566
             * @psalm-suppress RedundantConditionGivenDocblockType - wait for union-types :)
1567
             */
1568 14
            if ($strTmp instanceof self) {
1569 2
                if ($this->str !== $strTmp->str) {
1570 2
                    return false;
1571
                }
1572 12
            } elseif (\is_scalar($strTmp)) {
1573 12
                if ($this->str !== (string) $strTmp) {
1574 12
                    return false;
1575
                }
1576
            } else {
1577
                throw new \InvalidArgumentException('expected: int|float|string|Stringy -> given: ' . \print_r($strTmp, true) . ' [' . \gettype($strTmp) . ']');
1578
            }
1579
        }
1580
1581 3
        return true;
1582
    }
1583
1584
    /**
1585
     * Returns true if the string contains only hexadecimal chars, false otherwise.
1586
     *
1587
     * @psalm-mutation-free
1588
     *
1589
     * @return bool
1590
     *              <p>Whether or not $str contains only hexadecimal chars.</p>
1591
     */
1592 39
    public function isHexadecimal(): bool
1593
    {
1594 39
        return $this->utf8::is_hexadecimal($this->str);
1595
    }
1596
1597
    /**
1598
     * Returns true if the string contains HTML-Tags, false otherwise.
1599
     *
1600
     * @psalm-mutation-free
1601
     *
1602
     * @return bool
1603
     *              <p>Whether or not $str contains HTML-Tags.</p>
1604
     */
1605 2
    public function isHtml(): bool
1606
    {
1607 2
        return $this->utf8::is_html($this->str);
1608
    }
1609
1610
    /**
1611
     * Returns true if the string is JSON, false otherwise. Unlike json_decode
1612
     * in PHP 5.x, this method is consistent with PHP 7 and other JSON parsers,
1613
     * in that an empty string is not considered valid JSON.
1614
     *
1615
     * @param bool $onlyArrayOrObjectResultsAreValid
1616
     *
1617
     * @return bool
1618
     *              <p>Whether or not $str is JSON.</p>
1619
     */
1620 60
    public function isJson($onlyArrayOrObjectResultsAreValid = false): bool
1621
    {
1622 60
        return $this->utf8::is_json(
1623 60
            $this->str,
1624 60
            $onlyArrayOrObjectResultsAreValid
1625
        );
1626
    }
1627
1628
    /**
1629
     * Returns true if the string contains only lower case chars, false otherwise.
1630
     *
1631
     * @psalm-mutation-free
1632
     *
1633
     * @return bool
1634
     *              <p>Whether or not $str contains only lower case characters.</p>
1635
     */
1636 24
    public function isLowerCase(): bool
1637
    {
1638 24
        return $this->utf8::is_lowercase($this->str);
1639
    }
1640
1641
    /**
1642
     * Determine whether the string is considered to be NOT empty.
1643
     *
1644
     * A variable is considered NOT empty if it does exist or if its value equals TRUE.
1645
     *
1646
     * @psalm-mutation-free
1647
     *
1648
     * @return bool
1649
     *              <p>Whether or not $str is empty().</p>
1650
     */
1651 10
    public function isNotEmpty(): bool
1652
    {
1653 10
        return !$this->utf8::is_empty($this->str);
1654
    }
1655
1656
    /**
1657
     * Returns true if the string is serialized, false otherwise.
1658
     *
1659
     * @psalm-mutation-free
1660
     *
1661
     * @return bool
1662
     *              <p>Whether or not $str is serialized.</p>
1663
     */
1664 21
    public function isSerialized(): bool
1665
    {
1666 21
        return $this->utf8::is_serialized($this->str);
1667
    }
1668
1669
    /**
1670
     * Check if two strings are similar.
1671
     *
1672
     * @param string $str
1673
     * @param float  $minPercentForSimilarity
1674
     *
1675
     * @psalm-mutation-free
1676
     *
1677
     * @return bool
1678
     */
1679 2
    public function isSimilar(string $str, float $minPercentForSimilarity = 80.0): bool
1680
    {
1681 2
        return $this->similarity($str) >= $minPercentForSimilarity;
1682
    }
1683
1684
    /**
1685
     * Returns true if the string contains only lower case chars, false
1686
     * otherwise.
1687
     *
1688
     * @psalm-mutation-free
1689
     *
1690
     * @return bool
1691
     *              <p>Whether or not $str contains only lower case characters.</p>
1692
     */
1693 24
    public function isUpperCase(): bool
1694
    {
1695 24
        return $this->utf8::is_uppercase($this->str);
1696
    }
1697
1698
    /**
1699
     * Returns true if the string contains only whitespace chars, false otherwise.
1700
     *
1701
     * @psalm-mutation-free
1702
     *
1703
     * @return bool
1704
     *              <p>Whether or not $str contains only whitespace characters.</p>
1705
     */
1706 30
    public function isWhitespace(): bool
1707
    {
1708 30
        return $this->isBlank();
1709
    }
1710
1711
    /**
1712
     * Returns value which can be serialized by json_encode().
1713
     *
1714
     * @noinspection ReturnTypeCanBeDeclaredInspection
1715
     *
1716
     * @psalm-mutation-free
1717
     *
1718
     * @return string The current value of the $str property
1719
     */
1720 2
    public function jsonSerialize()
1721
    {
1722 2
        return (string) $this;
1723
    }
1724
1725
    /**
1726
     * Returns the last $n characters of the string.
1727
     *
1728
     * @param int $n <p>Number of characters to retrieve from the end.</p>
1729
     *
1730
     * @psalm-mutation-free
1731
     *
1732
     * @return static
1733
     *                <p>Object with its $str being the last $n chars.</p>
1734
     */
1735 36
    public function last(int $n): self
1736
    {
1737 36
        return static::create(
1738 36
            $this->utf8::str_last_char(
1739 36
                $this->str,
1740 36
                $n,
1741 36
                $this->encoding
1742
            ),
1743 36
            $this->encoding
1744
        );
1745
    }
1746
1747
    /**
1748
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1749
     * If no match is found returns new empty Stringy object.
1750
     *
1751
     * @param string $needle       <p>The string to look for.</p>
1752
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1753
     *
1754
     * @psalm-mutation-free
1755
     *
1756
     * @return static
1757
     */
1758 4 View Code Duplication
    public function lastSubstringOf(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1759
    {
1760 4
        return static::create(
1761 4
            $this->utf8::str_substr_last(
1762 4
                $this->str,
1763 4
                $needle,
1764 4
                $beforeNeedle,
1765 4
                $this->encoding
1766
            ),
1767 4
            $this->encoding
1768
        );
1769
    }
1770
1771
    /**
1772
     * Gets the substring after (or before via "$beforeNeedle") the last occurrence of the "$needle".
1773
     * If no match is found returns new empty Stringy object.
1774
     *
1775
     * @param string $needle       <p>The string to look for.</p>
1776
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
1777
     *
1778
     * @psalm-mutation-free
1779
     *
1780
     * @return static
1781
     */
1782 2 View Code Duplication
    public function lastSubstringOfIgnoreCase(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1783
    {
1784 2
        return static::create(
1785 2
            $this->utf8::str_isubstr_last(
1786 2
                $this->str,
1787 2
                $needle,
1788 2
                $beforeNeedle,
1789 2
                $this->encoding
1790
            ),
1791 2
            $this->encoding
1792
        );
1793
    }
1794
1795
    /**
1796
     * Returns the length of the string.
1797
     *
1798
     * @psalm-mutation-free
1799
     *
1800
     * @return int
1801
     *             <p>The number of characters in $str given the encoding.</p>
1802
     */
1803 17
    public function length(): int
1804
    {
1805 17
        return (int) $this->utf8::strlen($this->str, $this->encoding);
1806
    }
1807
1808
    /**
1809
     * Line-Wrap the string after $limit, but also after the next word.
1810
     *
1811
     * @param int         $limit           [optional] <p>The column width.</p>
1812
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
1813
     * @param bool        $add_final_break [optional] <p>
1814
     *                                     If this flag is true, then the method will add a $break at the end
1815
     *                                     of the result string.
1816
     *                                     </p>
1817
     * @param string|null $delimiter       [optional] <p>
1818
     *                                     You can change the default behavior, where we split the string by newline.
1819
     *                                     </p>
1820
     *
1821
     * @psalm-mutation-free
1822
     *
1823
     * @return static
1824
     */
1825 3 View Code Duplication
    public function lineWrap(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1826
        int $limit,
1827
        string $break = "\n",
1828
        bool $add_final_break = true,
1829
        string $delimiter = null
1830
    ): self {
1831 3
        return static::create(
1832 3
            $this->utf8::wordwrap_per_line(
1833 3
                $this->str,
1834 3
                $limit,
1835 3
                $break,
1836 3
                true,
1837 3
                $add_final_break,
1838 3
                $delimiter
1839
            ),
1840 3
            $this->encoding
1841
        );
1842
    }
1843
1844
    /**
1845
     * Line-Wrap the string after $limit, but also after the next word.
1846
     *
1847
     * @param int         $limit           [optional] <p>The column width.</p>
1848
     * @param string      $break           [optional] <p>The line is broken using the optional break parameter.</p>
1849
     * @param bool        $add_final_break [optional] <p>
1850
     *                                     If this flag is true, then the method will add a $break at the end
1851
     *                                     of the result string.
1852
     *                                     </p>
1853
     * @param string|null $delimiter       [optional] <p>
1854
     *                                     You can change the default behavior, where we split the string by newline.
1855
     *                                     </p>
1856
     *
1857
     * @psalm-mutation-free
1858
     *
1859
     * @return static
1860
     */
1861 4 View Code Duplication
    public function lineWrapAfterWord(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1862
        int $limit,
1863
        string $break = "\n",
1864
        bool $add_final_break = true,
1865
        string $delimiter = null
1866
    ): self {
1867 4
        return static::create(
1868 4
            $this->utf8::wordwrap_per_line(
1869 4
                $this->str,
1870 4
                $limit,
1871 4
                $break,
1872 4
                false,
1873 4
                $add_final_break,
1874 4
                $delimiter
1875
            ),
1876 4
            $this->encoding
1877
        );
1878
    }
1879
1880
    /**
1881
     * Splits on newlines and carriage returns, returning an array of Stringy
1882
     * objects corresponding to the lines in the string.
1883
     *
1884
     * @psalm-mutation-free
1885
     *
1886
     * @return CollectionStringy|static[]
1887
     *                                    <p>An collection of Stringy objects.</p>
1888
     *
1889
     * @psalm-return CollectionStringy<int,static>
1890
     */
1891 51
    public function lines(): CollectionStringy
1892
    {
1893 51
        $array = $this->utf8::str_to_lines($this->str);
1894
        /** @noinspection AlterInForeachInspection */
1895 51
        foreach ($array as $i => &$value) {
1896 51
            $value = static::create($value, $this->encoding);
1897
        }
1898
1899
        /** @noinspection PhpSillyAssignmentInspection */
1900
        /** @var static[] $array */
1901 51
        $array = $array;
0 ignored issues
show
Bug introduced by
Why assign $array to itself?

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

This assignement can be removed without consequences.

Loading history...
1902
1903
        /**
1904
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
1905
         */
1906 51
        return CollectionStringy::create($array);
1907
    }
1908
1909
    /**
1910
     * Returns the longest common prefix between the string and $otherStr.
1911
     *
1912
     * @param string $otherStr <p>Second string for comparison.</p>
1913
     *
1914
     * @psalm-mutation-free
1915
     *
1916
     * @return static
1917
     *                <p>Object with its $str being the longest common prefix.</p>
1918
     */
1919 30
    public function longestCommonPrefix(string $otherStr): self
1920
    {
1921 30
        return static::create(
1922 30
            $this->utf8::str_longest_common_prefix(
1923 30
                $this->str,
1924 30
                $otherStr,
1925 30
                $this->encoding
1926
            ),
1927 30
            $this->encoding
1928
        );
1929
    }
1930
1931
    /**
1932
     * Returns the longest common substring between the string and $otherStr.
1933
     * In the case of ties, it returns that which occurs first.
1934
     *
1935
     * @param string $otherStr <p>Second string for comparison.</p>
1936
     *
1937
     * @psalm-mutation-free
1938
     *
1939
     * @return static
1940
     *                <p>Object with its $str being the longest common substring.</p>
1941
     */
1942 30
    public function longestCommonSubstring(string $otherStr): self
1943
    {
1944 30
        return static::create(
1945 30
            $this->utf8::str_longest_common_substring(
1946 30
                $this->str,
1947 30
                $otherStr,
1948 30
                $this->encoding
1949
            ),
1950 30
            $this->encoding
1951
        );
1952
    }
1953
1954
    /**
1955
     * Returns the longest common suffix between the string and $otherStr.
1956
     *
1957
     * @param string $otherStr <p>Second string for comparison.</p>
1958
     *
1959
     * @psalm-mutation-free
1960
     *
1961
     * @return static
1962
     *                <p>Object with its $str being the longest common suffix.</p>
1963
     */
1964 30
    public function longestCommonSuffix(string $otherStr): self
1965
    {
1966 30
        return static::create(
1967 30
            $this->utf8::str_longest_common_suffix(
1968 30
                $this->str,
1969 30
                $otherStr,
1970 30
                $this->encoding
1971
            ),
1972 30
            $this->encoding
1973
        );
1974
    }
1975
1976
    /**
1977
     * Converts the first character of the string to lower case.
1978
     *
1979
     * @psalm-mutation-free
1980
     *
1981
     * @return static
1982
     *                <p>Object with the first character of $str being lower case.</p>
1983
     */
1984 15
    public function lowerCaseFirst(): self
1985
    {
1986 15
        return static::create(
1987 15
            $this->utf8::lcfirst($this->str, $this->encoding),
1988 15
            $this->encoding
1989
        );
1990
    }
1991
1992
    /**
1993
     * Determine if the string matches another string regardless of case.
1994
     * Alias for isEqualsCaseInsensitive()
1995
     *
1996
     * @psalm-mutation-free
1997
     *
1998
     * @param string|Stringy ...$str
1999
     *                               <p>The string to compare against.</p>
2000
     *
2001
     * @psalm-mutation-free
2002
     *
2003
     * @return bool
2004
     */
2005 3
    public function matchCaseInsensitive(...$str): bool
2006
    {
2007 3
        return $this->isEqualsCaseInsensitive(...$str);
2008
    }
2009
2010
    /**
2011
     * Determine if the string matches another string.
2012
     * Alias for isEqualsCaseSensitive()
2013
     *
2014
     * @psalm-mutation-free
2015
     *
2016
     * @param string|Stringy ...$str
2017
     *                               <p>The string to compare against.</p>
2018
     *
2019
     * @psalm-mutation-free
2020
     *
2021
     * @return bool
2022
     */
2023 7
    public function matchCaseSensitive(...$str): bool
2024
    {
2025 7
        return $this->isEqualsCaseSensitive(...$str);
2026
    }
2027
2028
    /**
2029
     * Create a md5 hash from the current string.
2030
     *
2031
     * @psalm-mutation-free
2032
     *
2033
     * @return static
2034
     */
2035 2
    public function md5(): self
2036
    {
2037 2
        return static::create($this->hash('md5'), $this->encoding);
2038
    }
2039
2040
    /**
2041
     * Get every nth character of the string.
2042
     *
2043
     * @param int $step   The number of characters to step
2044
     * @param int $offset The string offset to start at
2045
     *
2046
     * @psalm-mutation-free
2047
     *
2048
     * @return static
2049
     */
2050 4
    public function nth(int $step, int $offset = 0): self
2051
    {
2052 4
        $length = $step - 1;
2053 4
        $substring = $this->substr($offset)->toString();
2054
2055 4
        if ($substring === '') {
2056
            return new static('', $this->encoding);
2057
        }
2058
2059 4
        \preg_match_all(
2060 4
            "/(?:^|(?:.|\p{L}|\w){" . $length . "})(.|\p{L}|\w)/u",
2061 4
            $substring,
2062 4
            $matches
2063
        );
2064
2065 4
        return new static(\implode('', $matches[1] ?? []), $this->encoding);
2066
    }
2067
2068
    /**
2069
     * Return part of the string occurring before a specific string.
2070
     *
2071
     * @param string $string The delimiting string
2072
     *
2073
     * @psalm-mutation-free
2074
     *
2075
     * @return static
2076
     */
2077 4
    public function before(string $string): self
2078
    {
2079 4
        $strArray = UTF8::str_split_pattern(
2080 4
            $this->str,
2081 4
            $string,
2082 4
            1
2083
        );
2084
2085 4
        return new static(
2086 4
            $strArray[0] ?? '',
2087 4
            $this->encoding
2088
        );
2089
    }
2090
2091
    /**
2092
     * Return part of the string occurring after a specific string.
2093
     *
2094
     * @param string $string The delimiting string
2095
     *
2096
     * @psalm-mutation-free
2097
     *
2098
     * @return static
2099
     */
2100 4
    public function after(string $string): self
2101
    {
2102 4
        $strArray = UTF8::str_split_pattern(
2103 4
            $this->str,
2104 4
            $string
2105
        );
2106
2107 4
        unset($strArray[0]);
2108
2109 4
        return new static(
2110 4
            \implode(' ', $strArray),
2111 4
            $this->encoding
2112
        );
2113
    }
2114
2115
    /**
2116
     * Returns whether or not a character exists at an index. Offsets may be
2117
     * negative to count from the last character in the string. Implements
2118
     * part of the ArrayAccess interface.
2119
     *
2120
     * @param int $offset <p>The index to check.</p>
2121
     *
2122
     * @psalm-mutation-free
2123
     *
2124
     * @return bool
2125
     *              <p>Whether or not the index exists.</p>
2126
     */
2127 18
    public function offsetExists($offset): bool
2128
    {
2129 18
        return $this->utf8::str_offset_exists(
2130 18
            $this->str,
2131 18
            $offset,
2132 18
            $this->encoding
2133
        );
2134
    }
2135
2136
    /**
2137
     * Returns the character at the given index. Offsets may be negative to
2138
     * count from the last character in the string. Implements part of the
2139
     * ArrayAccess interface, and throws an OutOfBoundsException if the index
2140
     * does not exist.
2141
     *
2142
     * @param int $offset <p>The <strong>index</strong> from which to retrieve the char.</p>
2143
     *
2144
     * @throws \OutOfBoundsException
2145
     *                               <p>If the positive or negative offset does not exist.</p>
2146
     *
2147
     * @psalm-mutation-free
2148
     *
2149
     * @return string
2150
     *                <p>The character at the specified index.</p>
2151
     */
2152 6
    public function offsetGet($offset): string
2153
    {
2154 6
        return $this->utf8::str_offset_get($this->str, $offset, $this->encoding);
2155
    }
2156
2157
    /**
2158
     * Implements part of the ArrayAccess interface, but throws an exception
2159
     * when called. This maintains the immutability of Stringy objects.
2160
     *
2161
     * @param int   $offset <p>The index of the character.</p>
2162
     * @param mixed $value  <p>Value to set.</p>
2163
     *
2164
     * @throws \Exception
2165
     *                    <p>When called.</p>
2166
     *
2167
     * @return void
2168
     */
2169 3
    public function offsetSet($offset, $value)
2170
    {
2171
        // Stringy is immutable, cannot directly set char
2172
        /** @noinspection ThrowRawExceptionInspection */
2173 3
        throw new \Exception('Stringy object is immutable, cannot modify char');
2174
    }
2175
2176
    /**
2177
     * Implements part of the ArrayAccess interface, but throws an exception
2178
     * when called. This maintains the immutability of Stringy objects.
2179
     *
2180
     * @param int $offset <p>The index of the character.</p>
2181
     *
2182
     * @throws \Exception
2183
     *                    <p>When called.</p>
2184
     *
2185
     * @return void
2186
     */
2187 3
    public function offsetUnset($offset)
2188
    {
2189
        // Don't allow directly modifying the string
2190
        /** @noinspection ThrowRawExceptionInspection */
2191 3
        throw new \Exception('Stringy object is immutable, cannot unset char');
2192
    }
2193
2194
    /**
2195
     * Pads the string to a given length with $padStr. If length is less than
2196
     * or equal to the length of the string, no padding takes places. The
2197
     * default string used for padding is a space, and the default type (one of
2198
     * 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
2199
     * if $padType isn't one of those 3 values.
2200
     *
2201
     * @param int    $length  <p>Desired string length after padding.</p>
2202
     * @param string $padStr  [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2203
     * @param string $padType [optional] <p>One of 'left', 'right', 'both'. Default: 'right'</p>
2204
     *
2205
     * @throws \InvalidArgumentException
2206
     *                                   <p>If $padType isn't one of 'right', 'left' or 'both'.</p>
2207
     *
2208
     * @psalm-mutation-free
2209
     *
2210
     * @return static
2211
     *                <p>Object with a padded $str.</p>
2212
     */
2213 39
    public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
2214
    {
2215 39
        return static::create(
2216 39
            $this->utf8::str_pad(
2217 39
                $this->str,
2218 39
                $length,
2219 39
                $padStr,
2220 39
                $padType,
2221 39
                $this->encoding
2222
            )
2223
        );
2224
    }
2225
2226
    /**
2227
     * Returns a new string of a given length such that both sides of the
2228
     * string are padded. Alias for pad() with a $padType of 'both'.
2229
     *
2230
     * @param int    $length <p>Desired string length after padding.</p>
2231
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2232
     *
2233
     * @psalm-mutation-free
2234
     *
2235
     * @return static
2236
     *                <p>String with padding applied.</p>
2237
     */
2238 33
    public function padBoth(int $length, string $padStr = ' '): self
2239
    {
2240 33
        return static::create(
2241 33
            $this->utf8::str_pad_both(
2242 33
                $this->str,
2243 33
                $length,
2244 33
                $padStr,
2245 33
                $this->encoding
2246
            )
2247
        );
2248
    }
2249
2250
    /**
2251
     * Returns a new string of a given length such that the beginning of the
2252
     * string is padded. Alias for pad() with a $padType of 'left'.
2253
     *
2254
     * @param int    $length <p>Desired string length after padding.</p>
2255
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2256
     *
2257
     * @psalm-mutation-free
2258
     *
2259
     * @return static
2260
     *                <p>String with left padding.</p>
2261
     */
2262 21
    public function padLeft(int $length, string $padStr = ' '): self
2263
    {
2264 21
        return static::create(
2265 21
            $this->utf8::str_pad_left(
2266 21
                $this->str,
2267 21
                $length,
2268 21
                $padStr,
2269 21
                $this->encoding
2270
            )
2271
        );
2272
    }
2273
2274
    /**
2275
     * Returns a new string of a given length such that the end of the string
2276
     * is padded. Alias for pad() with a $padType of 'right'.
2277
     *
2278
     * @param int    $length <p>Desired string length after padding.</p>
2279
     * @param string $padStr [optional] <p>String used to pad, defaults to space. Default: ' '</p>
2280
     *
2281
     * @psalm-mutation-free
2282
     *
2283
     * @return static
2284
     *                <p>String with right padding.</p>
2285
     */
2286 21
    public function padRight(int $length, string $padStr = ' '): self
2287
    {
2288 21
        return static::create(
2289 21
            $this->utf8::str_pad_right(
2290 21
                $this->str,
2291 21
                $length,
2292 21
                $padStr,
2293 21
                $this->encoding
2294
            )
2295
        );
2296
    }
2297
2298
    /**
2299
     * Returns a new string starting with $prefix.
2300
     *
2301
     * @param string ...$prefix <p>The string to append.</p>
2302
     *
2303
     * @psalm-mutation-free
2304
     *
2305
     * @return static
2306
     *                <p>Object with appended $prefix.</p>
2307
     *
2308
     * @noinspection PhpDocSignatureInspection
2309
     */
2310 7 View Code Duplication
    public function prepend(string ...$prefix): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2311
    {
2312 7
        if (\count($prefix) <= 1) {
2313
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2314 6
            $prefix = $prefix[0];
2315
        } else {
2316
            /** @noinspection CallableParameterUseCaseInTypeContextInspection */
2317 1
            $prefix = \implode('', $prefix);
2318
        }
2319
2320 7
        return static::create($prefix . $this->str, $this->encoding);
2321
    }
2322
2323
    /**
2324
     * Replaces all occurrences of $pattern in $str by $replacement.
2325
     *
2326
     * @param string $pattern     <p>The regular expression pattern.</p>
2327
     * @param string $replacement <p>The string to replace with.</p>
2328
     * @param string $options     [optional] <p>Matching conditions to be used.</p>
2329
     * @param string $delimiter   [optional] <p>Delimiter the the regex. Default: '/'</p>
2330
     *
2331
     * @psalm-mutation-free
2332
     *
2333
     * @return static
2334
     *                <p>Object with the result2ing $str after the replacements.</p>
2335
     */
2336 29
    public function regexReplace(string $pattern, string $replacement, string $options = '', string $delimiter = '/'): self
2337
    {
2338 29
        return static::create(
2339 29
            $this->utf8::regex_replace(
2340 29
                $this->str,
2341 29
                $pattern,
2342 29
                $replacement,
2343 29
                $options,
2344 29
                $delimiter
2345
            ),
2346 29
            $this->encoding
2347
        );
2348
    }
2349
2350
    /**
2351
     * Remove html via "strip_tags()" from the string.
2352
     *
2353
     * @param string $allowableTags [optional] <p>You can use the optional second parameter to specify tags which should
2354
     *                              not be stripped. Default: null
2355
     *                              </p>
2356
     *
2357
     * @psalm-mutation-free
2358
     *
2359
     * @return static
2360
     */
2361 12
    public function removeHtml(string $allowableTags = ''): self
2362
    {
2363 12
        return static::create(
2364 12
            $this->utf8::remove_html($this->str, $allowableTags),
2365 12
            $this->encoding
2366
        );
2367
    }
2368
2369
    /**
2370
     * Remove all breaks [<br> | \r\n | \r | \n | ...] from the string.
2371
     *
2372
     * @param string $replacement [optional] <p>Default is a empty string.</p>
2373
     *
2374
     * @psalm-mutation-free
2375
     *
2376
     * @return static
2377
     */
2378 12
    public function removeHtmlBreak(string $replacement = ''): self
2379
    {
2380 12
        return static::create(
2381 12
            $this->utf8::remove_html_breaks($this->str, $replacement),
2382 12
            $this->encoding
2383
        );
2384
    }
2385
2386
    /**
2387
     * Returns a new string with the prefix $substring removed, if present.
2388
     *
2389
     * @param string $substring <p>The prefix to remove.</p>
2390
     *
2391
     * @psalm-mutation-free
2392
     *
2393
     * @return static
2394
     *                <p>Object having a $str without the prefix $substring.</p>
2395
     */
2396 36
    public function removeLeft(string $substring): self
2397
    {
2398 36
        return static::create(
2399 36
            $this->utf8::remove_left($this->str, $substring, $this->encoding),
2400 36
            $this->encoding
2401
        );
2402
    }
2403
2404
    /**
2405
     * Returns a new string with the suffix $substring removed, if present.
2406
     *
2407
     * @param string $substring <p>The suffix to remove.</p>
2408
     *
2409
     * @psalm-mutation-free
2410
     *
2411
     * @return static
2412
     *                <p>Object having a $str without the suffix $substring.</p>
2413
     */
2414 36
    public function removeRight(string $substring): self
2415
    {
2416 36
        return static::create(
2417 36
            $this->utf8::remove_right($this->str, $substring, $this->encoding),
2418 36
            $this->encoding
2419
        );
2420
    }
2421
2422
    /**
2423
     * Try to remove all XSS-attacks from the string.
2424
     *
2425
     * @psalm-mutation-free
2426
     *
2427
     * @return static
2428
     */
2429 12
    public function removeXss(): self
2430
    {
2431
        /**
2432
         * @var AntiXSS|null
2433
         *
2434
         * @psalm-suppress ImpureStaticVariable
2435
         */
2436 12
        static $antiXss = null;
2437
2438 12
        if ($antiXss === null) {
2439 1
            $antiXss = new AntiXSS();
2440
        }
2441
2442
        /**
2443
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the anti-xss class
2444
         */
2445 12
        $str = $antiXss->xss_clean($this->str);
2446
2447 12
        return static::create($str, $this->encoding);
2448
    }
2449
2450
    /**
2451
     * Returns a repeated string given a multiplier.
2452
     *
2453
     * @param int $multiplier <p>The number of times to repeat the string.</p>
2454
     *
2455
     * @psalm-mutation-free
2456
     *
2457
     * @return static
2458
     *                <p>Object with a repeated str.</p>
2459
     */
2460 21
    public function repeat(int $multiplier): self
2461
    {
2462 21
        return static::create(
2463 21
            \str_repeat($this->str, $multiplier),
2464 21
            $this->encoding
2465
        );
2466
    }
2467
2468
    /**
2469
     * Replaces all occurrences of $search in $str by $replacement.
2470
     *
2471
     * @param string $search        <p>The needle to search for.</p>
2472
     * @param string $replacement   <p>The string to replace with.</p>
2473
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2474
     *
2475
     * @psalm-mutation-free
2476
     *
2477
     * @return static
2478
     *                <p>Object with the resulting $str after the replacements.</p>
2479
     */
2480 76
    public function replace(string $search, string $replacement, bool $caseSensitive = true): self
2481
    {
2482 76
        if ($search === '' && $replacement === '') {
2483 16
            return static::create($this->str, $this->encoding);
2484
        }
2485
2486 60
        if ($this->str === '' && $search === '') {
2487 2
            return static::create($replacement, $this->encoding);
2488
        }
2489
2490 58
        if ($caseSensitive) {
2491 48
            return static::create(
2492 48
                $this->utf8::str_replace($search, $replacement, $this->str),
2493 48
                $this->encoding
2494
            );
2495
        }
2496
2497 10
        return static::create(
2498 10
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2499 10
            $this->encoding
2500
        );
2501
    }
2502
2503
    /**
2504
     * Replaces all occurrences of $search in $str by $replacement.
2505
     *
2506
     * @param string[]        $search        <p>The elements to search for.</p>
2507
     * @param string|string[] $replacement   <p>The string to replace with.</p>
2508
     * @param bool            $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2509
     *
2510
     * @psalm-mutation-free
2511
     *
2512
     * @return static
2513
     *                <p>Object with the resulting $str after the replacements.</p>
2514
     */
2515 61
    public function replaceAll(array $search, $replacement, bool $caseSensitive = true): self
2516
    {
2517 61
        if ($caseSensitive) {
2518 47
            return static::create(
2519 47
                $this->utf8::str_replace($search, $replacement, $this->str),
2520 47
                $this->encoding
2521
            );
2522
        }
2523
2524 14
        return static::create(
2525 14
            $this->utf8::str_ireplace($search, $replacement, $this->str),
2526 14
            $this->encoding
2527
        );
2528
    }
2529
2530
    /**
2531
     * Replaces all occurrences of $search from the beginning of string with $replacement.
2532
     *
2533
     * @param string $search      <p>The string to search for.</p>
2534
     * @param string $replacement <p>The replacement.</p>
2535
     *
2536
     * @psalm-mutation-free
2537
     *
2538
     * @return static
2539
     *                <p>Object with the resulting $str after the replacements.</p>
2540
     */
2541 32
    public function replaceBeginning(string $search, string $replacement): self
2542
    {
2543 32
        return static::create(
2544 32
            $this->utf8::str_replace_beginning($this->str, $search, $replacement),
2545 32
            $this->encoding
2546
        );
2547
    }
2548
2549
    /**
2550
     * Replaces all occurrences of $search from the ending of string with $replacement.
2551
     *
2552
     * @param string $search      <p>The string to search for.</p>
2553
     * @param string $replacement <p>The replacement.</p>
2554
     *
2555
     * @psalm-mutation-free
2556
     *
2557
     * @return static
2558
     *                <p>Object with the resulting $str after the replacements.</p>
2559
     */
2560 32
    public function replaceEnding(string $search, string $replacement): self
2561
    {
2562 32
        return static::create(
2563 32
            $this->utf8::str_replace_ending($this->str, $search, $replacement),
2564 32
            $this->encoding
2565
        );
2566
    }
2567
2568
    /**
2569
     * Replaces first occurrences of $search from the beginning of string with $replacement.
2570
     *
2571
     * @param string $search      <p>The string to search for.</p>
2572
     * @param string $replacement <p>The replacement.</p>
2573
     *
2574
     * @psalm-mutation-free
2575
     *
2576
     * @return static
2577
     *                <p>Object with the resulting $str after the replacements.</p>
2578
     */
2579 32
    public function replaceFirst(string $search, string $replacement): self
2580
    {
2581 32
        return static::create(
2582 32
            $this->utf8::str_replace_first($search, $replacement, $this->str),
2583 32
            $this->encoding
2584
        );
2585
    }
2586
2587
    /**
2588
     * Replaces last occurrences of $search from the ending of string with $replacement.
2589
     *
2590
     * @param string $search      <p>The string to search for.</p>
2591
     * @param string $replacement <p>The replacement.</p>
2592
     *
2593
     * @psalm-mutation-free
2594
     *
2595
     * @return static
2596
     *                <p>Object with the resulting $str after the replacements.</p>
2597
     */
2598 30
    public function replaceLast(string $search, string $replacement): self
2599
    {
2600 30
        return static::create(
2601 30
            $this->utf8::str_replace_last($search, $replacement, $this->str),
2602 30
            $this->encoding
2603
        );
2604
    }
2605
2606
    /**
2607
     * Returns a reversed string. A multibyte version of strrev().
2608
     *
2609
     * @psalm-mutation-free
2610
     *
2611
     * @return static
2612
     *                <p>Object with a reversed $str.</p>
2613
     */
2614 15
    public function reverse(): self
2615
    {
2616 15
        return static::create($this->utf8::strrev($this->str), $this->encoding);
2617
    }
2618
2619
    /**
2620
     * Truncates the string to a given length, while ensuring that it does not
2621
     * split words. If $substring is provided, and truncating occurs, the
2622
     * string is further truncated so that the substring may be appended without
2623
     * exceeding the desired length.
2624
     *
2625
     * @param int    $length                          <p>Desired length of the truncated string.</p>
2626
     * @param string $substring                       [optional] <p>The substring to append if it can fit. Default: ''</p>
2627
     * @param bool   $ignoreDoNotSplitWordsForOneWord
2628
     *
2629
     * @psalm-mutation-free
2630
     *
2631
     * @return static
2632
     *                <p>Object with the resulting $str after truncating.</p>
2633
     */
2634 68
    public function safeTruncate(
2635
        int $length,
2636
        string $substring = '',
2637
        bool $ignoreDoNotSplitWordsForOneWord = true
2638
    ): self {
2639 68
        return static::create(
2640 68
            $this->utf8::str_truncate_safe(
2641 68
                $this->str,
2642 68
                $length,
2643 68
                $substring,
2644 68
                $this->encoding,
2645 68
                $ignoreDoNotSplitWordsForOneWord
2646
            ),
2647 68
            $this->encoding
2648
        );
2649
    }
2650
2651
    /**
2652
     * Create a sha1 hash from the current string.
2653
     *
2654
     * @psalm-mutation-free
2655
     *
2656
     * @return static
2657
     */
2658 2
    public function sha1(): self
2659
    {
2660 2
        return static::create($this->hash('sha1'), $this->encoding);
2661
    }
2662
2663
    /**
2664
     * Create a sha256 hash from the current string.
2665
     *
2666
     * @psalm-mutation-free
2667
     *
2668
     * @return static
2669
     */
2670 2
    public function sha256(): self
2671
    {
2672 2
        return static::create($this->hash('sha256'), $this->encoding);
2673
    }
2674
2675
    /**
2676
     * Create a sha512 hash from the current string.
2677
     *
2678
     * @psalm-mutation-free
2679
     *
2680
     * @return static
2681
     */
2682 2
    public function sha512(): self
2683
    {
2684 2
        return static::create($this->hash('sha512'), $this->encoding);
2685
    }
2686
2687
    /**
2688
     * Shorten the string after $length, but also after the next word.
2689
     *
2690
     * @param int    $length
2691
     * @param string $strAddOn [optional] <p>Default: '…'</p>
2692
     *
2693
     * @psalm-mutation-free
2694
     *
2695
     * @return static
2696
     */
2697 8
    public function shortenAfterWord(int $length, string $strAddOn = '…'): self
2698
    {
2699 8
        return static::create(
2700 8
            $this->utf8::str_limit_after_word($this->str, $length, $strAddOn),
2701 8
            $this->encoding
2702
        );
2703
    }
2704
2705
    /**
2706
     * A multibyte string shuffle function. It returns a string with its
2707
     * characters in random order.
2708
     *
2709
     * @psalm-mutation-free
2710
     *
2711
     * @return static
2712
     *                <p>Object with a shuffled $str.</p>
2713
     */
2714 9
    public function shuffle(): self
2715
    {
2716 9
        return static::create($this->utf8::str_shuffle($this->str), $this->encoding);
2717
    }
2718
2719
    /**
2720
     * Calculate the similarity between two strings.
2721
     *
2722
     * @param string $str
2723
     *
2724
     * @psalm-mutation-free
2725
     *
2726
     * @return float
2727
     */
2728 2
    public function similarity(string $str): float
2729
    {
2730 2
        \similar_text($this->str, $str, $percent);
2731
2732 2
        return $percent;
2733
    }
2734
2735
    /**
2736
     * Returns the substring beginning at $start, and up to, but not including
2737
     * the index specified by $end. If $end is omitted, the function extracts
2738
     * the remaining string. If $end is negative, it is computed from the end
2739
     * of the string.
2740
     *
2741
     * @param int $start <p>Initial index from which to begin extraction.</p>
2742
     * @param int $end   [optional] <p>Index at which to end extraction. Default: null</p>
2743
     *
2744
     * @psalm-mutation-free
2745
     *
2746
     * @return static
2747
     *                <p>Object with its $str being the extracted substring.</p>
2748
     */
2749 50
    public function slice(int $start, int $end = null): self
2750
    {
2751 50
        return static::create(
2752 50
            $this->utf8::str_slice($this->str, $start, $end, $this->encoding),
2753 50
            $this->encoding
2754
        );
2755
    }
2756
2757
    /**
2758
     * Converts the string into an URL slug. This includes replacing non-ASCII
2759
     * characters with their closest ASCII equivalents, removing remaining
2760
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
2761
     * $separator. The separator defaults to a single dash, and the string
2762
     * is also converted to lowercase. The language of the source string can
2763
     * also be supplied for language-specific transliteration.
2764
     *
2765
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
2766
     * @param string                $language              [optional] <p>Language of the source string.</p>
2767
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
2768
     * @param bool                  $replace_extra_symbols [optional]  <p>Add some more replacements e.g. "£" with "
2769
     *                                                     pound ".</p>
2770
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
2771
     * @param bool                  $use_transliterate     [optional]  <p>Use ASCII::to_transliterate() for unknown
2772
     *                                                     chars.</p>
2773
     *
2774
     * @psalm-mutation-free
2775
     *
2776
     * @return static
2777
     *                <p>Object whose $str has been converted to an URL slug.</p>
2778
     *
2779
     * @noinspection PhpTooManyParametersInspection
2780
     */
2781 17
    public function slugify(
2782
        string $separator = '-',
2783
        string $language = 'en',
2784
        array $replacements = [],
2785
        bool $replace_extra_symbols = true,
2786
        bool $use_str_to_lower = true,
2787
        bool $use_transliterate = false
2788
    ): self {
2789 17
        return static::create(
2790 17
            $this->ascii::to_slugify(
2791 17
                $this->str,
2792 17
                $separator,
2793 17
                $language,
2794 17
                $replacements,
2795 17
                $replace_extra_symbols,
2796 17
                $use_str_to_lower,
2797 17
                $use_transliterate
2798
            ),
2799 17
            $this->encoding
2800
        );
2801
    }
2802
2803
    /**
2804
     * Convert a string to e.g.: "snake_case"
2805
     *
2806
     * @psalm-mutation-free
2807
     *
2808
     * @return static
2809
     *                <p>Object with $str in snake_case.</p>
2810
     */
2811 40
    public function snakeize(): self
2812
    {
2813 40
        return static::create(
2814 40
            $this->utf8::str_snakeize($this->str, $this->encoding),
2815 40
            $this->encoding
2816
        );
2817
    }
2818
2819
    /**
2820
     * Wrap the string after the first whitespace character after a given number
2821
     * of characters.
2822
     *
2823
     * @param int    $width Number of characters at which to wrap
2824
     * @param string $break Character used to break the string
2825
     *
2826
     * @psalm-mutation-free
2827
     *
2828
     * @return static
2829
     */
2830 2
    public function softWrap(int $width, string $break = "\n"): self
2831
    {
2832 2
        return $this->lineWrapAfterWord($width, $break, false);
2833
    }
2834
2835
    /**
2836
     * Splits the string with the provided regular expression, returning an
2837
     * array of Stringy objects. An optional integer $limit will truncate the
2838
     * results.
2839
     *
2840
     * @param string $pattern <p>The regex with which to split the string.</p>
2841
     * @param int    $limit   [optional] <p>Maximum number of results to return. Default: -1 === no limit</p>
2842
     *
2843
     * @psalm-mutation-free
2844
     *
2845
     * @return CollectionStringy|static[]
2846
     *                                    <p>An collection of Stringy objects.</p>
2847
     *
2848
     * @psalm-return CollectionStringy<int,static>
2849
     */
2850 51
    public function split(string $pattern, int $limit = null): CollectionStringy
2851
    {
2852 51
        if ($limit === null) {
2853 7
            $limit = -1;
2854
        }
2855
2856 51
        $array = $this->utf8::str_split_pattern($this->str, $pattern, $limit);
2857
        /** @noinspection AlterInForeachInspection */
2858 51
        foreach ($array as $i => &$value) {
2859 45
            $value = static::create($value, $this->encoding);
2860
        }
2861
2862
        /** @noinspection PhpSillyAssignmentInspection */
2863
        /** @var static[] $array */
2864 51
        $array = $array;
0 ignored issues
show
Bug introduced by
Why assign $array to itself?

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

This assignement can be removed without consequences.

Loading history...
2865
2866
        /**
2867
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
2868
         */
2869 51
        return CollectionStringy::create($array);
2870
    }
2871
2872
    /**
2873
     * Returns true if the string begins with $substring, false otherwise. By
2874
     * default, the comparison is case-sensitive, but can be made insensitive
2875
     * by setting $caseSensitive to false.
2876
     *
2877
     * @param string $substring     <p>The substring to look for.</p>
2878
     * @param bool   $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2879
     *
2880
     * @psalm-mutation-free
2881
     *
2882
     * @return bool
2883
     *              <p>Whether or not $str starts with $substring.</p>
2884
     */
2885 99
    public function startsWith(string $substring, bool $caseSensitive = true): bool
2886
    {
2887 99
        if ($caseSensitive) {
2888 53
            return $this->utf8::str_starts_with($this->str, $substring);
2889
        }
2890
2891 46
        return $this->utf8::str_istarts_with($this->str, $substring);
2892
    }
2893
2894
    /**
2895
     * Returns true if the string begins with any of $substrings, false otherwise.
2896
     * By default the comparison is case-sensitive, but can be made insensitive by
2897
     * setting $caseSensitive to false.
2898
     *
2899
     * @param string[] $substrings    <p>Substrings to look for.</p>
2900
     * @param bool     $caseSensitive [optional] <p>Whether or not to enforce case-sensitivity. Default: true</p>
2901
     *
2902
     * @psalm-mutation-free
2903
     *
2904
     * @return bool
2905
     *              <p>Whether or not $str starts with $substring.</p>
2906
     */
2907 35
    public function startsWithAny(array $substrings, bool $caseSensitive = true): bool
2908
    {
2909 35
        if ($caseSensitive) {
2910 23
            return $this->utf8::str_starts_with_any($this->str, $substrings);
2911
        }
2912
2913 12
        return $this->utf8::str_istarts_with_any($this->str, $substrings);
2914
    }
2915
2916
    /**
2917
     * Remove one or more strings from the string.
2918
     *
2919
     * @param string|string[] $search One or more strings to be removed
2920
     *
2921
     * @psalm-mutation-free
2922
     *
2923
     * @return static
2924
     */
2925 3
    public function strip($search): self
2926
    {
2927 3
        if (\is_array($search)) {
2928 1
            return $this->replaceAll($search, '');
2929
        }
2930
2931 2
        return $this->replace($search, '');
2932
    }
2933
2934
    /**
2935
     * Strip all whitespace characters. This includes tabs and newline characters,
2936
     * as well as multibyte whitespace such as the thin space and ideographic space.
2937
     *
2938
     * @psalm-mutation-free
2939
     *
2940
     * @return static
2941
     */
2942 36
    public function stripWhitespace(): self
2943
    {
2944 36
        return static::create(
2945 36
            $this->utf8::strip_whitespace($this->str),
2946 36
            $this->encoding
2947
        );
2948
    }
2949
2950
    /**
2951
     * Remove css media-queries.
2952
     *
2953
     * @psalm-mutation-free
2954
     *
2955
     * @return static
2956
     */
2957 2
    public function stripeCssMediaQueries(): self
2958
    {
2959 2
        return static::create(
2960 2
            $this->utf8::css_stripe_media_queries($this->str),
2961 2
            $this->encoding
2962
        );
2963
    }
2964
2965
    /**
2966
     * Remove empty html-tag.
2967
     *
2968
     * e.g.: <tag></tag>
2969
     *
2970
     * @psalm-mutation-free
2971
     *
2972
     * @return static
2973
     */
2974 2
    public function stripeEmptyHtmlTags(): self
2975
    {
2976 2
        return static::create(
2977 2
            $this->utf8::html_stripe_empty_tags($this->str),
2978 2
            $this->encoding
2979
        );
2980
    }
2981
2982
    /**
2983
     * Returns the substring beginning at $start with the specified $length.
2984
     * It differs from the $this->utf8::substr() function in that providing a $length of
2985
     * null will return the rest of the string, rather than an empty string.
2986
     *
2987
     * @param int $start  <p>Position of the first character to use.</p>
2988
     * @param int $length [optional] <p>Maximum number of characters used. Default: null</p>
2989
     *
2990
     * @psalm-mutation-free
2991
     *
2992
     * @return static
2993
     *                <p>Object with its $str being the substring.</p>
2994
     */
2995 31
    public function substr(int $start, int $length = null): self
2996
    {
2997 31
        return static::create(
2998 31
            $this->utf8::substr(
2999 31
                $this->str,
3000 31
                $start,
3001 31
                $length,
3002 31
                $this->encoding
3003
            ),
3004 31
            $this->encoding
3005
        );
3006
    }
3007
3008
    /**
3009
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3010
     * If no match is found returns new empty Stringy object.
3011
     *
3012
     * @param string $needle       <p>The string to look for.</p>
3013
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3014
     *
3015
     * @psalm-mutation-free
3016
     *
3017
     * @return static
3018
     */
3019 4 View Code Duplication
    public function substringOf(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
3020
    {
3021 4
        return static::create(
3022 4
            $this->utf8::str_substr_first(
3023 4
                $this->str,
3024 4
                $needle,
3025 4
                $beforeNeedle,
3026 4
                $this->encoding
3027
            ),
3028 4
            $this->encoding
3029
        );
3030
    }
3031
3032
    /**
3033
     * Gets the substring after (or before via "$beforeNeedle") the first occurrence of the "$needle".
3034
     * If no match is found returns new empty Stringy object.
3035
     *
3036
     * @param string $needle       <p>The string to look for.</p>
3037
     * @param bool   $beforeNeedle [optional] <p>Default: false</p>
3038
     *
3039
     * @psalm-mutation-free
3040
     *
3041
     * @return static
3042
     */
3043 4 View Code Duplication
    public function substringOfIgnoreCase(string $needle, bool $beforeNeedle = false): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
3044
    {
3045 4
        return static::create(
3046 4
            $this->utf8::str_isubstr_first(
3047 4
                $this->str,
3048 4
                $needle,
3049 4
                $beforeNeedle,
3050 4
                $this->encoding
3051
            ),
3052 4
            $this->encoding
3053
        );
3054
    }
3055
3056
    /**
3057
     * Surrounds $str with the given substring.
3058
     *
3059
     * @param string $substring <p>The substring to add to both sides.</P>
3060
     *
3061
     * @psalm-mutation-free
3062
     *
3063
     * @return static
3064
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3065
     */
3066 15
    public function surround(string $substring): self
3067
    {
3068 15
        return static::create(
3069 15
            $substring . $this->str . $substring,
3070 15
            $this->encoding
3071
        );
3072
    }
3073
3074
    /**
3075
     * Returns a case swapped version of the string.
3076
     *
3077
     * @psalm-mutation-free
3078
     *
3079
     * @return static
3080
     *                <p>Object whose $str has each character's case swapped.</P>
3081
     */
3082 15
    public function swapCase(): self
3083
    {
3084 15
        return static::create(
3085 15
            $this->utf8::swapCase($this->str, $this->encoding),
3086 15
            $this->encoding
3087
        );
3088
    }
3089
3090
    /**
3091
     * Returns a string with smart quotes, ellipsis characters, and dashes from
3092
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
3093
     * equivalents.
3094
     *
3095
     * @psalm-mutation-free
3096
     *
3097
     * @return static
3098
     *                <p>Object whose $str has those characters removed.</p>
3099
     */
3100 12
    public function tidy(): self
3101
    {
3102 12
        return static::create(
3103 12
            $this->ascii::normalize_msword($this->str),
3104 12
            $this->encoding
3105
        );
3106
    }
3107
3108
    /**
3109
     * Returns a trimmed string with the first letter of each word capitalized.
3110
     * Also accepts an array, $ignore, allowing you to list words not to be
3111
     * capitalized.
3112
     *
3113
     * @param array|string[]|null $ignore            [optional] <p>An array of words not to capitalize or null.
3114
     *                                               Default: null</p>
3115
     * @param string|null         $word_define_chars [optional] <p>An string of chars that will be used as whitespace
3116
     *                                               separator === words.</p>
3117
     * @param string|null         $language          [optional] <p>Language of the source string.</p>
3118
     *
3119
     * @psalm-mutation-free
3120
     *
3121
     * @return static
3122
     *                <p>Object with a titleized $str.</p>
3123
     */
3124 23
    public function titleize(
3125
        array $ignore = null,
3126
        string $word_define_chars = null,
3127
        string $language = null
3128
    ): self {
3129 23
        return static::create(
3130 23
            $this->utf8::str_titleize(
3131 23
                $this->str,
3132 23
                $ignore,
3133 23
                $this->encoding,
3134 23
                false,
3135 23
                $language,
3136 23
                false,
3137 23
                true,
3138 23
                $word_define_chars
3139
            ),
3140 23
            $this->encoding
3141
        );
3142
    }
3143
3144
    /**
3145
     * Returns a trimmed string in proper title case.
3146
     *
3147
     * Also accepts an array, $ignore, allowing you to list words not to be
3148
     * capitalized.
3149
     *
3150
     * Adapted from John Gruber's script.
3151
     *
3152
     * @see https://gist.github.com/gruber/9f9e8650d68b13ce4d78
3153
     *
3154
     * @param string[] $ignore <p>An array of words not to capitalize.</p>
3155
     *
3156
     * @psalm-mutation-free
3157
     *
3158
     * @return static
3159
     *                <p>Object with a titleized $str</p>
3160
     */
3161 70
    public function titleizeForHumans(array $ignore = []): self
3162
    {
3163 70
        return static::create(
3164 70
            $this->utf8::str_titleize_for_humans(
3165 70
                $this->str,
3166 70
                $ignore,
3167 70
                $this->encoding
3168
            ),
3169 70
            $this->encoding
3170
        );
3171
    }
3172
3173
    /**
3174
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3175
     * replaced with their closest ASCII counterparts, and the rest are removed
3176
     * by default. The language or locale of the source string can be supplied
3177
     * for language-specific transliteration in any of the following formats:
3178
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
3179
     * to "aeoeue" rather than "aou" as in other languages.
3180
     *
3181
     * @param string $language          [optional] <p>Language of the source string.</p>
3182
     * @param bool   $removeUnsupported [optional] <p>Whether or not to remove the
3183
     *                                  unsupported characters.</p>
3184
     *
3185
     * @psalm-mutation-free
3186
     *
3187
     * @return static
3188
     *                <p>Object whose $str contains only ASCII characters.</p>
3189
     */
3190 23
    public function toAscii(string $language = 'en', bool $removeUnsupported = true): self
3191
    {
3192 23
        return static::create(
3193 23
            $this->ascii::to_ascii(
3194 23
                $this->str,
3195 23
                $language,
3196 23
                $removeUnsupported
3197
            ),
3198 23
            $this->encoding
3199
        );
3200
    }
3201
3202
    /**
3203
     * Returns a boolean representation of the given logical string value.
3204
     * For example, 'true', '1', 'on' and 'yes' will return true. 'false', '0',
3205
     * 'off', and 'no' will return false. In all instances, case is ignored.
3206
     * For other numeric strings, their sign will determine the return value.
3207
     * In addition, blank strings consisting of only whitespace will return
3208
     * false. For all other strings, the return value is a result of a
3209
     * boolean cast.
3210
     *
3211
     * @psalm-mutation-free
3212
     *
3213
     * @return bool
3214
     *              <p>A boolean value for the string.</p>
3215
     */
3216 45
    public function toBoolean(): bool
3217
    {
3218 45
        return $this->utf8::to_boolean($this->str);
3219
    }
3220
3221
    /**
3222
     * Converts all characters in the string to lowercase.
3223
     *
3224
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3225
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3226
     *
3227
     * @psalm-mutation-free
3228
     *
3229
     * @return static
3230
     *                <p>Object with all characters of $str being lowercase.</p>
3231
     */
3232 17 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...
3233
    {
3234 17
        return static::create(
3235 17
            $this->utf8::strtolower(
3236 17
                $this->str,
3237 17
                $this->encoding,
3238 17
                false,
3239 17
                $lang,
3240 17
                $tryToKeepStringLength
3241
            ),
3242 17
            $this->encoding
3243
        );
3244
    }
3245
3246
    /**
3247
     * Converts each tab in the string to some number of spaces, as defined by
3248
     * $tabLength. By default, each tab is converted to 4 consecutive spaces.
3249
     *
3250
     * @param int $tabLength [optional] <p>Number of spaces to replace each tab with. Default: 4</p>
3251
     *
3252
     * @psalm-mutation-free
3253
     *
3254
     * @return static
3255
     *                <p>Object whose $str has had tabs switched to spaces.</p>
3256
     */
3257 18 View Code Duplication
    public function toSpaces(int $tabLength = 4): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
3258
    {
3259 18
        if ($tabLength === 4) {
3260 9
            $tab = '    ';
3261 9
        } elseif ($tabLength === 2) {
3262 3
            $tab = '  ';
3263
        } else {
3264 6
            $tab = \str_repeat(' ', $tabLength);
3265
        }
3266
3267 18
        return static::create(
3268 18
            \str_replace("\t", $tab, $this->str),
3269 18
            $this->encoding
3270
        );
3271
    }
3272
3273
    /**
3274
     * Return Stringy object as string, but you can also use (string) for automatically casting the object into a
3275
     * string.
3276
     *
3277
     * @psalm-mutation-free
3278
     *
3279
     * @return string
3280
     */
3281 2180
    public function toString(): string
3282
    {
3283 2180
        return (string) $this->str;
3284
    }
3285
3286
    /**
3287
     * Converts each occurrence of some consecutive number of spaces, as
3288
     * defined by $tabLength, to a tab. By default, each 4 consecutive spaces
3289
     * are converted to a tab.
3290
     *
3291
     * @param int $tabLength [optional] <p>Number of spaces to replace with a tab. Default: 4</p>
3292
     *
3293
     * @psalm-mutation-free
3294
     *
3295
     * @return static
3296
     *                <p>Object whose $str has had spaces switched to tabs.</p>
3297
     */
3298 15 View Code Duplication
    public function toTabs(int $tabLength = 4): self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
3299
    {
3300 15
        if ($tabLength === 4) {
3301 9
            $tab = '    ';
3302 6
        } elseif ($tabLength === 2) {
3303 3
            $tab = '  ';
3304
        } else {
3305 3
            $tab = \str_repeat(' ', $tabLength);
3306
        }
3307
3308 15
        return static::create(
3309 15
            \str_replace($tab, "\t", $this->str),
3310 15
            $this->encoding
3311
        );
3312
    }
3313
3314
    /**
3315
     * Converts the first character of each word in the string to uppercase
3316
     * and all other chars to lowercase.
3317
     *
3318
     * @psalm-mutation-free
3319
     *
3320
     * @return static
3321
     *                <p>Object with all characters of $str being title-cased.</p>
3322
     */
3323 15
    public function toTitleCase(): self
3324
    {
3325 15
        return static::create(
3326 15
            $this->utf8::titlecase($this->str, $this->encoding),
3327 15
            $this->encoding
3328
        );
3329
    }
3330
3331
    /**
3332
     * Returns an ASCII version of the string. A set of non-ASCII characters are
3333
     * replaced with their closest ASCII counterparts, and the rest are removed
3334
     * unless instructed otherwise.
3335
     *
3336
     * @param bool   $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl | WARNING: bad
3337
     *                        performance | Default: false</p>
3338
     * @param string $unknown [optional] <p>Character use if character unknown. (default is ?)</p>
3339
     *
3340
     * @psalm-mutation-free
3341
     *
3342
     * @return static
3343
     *                <p>Object whose $str contains only ASCII characters.</p>
3344
     */
3345 34
    public function toTransliterate(bool $strict = false, string $unknown = '?'): self
3346
    {
3347 34
        return static::create(
3348 34
            $this->ascii::to_transliterate($this->str, $unknown, $strict),
3349 34
            $this->encoding
3350
        );
3351
    }
3352
3353
    /**
3354
     * Converts all characters in the string to uppercase.
3355
     *
3356
     * @param bool        $tryToKeepStringLength [optional] <p>true === try to keep the string length: e.g. ẞ -> ß</p>
3357
     * @param string|null $lang                  [optional] <p>Set the language for special cases: az, el, lt, tr</p>
3358
     *
3359
     * @psalm-mutation-free
3360
     *
3361
     * @return static
3362
     *                <p>Object with all characters of $str being uppercase.</p>
3363
     */
3364 20 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...
3365
    {
3366 20
        return static::create(
3367 20
            $this->utf8::strtoupper($this->str, $this->encoding, false, $lang, $tryToKeepStringLength),
3368 20
            $this->encoding
3369
        );
3370
    }
3371
3372
    /**
3373
     * Returns a string with whitespace removed from the start and end of the
3374
     * string. Supports the removal of unicode whitespace. Accepts an optional
3375
     * string of characters to strip instead of the defaults.
3376
     *
3377
     * @param string $chars [optional] <p>String of characters to strip. Default: null</p>
3378
     *
3379
     * @psalm-mutation-free
3380
     *
3381
     * @return static
3382
     *                <p>Object with a trimmed $str.</p>
3383
     */
3384 36
    public function trim(string $chars = null): self
3385
    {
3386 36
        return static::create(
3387 36
            $this->utf8::trim($this->str, $chars),
3388 36
            $this->encoding
3389
        );
3390
    }
3391
3392
    /**
3393
     * Returns a string with whitespace removed from the start of the string.
3394
     * Supports the removal of unicode whitespace. Accepts an optional
3395
     * string of characters to strip instead of the defaults.
3396
     *
3397
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3398
     *
3399
     * @psalm-mutation-free
3400
     *
3401
     * @return static
3402
     *                <p>Object with a trimmed $str.</p>
3403
     */
3404 39
    public function trimLeft(string $chars = null): self
3405
    {
3406 39
        return static::create(
3407 39
            $this->utf8::ltrim($this->str, $chars),
3408 39
            $this->encoding
3409
        );
3410
    }
3411
3412
    /**
3413
     * Returns a string with whitespace removed from the end of the string.
3414
     * Supports the removal of unicode whitespace. Accepts an optional
3415
     * string of characters to strip instead of the defaults.
3416
     *
3417
     * @param string $chars [optional] <p>Optional string of characters to strip. Default: null</p>
3418
     *
3419
     * @psalm-mutation-free
3420
     *
3421
     * @return static
3422
     *                <p>Object with a trimmed $str.</p>
3423
     */
3424 39
    public function trimRight(string $chars = null): self
3425
    {
3426 39
        return static::create(
3427 39
            $this->utf8::rtrim($this->str, $chars),
3428 39
            $this->encoding
3429
        );
3430
    }
3431
3432
    /**
3433
     * Truncates the string to a given length. If $substring is provided, and
3434
     * truncating occurs, the string is further truncated so that the substring
3435
     * may be appended without exceeding the desired length.
3436
     *
3437
     * @param int    $length    <p>Desired length of the truncated string.</p>
3438
     * @param string $substring [optional] <p>The substring to append if it can fit. Default: ''</p>
3439
     *
3440
     * @psalm-mutation-free
3441
     *
3442
     * @return static
3443
     *                <p>Object with the resulting $str after truncating.</p>
3444
     */
3445 66
    public function truncate(int $length, string $substring = ''): self
3446
    {
3447 66
        return static::create(
3448 66
            $this->utf8::str_truncate($this->str, $length, $substring, $this->encoding),
3449 66
            $this->encoding
3450
        );
3451
    }
3452
3453
    /**
3454
     * Returns a lowercase and trimmed string separated by underscores.
3455
     * Underscores are inserted before uppercase characters (with the exception
3456
     * of the first character of the string), and in place of spaces as well as
3457
     * dashes.
3458
     *
3459
     * @psalm-mutation-free
3460
     *
3461
     * @return static
3462
     *                <p>Object with an underscored $str.</p>
3463
     */
3464 48
    public function underscored(): self
3465
    {
3466 48
        return $this->delimit('_');
3467
    }
3468
3469
    /**
3470
     * Returns an UpperCamelCase version of the supplied string. It trims
3471
     * surrounding spaces, capitalizes letters following digits, spaces, dashes
3472
     * and underscores, and removes spaces, dashes, underscores.
3473
     *
3474
     * @psalm-mutation-free
3475
     *
3476
     * @return static
3477
     *                <p>Object with $str in UpperCamelCase.</p>
3478
     */
3479 39
    public function upperCamelize(): self
3480
    {
3481 39
        return static::create(
3482 39
            $this->utf8::str_upper_camelize($this->str, $this->encoding),
3483 39
            $this->encoding
3484
        );
3485
    }
3486
3487
    /**
3488
     * Converts the first character of the supplied string to upper case.
3489
     *
3490
     * @psalm-mutation-free
3491
     *
3492
     * @return static
3493
     *                <p>Object with the first character of $str being upper case.</p>
3494
     */
3495 18
    public function upperCaseFirst(): self
3496
    {
3497 18
        return static::create($this->utf8::ucfirst($this->str, $this->encoding), $this->encoding);
3498
    }
3499
3500
    /**
3501
     * Converts the string into an URL slug. This includes replacing non-ASCII
3502
     * characters with their closest ASCII equivalents, removing remaining
3503
     * non-ASCII and non-alphanumeric characters, and replacing whitespace with
3504
     * $separator. The separator defaults to a single dash, and the string
3505
     * is also converted to lowercase.
3506
     *
3507
     * @param string                $separator    [optional] <p>The string used to replace whitespace. Default: '-'</p>
3508
     * @param string                $language     [optional] <p>The language for the url. Default: 'en'</p>
3509
     * @param array<string, string> $replacements [optional] <p>A map of replaceable strings.</p>
3510
     * @param bool                  $strToLower   [optional] <p>string to lower. Default: true</p>
3511
     *
3512
     * @psalm-mutation-free
3513
     *
3514
     * @return static
3515
     *                <p>Object whose $str has been converted to an URL slug.</p>
3516
     *
3517
     * @psalm-suppress ImpureMethodCall :/
3518
     */
3519 32
    public function urlify(
3520
        string $separator = '-',
3521
        string $language = 'en',
3522
        array $replacements = [],
3523
        bool $strToLower = true
3524
    ): self {
3525
        // init
3526 32
        $str = $this->str;
3527
3528 32
        foreach ($replacements as $from => $to) {
3529 32
            $str = \str_replace($from, $to, $str);
3530
        }
3531
3532 32
        return static::create(
3533 32
            URLify::slug(
3534 32
                $str,
3535 32
                $language,
3536 32
                $separator,
3537 32
                $strToLower
3538
            ),
3539 32
            $this->encoding
3540
        );
3541
    }
3542
3543
    /**
3544
     * Converts the string into an valid UTF-8 string.
3545
     *
3546
     * @psalm-mutation-free
3547
     *
3548
     * @return static
3549
     */
3550 2
    public function utf8ify(): self
3551
    {
3552 2
        return static::create($this->utf8::cleanup($this->str), $this->encoding);
3553
    }
3554
3555
    /**
3556
     * Convert a string into an array of words.
3557
     *
3558
     * @param string   $char_list           <p>Additional chars for the definition of "words".</p>
3559
     * @param bool     $remove_empty_values <p>Remove empty values.</p>
3560
     * @param int|null $remove_short_values <p>The min. string length or null to disable</p>
3561
     *
3562
     * @psalm-mutation-free
3563
     *
3564
     * @return CollectionStringy|static[]
3565
     *
3566
     * @psalm-return CollectionStringy<int,static>
3567
     */
3568 2
    public function words(
3569
        string $char_list = '',
3570
        bool $remove_empty_values = false,
3571
        int $remove_short_values = null
3572
    ): CollectionStringy {
3573
        /**
3574
         * @psalm-suppress ImpureMethodCall -> add more psalm stuff to the collection class
3575
         */
3576 2
        return CollectionStringy::createFromStrings(
3577 2
            $this->utf8::str_to_words(
3578 2
                $this->str,
3579 2
                $char_list,
3580 2
                $remove_empty_values,
3581 2
                $remove_short_values
3582
            )
3583
        );
3584
    }
3585
3586
    /**
3587
     * Surrounds $str with the given substring.
3588
     *
3589
     * @param string $substring <p>The substring to add to both sides.</P>
3590
     *
3591
     * @psalm-mutation-free
3592
     *
3593
     * @return static
3594
     *                <p>Object whose $str had the substring both prepended and appended.</p>
3595
     */
3596 10
    public function wrap(string $substring): self
3597
    {
3598 10
        return $this->surround($substring);
3599
    }
3600
3601
    /**
3602
     * Returns the replacements for the toAscii() method.
3603
     *
3604
     * @noinspection PhpUnused
3605
     *
3606
     * @psalm-mutation-free
3607
     *
3608
     * @return array<string, array<int, string>>
0 ignored issues
show
Documentation introduced by
The doc-type array<string, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
3609
     *                       <p>An array of replacements.</p>
3610
     *
3611
     * @deprecated   this is only here for backward-compatibly reasons
3612
     */
3613 1
    protected function charsArray(): array
3614
    {
3615 1
        return $this->ascii::charsArrayWithMultiLanguageValues();
3616
    }
3617
3618
    /**
3619
     * Returns true if $str matches the supplied pattern, false otherwise.
3620
     *
3621
     * @param string $pattern <p>Regex pattern to match against.</p>
3622
     *
3623
     * @psalm-mutation-free
3624
     *
3625
     * @return bool
3626
     *              <p>Whether or not $str matches the pattern.</p>
3627
     */
3628 24
    protected function matchesPattern(string $pattern): bool
3629
    {
3630 24
        return $this->utf8::str_matches_pattern($this->str, $pattern);
3631
    }
3632
}
3633