Completed
Push — develop ( f11ef2...d41b65 )
by David
06:01 queued 11s
created

ByteString::fromRandom()   B

Complexity

Conditions 10
Paths 7

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 7
nop 2
dl 0
loc 42
rs 7.6666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Symfony\Component\String;
13
14
use Symfony\Component\String\Exception\ExceptionInterface;
15
use Symfony\Component\String\Exception\InvalidArgumentException;
16
use Symfony\Component\String\Exception\RuntimeException;
17
18
/**
19
 * Represents a binary-safe string of bytes.
20
 *
21
 * @author Nicolas Grekas <[email protected]>
22
 * @author Hugo Hamon <[email protected]>
23
 *
24
 * @throws ExceptionInterface
25
 */
26
class ByteString extends AbstractString
27
{
28
    private const ALPHABET_ALPHANUMERIC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
29
30
    public function __construct(string $string = '')
31
    {
32
        $this->string = $string;
33
    }
34
35
    /*
36
     * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03)
37
     *
38
     * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16
39
     *
40
     * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE).
41
     *
42
     * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/)
43
     */
44
45
    public static function fromRandom(int $length = 16, string $alphabet = null): self
46
    {
47
        if ($length <= 0) {
48
            throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length));
49
        }
50
51
        $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC;
52
        $alphabetSize = \strlen($alphabet);
53
        $bits = (int) ceil(log($alphabetSize, 2.0));
54
        if ($bits <= 0 || $bits > 56) {
55
            throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.');
56
        }
57
58
        $ret = '';
59
        while ($length > 0) {
60
            $urandomLength = (int) ceil(2 * $length * $bits / 8.0);
61
            $data = random_bytes($urandomLength);
62
            $unpackedData = 0;
63
            $unpackedBits = 0;
64
            for ($i = 0; $i < $urandomLength && $length > 0; ++$i) {
65
                // Unpack 8 bits
66
                $unpackedData = ($unpackedData << 8) | \ord($data[$i]);
67
                $unpackedBits += 8;
68
69
                // While we have enough bits to select a character from the alphabet, keep
70
                // consuming the random data
71
                for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
72
                    $index = ($unpackedData & ((1 << $bits) - 1));
73
                    $unpackedData >>= $bits;
74
                    // Unfortunately, the alphabet size is not necessarily a power of two.
75
                    // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
76
                    // have around a 50% chance of missing as k gets larger
77
                    if ($index < $alphabetSize) {
78
                        $ret .= $alphabet[$index];
79
                        --$length;
80
                    }
81
                }
82
            }
83
        }
84
85
        return new static($ret);
86
    }
87
88
    public function bytesAt(int $offset): array
89
    {
90
        $str = $this->string[$offset] ?? '';
91
92
        return '' === $str ? [] : [\ord($str)];
93
    }
94
95
    public function append(string ...$suffix): parent
96
    {
97
        $str = clone $this;
98
        $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix);
99
100
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::append of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
101
    }
102
103
    public function camel(): parent
104
    {
105
        $str = clone $this;
106
        $str->string = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string))));
107
108
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::camel of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
109
    }
110
111
    public function chunk(int $length = 1): array
112
    {
113
        if (1 > $length) {
114
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
115
        }
116
117
        if ('' === $this->string) {
118
            return [];
119
        }
120
121
        $str = clone $this;
122
        $chunks = [];
123
124
        foreach (str_split($this->string, $length) as $chunk) {
125
            $str->string = $chunk;
126
            $chunks[] = clone $str;
127
        }
128
129
        return $chunks;
130
    }
131
132
    public function endsWith($suffix): bool
133
    {
134
        if ($suffix instanceof parent) {
135
            $suffix = $suffix->string;
136
        } elseif (\is_array($suffix) || $suffix instanceof \Traversable) {
137
            return parent::endsWith($suffix);
0 ignored issues
show
Documentation introduced by
$suffix is of type array|object<Traversable>, but the function expects a string|array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
138
        } else {
139
            $suffix = (string) $suffix;
140
        }
141
142
        return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase);
143
    }
144
145
    public function equalsTo($string): bool
146
    {
147
        if ($string instanceof parent) {
148
            $string = $string->string;
149
        } elseif (\is_array($string) || $string instanceof \Traversable) {
150
            return parent::equalsTo($string);
0 ignored issues
show
Documentation introduced by
$string is of type array|object<Traversable>, but the function expects a string|array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
151
        } else {
152
            $string = (string) $string;
153
        }
154
155
        if ('' !== $string && $this->ignoreCase) {
156
            return 0 === strcasecmp($string, $this->string);
157
        }
158
159
        return $string === $this->string;
160
    }
161
162
    public function folded(): parent
163
    {
164
        $str = clone $this;
165
        $str->string = strtolower($str->string);
166
167
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::folded of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
168
    }
