GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 3e245c...e1384c )
by Baptiste
02:13
created

Str::usesDefaultEncoding()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable;
5
6
use Innmind\Immutable\Exception\RegexException;
7
use Innmind\Immutable\Exception\SubstringException;
8
9
class Str implements PrimitiveInterface, StringableInterface
10
{
11
    const PAD_RIGHT = STR_PAD_RIGHT;
12
    const PAD_LEFT = STR_PAD_LEFT;
13
    const PAD_BOTH = STR_PAD_BOTH;
14
    const PREG_NO_FLAGS = 0;
15
    const PREG_SPLIT_NO_EMPTY = PREG_SPLIT_NO_EMPTY;
16
    const PREG_SPLIT_DELIM_CAPTURE = PREG_SPLIT_DELIM_CAPTURE;
17
    const PREG_SPLIT_OFFSET_CAPTURE = PREG_SPLIT_OFFSET_CAPTURE;
18
    const PREG_OFFSET_CAPTURE = PREG_OFFSET_CAPTURE;
19
20
    private $value;
21
    private $encoding;
22
23 312
    public function __construct(string $value, string $encoding = null)
24
    {
25 312
        $this->value = $value;
26 312
        $this->encoding = $encoding ?? mb_internal_encoding();
27 312
    }
28
29
    /**
30
     * {@inheritdoc}
31
     */
32 2
    public function toPrimitive()
33
    {
34 2
        return $this->value;
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 204
    public function __toString(): string
41
    {
42 204
        return $this->value;
43
    }
44
45 4
    public function encoding(): self
46
    {
47 4
        return new self($this->encoding);
48
    }
49
50 30
    public function toEncoding(string $encoding): self
51
    {
52 30
        return new self($this->value, $encoding);
53
    }
54
55
    /**
56
     * Split the string into a collection of ones
57
     *
58
     * @param string $delimiter
59
     *
60
     * @return StreamInterface<self>
0 ignored issues
show
Documentation introduced by
The doc-type StreamInterface<self> could not be parsed: Expected "|" or "end of type", but got "<" at position 15. (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...
61
     */
62 14
    public function split(string $delimiter = null): StreamInterface
63
    {
64 14
        if (is_null($delimiter) || $delimiter === '') {
65 6
            return $this->chunk();
66
        }
67
68 10
        $parts = explode($delimiter, $this->value);
69 10
        $stream = new Stream(self::class);
70
71 10
        foreach ($parts as $part) {
72 10
            $stream = $stream->add(new self($part, $this->encoding));
73
        }
74
75 10
        return $stream;
76
    }
77
78
    /**
79
     * Returns a collection of the string splitted by the given chunk size
80
     *
81
     * @param int $size
82
     *
83
     * @return StreamInterface<self>
0 ignored issues
show
Documentation introduced by
The doc-type StreamInterface<self> could not be parsed: Expected "|" or "end of type", but got "<" at position 15. (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...
84
     */
85 14
    public function chunk(int $size = 1): StreamInterface
86
    {
87 14
        $stream = new Stream(self::class);
88 14
        $string = $this;
89
90 14
        while ($string->length() > 0) {
91 14
            $stream = $stream->add($string->substring(0, $size));
92 14
            $string = $string->substring($size);
93
        }
94
95 14
        return $stream;
96
    }
97
98
    /**
99
     * Returns the position of the first occurence of the string
100
     *
101
     * @param string $needle
102
     * @param int $offset
103
     *
104
     * @throws SubstringException If the string is not found
105
     *
106
     * @return int
107
     */
108 12
    public function position(string $needle, int $offset = 0): int
109
    {
110 12
        $position = mb_strpos($this->value, $needle, $offset, $this->encoding);
111
112 12
        if ($position === false) {
113 6
            throw new SubstringException(sprintf(
114 6
                'Substring "%s" not found',
115 6
                $needle
116
            ));
117
        }
118
119 10
        return (int) $position;
120
    }
121
122
    /**
123
     * Replace all occurences of the search string with the replacement one
124
     *
125
     * @param string $search
126
     * @param string $replacement
127
     *
128
     * @return self
129
     */
130 4
    public function replace(string $search, string $replacement): self
131
    {
132 4
        if (!$this->contains($search)) {
133 2
            return $this;
134
        }
135
136
        return $this
137 4
            ->split($search)
138 4
            ->join($replacement);
139
    }
140
141
    /**
142
     * Returns the string following the given delimiter
143
     *
144
     * @param string $delimiter
145
     *
146
     * @throws SubstringException If the string is not found
147
     *
148
     * @return self
149
     */
150 6
    public function str(string $delimiter): self
151
    {
152 6
        $sub = mb_strstr($this->value, $delimiter, false, $this->encoding);
153
154 6
        if ($sub === false) {
155 2
            throw new SubstringException(sprintf(
156 2
                'Substring "%s" not found',
157 2
                $delimiter
158
            ));
159
        }
160
161 4
        return new self($sub, $this->encoding);
162
    }
163
164
    /**
165
     * Return the string in upper case
166
     *
167
     * @return self
168
     */
169 6
    public function toUpper(): self
170
    {
171 6
        return new self(mb_strtoupper($this->value), $this->encoding);
172
    }
173
174
    /**
175
     * Return the string in lower case
176
     *
177
     * @return self
178
     */
179 4
    public function toLower(): self
180
    {
181 4
        return new self(mb_strtolower($this->value), $this->encoding);
182
    }
183
184
    /**
185
     * Return the string length
186
     *
187
     * @return int
188
     */
189 28
    public function length(): int
190
    {
191 28
        return mb_strlen($this->value, $this->encoding);
192
    }
193
194
    /**
195
     * Reverse the string
196
     *
197
     * @return self
198
     */
199 2
    public function reverse(): self
200
    {
201
        return $this
202 2
            ->chunk()
203 2
            ->reverse()
204 2
            ->join('');
205
    }
206
207
    /**
208
     * Pad to the right
209
     *
210
     * @param int $length
211
     * @param string $character
212
     *
213
     * @return self
214
     */
215 2
    public function rightPad(int $length, string $character = ' '): self
216
    {
217 2
        return $this->pad($length, $character, self::PAD_RIGHT);
218
    }
219
220
    /**
221
     * Pad to the left
222
     *
223
     * @param int $length
224
     * @param string $character
225
     *
226
     * @return self
227
     */
228 2
    public function leftPad(int $length, string $character = ' '): self
229
    {
230 2
        return $this->pad($length, $character, self::PAD_LEFT);
231
    }
232
233
    /**
234
     * Pad both sides
235
     *
236
     * @param int $length
237
     * @param string $character
238
     *
239
     * @return self
240
     */
241 2
    public function uniPad(int $length, string $character = ' '): self
242
    {
243 2
        return $this->pad($length, $character, self::PAD_BOTH);
244
    }
245
246
    /**
247
     * Find length of initial segment not matching mask
248
     *
249
     * @param string $mask
250
     * @param int $start
251
     * @param int $length
252
     *
253
     * @return int
254
     */
255 2
    public function cspn(string $mask, int $start = 0, int $length = null): int
256
    {
257 2
        if ($length === null) {
258 2
            $value = strcspn($this->value, $mask, $start);
259
        } else {
260 2
            $value = strcspn(
261 2
                $this->value,
262 2
                $mask,
263 2
                $start,
264 2
                $length
265
            );
266
        }
267
268 2
        return (int) $value;
269
    }
270
271
    /**
272
     * Repeat the string n times
273
     *
274
     * @param int $repeat
275
     *
276
     * @return self
277
     */
278 2
    public function repeat(int $repeat): self
279
    {
280 2
        return new self(str_repeat($this->value, $repeat), $this->encoding);
281
    }
282
283
    /**
284
     * Shuffle the string
285
     *
286
     * @return self
287
     */
288 4
    public function shuffle(): self
289
    {
290 4
        $parts = $this->chunk()->toPrimitive();
291 4
        shuffle($parts);
292
293 4
        return new self(implode('', $parts), $this->encoding);
294
    }
295
296
    /**
297
     * Strip slashes
298
     *
299
     * @return self
300
     */
301 2
    public function stripSlashes(): self
302
    {
303 2
        return new self(stripslashes($this->value), $this->encoding);
304
    }
305
306
    /**
307
     * Strip C-like slashes
308
     *
309
     * @return self
310
     */
311 2
    public function stripCSlashes(): self
312
    {
313 2
        return new self(stripcslashes($this->value), $this->encoding);
314
    }
315
316
    /**
317
     * Return the word count
318
     *
319
     * @param string $charlist
320
     *
321
     * @return int
322
     */
323 2
    public function wordCount(string $charlist = ''): int
324
    {
325 2
        return (int) str_word_count(
326 2
            $this->value,
327 2
            0,
328 2
            $charlist
329
        );
330
    }
331
332
    /**
333
     * Return the collection of words
334
     *
335
     * @param string $charlist
336
     *
337
     * @return MapInterface<int, self>
0 ignored issues
show
Documentation introduced by
The doc-type MapInterface<int, could not be parsed: Expected "|" or "end of type", but got "<" at position 12. (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...
338
     */
339 2 View Code Duplication
    public function words(string $charlist = ''): MapInterface
340
    {
341 2
        $words = str_word_count($this->value, 2, $charlist);
342 2
        $map = new Map('int', self::class);
343
344 2
        foreach ($words as $position => $word) {
345 2
            $map = $map->put($position, new self($word, $this->encoding));
346
        }
347
348 2
        return $map;
349
    }
350
351
    /**
352
     * Split the string using a regular expression
353
     *
354
     * @param string $regex
355
     * @param int $limit
356
     *
357
     * @return StreamInterface<self>
0 ignored issues
show
Documentation introduced by
The doc-type StreamInterface<self> could not be parsed: Expected "|" or "end of type", but got "<" at position 15. (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...
358
     */
359 4 View Code Duplication
    public function pregSplit(string $regex, int $limit = -1): StreamInterface
360
    {
361 4
        $strings = preg_split($regex, $this->value, $limit);
362 4
        $stream = new Stream(self::class);
363
364 4
        foreach ($strings as $string) {
365 4
            $stream = $stream->add(new self($string, $this->encoding));
366
        }
367
368 4
        return $stream;
369
    }
370
371
    /**
372
     * Check if the string match the given regular expression
373
     *
374
     * @param string $regex
375
     * @param int $offset
376
     *
377
     * @throws Exception If the regex failed
378
     *
379
     * @return bool
380
     */
381 4
    public function matches(string $regex, int $offset = 0): bool
382
    {
383 4
        $matches = [];
384 4
        $value = preg_match($regex, $this->value, $matches, 0, $offset);
385
386 4
        if ($value === false) {
387 2
            throw new RegexException('', preg_last_error());
388
        }
389
390 2
        return (bool) $value;
391
    }
392
393
    /**
394
     * Return a collection of the elements matching the regex
395
     *
396
     * @deprecated replaced by self::capture, to be removed in 3.0
397
     *
398
     * @param string $regex
399
     * @param int $offset
400
     * @param int $flags
401
     *
402
     * @throws Exception If the regex failed
403
     *
404
     * @return MapInterface<scalar, self>
0 ignored issues
show
Documentation introduced by
The doc-type MapInterface<scalar, could not be parsed: Expected "|" or "end of type", but got "<" at position 12. (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...
405
     */
406 2
    public function getMatches(
407
        string $regex,
408
        int $offset = 0,
409
        int $flags = self::PREG_NO_FLAGS
410
    ): MapInterface {
411 2
        return $this->capture($regex, $offset, $flags);
412
    }
413
414
    /**
415
     * Return a collection of the elements matching the regex
416
     *
417
     * @param string $regex
418
     * @param int $offset
419
     * @param int $flags
420
     *
421
     * @throws Exception If the regex failed
422
     *
423
     * @return MapInterface<scalar, self>
0 ignored issues
show
Documentation introduced by
The doc-type MapInterface<scalar, could not be parsed: Expected "|" or "end of type", but got "<" at position 12. (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...
424
     */
425 6
    public function capture(
426
        string $regex,
427
        int $offset = 0,
428
        int $flags = self::PREG_NO_FLAGS
429
    ): MapInterface {
430 6
        $matches = [];
431 6
        $value = preg_match(
432 6
            $regex,
433 6
            $this->value,
434 6
            $matches,
435 6
            $flags,
436 6
            $offset
437
        );
438 6
        $map = new Map('scalar', self::class);
439
440 6
        foreach ($matches as $key => $match) {
441 4
            $map = $map->put($key, new self((string) $match, $this->encoding));
442
        }
443
444 6
        if ($value === false) {
445 2
            throw new RegexException('', preg_last_error());
446
        }
447
448 4
        return $map;
449
    }
450
451
    /**
452
     * Replace part of the string by using a regular expression
453
     *
454
     * @param string $regex
455
     * @param string $replacement
456
     * @param int $limit
457
     *
458
     * @throws Exception If the regex failed
459
     *
460
     * @return self
461
     */
462 2
    public function pregReplace(
463
        string $regex,
464
        string $replacement,
465
        int $limit = -1
466
    ): self {
467 2
        $value = preg_replace(
468 2
            $regex,
469 2
            $replacement,
470 2
            $this->value,
471 2
            $limit
472
        );
473
474 2
        if ($value === null) {
475
            throw new RegexException('', preg_last_error());
476
        }
477
478 2
        return new self($value, $this->encoding);
479
    }
480
481
    /**
482
     * Return part of the string
483
     *
484
     * @param int $start
485
     * @param int $length
486
     *
487
     * @return self
488
     */
489 24
    public function substring(int $start, int $length = null): self
490
    {
491 24
        if ($this->length() === 0) {
492 2
            return $this;
493
        }
494
495 24
        $sub = mb_substr($this->value, $start, $length, $this->encoding);
496
497 24
        return new self($sub, $this->encoding);
498
    }
499
500
    /**
501
     * Return a formatted string
502
     *
503
     * @return self
504
     */
505 2
    public function sprintf(...$values): self
506
    {
507 2
        return new self(sprintf($this->value, ...$values), $this->encoding);
508
    }
509
510
    /**
511
     * Return the string with the first letter as uppercase
512
     *
513
     * @return self
514
     */
515 4
    public function ucfirst(): self
516
    {
517
        return $this
518 4
            ->substring(0, 1)
519 4
            ->toUpper()
520 4
            ->append((string) $this->substring(1));
521
    }
522
523
    /**
524
     * Return the string with the first letter as lowercase
525
     *
526
     * @return self
527
     */
528 2
    public function lcfirst(): self
529
    {
530
        return $this
531 2
            ->substring(0, 1)
532 2
            ->toLower()
533 2
            ->append((string) $this->substring(1));
534
    }
535
536
    /**
537
     * Return a CamelCase representation of the string
538
     *
539
     * @return self
540
     */
541 2
    public function camelize(): self
542
    {
543
        return $this
544 2
            ->pregSplit('/_| /')
545 2
            ->map(function(self $part) {
546 2
                return $part->ucfirst();
547 2
            })
548 2
            ->join('')
549 2
            ->toEncoding($this->encoding);
550
    }
551
552
    /**
553
     * Append a string at the end of the current one
554
     *
555
     * @param string $string
556
     *
557
     * @return self
558
     */
559 8
    public function append(string $string): self
560
    {
561 8
        return new self((string) $this.$string, $this->encoding);
562
    }
563
564
    /**
565
     * Prepend a string at the beginning of the current one
566
     *
567
     * @param string $string
568
     *
569
     * @return self
570
     */
571 2
    public function prepend(string $string): self
572
    {
573 2
        return new self($string.(string) $this, $this->encoding);
574
    }
575
576
    /**
577
     * Check if the 2 strings are equal
578
     *
579
     * @param self $string
580
     *
581
     * @return bool
582
     */
583 56
    public function equals(self $string): bool
584
    {
585 56
        return (string) $this === (string) $string;
586
    }
587
588
    /**
589
     * Trim the string
590
     *
591
     * @param string $mask
592
     *
593
     * @return self
594
     */
595 2 View Code Duplication
    public function trim(string $mask = null): self
596
    {
597 2
        return new self(
598 2
            $mask === null ? trim((string) $this) : trim((string) $this, $mask),
599 2
            $this->encoding
600
        );
601
    }
602
603
    /**
604
     * Trim the right side of the string
605
     *
606
     * @param string $mask
607
     *
608
     * @return self
609
     */
610 2 View Code Duplication
    public function rightTrim(string $mask = null): self
611
    {
612 2
        return new self(
613 2
            $mask === null ? rtrim((string) $this) : rtrim((string) $this, $mask),
614 2
            $this->encoding
615
        );
616
    }
617
618
    /**
619
     * Trim the left side of the string
620
     *
621
     * @param string $mask
622
     *
623
     * @return self
624
     */
625 2 View Code Duplication
    public function leftTrim(string $mask = null): self
626
    {
627 2
        return new self(
628 2
            $mask === null ? ltrim((string) $this) : ltrim((string) $this, $mask),
629 2
            $this->encoding
630
        );
631
    }
632
633
    /**
634
     * Check if the given string is present in the current one
635
     *
636
     * @param string $value
637
     *
638
     * @return bool
639
     */
640 6
    public function contains(string $value): bool
641
    {
642
        try {
643 6
            $this->position($value);
644
645 6
            return true;
646 4
        } catch (SubstringException $e) {
647 4
            return false;
648
        }
649
    }
650
651
    /**
652
     * Quote regular expression characters
653
     *
654
     * @param string $delimiter
655
     *
656
     * @return self
657
     */
658 2
    public function pregQuote(string $delimiter = ''): self
659
    {
660 2
        return new self(preg_quote((string) $this, $delimiter), $this->encoding);
661
    }
662
663
    /**
664
     * Pad the string
665
     *
666
     * @param int $length
667
     * @param string $character
668
     * @param int $direction
669
     *
670
     * @return self
671
     */
672 2
    private function pad(
673
        int $length,
674
        string $character = ' ',
675
        int $direction = self::PAD_RIGHT
676
    ): self {
677 2
        return new self(str_pad(
678 2
            $this->value,
679 2
            $length,
680 2
            $character,
681 2
            $direction
682 2
        ), $this->encoding);
683
    }
684
}
685