169
170
    public function indexOf($needle, int $offset = 0): ?int
171
    {
172
        if ($needle instanceof parent) {
173
            $needle = $needle->string;
174
        } elseif (\is_array($needle) || $needle instanceof \Traversable) {
175
            return parent::indexOf($needle, $offset);
0 ignored issues
show
Documentation introduced by
$needle is of type array|object<Traversable>, but the function expects a string|array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
        } else {
177
            $needle = (string) $needle;
178
        }
179
180
        if ('' === $needle) {
181
            return null;
182
        }
183
184
        $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset);
185
186
        return false === $i ? null : $i;
187
    }
188
189
    public function indexOfLast($needle, int $offset = 0): ?int
190
    {
191
        if ($needle instanceof parent) {
192
            $needle = $needle->string;
193
        } elseif (\is_array($needle) || $needle instanceof \Traversable) {
194
            return parent::indexOfLast($needle, $offset);
0 ignored issues
show
Documentation introduced by
$needle is of type array|object<Traversable>, but the function expects a string|array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195
        } else {
196
            $needle = (string) $needle;
197
        }
198
199
        if ('' === $needle) {
200
            return null;
201
        }
202
203
        $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset);
204
205
        return false === $i ? null : $i;
206
    }
207
208
    public function isUtf8(): bool
209
    {
210
        return '' === $this->string || preg_match('//u', $this->string);
211
    }
212
213
    public function join(array $strings, string $lastGlue = null): parent
214
    {
215
        $str = clone $this;
216
217
        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : '';
218
        $str->string = implode($this->string, $strings).$tail;
219
220
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::join of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
221
    }
222
223
    public function length(): int
224
    {
225
        return \strlen($this->string);
226
    }
227
228
    public function lower(): parent
229
    {
230
        $str = clone $this;
231
        $str->string = strtolower($str->string);
232
233
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::lower of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
234
    }
235
236
    public function match(string $regexp, int $flags = 0, int $offset = 0): array
237
    {
238
        $match = ((PREG_PATTERN_ORDER | PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match';
239
240
        if ($this->ignoreCase) {
241
            $regexp .= 'i';
242
        }
243
244
        set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); });
245
246
        try {
247
            if (false === $match($regexp, $this->string, $matches, $flags | PREG_UNMATCHED_AS_NULL, $offset)) {
0 ignored issues
show
Bug introduced by
The variable $matches does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
248
                $lastError = preg_last_error();
249
250
                foreach (get_defined_constants(true)['pcre'] as $k => $v) {
251
                    if ($lastError === $v && '_ERROR' === substr($k, -6)) {
252
                        throw new RuntimeException('Matching failed with '.$k.'.');
253
                    }
254
                }
255
256
                throw new RuntimeException('Matching failed with unknown error code.');
257
            }
258
        } finally {
259
            restore_error_handler();
260
        }
261
262
        return $matches;
263
    }
264
265
    public function padBoth(int $length, string $padStr = ' '): parent
266
    {
267
        $str = clone $this;
268
        $str->string = str_pad($this->string, $length, $padStr, STR_PAD_BOTH);
269
270
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::padBoth of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
271
    }
272
273
    public function padEnd(int $length, string $padStr = ' '): parent
274
    {
275
        $str = clone $this;
276
        $str->string = str_pad($this->string, $length, $padStr, STR_PAD_RIGHT);
277
278
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::padEnd of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
279
    }
280
281
    public function padStart(int $length, string $padStr = ' '): parent
282
    {
283
        $str = clone $this;
284
        $str->string = str_pad($this->string, $length, $padStr, STR_PAD_LEFT);
285
286
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::padStart of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
287
    }
288
289
    public function prepend(string ...$prefix): parent
290
    {
291
        $str = clone $this;
292
        $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string;
293
294
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::prepend of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
295
    }
296
297
    public function replace(string $from, string $to): parent
298
    {
299
        $str = clone $this;
300
301
        if ('' !== $from) {
302
            $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string);
303
        }
304
305
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::replace of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
306
    }
307
308
    public function replaceMatches(string $fromRegexp, $to): parent
309
    {
310
        if ($this->ignoreCase) {
311
            $fromRegexp .= 'i';
312
        }
313
314
        if (\is_array($to)) {
315
            if (!\is_callable($to)) {
316
                throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class));
317
            }
318
319
            $replace = 'preg_replace_callback';
320
        } else {
321
            $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace';
322
        }
323
324
        set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); });
325
326
        try {
327
            if (null === $string = $replace($fromRegexp, $to, $this->string)) {
328
                $lastError = preg_last_error();
329
330
                foreach (get_defined_constants(true)['pcre'] as $k => $v) {
331
                    if ($lastError === $v && '_ERROR' === substr($k, -6)) {
332
                        throw new RuntimeException('Matching failed with '.$k.'.');
333
                    }
334
                }
335
336
                throw new RuntimeException('Matching failed with unknown error code.');
337
            }
338
        } finally {
339
            restore_error_handler();
340
        }
341
342
        $str = clone $this;
343
        $str->string = $string;
344
345
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String...tString::replaceMatches of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
346
    }
347
348
    public function reverse(): parent
349
    {
350
        $str = clone $this;
351
        $str->string = strrev($str->string);
352
353
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::reverse of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
354
    }
355
356
    public function slice(int $start = 0, int $length = null): parent
357
    {
358
        $str = clone $this;
359
        $str->string = (string) substr($this->string, $start, $length ?? PHP_INT_MAX);
360
361
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::slice of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
362
    }
363
364
    public function snake(): parent
365
    {
366
        $str = $this->camel()->title();
367
        $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string));
368
369
        return $str;
370
    }
371
372
    public function splice(string $replacement, int $start = 0, int $length = null): parent
373
    {
374
        $str = clone $this;
375
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? PHP_INT_MAX);
376
377
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::splice of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
378
    }
379
380
    public function split(string $delimiter, int $limit = null, int $flags = null): array
381
    {
382
        if (1 > $limit = $limit ?? PHP_INT_MAX) {
383
            throw new InvalidArgumentException('Split limit must be a positive integer.');
384
        }
385
386
        if ('' === $delimiter) {
387
            throw new InvalidArgumentException('Split delimiter is empty.');
388
        }
389
390
        if (null !== $flags) {
391
            return parent::split($delimiter, $limit, $flags);
392
        }
393
394
        $str = clone $this;
395
        $chunks = $this->ignoreCase
396
            ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit)
397
            : explode($delimiter, $this->string, $limit);
398
399
        foreach ($chunks as &$chunk) {
400
            $str->string = $chunk;
401
            $chunk = clone $str;
402
        }
403
404
        return $chunks;
405
    }
406
407
    public function startsWith($prefix): bool
408
    {
409
        if ($prefix instanceof parent) {
410
            $prefix = $prefix->string;
411
        } elseif (!\is_string($prefix)) {
412
            return parent::startsWith($prefix);
413
        }
414
415
        return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix)));
416
    }
417
418
    public function title(bool $allWords = false): parent
419
    {
420
        $str = clone $this;
421
        $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string);
422
423
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::title of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
424
    }
425
426
    public function toUnicodeString(string $fromEncoding = null): UnicodeString
427
    {
428
        return new UnicodeString($this->toCodePointString($fromEncoding)->string);
0 ignored issues
show
Bug introduced by
The property string cannot be accessed from this context as it is declared protected in class Symfony\Component\String\AbstractString.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
429
    }
430
431
    public function toCodePointString(string $fromEncoding = null): CodePointString
432
    {
433
        $u = new CodePointString();
434
435
        if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) {
436
            $u->string = $this->string;
0 ignored issues
show
Bug introduced by
The property string cannot be accessed from this context as it is declared protected in class Symfony\Component\String\AbstractString.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
437
438
            return $u;
439
        }
440
441
        set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); });
442
443
        try {
444
            try {
445
                $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true);
446
            } catch (InvalidArgumentException $e) {
447
                if (!\function_exists('iconv')) {
448
                    throw $e;
449
                }
450
451
                $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string);
0 ignored issues
show
Bug introduced by
The property string cannot be accessed from this context as it is declared protected in class Symfony\Component\String\AbstractString.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
452
453
                return $u;
454
            }
455
        } finally {
456
            restore_error_handler();
457
        }
458
459
        if (!$validEncoding) {
460
            throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
461
        }
462
463
        $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');
0 ignored issues
show
Bug introduced by
The property string cannot be accessed from this context as it is declared protected in class Symfony\Component\String\AbstractString.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
464
465
        return $u;
466
    }
467
468
    public function trim(string $chars = " \t\n\r\0\x0B\x0C"): parent
469
    {
470
        $str = clone $this;
471
        $str->string = trim($str->string, $chars);
472
473
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::trim of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
474
    }
475
476
    public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): parent
477
    {
478
        $str = clone $this;
479
        $str->string = rtrim($str->string, $chars);
480
481
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::trimEnd of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
482
    }
483
484
    public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): parent
485
    {
486
        $str = clone $this;
487
        $str->string = ltrim($str->string, $chars);
488
489
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::trimStart of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
490
    }
491
492
    public function upper(): parent
493
    {
494
        $str = clone $this;
495
        $str->string = strtoupper($str->string);
496
497
        return $str;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $str; (Symfony\Component\String\ByteString) is incompatible with the return type declared by the abstract method Symfony\Component\String\AbstractString::upper of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
498
    }
499
500
    public function width(bool $ignoreAnsiDecoration = true): int
501
    {
502
        $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string);
503
504
        return (new CodePointString($string))->width($ignoreAnsiDecoration);
505
    }
506
}
507