@@ -25,14 +25,14 @@ discard block |
||
25 | 25 | */ |
26 | 26 | class ByteString extends AbstractString |
27 | 27 | { |
28 | - private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; |
|
28 | + private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; |
|
29 | 29 | |
30 | - public function __construct(string $string = '') |
|
31 | - { |
|
32 | - $this->string = $string; |
|
33 | - } |
|
30 | + public function __construct(string $string = '') |
|
31 | + { |
|
32 | + $this->string = $string; |
|
33 | + } |
|
34 | 34 | |
35 | - /* |
|
35 | + /* |
|
36 | 36 | * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) |
37 | 37 | * |
38 | 38 | * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 |
@@ -42,465 +42,465 @@ discard block |
||
42 | 42 | * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) |
43 | 43 | */ |
44 | 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; |
|
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; |
|
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); |
|
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); |
|
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; |
|
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); |
|
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); |
|
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; |
|
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; |
|
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)) { |
|
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; |
|
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; |
|
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; |
|
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; |
|
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; |
|
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; |
|
346 | - } |
|
347 | - |
|
348 | - public function reverse(): parent |
|
349 | - { |
|
350 | - $str = clone $this; |
|
351 | - $str->string = strrev($str->string); |
|
352 | - |
|
353 | - return $str; |
|
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; |
|
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; |
|
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; |
|
424 | - } |
|
425 | - |
|
426 | - public function toUnicodeString(string $fromEncoding = null): UnicodeString |
|
427 | - { |
|
428 | - return new UnicodeString($this->toCodePointString($fromEncoding)->string); |
|
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; |
|
437 | - |
|
438 | - return $u; |
|
439 | - } |
|
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; |
|
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; |
|
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); |
|
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); |
|
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; |
|
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); |
|
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); |
|
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; |
|
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; |
|
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)) { |
|
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; |
|
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; |
|
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; |
|
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; |
|
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; |
|
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; |
|
346 | + } |
|
347 | + |
|
348 | + public function reverse(): parent |
|
349 | + { |
|
350 | + $str = clone $this; |
|
351 | + $str->string = strrev($str->string); |
|
352 | + |
|
353 | + return $str; |
|
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; |
|
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; |
|
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; |
|
424 | + } |
|
425 | + |
|
426 | + public function toUnicodeString(string $fromEncoding = null): UnicodeString |
|
427 | + { |
|
428 | + return new UnicodeString($this->toCodePointString($fromEncoding)->string); |
|
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; |
|
437 | + |
|
438 | + return $u; |
|
439 | + } |
|
440 | 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); |
|
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); |
|
452 | 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'); |
|
464 | - |
|
465 | - return $u; |
|
466 | - } |
|
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'); |
|
464 | + |
|
465 | + return $u; |
|
466 | + } |
|
467 | 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; |
|
474 | - } |
|
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; |
|
474 | + } |
|
475 | 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; |
|
482 | - } |
|
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; |
|
482 | + } |
|
483 | 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); |
|
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 | 488 | |
489 | - return $str; |
|
490 | - } |
|
489 | + return $str; |
|
490 | + } |
|
491 | 491 | |
492 | - public function upper(): parent |
|
493 | - { |
|
494 | - $str = clone $this; |
|
495 | - $str->string = strtoupper($str->string); |
|
492 | + public function upper(): parent |
|
493 | + { |
|
494 | + $str = clone $this; |
|
495 | + $str->string = strtoupper($str->string); |
|
496 | 496 | |
497 | - return $str; |
|
498 | - } |
|
497 | + return $str; |
|
498 | + } |
|
499 | 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); |
|
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 | 503 | |
504 | - return (new CodePointString($string))->width($ignoreAnsiDecoration); |
|
505 | - } |
|
504 | + return (new CodePointString($string))->width($ignoreAnsiDecoration); |
|
505 | + } |
|
506 | 506 | } |
@@ -27,7 +27,7 @@ discard block |
||
27 | 27 | { |
28 | 28 | private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; |
29 | 29 | |
30 | - public function __construct(string $string = '') |
|
30 | + public function __construct( string $string = '' ) |
|
31 | 31 | { |
32 | 32 | $this->string = $string; |
33 | 33 | } |
@@ -42,60 +42,60 @@ discard block |
||
42 | 42 | * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) |
43 | 43 | */ |
44 | 44 | |
45 | - public static function fromRandom(int $length = 16, string $alphabet = null): self |
|
45 | + public static function fromRandom( int $length = 16, string $alphabet = null ): self |
|
46 | 46 | { |
47 | - if ($length <= 0) { |
|
48 | - throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length)); |
|
47 | + if ( $length <= 0 ) { |
|
48 | + throw new InvalidArgumentException( sprintf( 'A strictly positive length is expected, "%d" given.', $length ) ); |
|
49 | 49 | } |
50 | 50 | |
51 | 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.'); |
|
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 | 56 | } |
57 | 57 | |
58 | 58 | $ret = ''; |
59 | - while ($length > 0) { |
|
60 | - $urandomLength = (int) ceil(2 * $length * $bits / 8.0); |
|
61 | - $data = random_bytes($urandomLength); |
|
59 | + while ( $length > 0 ) { |
|
60 | + $urandomLength = (int)ceil( 2 * $length * $bits / 8.0 ); |
|
61 | + $data = random_bytes( $urandomLength ); |
|
62 | 62 | $unpackedData = 0; |
63 | 63 | $unpackedBits = 0; |
64 | - for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { |
|
64 | + for ( $i = 0; $i < $urandomLength && $length > 0; ++$i ) { |
|
65 | 65 | // Unpack 8 bits |
66 | - $unpackedData = ($unpackedData << 8) | \ord($data[$i]); |
|
66 | + $unpackedData = ( $unpackedData << 8 ) | \ord( $data[ $i ] ); |
|
67 | 67 | $unpackedBits += 8; |
68 | 68 | |
69 | 69 | // While we have enough bits to select a character from the alphabet, keep |
70 | 70 | // consuming the random data |
71 | - for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { |
|
72 | - $index = ($unpackedData & ((1 << $bits) - 1)); |
|
71 | + for ( ; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits ) { |
|
72 | + $index = ( $unpackedData & ( ( 1 << $bits ) - 1 ) ); |
|
73 | 73 | $unpackedData >>= $bits; |
74 | 74 | // Unfortunately, the alphabet size is not necessarily a power of two. |
75 | 75 | // Worst case, it is 2^k + 1, which means we need (k+1) bits and we |
76 | 76 | // have around a 50% chance of missing as k gets larger |
77 | - if ($index < $alphabetSize) { |
|
78 | - $ret .= $alphabet[$index]; |
|
77 | + if ( $index < $alphabetSize ) { |
|
78 | + $ret .= $alphabet[ $index ]; |
|
79 | 79 | --$length; |
80 | 80 | } |
81 | 81 | } |
82 | 82 | } |
83 | 83 | } |
84 | 84 | |
85 | - return new static($ret); |
|
85 | + return new static( $ret ); |
|
86 | 86 | } |
87 | 87 | |
88 | - public function bytesAt(int $offset): array |
|
88 | + public function bytesAt( int $offset ): array |
|
89 | 89 | { |
90 | - $str = $this->string[$offset] ?? ''; |
|
90 | + $str = $this->string[ $offset ] ?? ''; |
|
91 | 91 | |
92 | - return '' === $str ? [] : [\ord($str)]; |
|
92 | + return '' === $str ? [ ] : [ \ord( $str ) ]; |
|
93 | 93 | } |
94 | 94 | |
95 | - public function append(string ...$suffix): parent |
|
95 | + public function append( string ...$suffix ): parent |
|
96 | 96 | { |
97 | 97 | $str = clone $this; |
98 | - $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); |
|
98 | + $str->string .= 1 >= \count( $suffix ) ? ( $suffix[ 0 ] ?? '' ) : implode( '', $suffix ); |
|
99 | 99 | |
100 | 100 | return $str; |
101 | 101 | } |
@@ -103,57 +103,57 @@ discard block |
||
103 | 103 | public function camel(): parent |
104 | 104 | { |
105 | 105 | $str = clone $this; |
106 | - $str->string = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string)))); |
|
106 | + $str->string = lcfirst( str_replace( ' ', '', ucwords( preg_replace( '/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string ) ) ) ); |
|
107 | 107 | |
108 | 108 | return $str; |
109 | 109 | } |
110 | 110 | |
111 | - public function chunk(int $length = 1): array |
|
111 | + public function chunk( int $length = 1 ): array |
|
112 | 112 | { |
113 | - if (1 > $length) { |
|
114 | - throw new InvalidArgumentException('The chunk length must be greater than zero.'); |
|
113 | + if ( 1 > $length ) { |
|
114 | + throw new InvalidArgumentException( 'The chunk length must be greater than zero.' ); |
|
115 | 115 | } |
116 | 116 | |
117 | - if ('' === $this->string) { |
|
118 | - return []; |
|
117 | + if ( '' === $this->string ) { |
|
118 | + return [ ]; |
|
119 | 119 | } |
120 | 120 | |
121 | 121 | $str = clone $this; |
122 | - $chunks = []; |
|
122 | + $chunks = [ ]; |
|
123 | 123 | |
124 | - foreach (str_split($this->string, $length) as $chunk) { |
|
124 | + foreach ( str_split( $this->string, $length ) as $chunk ) { |
|
125 | 125 | $str->string = $chunk; |
126 | - $chunks[] = clone $str; |
|
126 | + $chunks[ ] = clone $str; |
|
127 | 127 | } |
128 | 128 | |
129 | 129 | return $chunks; |
130 | 130 | } |
131 | 131 | |
132 | - public function endsWith($suffix): bool |
|
132 | + public function endsWith( $suffix ): bool |
|
133 | 133 | { |
134 | - if ($suffix instanceof parent) { |
|
134 | + if ( $suffix instanceof parent ) { |
|
135 | 135 | $suffix = $suffix->string; |
136 | - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { |
|
137 | - return parent::endsWith($suffix); |
|
136 | + } elseif ( \is_array( $suffix ) || $suffix instanceof \Traversable ) { |
|
137 | + return parent::endsWith( $suffix ); |
|
138 | 138 | } else { |
139 | - $suffix = (string) $suffix; |
|
139 | + $suffix = (string)$suffix; |
|
140 | 140 | } |
141 | 141 | |
142 | - return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); |
|
142 | + return '' !== $suffix && \strlen( $this->string ) >= \strlen( $suffix ) && 0 === substr_compare( $this->string, $suffix, -\strlen( $suffix ), null, $this->ignoreCase ); |
|
143 | 143 | } |
144 | 144 | |
145 | - public function equalsTo($string): bool |
|
145 | + public function equalsTo( $string ): bool |
|
146 | 146 | { |
147 | - if ($string instanceof parent) { |
|
147 | + if ( $string instanceof parent ) { |
|
148 | 148 | $string = $string->string; |
149 | - } elseif (\is_array($string) || $string instanceof \Traversable) { |
|
150 | - return parent::equalsTo($string); |
|
149 | + } elseif ( \is_array( $string ) || $string instanceof \Traversable ) { |
|
150 | + return parent::equalsTo( $string ); |
|
151 | 151 | } else { |
152 | - $string = (string) $string; |
|
152 | + $string = (string)$string; |
|
153 | 153 | } |
154 | 154 | |
155 | - if ('' !== $string && $this->ignoreCase) { |
|
156 | - return 0 === strcasecmp($string, $this->string); |
|
155 | + if ( '' !== $string && $this->ignoreCase ) { |
|
156 | + return 0 === strcasecmp( $string, $this->string ); |
|
157 | 157 | } |
158 | 158 | |
159 | 159 | return $string === $this->string; |
@@ -162,98 +162,98 @@ discard block |
||
162 | 162 | public function folded(): parent |
163 | 163 | { |
164 | 164 | $str = clone $this; |
165 | - $str->string = strtolower($str->string); |
|
165 | + $str->string = strtolower( $str->string ); |
|
166 | 166 | |
167 | 167 | return $str; |
168 | 168 | } |
169 | 169 | |
170 | - public function indexOf($needle, int $offset = 0): ?int |
|
170 | + public function indexOf( $needle, int $offset = 0 ): ?int |
|
171 | 171 | { |
172 | - if ($needle instanceof parent) { |
|
172 | + if ( $needle instanceof parent ) { |
|
173 | 173 | $needle = $needle->string; |
174 | - } elseif (\is_array($needle) || $needle instanceof \Traversable) { |
|
175 | - return parent::indexOf($needle, $offset); |
|
174 | + } elseif ( \is_array( $needle ) || $needle instanceof \Traversable ) { |
|
175 | + return parent::indexOf( $needle, $offset ); |
|
176 | 176 | } else { |
177 | - $needle = (string) $needle; |
|
177 | + $needle = (string)$needle; |
|
178 | 178 | } |
179 | 179 | |
180 | - if ('' === $needle) { |
|
180 | + if ( '' === $needle ) { |
|
181 | 181 | return null; |
182 | 182 | } |
183 | 183 | |
184 | - $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset); |
|
184 | + $i = $this->ignoreCase ? stripos( $this->string, $needle, $offset ) : strpos( $this->string, $needle, $offset ); |
|
185 | 185 | |
186 | 186 | return false === $i ? null : $i; |
187 | 187 | } |
188 | 188 | |
189 | - public function indexOfLast($needle, int $offset = 0): ?int |
|
189 | + public function indexOfLast( $needle, int $offset = 0 ): ?int |
|
190 | 190 | { |
191 | - if ($needle instanceof parent) { |
|
191 | + if ( $needle instanceof parent ) { |
|
192 | 192 | $needle = $needle->string; |
193 | - } elseif (\is_array($needle) || $needle instanceof \Traversable) { |
|
194 | - return parent::indexOfLast($needle, $offset); |
|
193 | + } elseif ( \is_array( $needle ) || $needle instanceof \Traversable ) { |
|
194 | + return parent::indexOfLast( $needle, $offset ); |
|
195 | 195 | } else { |
196 | - $needle = (string) $needle; |
|
196 | + $needle = (string)$needle; |
|
197 | 197 | } |
198 | 198 | |
199 | - if ('' === $needle) { |
|
199 | + if ( '' === $needle ) { |
|
200 | 200 | return null; |
201 | 201 | } |
202 | 202 | |
203 | - $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset); |
|
203 | + $i = $this->ignoreCase ? strripos( $this->string, $needle, $offset ) : strrpos( $this->string, $needle, $offset ); |
|
204 | 204 | |
205 | 205 | return false === $i ? null : $i; |
206 | 206 | } |
207 | 207 | |
208 | 208 | public function isUtf8(): bool |
209 | 209 | { |
210 | - return '' === $this->string || preg_match('//u', $this->string); |
|
210 | + return '' === $this->string || preg_match( '//u', $this->string ); |
|
211 | 211 | } |
212 | 212 | |
213 | - public function join(array $strings, string $lastGlue = null): parent |
|
213 | + public function join( array $strings, string $lastGlue = null ): parent |
|
214 | 214 | { |
215 | 215 | $str = clone $this; |
216 | 216 | |
217 | - $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; |
|
218 | - $str->string = implode($this->string, $strings).$tail; |
|
217 | + $tail = null !== $lastGlue && 1 < \count( $strings ) ? $lastGlue . array_pop( $strings ) : ''; |
|
218 | + $str->string = implode( $this->string, $strings ) . $tail; |
|
219 | 219 | |
220 | 220 | return $str; |
221 | 221 | } |
222 | 222 | |
223 | 223 | public function length(): int |
224 | 224 | { |
225 | - return \strlen($this->string); |
|
225 | + return \strlen( $this->string ); |
|
226 | 226 | } |
227 | 227 | |
228 | 228 | public function lower(): parent |
229 | 229 | { |
230 | 230 | $str = clone $this; |
231 | - $str->string = strtolower($str->string); |
|
231 | + $str->string = strtolower( $str->string ); |
|
232 | 232 | |
233 | 233 | return $str; |
234 | 234 | } |
235 | 235 | |
236 | - public function match(string $regexp, int $flags = 0, int $offset = 0): array |
|
236 | + public function match( string $regexp, int $flags = 0, int $offset = 0 ): array |
|
237 | 237 | { |
238 | - $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; |
|
238 | + $match = ( ( \PREG_PATTERN_ORDER | \PREG_SET_ORDER ) & $flags ) ? 'preg_match_all' : 'preg_match'; |
|
239 | 239 | |
240 | - if ($this->ignoreCase) { |
|
240 | + if ( $this->ignoreCase ) { |
|
241 | 241 | $regexp .= 'i'; |
242 | 242 | } |
243 | 243 | |
244 | - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); |
|
244 | + set_error_handler( static function( $t, $m ) { throw new InvalidArgumentException( $m ); }); |
|
245 | 245 | |
246 | 246 | try { |
247 | - if (false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { |
|
247 | + if ( false === $match( $regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset ) ) { |
|
248 | 248 | $lastError = preg_last_error(); |
249 | 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.'.'); |
|
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 | 253 | } |
254 | 254 | } |
255 | 255 | |
256 | - throw new RuntimeException('Matching failed with unknown error code.'); |
|
256 | + throw new RuntimeException( 'Matching failed with unknown error code.' ); |
|
257 | 257 | } |
258 | 258 | } finally { |
259 | 259 | restore_error_handler(); |
@@ -262,58 +262,58 @@ discard block |
||
262 | 262 | return $matches; |
263 | 263 | } |
264 | 264 | |
265 | - public function padBoth(int $length, string $padStr = ' '): parent |
|
265 | + public function padBoth( int $length, string $padStr = ' ' ): parent |
|
266 | 266 | { |
267 | 267 | $str = clone $this; |
268 | - $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); |
|
268 | + $str->string = str_pad( $this->string, $length, $padStr, \STR_PAD_BOTH ); |
|
269 | 269 | |
270 | 270 | return $str; |
271 | 271 | } |
272 | 272 | |
273 | - public function padEnd(int $length, string $padStr = ' '): parent |
|
273 | + public function padEnd( int $length, string $padStr = ' ' ): parent |
|
274 | 274 | { |
275 | 275 | $str = clone $this; |
276 | - $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); |
|
276 | + $str->string = str_pad( $this->string, $length, $padStr, \STR_PAD_RIGHT ); |
|
277 | 277 | |
278 | 278 | return $str; |
279 | 279 | } |
280 | 280 | |
281 | - public function padStart(int $length, string $padStr = ' '): parent |
|
281 | + public function padStart( int $length, string $padStr = ' ' ): parent |
|
282 | 282 | { |
283 | 283 | $str = clone $this; |
284 | - $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); |
|
284 | + $str->string = str_pad( $this->string, $length, $padStr, \STR_PAD_LEFT ); |
|
285 | 285 | |
286 | 286 | return $str; |
287 | 287 | } |
288 | 288 | |
289 | - public function prepend(string ...$prefix): parent |
|
289 | + public function prepend( string ...$prefix ): parent |
|
290 | 290 | { |
291 | 291 | $str = clone $this; |
292 | - $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string; |
|
292 | + $str->string = ( 1 >= \count( $prefix ) ? ( $prefix[ 0 ] ?? '' ) : implode( '', $prefix ) ) . $str->string; |
|
293 | 293 | |
294 | 294 | return $str; |
295 | 295 | } |
296 | 296 | |
297 | - public function replace(string $from, string $to): parent |
|
297 | + public function replace( string $from, string $to ): parent |
|
298 | 298 | { |
299 | 299 | $str = clone $this; |
300 | 300 | |
301 | - if ('' !== $from) { |
|
302 | - $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string); |
|
301 | + if ( '' !== $from ) { |
|
302 | + $str->string = $this->ignoreCase ? str_ireplace( $from, $to, $this->string ) : str_replace( $from, $to, $this->string ); |
|
303 | 303 | } |
304 | 304 | |
305 | 305 | return $str; |
306 | 306 | } |
307 | 307 | |
308 | - public function replaceMatches(string $fromRegexp, $to): parent |
|
308 | + public function replaceMatches( string $fromRegexp, $to ): parent |
|
309 | 309 | { |
310 | - if ($this->ignoreCase) { |
|
310 | + if ( $this->ignoreCase ) { |
|
311 | 311 | $fromRegexp .= 'i'; |
312 | 312 | } |
313 | 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)); |
|
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 | 317 | } |
318 | 318 | |
319 | 319 | $replace = 'preg_replace_callback'; |
@@ -321,19 +321,19 @@ discard block |
||
321 | 321 | $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; |
322 | 322 | } |
323 | 323 | |
324 | - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); |
|
324 | + set_error_handler( static function( $t, $m ) { throw new InvalidArgumentException( $m ); }); |
|
325 | 325 | |
326 | 326 | try { |
327 | - if (null === $string = $replace($fromRegexp, $to, $this->string)) { |
|
327 | + if ( null === $string = $replace( $fromRegexp, $to, $this->string ) ) { |
|
328 | 328 | $lastError = preg_last_error(); |
329 | 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.'.'); |
|
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 | 333 | } |
334 | 334 | } |
335 | 335 | |
336 | - throw new RuntimeException('Matching failed with unknown error code.'); |
|
336 | + throw new RuntimeException( 'Matching failed with unknown error code.' ); |
|
337 | 337 | } |
338 | 338 | } finally { |
339 | 339 | restore_error_handler(); |
@@ -348,15 +348,15 @@ discard block |
||
348 | 348 | public function reverse(): parent |
349 | 349 | { |
350 | 350 | $str = clone $this; |
351 | - $str->string = strrev($str->string); |
|
351 | + $str->string = strrev( $str->string ); |
|
352 | 352 | |
353 | 353 | return $str; |
354 | 354 | } |
355 | 355 | |
356 | - public function slice(int $start = 0, int $length = null): parent |
|
356 | + public function slice( int $start = 0, int $length = null ): parent |
|
357 | 357 | { |
358 | 358 | $str = clone $this; |
359 | - $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX); |
|
359 | + $str->string = (string)substr( $this->string, $start, $length ?? \PHP_INT_MAX ); |
|
360 | 360 | |
361 | 361 | return $str; |
362 | 362 | } |
@@ -364,39 +364,39 @@ discard block |
||
364 | 364 | public function snake(): parent |
365 | 365 | { |
366 | 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)); |
|
367 | + $str->string = strtolower( preg_replace( [ '/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/' ], '\1_\2', $str->string ) ); |
|
368 | 368 | |
369 | 369 | return $str; |
370 | 370 | } |
371 | 371 | |
372 | - public function splice(string $replacement, int $start = 0, int $length = null): parent |
|
372 | + public function splice( string $replacement, int $start = 0, int $length = null ): parent |
|
373 | 373 | { |
374 | 374 | $str = clone $this; |
375 | - $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); |
|
375 | + $str->string = substr_replace( $this->string, $replacement, $start, $length ?? \PHP_INT_MAX ); |
|
376 | 376 | |
377 | 377 | return $str; |
378 | 378 | } |
379 | 379 | |
380 | - public function split(string $delimiter, int $limit = null, int $flags = null): array |
|
380 | + public function split( string $delimiter, int $limit = null, int $flags = null ): array |
|
381 | 381 | { |
382 | - if (1 > $limit = $limit ?? \PHP_INT_MAX) { |
|
383 | - throw new InvalidArgumentException('Split limit must be a positive integer.'); |
|
382 | + if ( 1 > $limit = $limit ?? \PHP_INT_MAX ) { |
|
383 | + throw new InvalidArgumentException( 'Split limit must be a positive integer.' ); |
|
384 | 384 | } |
385 | 385 | |
386 | - if ('' === $delimiter) { |
|
387 | - throw new InvalidArgumentException('Split delimiter is empty.'); |
|
386 | + if ( '' === $delimiter ) { |
|
387 | + throw new InvalidArgumentException( 'Split delimiter is empty.' ); |
|
388 | 388 | } |
389 | 389 | |
390 | - if (null !== $flags) { |
|
391 | - return parent::split($delimiter, $limit, $flags); |
|
390 | + if ( null !== $flags ) { |
|
391 | + return parent::split( $delimiter, $limit, $flags ); |
|
392 | 392 | } |
393 | 393 | |
394 | 394 | $str = clone $this; |
395 | 395 | $chunks = $this->ignoreCase |
396 | - ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit) |
|
397 | - : explode($delimiter, $this->string, $limit); |
|
396 | + ? preg_split( '{' . preg_quote( $delimiter ) . '}iD', $this->string, $limit ) |
|
397 | + : explode( $delimiter, $this->string, $limit ); |
|
398 | 398 | |
399 | - foreach ($chunks as &$chunk) { |
|
399 | + foreach ( $chunks as &$chunk ) { |
|
400 | 400 | $str->string = $chunk; |
401 | 401 | $chunk = clone $str; |
402 | 402 | } |
@@ -404,51 +404,51 @@ discard block |
||
404 | 404 | return $chunks; |
405 | 405 | } |
406 | 406 | |
407 | - public function startsWith($prefix): bool |
|
407 | + public function startsWith( $prefix ): bool |
|
408 | 408 | { |
409 | - if ($prefix instanceof parent) { |
|
409 | + if ( $prefix instanceof parent ) { |
|
410 | 410 | $prefix = $prefix->string; |
411 | - } elseif (!\is_string($prefix)) { |
|
412 | - return parent::startsWith($prefix); |
|
411 | + } elseif ( ! \is_string( $prefix ) ) { |
|
412 | + return parent::startsWith( $prefix ); |
|
413 | 413 | } |
414 | 414 | |
415 | - return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix))); |
|
415 | + return '' !== $prefix && 0 === ( $this->ignoreCase ? strncasecmp( $this->string, $prefix, \strlen( $prefix ) ) : strncmp( $this->string, $prefix, \strlen( $prefix ) ) ); |
|
416 | 416 | } |
417 | 417 | |
418 | - public function title(bool $allWords = false): parent |
|
418 | + public function title( bool $allWords = false ): parent |
|
419 | 419 | { |
420 | 420 | $str = clone $this; |
421 | - $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string); |
|
421 | + $str->string = $allWords ? ucwords( $str->string ) : ucfirst( $str->string ); |
|
422 | 422 | |
423 | 423 | return $str; |
424 | 424 | } |
425 | 425 | |
426 | - public function toUnicodeString(string $fromEncoding = null): UnicodeString |
|
426 | + public function toUnicodeString( string $fromEncoding = null ): UnicodeString |
|
427 | 427 | { |
428 | - return new UnicodeString($this->toCodePointString($fromEncoding)->string); |
|
428 | + return new UnicodeString( $this->toCodePointString( $fromEncoding )->string ); |
|
429 | 429 | } |
430 | 430 | |
431 | - public function toCodePointString(string $fromEncoding = null): CodePointString |
|
431 | + public function toCodePointString( string $fromEncoding = null ): CodePointString |
|
432 | 432 | { |
433 | 433 | $u = new CodePointString(); |
434 | 434 | |
435 | - if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) { |
|
435 | + if ( \in_array( $fromEncoding, [ null, 'utf8', 'utf-8', 'UTF8', 'UTF-8' ], true ) && preg_match( '//u', $this->string ) ) { |
|
436 | 436 | $u->string = $this->string; |
437 | 437 | |
438 | 438 | return $u; |
439 | 439 | } |
440 | 440 | |
441 | - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); |
|
441 | + set_error_handler( static function( $t, $m ) { throw new InvalidArgumentException( $m ); }); |
|
442 | 442 | |
443 | 443 | try { |
444 | 444 | try { |
445 | - $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true); |
|
446 | - } catch (InvalidArgumentException $e) { |
|
447 | - if (!\function_exists('iconv')) { |
|
445 | + $validEncoding = false !== mb_detect_encoding( $this->string, $fromEncoding ?? 'Windows-1252', true ); |
|
446 | + } catch ( InvalidArgumentException $e ) { |
|
447 | + if ( ! \function_exists( 'iconv' ) ) { |
|
448 | 448 | throw $e; |
449 | 449 | } |
450 | 450 | |
451 | - $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); |
|
451 | + $u->string = iconv( $fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string ); |
|
452 | 452 | |
453 | 453 | return $u; |
454 | 454 | } |
@@ -456,35 +456,35 @@ discard block |
||
456 | 456 | restore_error_handler(); |
457 | 457 | } |
458 | 458 | |
459 | - if (!$validEncoding) { |
|
460 | - throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); |
|
459 | + if ( ! $validEncoding ) { |
|
460 | + throw new InvalidArgumentException( sprintf( 'Invalid "%s" string.', $fromEncoding ?? 'Windows-1252' ) ); |
|
461 | 461 | } |
462 | 462 | |
463 | - $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); |
|
463 | + $u->string = mb_convert_encoding( $this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252' ); |
|
464 | 464 | |
465 | 465 | return $u; |
466 | 466 | } |
467 | 467 | |
468 | - public function trim(string $chars = " \t\n\r\0\x0B\x0C"): parent |
|
468 | + public function trim( string $chars = " \t\n\r\0\x0B\x0C" ): parent |
|
469 | 469 | { |
470 | 470 | $str = clone $this; |
471 | - $str->string = trim($str->string, $chars); |
|
471 | + $str->string = trim( $str->string, $chars ); |
|
472 | 472 | |
473 | 473 | return $str; |
474 | 474 | } |
475 | 475 | |
476 | - public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): parent |
|
476 | + public function trimEnd( string $chars = " \t\n\r\0\x0B\x0C" ): parent |
|
477 | 477 | { |
478 | 478 | $str = clone $this; |
479 | - $str->string = rtrim($str->string, $chars); |
|
479 | + $str->string = rtrim( $str->string, $chars ); |
|
480 | 480 | |
481 | 481 | return $str; |
482 | 482 | } |
483 | 483 | |
484 | - public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): parent |
|
484 | + public function trimStart( string $chars = " \t\n\r\0\x0B\x0C" ): parent |
|
485 | 485 | { |
486 | 486 | $str = clone $this; |
487 | - $str->string = ltrim($str->string, $chars); |
|
487 | + $str->string = ltrim( $str->string, $chars ); |
|
488 | 488 | |
489 | 489 | return $str; |
490 | 490 | } |
@@ -492,15 +492,15 @@ discard block |
||
492 | 492 | public function upper(): parent |
493 | 493 | { |
494 | 494 | $str = clone $this; |
495 | - $str->string = strtoupper($str->string); |
|
495 | + $str->string = strtoupper( $str->string ); |
|
496 | 496 | |
497 | 497 | return $str; |
498 | 498 | } |
499 | 499 | |
500 | - public function width(bool $ignoreAnsiDecoration = true): int |
|
500 | + public function width( bool $ignoreAnsiDecoration = true ): int |
|
501 | 501 | { |
502 | - $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string); |
|
502 | + $string = preg_match( '//u', $this->string ) ? $this->string : preg_replace( '/[\x80-\xFF]/', '?', $this->string ); |
|
503 | 503 | |
504 | - return (new CodePointString($string))->width($ignoreAnsiDecoration); |
|
504 | + return ( new CodePointString( $string ) )->width( $ignoreAnsiDecoration ); |
|
505 | 505 | } |
506 | 506 | } |
@@ -23,12 +23,10 @@ |
||
23 | 23 | * |
24 | 24 | * @throws ExceptionInterface |
25 | 25 | */ |
26 | -class ByteString extends AbstractString |
|
27 | -{ |
|
26 | +class ByteString extends AbstractString { |
|
28 | 27 | private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; |
29 | 28 | |
30 | - public function __construct(string $string = '') |
|
31 | - { |
|
29 | + public function __construct(string $string = '') { |
|
32 | 30 | $this->string = $string; |
33 | 31 | } |
34 | 32 |
@@ -18,140 +18,140 @@ |
||
18 | 18 | */ |
19 | 19 | final class FrenchInflector implements InflectorInterface |
20 | 20 | { |
21 | - /** |
|
22 | - * A list of all rules for pluralise. |
|
23 | - * |
|
24 | - * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php |
|
25 | - */ |
|
26 | - private const PLURALIZE_REGEXP = [ |
|
27 | - // First entry: regexp |
|
28 | - // Second entry: replacement |
|
29 | - |
|
30 | - // Words finishing with "s", "x" or "z" are invariables |
|
31 | - // Les mots finissant par "s", "x" ou "z" sont invariables |
|
32 | - ['/(s|x|z)$/i', '\1'], |
|
33 | - |
|
34 | - // Words finishing with "eau" are pluralized with a "x" |
|
35 | - // Les mots finissant par "eau" prennent tous un "x" au pluriel |
|
36 | - ['/(eau)$/i', '\1x'], |
|
37 | - |
|
38 | - // Words finishing with "au" are pluralized with a "x" excepted "landau" |
|
39 | - // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" |
|
40 | - ['/^(landau)$/i', '\1s'], |
|
41 | - ['/(au)$/i', '\1x'], |
|
42 | - |
|
43 | - // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" |
|
44 | - // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" |
|
45 | - ['/^(pneu|bleu|émeu)$/i', '\1s'], |
|
46 | - ['/(eu)$/i', '\1x'], |
|
47 | - |
|
48 | - // Words finishing with "al" are pluralized with a "aux" excepted |
|
49 | - // Les mots finissant en "al" se terminent en "aux" sauf |
|
50 | - ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'], |
|
51 | - ['/al$/i', '\1aux'], |
|
52 | - |
|
53 | - // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux |
|
54 | - ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'], |
|
55 | - |
|
56 | - // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel |
|
57 | - ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'], |
|
58 | - |
|
59 | - // Invariable words |
|
60 | - ['/^(cinquante|soixante|mille)$/i', '\1'], |
|
61 | - |
|
62 | - // French titles |
|
63 | - ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'], |
|
64 | - ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'], |
|
65 | - ]; |
|
66 | - |
|
67 | - /** |
|
68 | - * A list of all rules for singularize. |
|
69 | - */ |
|
70 | - private const SINGULARIZE_REGEXP = [ |
|
71 | - // First entry: regexp |
|
72 | - // Second entry: replacement |
|
73 | - |
|
74 | - // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux |
|
75 | - ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'], |
|
76 | - |
|
77 | - // Words finishing with "eau" are pluralized with a "x" |
|
78 | - // Les mots finissant par "eau" prennent tous un "x" au pluriel |
|
79 | - ['/(eau)x$/i', '\1'], |
|
80 | - |
|
81 | - // Words finishing with "al" are pluralized with a "aux" expected |
|
82 | - // Les mots finissant en "al" se terminent en "aux" sauf |
|
83 | - ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'], |
|
84 | - |
|
85 | - // Words finishing with "au" are pluralized with a "x" excepted "landau" |
|
86 | - // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" |
|
87 | - ['/(au)x$/i', '\1'], |
|
88 | - |
|
89 | - // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" |
|
90 | - // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" |
|
91 | - ['/(eu)x$/i', '\1'], |
|
92 | - |
|
93 | - // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou |
|
94 | - // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou |
|
95 | - ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'], |
|
96 | - |
|
97 | - // French titles |
|
98 | - ['/^mes(dame|demoiselle)s$/', 'ma\1'], |
|
99 | - ['/^Mes(dame|demoiselle)s$/', 'Ma\1'], |
|
100 | - ['/^mes(sieur|seigneur)s$/', 'mon\1'], |
|
101 | - ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], |
|
102 | - |
|
103 | - //Default rule |
|
104 | - ['/s$/i', ''], |
|
105 | - ]; |
|
106 | - |
|
107 | - /** |
|
108 | - * A list of words which should not be inflected. |
|
109 | - * This list is only used by singularize. |
|
110 | - */ |
|
111 | - private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; |
|
112 | - |
|
113 | - /** |
|
114 | - * {@inheritdoc} |
|
115 | - */ |
|
116 | - public function singularize(string $plural): array |
|
117 | - { |
|
118 | - if ($this->isInflectedWord($plural)) { |
|
119 | - return [$plural]; |
|
120 | - } |
|
121 | - |
|
122 | - foreach (self::SINGULARIZE_REGEXP as $rule) { |
|
123 | - [$regexp, $replace] = $rule; |
|
124 | - |
|
125 | - if (1 === preg_match($regexp, $plural)) { |
|
126 | - return [preg_replace($regexp, $replace, $plural)]; |
|
127 | - } |
|
128 | - } |
|
129 | - |
|
130 | - return [$plural]; |
|
131 | - } |
|
132 | - |
|
133 | - /** |
|
134 | - * {@inheritdoc} |
|
135 | - */ |
|
136 | - public function pluralize(string $singular): array |
|
137 | - { |
|
138 | - if ($this->isInflectedWord($singular)) { |
|
139 | - return [$singular]; |
|
140 | - } |
|
141 | - |
|
142 | - foreach (self::PLURALIZE_REGEXP as $rule) { |
|
143 | - [$regexp, $replace] = $rule; |
|
144 | - |
|
145 | - if (1 === preg_match($regexp, $singular)) { |
|
146 | - return [preg_replace($regexp, $replace, $singular)]; |
|
147 | - } |
|
148 | - } |
|
149 | - |
|
150 | - return [$singular.'s']; |
|
151 | - } |
|
152 | - |
|
153 | - private function isInflectedWord(string $word): bool |
|
154 | - { |
|
155 | - return 1 === preg_match(self::UNINFLECTED, $word); |
|
156 | - } |
|
21 | + /** |
|
22 | + * A list of all rules for pluralise. |
|
23 | + * |
|
24 | + * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php |
|
25 | + */ |
|
26 | + private const PLURALIZE_REGEXP = [ |
|
27 | + // First entry: regexp |
|
28 | + // Second entry: replacement |
|
29 | + |
|
30 | + // Words finishing with "s", "x" or "z" are invariables |
|
31 | + // Les mots finissant par "s", "x" ou "z" sont invariables |
|
32 | + ['/(s|x|z)$/i', '\1'], |
|
33 | + |
|
34 | + // Words finishing with "eau" are pluralized with a "x" |
|
35 | + // Les mots finissant par "eau" prennent tous un "x" au pluriel |
|
36 | + ['/(eau)$/i', '\1x'], |
|
37 | + |
|
38 | + // Words finishing with "au" are pluralized with a "x" excepted "landau" |
|
39 | + // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" |
|
40 | + ['/^(landau)$/i', '\1s'], |
|
41 | + ['/(au)$/i', '\1x'], |
|
42 | + |
|
43 | + // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" |
|
44 | + // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" |
|
45 | + ['/^(pneu|bleu|émeu)$/i', '\1s'], |
|
46 | + ['/(eu)$/i', '\1x'], |
|
47 | + |
|
48 | + // Words finishing with "al" are pluralized with a "aux" excepted |
|
49 | + // Les mots finissant en "al" se terminent en "aux" sauf |
|
50 | + ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'], |
|
51 | + ['/al$/i', '\1aux'], |
|
52 | + |
|
53 | + // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux |
|
54 | + ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'], |
|
55 | + |
|
56 | + // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel |
|
57 | + ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'], |
|
58 | + |
|
59 | + // Invariable words |
|
60 | + ['/^(cinquante|soixante|mille)$/i', '\1'], |
|
61 | + |
|
62 | + // French titles |
|
63 | + ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'], |
|
64 | + ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'], |
|
65 | + ]; |
|
66 | + |
|
67 | + /** |
|
68 | + * A list of all rules for singularize. |
|
69 | + */ |
|
70 | + private const SINGULARIZE_REGEXP = [ |
|
71 | + // First entry: regexp |
|
72 | + // Second entry: replacement |
|
73 | + |
|
74 | + // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux |
|
75 | + ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'], |
|
76 | + |
|
77 | + // Words finishing with "eau" are pluralized with a "x" |
|
78 | + // Les mots finissant par "eau" prennent tous un "x" au pluriel |
|
79 | + ['/(eau)x$/i', '\1'], |
|
80 | + |
|
81 | + // Words finishing with "al" are pluralized with a "aux" expected |
|
82 | + // Les mots finissant en "al" se terminent en "aux" sauf |
|
83 | + ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'], |
|
84 | + |
|
85 | + // Words finishing with "au" are pluralized with a "x" excepted "landau" |
|
86 | + // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" |
|
87 | + ['/(au)x$/i', '\1'], |
|
88 | + |
|
89 | + // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" |
|
90 | + // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" |
|
91 | + ['/(eu)x$/i', '\1'], |
|
92 | + |
|
93 | + // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou |
|
94 | + // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou |
|
95 | + ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'], |
|
96 | + |
|
97 | + // French titles |
|
98 | + ['/^mes(dame|demoiselle)s$/', 'ma\1'], |
|
99 | + ['/^Mes(dame|demoiselle)s$/', 'Ma\1'], |
|
100 | + ['/^mes(sieur|seigneur)s$/', 'mon\1'], |
|
101 | + ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], |
|
102 | + |
|
103 | + //Default rule |
|
104 | + ['/s$/i', ''], |
|
105 | + ]; |
|
106 | + |
|
107 | + /** |
|
108 | + * A list of words which should not be inflected. |
|
109 | + * This list is only used by singularize. |
|
110 | + */ |
|
111 | + private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; |
|
112 | + |
|
113 | + /** |
|
114 | + * {@inheritdoc} |
|
115 | + */ |
|
116 | + public function singularize(string $plural): array |
|
117 | + { |
|
118 | + if ($this->isInflectedWord($plural)) { |
|
119 | + return [$plural]; |
|
120 | + } |
|
121 | + |
|
122 | + foreach (self::SINGULARIZE_REGEXP as $rule) { |
|
123 | + [$regexp, $replace] = $rule; |
|
124 | + |
|
125 | + if (1 === preg_match($regexp, $plural)) { |
|
126 | + return [preg_replace($regexp, $replace, $plural)]; |
|
127 | + } |
|
128 | + } |
|
129 | + |
|
130 | + return [$plural]; |
|
131 | + } |
|
132 | + |
|
133 | + /** |
|
134 | + * {@inheritdoc} |
|
135 | + */ |
|
136 | + public function pluralize(string $singular): array |
|
137 | + { |
|
138 | + if ($this->isInflectedWord($singular)) { |
|
139 | + return [$singular]; |
|
140 | + } |
|
141 | + |
|
142 | + foreach (self::PLURALIZE_REGEXP as $rule) { |
|
143 | + [$regexp, $replace] = $rule; |
|
144 | + |
|
145 | + if (1 === preg_match($regexp, $singular)) { |
|
146 | + return [preg_replace($regexp, $replace, $singular)]; |
|
147 | + } |
|
148 | + } |
|
149 | + |
|
150 | + return [$singular.'s']; |
|
151 | + } |
|
152 | + |
|
153 | + private function isInflectedWord(string $word): bool |
|
154 | + { |
|
155 | + return 1 === preg_match(self::UNINFLECTED, $word); |
|
156 | + } |
|
157 | 157 | } |
@@ -29,39 +29,39 @@ discard block |
||
29 | 29 | |
30 | 30 | // Words finishing with "s", "x" or "z" are invariables |
31 | 31 | // Les mots finissant par "s", "x" ou "z" sont invariables |
32 | - ['/(s|x|z)$/i', '\1'], |
|
32 | + [ '/(s|x|z)$/i', '\1' ], |
|
33 | 33 | |
34 | 34 | // Words finishing with "eau" are pluralized with a "x" |
35 | 35 | // Les mots finissant par "eau" prennent tous un "x" au pluriel |
36 | - ['/(eau)$/i', '\1x'], |
|
36 | + [ '/(eau)$/i', '\1x' ], |
|
37 | 37 | |
38 | 38 | // Words finishing with "au" are pluralized with a "x" excepted "landau" |
39 | 39 | // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" |
40 | - ['/^(landau)$/i', '\1s'], |
|
41 | - ['/(au)$/i', '\1x'], |
|
40 | + [ '/^(landau)$/i', '\1s' ], |
|
41 | + [ '/(au)$/i', '\1x' ], |
|
42 | 42 | |
43 | 43 | // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" |
44 | 44 | // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" |
45 | - ['/^(pneu|bleu|émeu)$/i', '\1s'], |
|
46 | - ['/(eu)$/i', '\1x'], |
|
45 | + [ '/^(pneu|bleu|émeu)$/i', '\1s' ], |
|
46 | + [ '/(eu)$/i', '\1x' ], |
|
47 | 47 | |
48 | 48 | // Words finishing with "al" are pluralized with a "aux" excepted |
49 | 49 | // Les mots finissant en "al" se terminent en "aux" sauf |
50 | - ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'], |
|
51 | - ['/al$/i', '\1aux'], |
|
50 | + [ '/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s' ], |
|
51 | + [ '/al$/i', '\1aux' ], |
|
52 | 52 | |
53 | 53 | // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux |
54 | - ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'], |
|
54 | + [ '/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux' ], |
|
55 | 55 | |
56 | 56 | // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel |
57 | - ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'], |
|
57 | + [ '/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux' ], |
|
58 | 58 | |
59 | 59 | // Invariable words |
60 | - ['/^(cinquante|soixante|mille)$/i', '\1'], |
|
60 | + [ '/^(cinquante|soixante|mille)$/i', '\1' ], |
|
61 | 61 | |
62 | 62 | // French titles |
63 | - ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'], |
|
64 | - ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'], |
|
63 | + [ '/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s' ], |
|
64 | + [ '/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s' ], |
|
65 | 65 | ]; |
66 | 66 | |
67 | 67 | /** |
@@ -72,36 +72,36 @@ discard block |
||
72 | 72 | // Second entry: replacement |
73 | 73 | |
74 | 74 | // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux |
75 | - ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'], |
|
75 | + [ '/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail' ], |
|
76 | 76 | |
77 | 77 | // Words finishing with "eau" are pluralized with a "x" |
78 | 78 | // Les mots finissant par "eau" prennent tous un "x" au pluriel |
79 | - ['/(eau)x$/i', '\1'], |
|
79 | + [ '/(eau)x$/i', '\1' ], |
|
80 | 80 | |
81 | 81 | // Words finishing with "al" are pluralized with a "aux" expected |
82 | 82 | // Les mots finissant en "al" se terminent en "aux" sauf |
83 | - ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'], |
|
83 | + [ '/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al' ], |
|
84 | 84 | |
85 | 85 | // Words finishing with "au" are pluralized with a "x" excepted "landau" |
86 | 86 | // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" |
87 | - ['/(au)x$/i', '\1'], |
|
87 | + [ '/(au)x$/i', '\1' ], |
|
88 | 88 | |
89 | 89 | // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" |
90 | 90 | // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" |
91 | - ['/(eu)x$/i', '\1'], |
|
91 | + [ '/(eu)x$/i', '\1' ], |
|
92 | 92 | |
93 | 93 | // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou |
94 | 94 | // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou |
95 | - ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'], |
|
95 | + [ '/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou' ], |
|
96 | 96 | |
97 | 97 | // French titles |
98 | - ['/^mes(dame|demoiselle)s$/', 'ma\1'], |
|
99 | - ['/^Mes(dame|demoiselle)s$/', 'Ma\1'], |
|
100 | - ['/^mes(sieur|seigneur)s$/', 'mon\1'], |
|
101 | - ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], |
|
98 | + [ '/^mes(dame|demoiselle)s$/', 'ma\1' ], |
|
99 | + [ '/^Mes(dame|demoiselle)s$/', 'Ma\1' ], |
|
100 | + [ '/^mes(sieur|seigneur)s$/', 'mon\1' ], |
|
101 | + [ '/^Mes(sieur|seigneur)s$/', 'Mon\1' ], |
|
102 | 102 | |
103 | 103 | //Default rule |
104 | - ['/s$/i', ''], |
|
104 | + [ '/s$/i', '' ], |
|
105 | 105 | ]; |
106 | 106 | |
107 | 107 | /** |
@@ -113,45 +113,45 @@ discard block |
||
113 | 113 | /** |
114 | 114 | * {@inheritdoc} |
115 | 115 | */ |
116 | - public function singularize(string $plural): array |
|
116 | + public function singularize( string $plural ): array |
|
117 | 117 | { |
118 | - if ($this->isInflectedWord($plural)) { |
|
119 | - return [$plural]; |
|
118 | + if ( $this->isInflectedWord( $plural ) ) { |
|
119 | + return [ $plural ]; |
|
120 | 120 | } |
121 | 121 | |
122 | - foreach (self::SINGULARIZE_REGEXP as $rule) { |
|
123 | - [$regexp, $replace] = $rule; |
|
122 | + foreach ( self::SINGULARIZE_REGEXP as $rule ) { |
|
123 | + [ $regexp, $replace ] = $rule; |
|
124 | 124 | |
125 | - if (1 === preg_match($regexp, $plural)) { |
|
126 | - return [preg_replace($regexp, $replace, $plural)]; |
|
125 | + if ( 1 === preg_match( $regexp, $plural ) ) { |
|
126 | + return [ preg_replace( $regexp, $replace, $plural ) ]; |
|
127 | 127 | } |
128 | 128 | } |
129 | 129 | |
130 | - return [$plural]; |
|
130 | + return [ $plural ]; |
|
131 | 131 | } |
132 | 132 | |
133 | 133 | /** |
134 | 134 | * {@inheritdoc} |
135 | 135 | */ |
136 | - public function pluralize(string $singular): array |
|
136 | + public function pluralize( string $singular ): array |
|
137 | 137 | { |
138 | - if ($this->isInflectedWord($singular)) { |
|
139 | - return [$singular]; |
|
138 | + if ( $this->isInflectedWord( $singular ) ) { |
|
139 | + return [ $singular ]; |
|
140 | 140 | } |
141 | 141 | |
142 | - foreach (self::PLURALIZE_REGEXP as $rule) { |
|
143 | - [$regexp, $replace] = $rule; |
|
142 | + foreach ( self::PLURALIZE_REGEXP as $rule ) { |
|
143 | + [ $regexp, $replace ] = $rule; |
|
144 | 144 | |
145 | - if (1 === preg_match($regexp, $singular)) { |
|
146 | - return [preg_replace($regexp, $replace, $singular)]; |
|
145 | + if ( 1 === preg_match( $regexp, $singular ) ) { |
|
146 | + return [ preg_replace( $regexp, $replace, $singular ) ]; |
|
147 | 147 | } |
148 | 148 | } |
149 | 149 | |
150 | - return [$singular.'s']; |
|
150 | + return [ $singular . 's' ]; |
|
151 | 151 | } |
152 | 152 | |
153 | - private function isInflectedWord(string $word): bool |
|
153 | + private function isInflectedWord( string $word ): bool |
|
154 | 154 | { |
155 | - return 1 === preg_match(self::UNINFLECTED, $word); |
|
155 | + return 1 === preg_match( self::UNINFLECTED, $word ); |
|
156 | 156 | } |
157 | 157 | } |
@@ -16,8 +16,7 @@ |
||
16 | 16 | * |
17 | 17 | * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix". |
18 | 18 | */ |
19 | -final class FrenchInflector implements InflectorInterface |
|
20 | -{ |
|
19 | +final class FrenchInflector implements InflectorInterface { |
|
21 | 20 | /** |
22 | 21 | * A list of all rules for pluralise. |
23 | 22 | * |
@@ -13,21 +13,21 @@ |
||
13 | 13 | |
14 | 14 | interface InflectorInterface |
15 | 15 | { |
16 | - /** |
|
17 | - * Returns the singular forms of a string. |
|
18 | - * |
|
19 | - * If the method can't determine the form with certainty, several possible singulars are returned. |
|
20 | - * |
|
21 | - * @return string[] An array of possible singular forms |
|
22 | - */ |
|
23 | - public function singularize(string $plural): array; |
|
16 | + /** |
|
17 | + * Returns the singular forms of a string. |
|
18 | + * |
|
19 | + * If the method can't determine the form with certainty, several possible singulars are returned. |
|
20 | + * |
|
21 | + * @return string[] An array of possible singular forms |
|
22 | + */ |
|
23 | + public function singularize(string $plural): array; |
|
24 | 24 | |
25 | - /** |
|
26 | - * Returns the plural forms of a string. |
|
27 | - * |
|
28 | - * If the method can't determine the form with certainty, several possible plurals are returned. |
|
29 | - * |
|
30 | - * @return string[] An array of possible plural forms |
|
31 | - */ |
|
32 | - public function pluralize(string $singular): array; |
|
25 | + /** |
|
26 | + * Returns the plural forms of a string. |
|
27 | + * |
|
28 | + * If the method can't determine the form with certainty, several possible plurals are returned. |
|
29 | + * |
|
30 | + * @return string[] An array of possible plural forms |
|
31 | + */ |
|
32 | + public function pluralize(string $singular): array; |
|
33 | 33 | } |
@@ -20,7 +20,7 @@ discard block |
||
20 | 20 | * |
21 | 21 | * @return string[] An array of possible singular forms |
22 | 22 | */ |
23 | - public function singularize(string $plural): array; |
|
23 | + public function singularize( string $plural ): array; |
|
24 | 24 | |
25 | 25 | /** |
26 | 26 | * Returns the plural forms of a string. |
@@ -29,5 +29,5 @@ discard block |
||
29 | 29 | * |
30 | 30 | * @return string[] An array of possible plural forms |
31 | 31 | */ |
32 | - public function pluralize(string $singular): array; |
|
32 | + public function pluralize( string $singular ): array; |
|
33 | 33 | } |
@@ -11,8 +11,7 @@ |
||
11 | 11 | |
12 | 12 | namespace Symfony\Component\String\Inflector; |
13 | 13 | |
14 | -interface InflectorInterface |
|
15 | -{ |
|
14 | +interface InflectorInterface { |
|
16 | 15 | /** |
17 | 16 | * Returns the singular forms of a string. |
18 | 17 | * |
@@ -13,496 +13,496 @@ |
||
13 | 13 | |
14 | 14 | final class EnglishInflector implements InflectorInterface |
15 | 15 | { |
16 | - /** |
|
17 | - * Map English plural to singular suffixes. |
|
18 | - * |
|
19 | - * @see http://english-zone.com/spelling/plurals.html |
|
20 | - */ |
|
21 | - private const PLURAL_MAP = [ |
|
22 | - // First entry: plural suffix, reversed |
|
23 | - // Second entry: length of plural suffix |
|
24 | - // Third entry: Whether the suffix may succeed a vocal |
|
25 | - // Fourth entry: Whether the suffix may succeed a consonant |
|
26 | - // Fifth entry: singular suffix, normal |
|
16 | + /** |
|
17 | + * Map English plural to singular suffixes. |
|
18 | + * |
|
19 | + * @see http://english-zone.com/spelling/plurals.html |
|
20 | + */ |
|
21 | + private const PLURAL_MAP = [ |
|
22 | + // First entry: plural suffix, reversed |
|
23 | + // Second entry: length of plural suffix |
|
24 | + // Third entry: Whether the suffix may succeed a vocal |
|
25 | + // Fourth entry: Whether the suffix may succeed a consonant |
|
26 | + // Fifth entry: singular suffix, normal |
|
27 | 27 | |
28 | - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
29 | - ['a', 1, true, true, ['on', 'um']], |
|
28 | + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
29 | + ['a', 1, true, true, ['on', 'um']], |
|
30 | 30 | |
31 | - // nebulae (nebula) |
|
32 | - ['ea', 2, true, true, 'a'], |
|
31 | + // nebulae (nebula) |
|
32 | + ['ea', 2, true, true, 'a'], |
|
33 | 33 | |
34 | - // services (service) |
|
35 | - ['secivres', 8, true, true, 'service'], |
|
34 | + // services (service) |
|
35 | + ['secivres', 8, true, true, 'service'], |
|
36 | 36 | |
37 | - // mice (mouse), lice (louse) |
|
38 | - ['eci', 3, false, true, 'ouse'], |
|
37 | + // mice (mouse), lice (louse) |
|
38 | + ['eci', 3, false, true, 'ouse'], |
|
39 | 39 | |
40 | - // geese (goose) |
|
41 | - ['esee', 4, false, true, 'oose'], |
|
40 | + // geese (goose) |
|
41 | + ['esee', 4, false, true, 'oose'], |
|
42 | 42 | |
43 | - // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) |
|
44 | - ['i', 1, true, true, 'us'], |
|
43 | + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) |
|
44 | + ['i', 1, true, true, 'us'], |
|
45 | 45 | |
46 | - // men (man), women (woman) |
|
47 | - ['nem', 3, true, true, 'man'], |
|
46 | + // men (man), women (woman) |
|
47 | + ['nem', 3, true, true, 'man'], |
|
48 | 48 | |
49 | - // children (child) |
|
50 | - ['nerdlihc', 8, true, true, 'child'], |
|
49 | + // children (child) |
|
50 | + ['nerdlihc', 8, true, true, 'child'], |
|
51 | 51 | |
52 | - // oxen (ox) |
|
53 | - ['nexo', 4, false, false, 'ox'], |
|
52 | + // oxen (ox) |
|
53 | + ['nexo', 4, false, false, 'ox'], |
|
54 | 54 | |
55 | - // indices (index), appendices (appendix), prices (price) |
|
56 | - ['seci', 4, false, true, ['ex', 'ix', 'ice']], |
|
55 | + // indices (index), appendices (appendix), prices (price) |
|
56 | + ['seci', 4, false, true, ['ex', 'ix', 'ice']], |
|
57 | 57 | |
58 | - // selfies (selfie) |
|
59 | - ['seifles', 7, true, true, 'selfie'], |
|
58 | + // selfies (selfie) |
|
59 | + ['seifles', 7, true, true, 'selfie'], |
|
60 | 60 | |
61 | - // movies (movie) |
|
62 | - ['seivom', 6, true, true, 'movie'], |
|
61 | + // movies (movie) |
|
62 | + ['seivom', 6, true, true, 'movie'], |
|
63 | 63 | |
64 | - // conspectuses (conspectus), prospectuses (prospectus) |
|
65 | - ['sesutcep', 8, true, true, 'pectus'], |
|
64 | + // conspectuses (conspectus), prospectuses (prospectus) |
|
65 | + ['sesutcep', 8, true, true, 'pectus'], |
|
66 | 66 | |
67 | - // feet (foot) |
|
68 | - ['teef', 4, true, true, 'foot'], |
|
67 | + // feet (foot) |
|
68 | + ['teef', 4, true, true, 'foot'], |
|
69 | 69 | |
70 | - // geese (goose) |
|
71 | - ['eseeg', 5, true, true, 'goose'], |
|
70 | + // geese (goose) |
|
71 | + ['eseeg', 5, true, true, 'goose'], |
|
72 | 72 | |
73 | - // teeth (tooth) |
|
74 | - ['hteet', 5, true, true, 'tooth'], |
|
73 | + // teeth (tooth) |
|
74 | + ['hteet', 5, true, true, 'tooth'], |
|
75 | 75 | |
76 | - // news (news) |
|
77 | - ['swen', 4, true, true, 'news'], |
|
76 | + // news (news) |
|
77 | + ['swen', 4, true, true, 'news'], |
|
78 | 78 | |
79 | - // series (series) |
|
80 | - ['seires', 6, true, true, 'series'], |
|
79 | + // series (series) |
|
80 | + ['seires', 6, true, true, 'series'], |
|
81 | 81 | |
82 | - // babies (baby) |
|
83 | - ['sei', 3, false, true, 'y'], |
|
82 | + // babies (baby) |
|
83 | + ['sei', 3, false, true, 'y'], |
|
84 | 84 | |
85 | - // accesses (access), addresses (address), kisses (kiss) |
|
86 | - ['sess', 4, true, false, 'ss'], |
|
85 | + // accesses (access), addresses (address), kisses (kiss) |
|
86 | + ['sess', 4, true, false, 'ss'], |
|
87 | 87 | |
88 | - // analyses (analysis), ellipses (ellipsis), fungi (fungus), |
|
89 | - // neuroses (neurosis), theses (thesis), emphases (emphasis), |
|
90 | - // oases (oasis), crises (crisis), houses (house), bases (base), |
|
91 | - // atlases (atlas) |
|
92 | - ['ses', 3, true, true, ['s', 'se', 'sis']], |
|
88 | + // analyses (analysis), ellipses (ellipsis), fungi (fungus), |
|
89 | + // neuroses (neurosis), theses (thesis), emphases (emphasis), |
|
90 | + // oases (oasis), crises (crisis), houses (house), bases (base), |
|
91 | + // atlases (atlas) |
|
92 | + ['ses', 3, true, true, ['s', 'se', 'sis']], |
|
93 | 93 | |
94 | - // objectives (objective), alternative (alternatives) |
|
95 | - ['sevit', 5, true, true, 'tive'], |
|
94 | + // objectives (objective), alternative (alternatives) |
|
95 | + ['sevit', 5, true, true, 'tive'], |
|
96 | 96 | |
97 | - // drives (drive) |
|
98 | - ['sevird', 6, false, true, 'drive'], |
|
97 | + // drives (drive) |
|
98 | + ['sevird', 6, false, true, 'drive'], |
|
99 | 99 | |
100 | - // lives (life), wives (wife) |
|
101 | - ['sevi', 4, false, true, 'ife'], |
|
100 | + // lives (life), wives (wife) |
|
101 | + ['sevi', 4, false, true, 'ife'], |
|
102 | 102 | |
103 | - // moves (move) |
|
104 | - ['sevom', 5, true, true, 'move'], |
|
103 | + // moves (move) |
|
104 | + ['sevom', 5, true, true, 'move'], |
|
105 | 105 | |
106 | - // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) |
|
107 | - ['sev', 3, true, true, ['f', 've', 'ff']], |
|
106 | + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) |
|
107 | + ['sev', 3, true, true, ['f', 've', 'ff']], |
|
108 | 108 | |
109 | - // axes (axis), axes (ax), axes (axe) |
|
110 | - ['sexa', 4, false, false, ['ax', 'axe', 'axis']], |
|
109 | + // axes (axis), axes (ax), axes (axe) |
|
110 | + ['sexa', 4, false, false, ['ax', 'axe', 'axis']], |
|
111 | 111 | |
112 | - // indexes (index), matrixes (matrix) |
|
113 | - ['sex', 3, true, false, 'x'], |
|
112 | + // indexes (index), matrixes (matrix) |
|
113 | + ['sex', 3, true, false, 'x'], |
|
114 | 114 | |
115 | - // quizzes (quiz) |
|
116 | - ['sezz', 4, true, false, 'z'], |
|
115 | + // quizzes (quiz) |
|
116 | + ['sezz', 4, true, false, 'z'], |
|
117 | 117 | |
118 | - // bureaus (bureau) |
|
119 | - ['suae', 4, false, true, 'eau'], |
|
118 | + // bureaus (bureau) |
|
119 | + ['suae', 4, false, true, 'eau'], |
|
120 | 120 | |
121 | - // fees (fee), trees (tree), employees (employee) |
|
122 | - ['see', 3, true, true, 'ee'], |
|
121 | + // fees (fee), trees (tree), employees (employee) |
|
122 | + ['see', 3, true, true, 'ee'], |
|
123 | 123 | |
124 | - // edges (edge) |
|
125 | - ['segd', 4, true, true, 'dge'], |
|
124 | + // edges (edge) |
|
125 | + ['segd', 4, true, true, 'dge'], |
|
126 | 126 | |
127 | - // roses (rose), garages (garage), cassettes (cassette), |
|
128 | - // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), |
|
129 | - // shoes (shoe) |
|
130 | - ['se', 2, true, true, ['', 'e']], |
|
127 | + // roses (rose), garages (garage), cassettes (cassette), |
|
128 | + // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), |
|
129 | + // shoes (shoe) |
|
130 | + ['se', 2, true, true, ['', 'e']], |
|
131 | 131 | |
132 | - // tags (tag) |
|
133 | - ['s', 1, true, true, ''], |
|
132 | + // tags (tag) |
|
133 | + ['s', 1, true, true, ''], |
|
134 | 134 | |
135 | - // chateaux (chateau) |
|
136 | - ['xuae', 4, false, true, 'eau'], |
|
135 | + // chateaux (chateau) |
|
136 | + ['xuae', 4, false, true, 'eau'], |
|
137 | 137 | |
138 | - // people (person) |
|
139 | - ['elpoep', 6, true, true, 'person'], |
|
140 | - ]; |
|
138 | + // people (person) |
|
139 | + ['elpoep', 6, true, true, 'person'], |
|
140 | + ]; |
|
141 | 141 | |
142 | - /** |
|
143 | - * Map English singular to plural suffixes. |
|
144 | - * |
|
145 | - * @see http://english-zone.com/spelling/plurals.html |
|
146 | - */ |
|
147 | - private const SINGULAR_MAP = [ |
|
148 | - // First entry: singular suffix, reversed |
|
149 | - // Second entry: length of singular suffix |
|
150 | - // Third entry: Whether the suffix may succeed a vocal |
|
151 | - // Fourth entry: Whether the suffix may succeed a consonant |
|
152 | - // Fifth entry: plural suffix, normal |
|
142 | + /** |
|
143 | + * Map English singular to plural suffixes. |
|
144 | + * |
|
145 | + * @see http://english-zone.com/spelling/plurals.html |
|
146 | + */ |
|
147 | + private const SINGULAR_MAP = [ |
|
148 | + // First entry: singular suffix, reversed |
|
149 | + // Second entry: length of singular suffix |
|
150 | + // Third entry: Whether the suffix may succeed a vocal |
|
151 | + // Fourth entry: Whether the suffix may succeed a consonant |
|
152 | + // Fifth entry: plural suffix, normal |
|
153 | 153 | |
154 | - // criterion (criteria) |
|
155 | - ['airetirc', 8, false, false, 'criterion'], |
|
154 | + // criterion (criteria) |
|
155 | + ['airetirc', 8, false, false, 'criterion'], |
|
156 | 156 | |
157 | - // nebulae (nebula) |
|
158 | - ['aluben', 6, false, false, 'nebulae'], |
|
157 | + // nebulae (nebula) |
|
158 | + ['aluben', 6, false, false, 'nebulae'], |
|
159 | 159 | |
160 | - // children (child) |
|
161 | - ['dlihc', 5, true, true, 'children'], |
|
160 | + // children (child) |
|
161 | + ['dlihc', 5, true, true, 'children'], |
|
162 | 162 | |
163 | - // prices (price) |
|
164 | - ['eci', 3, false, true, 'ices'], |
|
163 | + // prices (price) |
|
164 | + ['eci', 3, false, true, 'ices'], |
|
165 | 165 | |
166 | - // services (service) |
|
167 | - ['ecivres', 7, true, true, 'services'], |
|
166 | + // services (service) |
|
167 | + ['ecivres', 7, true, true, 'services'], |
|
168 | 168 | |
169 | - // lives (life), wives (wife) |
|
170 | - ['efi', 3, false, true, 'ives'], |
|
169 | + // lives (life), wives (wife) |
|
170 | + ['efi', 3, false, true, 'ives'], |
|
171 | 171 | |
172 | - // selfies (selfie) |
|
173 | - ['eifles', 6, true, true, 'selfies'], |
|
172 | + // selfies (selfie) |
|
173 | + ['eifles', 6, true, true, 'selfies'], |
|
174 | 174 | |
175 | - // movies (movie) |
|
176 | - ['eivom', 5, true, true, 'movies'], |
|
175 | + // movies (movie) |
|
176 | + ['eivom', 5, true, true, 'movies'], |
|
177 | 177 | |
178 | - // lice (louse) |
|
179 | - ['esuol', 5, false, true, 'lice'], |
|
178 | + // lice (louse) |
|
179 | + ['esuol', 5, false, true, 'lice'], |
|
180 | 180 | |
181 | - // mice (mouse) |
|
182 | - ['esuom', 5, false, true, 'mice'], |
|
181 | + // mice (mouse) |
|
182 | + ['esuom', 5, false, true, 'mice'], |
|
183 | 183 | |
184 | - // geese (goose) |
|
185 | - ['esoo', 4, false, true, 'eese'], |
|
184 | + // geese (goose) |
|
185 | + ['esoo', 4, false, true, 'eese'], |
|
186 | 186 | |
187 | - // houses (house), bases (base) |
|
188 | - ['es', 2, true, true, 'ses'], |
|
187 | + // houses (house), bases (base) |
|
188 | + ['es', 2, true, true, 'ses'], |
|
189 | 189 | |
190 | - // geese (goose) |
|
191 | - ['esoog', 5, true, true, 'geese'], |
|
190 | + // geese (goose) |
|
191 | + ['esoog', 5, true, true, 'geese'], |
|
192 | 192 | |
193 | - // caves (cave) |
|
194 | - ['ev', 2, true, true, 'ves'], |
|
193 | + // caves (cave) |
|
194 | + ['ev', 2, true, true, 'ves'], |
|
195 | 195 | |
196 | - // drives (drive) |
|
197 | - ['evird', 5, false, true, 'drives'], |
|
196 | + // drives (drive) |
|
197 | + ['evird', 5, false, true, 'drives'], |
|
198 | 198 | |
199 | - // objectives (objective), alternative (alternatives) |
|
200 | - ['evit', 4, true, true, 'tives'], |
|
199 | + // objectives (objective), alternative (alternatives) |
|
200 | + ['evit', 4, true, true, 'tives'], |
|
201 | 201 | |
202 | - // moves (move) |
|
203 | - ['evom', 4, true, true, 'moves'], |
|
202 | + // moves (move) |
|
203 | + ['evom', 4, true, true, 'moves'], |
|
204 | 204 | |
205 | - // staves (staff) |
|
206 | - ['ffats', 5, true, true, 'staves'], |
|
205 | + // staves (staff) |
|
206 | + ['ffats', 5, true, true, 'staves'], |
|
207 | 207 | |
208 | - // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) |
|
209 | - ['ff', 2, true, true, 'ffs'], |
|
208 | + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) |
|
209 | + ['ff', 2, true, true, 'ffs'], |
|
210 | 210 | |
211 | - // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) |
|
212 | - ['f', 1, true, true, ['fs', 'ves']], |
|
211 | + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) |
|
212 | + ['f', 1, true, true, ['fs', 'ves']], |
|
213 | 213 | |
214 | - // arches (arch) |
|
215 | - ['hc', 2, true, true, 'ches'], |
|
214 | + // arches (arch) |
|
215 | + ['hc', 2, true, true, 'ches'], |
|
216 | 216 | |
217 | - // bushes (bush) |
|
218 | - ['hs', 2, true, true, 'shes'], |
|
217 | + // bushes (bush) |
|
218 | + ['hs', 2, true, true, 'shes'], |
|
219 | 219 | |
220 | - // teeth (tooth) |
|
221 | - ['htoot', 5, true, true, 'teeth'], |
|
220 | + // teeth (tooth) |
|
221 | + ['htoot', 5, true, true, 'teeth'], |
|
222 | 222 | |
223 | - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
224 | - ['mu', 2, true, true, 'a'], |
|
223 | + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
224 | + ['mu', 2, true, true, 'a'], |
|
225 | 225 | |
226 | - // men (man), women (woman) |
|
227 | - ['nam', 3, true, true, 'men'], |
|
226 | + // men (man), women (woman) |
|
227 | + ['nam', 3, true, true, 'men'], |
|
228 | 228 | |
229 | - // people (person) |
|
230 | - ['nosrep', 6, true, true, ['persons', 'people']], |
|
229 | + // people (person) |
|
230 | + ['nosrep', 6, true, true, ['persons', 'people']], |
|
231 | 231 | |
232 | - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
233 | - ['noi', 3, true, true, 'ions'], |
|
232 | + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
233 | + ['noi', 3, true, true, 'ions'], |
|
234 | 234 | |
235 | - // coupon (coupons) |
|
236 | - ['nop', 3, true, true, 'pons'], |
|
235 | + // coupon (coupons) |
|
236 | + ['nop', 3, true, true, 'pons'], |
|
237 | 237 | |
238 | - // seasons (season), treasons (treason), poisons (poison), lessons (lesson) |
|
239 | - ['nos', 3, true, true, 'sons'], |
|
238 | + // seasons (season), treasons (treason), poisons (poison), lessons (lesson) |
|
239 | + ['nos', 3, true, true, 'sons'], |
|
240 | 240 | |
241 | - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
242 | - ['no', 2, true, true, 'a'], |
|
241 | + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
|
242 | + ['no', 2, true, true, 'a'], |
|
243 | 243 | |
244 | - // echoes (echo) |
|
245 | - ['ohce', 4, true, true, 'echoes'], |
|
244 | + // echoes (echo) |
|
245 | + ['ohce', 4, true, true, 'echoes'], |
|
246 | 246 | |
247 | - // heroes (hero) |
|
248 | - ['oreh', 4, true, true, 'heroes'], |
|
247 | + // heroes (hero) |
|
248 | + ['oreh', 4, true, true, 'heroes'], |
|
249 | 249 | |
250 | - // atlases (atlas) |
|
251 | - ['salta', 5, true, true, 'atlases'], |
|
250 | + // atlases (atlas) |
|
251 | + ['salta', 5, true, true, 'atlases'], |
|
252 | 252 | |
253 | - // irises (iris) |
|
254 | - ['siri', 4, true, true, 'irises'], |
|
253 | + // irises (iris) |
|
254 | + ['siri', 4, true, true, 'irises'], |
|
255 | 255 | |
256 | - // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) |
|
257 | - // theses (thesis), emphases (emphasis), oases (oasis), |
|
258 | - // crises (crisis) |
|
259 | - ['sis', 3, true, true, 'ses'], |
|
256 | + // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) |
|
257 | + // theses (thesis), emphases (emphasis), oases (oasis), |
|
258 | + // crises (crisis) |
|
259 | + ['sis', 3, true, true, 'ses'], |
|
260 | 260 | |
261 | - // accesses (access), addresses (address), kisses (kiss) |
|
262 | - ['ss', 2, true, false, 'sses'], |
|
261 | + // accesses (access), addresses (address), kisses (kiss) |
|
262 | + ['ss', 2, true, false, 'sses'], |
|
263 | 263 | |
264 | - // syllabi (syllabus) |
|
265 | - ['suballys', 8, true, true, 'syllabi'], |
|
264 | + // syllabi (syllabus) |
|
265 | + ['suballys', 8, true, true, 'syllabi'], |
|
266 | 266 | |
267 | - // buses (bus) |
|
268 | - ['sub', 3, true, true, 'buses'], |
|
267 | + // buses (bus) |
|
268 | + ['sub', 3, true, true, 'buses'], |
|
269 | 269 | |
270 | - // circuses (circus) |
|
271 | - ['suc', 3, true, true, 'cuses'], |
|
270 | + // circuses (circus) |
|
271 | + ['suc', 3, true, true, 'cuses'], |
|
272 | 272 | |
273 | - // conspectuses (conspectus), prospectuses (prospectus) |
|
274 | - ['sutcep', 6, true, true, 'pectuses'], |
|
273 | + // conspectuses (conspectus), prospectuses (prospectus) |
|
274 | + ['sutcep', 6, true, true, 'pectuses'], |
|
275 | 275 | |
276 | - // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) |
|
277 | - ['su', 2, true, true, 'i'], |
|
276 | + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) |
|
277 | + ['su', 2, true, true, 'i'], |
|
278 | 278 | |
279 | - // news (news) |
|
280 | - ['swen', 4, true, true, 'news'], |
|
279 | + // news (news) |
|
280 | + ['swen', 4, true, true, 'news'], |
|
281 | 281 | |
282 | - // feet (foot) |
|
283 | - ['toof', 4, true, true, 'feet'], |
|
282 | + // feet (foot) |
|
283 | + ['toof', 4, true, true, 'feet'], |
|
284 | 284 | |
285 | - // chateaux (chateau), bureaus (bureau) |
|
286 | - ['uae', 3, false, true, ['eaus', 'eaux']], |
|
285 | + // chateaux (chateau), bureaus (bureau) |
|
286 | + ['uae', 3, false, true, ['eaus', 'eaux']], |
|
287 | 287 | |
288 | - // oxen (ox) |
|
289 | - ['xo', 2, false, false, 'oxen'], |
|
288 | + // oxen (ox) |
|
289 | + ['xo', 2, false, false, 'oxen'], |
|
290 | 290 | |
291 | - // hoaxes (hoax) |
|
292 | - ['xaoh', 4, true, false, 'hoaxes'], |
|
291 | + // hoaxes (hoax) |
|
292 | + ['xaoh', 4, true, false, 'hoaxes'], |
|
293 | 293 | |
294 | - // indices (index) |
|
295 | - ['xedni', 5, false, true, ['indicies', 'indexes']], |
|
294 | + // indices (index) |
|
295 | + ['xedni', 5, false, true, ['indicies', 'indexes']], |
|
296 | 296 | |
297 | - // boxes (box) |
|
298 | - ['xo', 2, false, true, 'oxes'], |
|
297 | + // boxes (box) |
|
298 | + ['xo', 2, false, true, 'oxes'], |
|
299 | 299 | |
300 | - // indexes (index), matrixes (matrix) |
|
301 | - ['x', 1, true, false, ['cies', 'xes']], |
|
300 | + // indexes (index), matrixes (matrix) |
|
301 | + ['x', 1, true, false, ['cies', 'xes']], |
|
302 | 302 | |
303 | - // appendices (appendix) |
|
304 | - ['xi', 2, false, true, 'ices'], |
|
303 | + // appendices (appendix) |
|
304 | + ['xi', 2, false, true, 'ices'], |
|
305 | 305 | |
306 | - // babies (baby) |
|
307 | - ['y', 1, false, true, 'ies'], |
|
306 | + // babies (baby) |
|
307 | + ['y', 1, false, true, 'ies'], |
|
308 | 308 | |
309 | - // quizzes (quiz) |
|
310 | - ['ziuq', 4, true, false, 'quizzes'], |
|
309 | + // quizzes (quiz) |
|
310 | + ['ziuq', 4, true, false, 'quizzes'], |
|
311 | 311 | |
312 | - // waltzes (waltz) |
|
313 | - ['z', 1, true, true, 'zes'], |
|
314 | - ]; |
|
312 | + // waltzes (waltz) |
|
313 | + ['z', 1, true, true, 'zes'], |
|
314 | + ]; |
|
315 | 315 | |
316 | - /** |
|
317 | - * A list of words which should not be inflected, reversed. |
|
318 | - */ |
|
319 | - private const UNINFLECTED = [ |
|
320 | - '', |
|
316 | + /** |
|
317 | + * A list of words which should not be inflected, reversed. |
|
318 | + */ |
|
319 | + private const UNINFLECTED = [ |
|
320 | + '', |
|
321 | 321 | |
322 | - // data |
|
323 | - 'atad', |
|
322 | + // data |
|
323 | + 'atad', |
|
324 | 324 | |
325 | - // deer |
|
326 | - 'reed', |
|
325 | + // deer |
|
326 | + 'reed', |
|
327 | 327 | |
328 | - // feedback |
|
329 | - 'kcabdeef', |
|
328 | + // feedback |
|
329 | + 'kcabdeef', |
|
330 | 330 | |
331 | - // fish |
|
332 | - 'hsif', |
|
331 | + // fish |
|
332 | + 'hsif', |
|
333 | 333 | |
334 | - // info |
|
335 | - 'ofni', |
|
334 | + // info |
|
335 | + 'ofni', |
|
336 | 336 | |
337 | - // moose |
|
338 | - 'esoom', |
|
337 | + // moose |
|
338 | + 'esoom', |
|
339 | 339 | |
340 | - // series |
|
341 | - 'seires', |
|
340 | + // series |
|
341 | + 'seires', |
|
342 | 342 | |
343 | - // sheep |
|
344 | - 'peehs', |
|
343 | + // sheep |
|
344 | + 'peehs', |
|
345 | 345 | |
346 | - // species |
|
347 | - 'seiceps', |
|
348 | - ]; |
|
349 | - |
|
350 | - /** |
|
351 | - * {@inheritdoc} |
|
352 | - */ |
|
353 | - public function singularize(string $plural): array |
|
354 | - { |
|
355 | - $pluralRev = strrev($plural); |
|
356 | - $lowerPluralRev = strtolower($pluralRev); |
|
357 | - $pluralLength = \strlen($lowerPluralRev); |
|
358 | - |
|
359 | - // Check if the word is one which is not inflected, return early if so |
|
360 | - if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) { |
|
361 | - return [$plural]; |
|
362 | - } |
|
363 | - |
|
364 | - // The outer loop iterates over the entries of the plural table |
|
365 | - // The inner loop $j iterates over the characters of the plural suffix |
|
366 | - // in the plural table to compare them with the characters of the actual |
|
367 | - // given plural suffix |
|
368 | - foreach (self::PLURAL_MAP as $map) { |
|
369 | - $suffix = $map[0]; |
|
370 | - $suffixLength = $map[1]; |
|
371 | - $j = 0; |
|
372 | - |
|
373 | - // Compare characters in the plural table and of the suffix of the |
|
374 | - // given plural one by one |
|
375 | - while ($suffix[$j] === $lowerPluralRev[$j]) { |
|
376 | - // Let $j point to the next character |
|
377 | - ++$j; |
|
378 | - |
|
379 | - // Successfully compared the last character |
|
380 | - // Add an entry with the singular suffix to the singular array |
|
381 | - if ($j === $suffixLength) { |
|
382 | - // Is there any character preceding the suffix in the plural string? |
|
383 | - if ($j < $pluralLength) { |
|
384 | - $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); |
|
385 | - |
|
386 | - if (!$map[2] && $nextIsVocal) { |
|
387 | - // suffix may not succeed a vocal but next char is one |
|
388 | - break; |
|
389 | - } |
|
390 | - |
|
391 | - if (!$map[3] && !$nextIsVocal) { |
|
392 | - // suffix may not succeed a consonant but next char is one |
|
393 | - break; |
|
394 | - } |
|
395 | - } |
|
396 | - |
|
397 | - $newBase = substr($plural, 0, $pluralLength - $suffixLength); |
|
398 | - $newSuffix = $map[4]; |
|
399 | - |
|
400 | - // Check whether the first character in the plural suffix |
|
401 | - // is uppercased. If yes, uppercase the first character in |
|
402 | - // the singular suffix too |
|
403 | - $firstUpper = ctype_upper($pluralRev[$j - 1]); |
|
404 | - |
|
405 | - if (\is_array($newSuffix)) { |
|
406 | - $singulars = []; |
|
407 | - |
|
408 | - foreach ($newSuffix as $newSuffixEntry) { |
|
409 | - $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); |
|
410 | - } |
|
411 | - |
|
412 | - return $singulars; |
|
413 | - } |
|
414 | - |
|
415 | - return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; |
|
416 | - } |
|
417 | - |
|
418 | - // Suffix is longer than word |
|
419 | - if ($j === $pluralLength) { |
|
420 | - break; |
|
421 | - } |
|
422 | - } |
|
423 | - } |
|
424 | - |
|
425 | - // Assume that plural and singular is identical |
|
426 | - return [$plural]; |
|
427 | - } |
|
428 | - |
|
429 | - /** |
|
430 | - * {@inheritdoc} |
|
431 | - */ |
|
432 | - public function pluralize(string $singular): array |
|
433 | - { |
|
434 | - $singularRev = strrev($singular); |
|
435 | - $lowerSingularRev = strtolower($singularRev); |
|
436 | - $singularLength = \strlen($lowerSingularRev); |
|
437 | - |
|
438 | - // Check if the word is one which is not inflected, return early if so |
|
439 | - if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) { |
|
440 | - return [$singular]; |
|
441 | - } |
|
442 | - |
|
443 | - // The outer loop iterates over the entries of the singular table |
|
444 | - // The inner loop $j iterates over the characters of the singular suffix |
|
445 | - // in the singular table to compare them with the characters of the actual |
|
446 | - // given singular suffix |
|
447 | - foreach (self::SINGULAR_MAP as $map) { |
|
448 | - $suffix = $map[0]; |
|
449 | - $suffixLength = $map[1]; |
|
450 | - $j = 0; |
|
451 | - |
|
452 | - // Compare characters in the singular table and of the suffix of the |
|
453 | - // given plural one by one |
|
454 | - |
|
455 | - while ($suffix[$j] === $lowerSingularRev[$j]) { |
|
456 | - // Let $j point to the next character |
|
457 | - ++$j; |
|
458 | - |
|
459 | - // Successfully compared the last character |
|
460 | - // Add an entry with the plural suffix to the plural array |
|
461 | - if ($j === $suffixLength) { |
|
462 | - // Is there any character preceding the suffix in the plural string? |
|
463 | - if ($j < $singularLength) { |
|
464 | - $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); |
|
465 | - |
|
466 | - if (!$map[2] && $nextIsVocal) { |
|
467 | - // suffix may not succeed a vocal but next char is one |
|
468 | - break; |
|
469 | - } |
|
470 | - |
|
471 | - if (!$map[3] && !$nextIsVocal) { |
|
472 | - // suffix may not succeed a consonant but next char is one |
|
473 | - break; |
|
474 | - } |
|
475 | - } |
|
476 | - |
|
477 | - $newBase = substr($singular, 0, $singularLength - $suffixLength); |
|
478 | - $newSuffix = $map[4]; |
|
479 | - |
|
480 | - // Check whether the first character in the singular suffix |
|
481 | - // is uppercased. If yes, uppercase the first character in |
|
482 | - // the singular suffix too |
|
483 | - $firstUpper = ctype_upper($singularRev[$j - 1]); |
|
484 | - |
|
485 | - if (\is_array($newSuffix)) { |
|
486 | - $plurals = []; |
|
487 | - |
|
488 | - foreach ($newSuffix as $newSuffixEntry) { |
|
489 | - $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); |
|
490 | - } |
|
491 | - |
|
492 | - return $plurals; |
|
493 | - } |
|
494 | - |
|
495 | - return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; |
|
496 | - } |
|
497 | - |
|
498 | - // Suffix is longer than word |
|
499 | - if ($j === $singularLength) { |
|
500 | - break; |
|
501 | - } |
|
502 | - } |
|
503 | - } |
|
504 | - |
|
505 | - // Assume that plural is singular with a trailing `s` |
|
506 | - return [$singular.'s']; |
|
507 | - } |
|
346 | + // species |
|
347 | + 'seiceps', |
|
348 | + ]; |
|
349 | + |
|
350 | + /** |
|
351 | + * {@inheritdoc} |
|
352 | + */ |
|
353 | + public function singularize(string $plural): array |
|
354 | + { |
|
355 | + $pluralRev = strrev($plural); |
|
356 | + $lowerPluralRev = strtolower($pluralRev); |
|
357 | + $pluralLength = \strlen($lowerPluralRev); |
|
358 | + |
|
359 | + // Check if the word is one which is not inflected, return early if so |
|
360 | + if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) { |
|
361 | + return [$plural]; |
|
362 | + } |
|
363 | + |
|
364 | + // The outer loop iterates over the entries of the plural table |
|
365 | + // The inner loop $j iterates over the characters of the plural suffix |
|
366 | + // in the plural table to compare them with the characters of the actual |
|
367 | + // given plural suffix |
|
368 | + foreach (self::PLURAL_MAP as $map) { |
|
369 | + $suffix = $map[0]; |
|
370 | + $suffixLength = $map[1]; |
|
371 | + $j = 0; |
|
372 | + |
|
373 | + // Compare characters in the plural table and of the suffix of the |
|
374 | + // given plural one by one |
|
375 | + while ($suffix[$j] === $lowerPluralRev[$j]) { |
|
376 | + // Let $j point to the next character |
|
377 | + ++$j; |
|
378 | + |
|
379 | + // Successfully compared the last character |
|
380 | + // Add an entry with the singular suffix to the singular array |
|
381 | + if ($j === $suffixLength) { |
|
382 | + // Is there any character preceding the suffix in the plural string? |
|
383 | + if ($j < $pluralLength) { |
|
384 | + $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); |
|
385 | + |
|
386 | + if (!$map[2] && $nextIsVocal) { |
|
387 | + // suffix may not succeed a vocal but next char is one |
|
388 | + break; |
|
389 | + } |
|
390 | + |
|
391 | + if (!$map[3] && !$nextIsVocal) { |
|
392 | + // suffix may not succeed a consonant but next char is one |
|
393 | + break; |
|
394 | + } |
|
395 | + } |
|
396 | + |
|
397 | + $newBase = substr($plural, 0, $pluralLength - $suffixLength); |
|
398 | + $newSuffix = $map[4]; |
|
399 | + |
|
400 | + // Check whether the first character in the plural suffix |
|
401 | + // is uppercased. If yes, uppercase the first character in |
|
402 | + // the singular suffix too |
|
403 | + $firstUpper = ctype_upper($pluralRev[$j - 1]); |
|
404 | + |
|
405 | + if (\is_array($newSuffix)) { |
|
406 | + $singulars = []; |
|
407 | + |
|
408 | + foreach ($newSuffix as $newSuffixEntry) { |
|
409 | + $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); |
|
410 | + } |
|
411 | + |
|
412 | + return $singulars; |
|
413 | + } |
|
414 | + |
|
415 | + return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; |
|
416 | + } |
|
417 | + |
|
418 | + // Suffix is longer than word |
|
419 | + if ($j === $pluralLength) { |
|
420 | + break; |
|
421 | + } |
|
422 | + } |
|
423 | + } |
|
424 | + |
|
425 | + // Assume that plural and singular is identical |
|
426 | + return [$plural]; |
|
427 | + } |
|
428 | + |
|
429 | + /** |
|
430 | + * {@inheritdoc} |
|
431 | + */ |
|
432 | + public function pluralize(string $singular): array |
|
433 | + { |
|
434 | + $singularRev = strrev($singular); |
|
435 | + $lowerSingularRev = strtolower($singularRev); |
|
436 | + $singularLength = \strlen($lowerSingularRev); |
|
437 | + |
|
438 | + // Check if the word is one which is not inflected, return early if so |
|
439 | + if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) { |
|
440 | + return [$singular]; |
|
441 | + } |
|
442 | + |
|
443 | + // The outer loop iterates over the entries of the singular table |
|
444 | + // The inner loop $j iterates over the characters of the singular suffix |
|
445 | + // in the singular table to compare them with the characters of the actual |
|
446 | + // given singular suffix |
|
447 | + foreach (self::SINGULAR_MAP as $map) { |
|
448 | + $suffix = $map[0]; |
|
449 | + $suffixLength = $map[1]; |
|
450 | + $j = 0; |
|
451 | + |
|
452 | + // Compare characters in the singular table and of the suffix of the |
|
453 | + // given plural one by one |
|
454 | + |
|
455 | + while ($suffix[$j] === $lowerSingularRev[$j]) { |
|
456 | + // Let $j point to the next character |
|
457 | + ++$j; |
|
458 | + |
|
459 | + // Successfully compared the last character |
|
460 | + // Add an entry with the plural suffix to the plural array |
|
461 | + if ($j === $suffixLength) { |
|
462 | + // Is there any character preceding the suffix in the plural string? |
|
463 | + if ($j < $singularLength) { |
|
464 | + $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); |
|
465 | + |
|
466 | + if (!$map[2] && $nextIsVocal) { |
|
467 | + // suffix may not succeed a vocal but next char is one |
|
468 | + break; |
|
469 | + } |
|
470 | + |
|
471 | + if (!$map[3] && !$nextIsVocal) { |
|
472 | + // suffix may not succeed a consonant but next char is one |
|
473 | + break; |
|
474 | + } |
|
475 | + } |
|
476 | + |
|
477 | + $newBase = substr($singular, 0, $singularLength - $suffixLength); |
|
478 | + $newSuffix = $map[4]; |
|
479 | + |
|
480 | + // Check whether the first character in the singular suffix |
|
481 | + // is uppercased. If yes, uppercase the first character in |
|
482 | + // the singular suffix too |
|
483 | + $firstUpper = ctype_upper($singularRev[$j - 1]); |
|
484 | + |
|
485 | + if (\is_array($newSuffix)) { |
|
486 | + $plurals = []; |
|
487 | + |
|
488 | + foreach ($newSuffix as $newSuffixEntry) { |
|
489 | + $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); |
|
490 | + } |
|
491 | + |
|
492 | + return $plurals; |
|
493 | + } |
|
494 | + |
|
495 | + return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; |
|
496 | + } |
|
497 | + |
|
498 | + // Suffix is longer than word |
|
499 | + if ($j === $singularLength) { |
|
500 | + break; |
|
501 | + } |
|
502 | + } |
|
503 | + } |
|
504 | + |
|
505 | + // Assume that plural is singular with a trailing `s` |
|
506 | + return [$singular.'s']; |
|
507 | + } |
|
508 | 508 | } |
@@ -26,117 +26,117 @@ discard block |
||
26 | 26 | // Fifth entry: singular suffix, normal |
27 | 27 | |
28 | 28 | // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
29 | - ['a', 1, true, true, ['on', 'um']], |
|
29 | + [ 'a', 1, true, true, [ 'on', 'um' ] ], |
|
30 | 30 | |
31 | 31 | // nebulae (nebula) |
32 | - ['ea', 2, true, true, 'a'], |
|
32 | + [ 'ea', 2, true, true, 'a' ], |
|
33 | 33 | |
34 | 34 | // services (service) |
35 | - ['secivres', 8, true, true, 'service'], |
|
35 | + [ 'secivres', 8, true, true, 'service' ], |
|
36 | 36 | |
37 | 37 | // mice (mouse), lice (louse) |
38 | - ['eci', 3, false, true, 'ouse'], |
|
38 | + [ 'eci', 3, false, true, 'ouse' ], |
|
39 | 39 | |
40 | 40 | // geese (goose) |
41 | - ['esee', 4, false, true, 'oose'], |
|
41 | + [ 'esee', 4, false, true, 'oose' ], |
|
42 | 42 | |
43 | 43 | // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) |
44 | - ['i', 1, true, true, 'us'], |
|
44 | + [ 'i', 1, true, true, 'us' ], |
|
45 | 45 | |
46 | 46 | // men (man), women (woman) |
47 | - ['nem', 3, true, true, 'man'], |
|
47 | + [ 'nem', 3, true, true, 'man' ], |
|
48 | 48 | |
49 | 49 | // children (child) |
50 | - ['nerdlihc', 8, true, true, 'child'], |
|
50 | + [ 'nerdlihc', 8, true, true, 'child' ], |
|
51 | 51 | |
52 | 52 | // oxen (ox) |
53 | - ['nexo', 4, false, false, 'ox'], |
|
53 | + [ 'nexo', 4, false, false, 'ox' ], |
|
54 | 54 | |
55 | 55 | // indices (index), appendices (appendix), prices (price) |
56 | - ['seci', 4, false, true, ['ex', 'ix', 'ice']], |
|
56 | + [ 'seci', 4, false, true, [ 'ex', 'ix', 'ice' ] ], |
|
57 | 57 | |
58 | 58 | // selfies (selfie) |
59 | - ['seifles', 7, true, true, 'selfie'], |
|
59 | + [ 'seifles', 7, true, true, 'selfie' ], |
|
60 | 60 | |
61 | 61 | // movies (movie) |
62 | - ['seivom', 6, true, true, 'movie'], |
|
62 | + [ 'seivom', 6, true, true, 'movie' ], |
|
63 | 63 | |
64 | 64 | // conspectuses (conspectus), prospectuses (prospectus) |
65 | - ['sesutcep', 8, true, true, 'pectus'], |
|
65 | + [ 'sesutcep', 8, true, true, 'pectus' ], |
|
66 | 66 | |
67 | 67 | // feet (foot) |
68 | - ['teef', 4, true, true, 'foot'], |
|
68 | + [ 'teef', 4, true, true, 'foot' ], |
|
69 | 69 | |
70 | 70 | // geese (goose) |
71 | - ['eseeg', 5, true, true, 'goose'], |
|
71 | + [ 'eseeg', 5, true, true, 'goose' ], |
|
72 | 72 | |
73 | 73 | // teeth (tooth) |
74 | - ['hteet', 5, true, true, 'tooth'], |
|
74 | + [ 'hteet', 5, true, true, 'tooth' ], |
|
75 | 75 | |
76 | 76 | // news (news) |
77 | - ['swen', 4, true, true, 'news'], |
|
77 | + [ 'swen', 4, true, true, 'news' ], |
|
78 | 78 | |
79 | 79 | // series (series) |
80 | - ['seires', 6, true, true, 'series'], |
|
80 | + [ 'seires', 6, true, true, 'series' ], |
|
81 | 81 | |
82 | 82 | // babies (baby) |
83 | - ['sei', 3, false, true, 'y'], |
|
83 | + [ 'sei', 3, false, true, 'y' ], |
|
84 | 84 | |
85 | 85 | // accesses (access), addresses (address), kisses (kiss) |
86 | - ['sess', 4, true, false, 'ss'], |
|
86 | + [ 'sess', 4, true, false, 'ss' ], |
|
87 | 87 | |
88 | 88 | // analyses (analysis), ellipses (ellipsis), fungi (fungus), |
89 | 89 | // neuroses (neurosis), theses (thesis), emphases (emphasis), |
90 | 90 | // oases (oasis), crises (crisis), houses (house), bases (base), |
91 | 91 | // atlases (atlas) |
92 | - ['ses', 3, true, true, ['s', 'se', 'sis']], |
|
92 | + [ 'ses', 3, true, true, [ 's', 'se', 'sis' ] ], |
|
93 | 93 | |
94 | 94 | // objectives (objective), alternative (alternatives) |
95 | - ['sevit', 5, true, true, 'tive'], |
|
95 | + [ 'sevit', 5, true, true, 'tive' ], |
|
96 | 96 | |
97 | 97 | // drives (drive) |
98 | - ['sevird', 6, false, true, 'drive'], |
|
98 | + [ 'sevird', 6, false, true, 'drive' ], |
|
99 | 99 | |
100 | 100 | // lives (life), wives (wife) |
101 | - ['sevi', 4, false, true, 'ife'], |
|
101 | + [ 'sevi', 4, false, true, 'ife' ], |
|
102 | 102 | |
103 | 103 | // moves (move) |
104 | - ['sevom', 5, true, true, 'move'], |
|
104 | + [ 'sevom', 5, true, true, 'move' ], |
|
105 | 105 | |
106 | 106 | // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) |
107 | - ['sev', 3, true, true, ['f', 've', 'ff']], |
|
107 | + [ 'sev', 3, true, true, [ 'f', 've', 'ff' ] ], |
|
108 | 108 | |
109 | 109 | // axes (axis), axes (ax), axes (axe) |
110 | - ['sexa', 4, false, false, ['ax', 'axe', 'axis']], |
|
110 | + [ 'sexa', 4, false, false, [ 'ax', 'axe', 'axis' ] ], |
|
111 | 111 | |
112 | 112 | // indexes (index), matrixes (matrix) |
113 | - ['sex', 3, true, false, 'x'], |
|
113 | + [ 'sex', 3, true, false, 'x' ], |
|
114 | 114 | |
115 | 115 | // quizzes (quiz) |
116 | - ['sezz', 4, true, false, 'z'], |
|
116 | + [ 'sezz', 4, true, false, 'z' ], |
|
117 | 117 | |
118 | 118 | // bureaus (bureau) |
119 | - ['suae', 4, false, true, 'eau'], |
|
119 | + [ 'suae', 4, false, true, 'eau' ], |
|
120 | 120 | |
121 | 121 | // fees (fee), trees (tree), employees (employee) |
122 | - ['see', 3, true, true, 'ee'], |
|
122 | + [ 'see', 3, true, true, 'ee' ], |
|
123 | 123 | |
124 | 124 | // edges (edge) |
125 | - ['segd', 4, true, true, 'dge'], |
|
125 | + [ 'segd', 4, true, true, 'dge' ], |
|
126 | 126 | |
127 | 127 | // roses (rose), garages (garage), cassettes (cassette), |
128 | 128 | // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), |
129 | 129 | // shoes (shoe) |
130 | - ['se', 2, true, true, ['', 'e']], |
|
130 | + [ 'se', 2, true, true, [ '', 'e' ] ], |
|
131 | 131 | |
132 | 132 | // tags (tag) |
133 | - ['s', 1, true, true, ''], |
|
133 | + [ 's', 1, true, true, '' ], |
|
134 | 134 | |
135 | 135 | // chateaux (chateau) |
136 | - ['xuae', 4, false, true, 'eau'], |
|
136 | + [ 'xuae', 4, false, true, 'eau' ], |
|
137 | 137 | |
138 | 138 | // people (person) |
139 | - ['elpoep', 6, true, true, 'person'], |
|
139 | + [ 'elpoep', 6, true, true, 'person' ], |
|
140 | 140 | ]; |
141 | 141 | |
142 | 142 | /** |
@@ -152,165 +152,165 @@ discard block |
||
152 | 152 | // Fifth entry: plural suffix, normal |
153 | 153 | |
154 | 154 | // criterion (criteria) |
155 | - ['airetirc', 8, false, false, 'criterion'], |
|
155 | + [ 'airetirc', 8, false, false, 'criterion' ], |
|
156 | 156 | |
157 | 157 | // nebulae (nebula) |
158 | - ['aluben', 6, false, false, 'nebulae'], |
|
158 | + [ 'aluben', 6, false, false, 'nebulae' ], |
|
159 | 159 | |
160 | 160 | // children (child) |
161 | - ['dlihc', 5, true, true, 'children'], |
|
161 | + [ 'dlihc', 5, true, true, 'children' ], |
|
162 | 162 | |
163 | 163 | // prices (price) |
164 | - ['eci', 3, false, true, 'ices'], |
|
164 | + [ 'eci', 3, false, true, 'ices' ], |
|
165 | 165 | |
166 | 166 | // services (service) |
167 | - ['ecivres', 7, true, true, 'services'], |
|
167 | + [ 'ecivres', 7, true, true, 'services' ], |
|
168 | 168 | |
169 | 169 | // lives (life), wives (wife) |
170 | - ['efi', 3, false, true, 'ives'], |
|
170 | + [ 'efi', 3, false, true, 'ives' ], |
|
171 | 171 | |
172 | 172 | // selfies (selfie) |
173 | - ['eifles', 6, true, true, 'selfies'], |
|
173 | + [ 'eifles', 6, true, true, 'selfies' ], |
|
174 | 174 | |
175 | 175 | // movies (movie) |
176 | - ['eivom', 5, true, true, 'movies'], |
|
176 | + [ 'eivom', 5, true, true, 'movies' ], |
|
177 | 177 | |
178 | 178 | // lice (louse) |
179 | - ['esuol', 5, false, true, 'lice'], |
|
179 | + [ 'esuol', 5, false, true, 'lice' ], |
|
180 | 180 | |
181 | 181 | // mice (mouse) |
182 | - ['esuom', 5, false, true, 'mice'], |
|
182 | + [ 'esuom', 5, false, true, 'mice' ], |
|
183 | 183 | |
184 | 184 | // geese (goose) |
185 | - ['esoo', 4, false, true, 'eese'], |
|
185 | + [ 'esoo', 4, false, true, 'eese' ], |
|
186 | 186 | |
187 | 187 | // houses (house), bases (base) |
188 | - ['es', 2, true, true, 'ses'], |
|
188 | + [ 'es', 2, true, true, 'ses' ], |
|
189 | 189 | |
190 | 190 | // geese (goose) |
191 | - ['esoog', 5, true, true, 'geese'], |
|
191 | + [ 'esoog', 5, true, true, 'geese' ], |
|
192 | 192 | |
193 | 193 | // caves (cave) |
194 | - ['ev', 2, true, true, 'ves'], |
|
194 | + [ 'ev', 2, true, true, 'ves' ], |
|
195 | 195 | |
196 | 196 | // drives (drive) |
197 | - ['evird', 5, false, true, 'drives'], |
|
197 | + [ 'evird', 5, false, true, 'drives' ], |
|
198 | 198 | |
199 | 199 | // objectives (objective), alternative (alternatives) |
200 | - ['evit', 4, true, true, 'tives'], |
|
200 | + [ 'evit', 4, true, true, 'tives' ], |
|
201 | 201 | |
202 | 202 | // moves (move) |
203 | - ['evom', 4, true, true, 'moves'], |
|
203 | + [ 'evom', 4, true, true, 'moves' ], |
|
204 | 204 | |
205 | 205 | // staves (staff) |
206 | - ['ffats', 5, true, true, 'staves'], |
|
206 | + [ 'ffats', 5, true, true, 'staves' ], |
|
207 | 207 | |
208 | 208 | // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) |
209 | - ['ff', 2, true, true, 'ffs'], |
|
209 | + [ 'ff', 2, true, true, 'ffs' ], |
|
210 | 210 | |
211 | 211 | // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) |
212 | - ['f', 1, true, true, ['fs', 'ves']], |
|
212 | + [ 'f', 1, true, true, [ 'fs', 'ves' ] ], |
|
213 | 213 | |
214 | 214 | // arches (arch) |
215 | - ['hc', 2, true, true, 'ches'], |
|
215 | + [ 'hc', 2, true, true, 'ches' ], |
|
216 | 216 | |
217 | 217 | // bushes (bush) |
218 | - ['hs', 2, true, true, 'shes'], |
|
218 | + [ 'hs', 2, true, true, 'shes' ], |
|
219 | 219 | |
220 | 220 | // teeth (tooth) |
221 | - ['htoot', 5, true, true, 'teeth'], |
|
221 | + [ 'htoot', 5, true, true, 'teeth' ], |
|
222 | 222 | |
223 | 223 | // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
224 | - ['mu', 2, true, true, 'a'], |
|
224 | + [ 'mu', 2, true, true, 'a' ], |
|
225 | 225 | |
226 | 226 | // men (man), women (woman) |
227 | - ['nam', 3, true, true, 'men'], |
|
227 | + [ 'nam', 3, true, true, 'men' ], |
|
228 | 228 | |
229 | 229 | // people (person) |
230 | - ['nosrep', 6, true, true, ['persons', 'people']], |
|
230 | + [ 'nosrep', 6, true, true, [ 'persons', 'people' ] ], |
|
231 | 231 | |
232 | 232 | // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
233 | - ['noi', 3, true, true, 'ions'], |
|
233 | + [ 'noi', 3, true, true, 'ions' ], |
|
234 | 234 | |
235 | 235 | // coupon (coupons) |
236 | - ['nop', 3, true, true, 'pons'], |
|
236 | + [ 'nop', 3, true, true, 'pons' ], |
|
237 | 237 | |
238 | 238 | // seasons (season), treasons (treason), poisons (poison), lessons (lesson) |
239 | - ['nos', 3, true, true, 'sons'], |
|
239 | + [ 'nos', 3, true, true, 'sons' ], |
|
240 | 240 | |
241 | 241 | // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) |
242 | - ['no', 2, true, true, 'a'], |
|
242 | + [ 'no', 2, true, true, 'a' ], |
|
243 | 243 | |
244 | 244 | // echoes (echo) |
245 | - ['ohce', 4, true, true, 'echoes'], |
|
245 | + [ 'ohce', 4, true, true, 'echoes' ], |
|
246 | 246 | |
247 | 247 | // heroes (hero) |
248 | - ['oreh', 4, true, true, 'heroes'], |
|
248 | + [ 'oreh', 4, true, true, 'heroes' ], |
|
249 | 249 | |
250 | 250 | // atlases (atlas) |
251 | - ['salta', 5, true, true, 'atlases'], |
|
251 | + [ 'salta', 5, true, true, 'atlases' ], |
|
252 | 252 | |
253 | 253 | // irises (iris) |
254 | - ['siri', 4, true, true, 'irises'], |
|
254 | + [ 'siri', 4, true, true, 'irises' ], |
|
255 | 255 | |
256 | 256 | // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) |
257 | 257 | // theses (thesis), emphases (emphasis), oases (oasis), |
258 | 258 | // crises (crisis) |
259 | - ['sis', 3, true, true, 'ses'], |
|
259 | + [ 'sis', 3, true, true, 'ses' ], |
|
260 | 260 | |
261 | 261 | // accesses (access), addresses (address), kisses (kiss) |
262 | - ['ss', 2, true, false, 'sses'], |
|
262 | + [ 'ss', 2, true, false, 'sses' ], |
|
263 | 263 | |
264 | 264 | // syllabi (syllabus) |
265 | - ['suballys', 8, true, true, 'syllabi'], |
|
265 | + [ 'suballys', 8, true, true, 'syllabi' ], |
|
266 | 266 | |
267 | 267 | // buses (bus) |
268 | - ['sub', 3, true, true, 'buses'], |
|
268 | + [ 'sub', 3, true, true, 'buses' ], |
|
269 | 269 | |
270 | 270 | // circuses (circus) |
271 | - ['suc', 3, true, true, 'cuses'], |
|
271 | + [ 'suc', 3, true, true, 'cuses' ], |
|
272 | 272 | |
273 | 273 | // conspectuses (conspectus), prospectuses (prospectus) |
274 | - ['sutcep', 6, true, true, 'pectuses'], |
|
274 | + [ 'sutcep', 6, true, true, 'pectuses' ], |
|
275 | 275 | |
276 | 276 | // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) |
277 | - ['su', 2, true, true, 'i'], |
|
277 | + [ 'su', 2, true, true, 'i' ], |
|
278 | 278 | |
279 | 279 | // news (news) |
280 | - ['swen', 4, true, true, 'news'], |
|
280 | + [ 'swen', 4, true, true, 'news' ], |
|
281 | 281 | |
282 | 282 | // feet (foot) |
283 | - ['toof', 4, true, true, 'feet'], |
|
283 | + [ 'toof', 4, true, true, 'feet' ], |
|
284 | 284 | |
285 | 285 | // chateaux (chateau), bureaus (bureau) |
286 | - ['uae', 3, false, true, ['eaus', 'eaux']], |
|
286 | + [ 'uae', 3, false, true, [ 'eaus', 'eaux' ] ], |
|
287 | 287 | |
288 | 288 | // oxen (ox) |
289 | - ['xo', 2, false, false, 'oxen'], |
|
289 | + [ 'xo', 2, false, false, 'oxen' ], |
|
290 | 290 | |
291 | 291 | // hoaxes (hoax) |
292 | - ['xaoh', 4, true, false, 'hoaxes'], |
|
292 | + [ 'xaoh', 4, true, false, 'hoaxes' ], |
|
293 | 293 | |
294 | 294 | // indices (index) |
295 | - ['xedni', 5, false, true, ['indicies', 'indexes']], |
|
295 | + [ 'xedni', 5, false, true, [ 'indicies', 'indexes' ] ], |
|
296 | 296 | |
297 | 297 | // boxes (box) |
298 | - ['xo', 2, false, true, 'oxes'], |
|
298 | + [ 'xo', 2, false, true, 'oxes' ], |
|
299 | 299 | |
300 | 300 | // indexes (index), matrixes (matrix) |
301 | - ['x', 1, true, false, ['cies', 'xes']], |
|
301 | + [ 'x', 1, true, false, [ 'cies', 'xes' ] ], |
|
302 | 302 | |
303 | 303 | // appendices (appendix) |
304 | - ['xi', 2, false, true, 'ices'], |
|
304 | + [ 'xi', 2, false, true, 'ices' ], |
|
305 | 305 | |
306 | 306 | // babies (baby) |
307 | - ['y', 1, false, true, 'ies'], |
|
307 | + [ 'y', 1, false, true, 'ies' ], |
|
308 | 308 | |
309 | 309 | // quizzes (quiz) |
310 | - ['ziuq', 4, true, false, 'quizzes'], |
|
310 | + [ 'ziuq', 4, true, false, 'quizzes' ], |
|
311 | 311 | |
312 | 312 | // waltzes (waltz) |
313 | - ['z', 1, true, true, 'zes'], |
|
313 | + [ 'z', 1, true, true, 'zes' ], |
|
314 | 314 | ]; |
315 | 315 | |
316 | 316 | /** |
@@ -350,159 +350,159 @@ discard block |
||
350 | 350 | /** |
351 | 351 | * {@inheritdoc} |
352 | 352 | */ |
353 | - public function singularize(string $plural): array |
|
353 | + public function singularize( string $plural ): array |
|
354 | 354 | { |
355 | - $pluralRev = strrev($plural); |
|
356 | - $lowerPluralRev = strtolower($pluralRev); |
|
357 | - $pluralLength = \strlen($lowerPluralRev); |
|
355 | + $pluralRev = strrev( $plural ); |
|
356 | + $lowerPluralRev = strtolower( $pluralRev ); |
|
357 | + $pluralLength = \strlen( $lowerPluralRev ); |
|
358 | 358 | |
359 | 359 | // Check if the word is one which is not inflected, return early if so |
360 | - if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) { |
|
361 | - return [$plural]; |
|
360 | + if ( \in_array( $lowerPluralRev, self::UNINFLECTED, true ) ) { |
|
361 | + return [ $plural ]; |
|
362 | 362 | } |
363 | 363 | |
364 | 364 | // The outer loop iterates over the entries of the plural table |
365 | 365 | // The inner loop $j iterates over the characters of the plural suffix |
366 | 366 | // in the plural table to compare them with the characters of the actual |
367 | 367 | // given plural suffix |
368 | - foreach (self::PLURAL_MAP as $map) { |
|
369 | - $suffix = $map[0]; |
|
370 | - $suffixLength = $map[1]; |
|
368 | + foreach ( self::PLURAL_MAP as $map ) { |
|
369 | + $suffix = $map[ 0 ]; |
|
370 | + $suffixLength = $map[ 1 ]; |
|
371 | 371 | $j = 0; |
372 | 372 | |
373 | 373 | // Compare characters in the plural table and of the suffix of the |
374 | 374 | // given plural one by one |
375 | - while ($suffix[$j] === $lowerPluralRev[$j]) { |
|
375 | + while ( $suffix[ $j ] === $lowerPluralRev[ $j ] ) { |
|
376 | 376 | // Let $j point to the next character |
377 | 377 | ++$j; |
378 | 378 | |
379 | 379 | // Successfully compared the last character |
380 | 380 | // Add an entry with the singular suffix to the singular array |
381 | - if ($j === $suffixLength) { |
|
381 | + if ( $j === $suffixLength ) { |
|
382 | 382 | // Is there any character preceding the suffix in the plural string? |
383 | - if ($j < $pluralLength) { |
|
384 | - $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); |
|
383 | + if ( $j < $pluralLength ) { |
|
384 | + $nextIsVocal = false !== strpos( 'aeiou', $lowerPluralRev[ $j ] ); |
|
385 | 385 | |
386 | - if (!$map[2] && $nextIsVocal) { |
|
386 | + if ( ! $map[ 2 ] && $nextIsVocal ) { |
|
387 | 387 | // suffix may not succeed a vocal but next char is one |
388 | 388 | break; |
389 | 389 | } |
390 | 390 | |
391 | - if (!$map[3] && !$nextIsVocal) { |
|
391 | + if ( ! $map[ 3 ] && ! $nextIsVocal ) { |
|
392 | 392 | // suffix may not succeed a consonant but next char is one |
393 | 393 | break; |
394 | 394 | } |
395 | 395 | } |
396 | 396 | |
397 | - $newBase = substr($plural, 0, $pluralLength - $suffixLength); |
|
398 | - $newSuffix = $map[4]; |
|
397 | + $newBase = substr( $plural, 0, $pluralLength - $suffixLength ); |
|
398 | + $newSuffix = $map[ 4 ]; |
|
399 | 399 | |
400 | 400 | // Check whether the first character in the plural suffix |
401 | 401 | // is uppercased. If yes, uppercase the first character in |
402 | 402 | // the singular suffix too |
403 | - $firstUpper = ctype_upper($pluralRev[$j - 1]); |
|
403 | + $firstUpper = ctype_upper( $pluralRev[ $j - 1 ] ); |
|
404 | 404 | |
405 | - if (\is_array($newSuffix)) { |
|
406 | - $singulars = []; |
|
405 | + if ( \is_array( $newSuffix ) ) { |
|
406 | + $singulars = [ ]; |
|
407 | 407 | |
408 | - foreach ($newSuffix as $newSuffixEntry) { |
|
409 | - $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); |
|
408 | + foreach ( $newSuffix as $newSuffixEntry ) { |
|
409 | + $singulars[ ] = $newBase . ( $firstUpper ? ucfirst( $newSuffixEntry ) : $newSuffixEntry ); |
|
410 | 410 | } |
411 | 411 | |
412 | 412 | return $singulars; |
413 | 413 | } |
414 | 414 | |
415 | - return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; |
|
415 | + return [ $newBase . ( $firstUpper ? ucfirst( $newSuffix ) : $newSuffix ) ]; |
|
416 | 416 | } |
417 | 417 | |
418 | 418 | // Suffix is longer than word |
419 | - if ($j === $pluralLength) { |
|
419 | + if ( $j === $pluralLength ) { |
|
420 | 420 | break; |
421 | 421 | } |
422 | 422 | } |
423 | 423 | } |
424 | 424 | |
425 | 425 | // Assume that plural and singular is identical |
426 | - return [$plural]; |
|
426 | + return [ $plural ]; |
|
427 | 427 | } |
428 | 428 | |
429 | 429 | /** |
430 | 430 | * {@inheritdoc} |
431 | 431 | */ |
432 | - public function pluralize(string $singular): array |
|
432 | + public function pluralize( string $singular ): array |
|
433 | 433 | { |
434 | - $singularRev = strrev($singular); |
|
435 | - $lowerSingularRev = strtolower($singularRev); |
|
436 | - $singularLength = \strlen($lowerSingularRev); |
|
434 | + $singularRev = strrev( $singular ); |
|
435 | + $lowerSingularRev = strtolower( $singularRev ); |
|
436 | + $singularLength = \strlen( $lowerSingularRev ); |
|
437 | 437 | |
438 | 438 | // Check if the word is one which is not inflected, return early if so |
439 | - if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) { |
|
440 | - return [$singular]; |
|
439 | + if ( \in_array( $lowerSingularRev, self::UNINFLECTED, true ) ) { |
|
440 | + return [ $singular ]; |
|
441 | 441 | } |
442 | 442 | |
443 | 443 | // The outer loop iterates over the entries of the singular table |
444 | 444 | // The inner loop $j iterates over the characters of the singular suffix |
445 | 445 | // in the singular table to compare them with the characters of the actual |
446 | 446 | // given singular suffix |
447 | - foreach (self::SINGULAR_MAP as $map) { |
|
448 | - $suffix = $map[0]; |
|
449 | - $suffixLength = $map[1]; |
|
447 | + foreach ( self::SINGULAR_MAP as $map ) { |
|
448 | + $suffix = $map[ 0 ]; |
|
449 | + $suffixLength = $map[ 1 ]; |
|
450 | 450 | $j = 0; |
451 | 451 | |
452 | 452 | // Compare characters in the singular table and of the suffix of the |
453 | 453 | // given plural one by one |
454 | 454 | |
455 | - while ($suffix[$j] === $lowerSingularRev[$j]) { |
|
455 | + while ( $suffix[ $j ] === $lowerSingularRev[ $j ] ) { |
|
456 | 456 | // Let $j point to the next character |
457 | 457 | ++$j; |
458 | 458 | |
459 | 459 | // Successfully compared the last character |
460 | 460 | // Add an entry with the plural suffix to the plural array |
461 | - if ($j === $suffixLength) { |
|
461 | + if ( $j === $suffixLength ) { |
|
462 | 462 | // Is there any character preceding the suffix in the plural string? |
463 | - if ($j < $singularLength) { |
|
464 | - $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); |
|
463 | + if ( $j < $singularLength ) { |
|
464 | + $nextIsVocal = false !== strpos( 'aeiou', $lowerSingularRev[ $j ] ); |
|
465 | 465 | |
466 | - if (!$map[2] && $nextIsVocal) { |
|
466 | + if ( ! $map[ 2 ] && $nextIsVocal ) { |
|
467 | 467 | // suffix may not succeed a vocal but next char is one |
468 | 468 | break; |
469 | 469 | } |
470 | 470 | |
471 | - if (!$map[3] && !$nextIsVocal) { |
|
471 | + if ( ! $map[ 3 ] && ! $nextIsVocal ) { |
|
472 | 472 | // suffix may not succeed a consonant but next char is one |
473 | 473 | break; |
474 | 474 | } |
475 | 475 | } |
476 | 476 | |
477 | - $newBase = substr($singular, 0, $singularLength - $suffixLength); |
|
478 | - $newSuffix = $map[4]; |
|
477 | + $newBase = substr( $singular, 0, $singularLength - $suffixLength ); |
|
478 | + $newSuffix = $map[ 4 ]; |
|
479 | 479 | |
480 | 480 | // Check whether the first character in the singular suffix |
481 | 481 | // is uppercased. If yes, uppercase the first character in |
482 | 482 | // the singular suffix too |
483 | - $firstUpper = ctype_upper($singularRev[$j - 1]); |
|
483 | + $firstUpper = ctype_upper( $singularRev[ $j - 1 ] ); |
|
484 | 484 | |
485 | - if (\is_array($newSuffix)) { |
|
486 | - $plurals = []; |
|
485 | + if ( \is_array( $newSuffix ) ) { |
|
486 | + $plurals = [ ]; |
|
487 | 487 | |
488 | - foreach ($newSuffix as $newSuffixEntry) { |
|
489 | - $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); |
|
488 | + foreach ( $newSuffix as $newSuffixEntry ) { |
|
489 | + $plurals[ ] = $newBase . ( $firstUpper ? ucfirst( $newSuffixEntry ) : $newSuffixEntry ); |
|
490 | 490 | } |
491 | 491 | |
492 | 492 | return $plurals; |
493 | 493 | } |
494 | 494 | |
495 | - return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; |
|
495 | + return [ $newBase . ( $firstUpper ? ucfirst( $newSuffix ) : $newSuffix ) ]; |
|
496 | 496 | } |
497 | 497 | |
498 | 498 | // Suffix is longer than word |
499 | - if ($j === $singularLength) { |
|
499 | + if ( $j === $singularLength ) { |
|
500 | 500 | break; |
501 | 501 | } |
502 | 502 | } |
503 | 503 | } |
504 | 504 | |
505 | 505 | // Assume that plural is singular with a trailing `s` |
506 | - return [$singular.'s']; |
|
506 | + return [ $singular . 's' ]; |
|
507 | 507 | } |
508 | 508 | } |
@@ -11,8 +11,7 @@ |
||
11 | 11 | |
12 | 12 | namespace Symfony\Component\String\Inflector; |
13 | 13 | |
14 | -final class EnglishInflector implements InflectorInterface |
|
15 | -{ |
|
14 | +final class EnglishInflector implements InflectorInterface { |
|
16 | 15 | /** |
17 | 16 | * Map English plural to singular suffixes. |
18 | 17 | * |
@@ -14,6 +14,5 @@ |
||
14 | 14 | /** |
15 | 15 | * @author Christian Flothmann <[email protected]> |
16 | 16 | */ |
17 | -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface |
|
18 | -{ |
|
17 | +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { |
|
19 | 18 | } |
@@ -19,16 +19,16 @@ |
||
19 | 19 | */ |
20 | 20 | class FileNotFoundException extends IOException |
21 | 21 | { |
22 | - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) |
|
23 | - { |
|
24 | - if (null === $message) { |
|
25 | - if (null === $path) { |
|
26 | - $message = 'File could not be found.'; |
|
27 | - } else { |
|
28 | - $message = sprintf('File "%s" could not be found.', $path); |
|
29 | - } |
|
30 | - } |
|
22 | + public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) |
|
23 | + { |
|
24 | + if (null === $message) { |
|
25 | + if (null === $path) { |
|
26 | + $message = 'File could not be found.'; |
|
27 | + } else { |
|
28 | + $message = sprintf('File "%s" could not be found.', $path); |
|
29 | + } |
|
30 | + } |
|
31 | 31 | |
32 | - parent::__construct($message, $code, $previous, $path); |
|
33 | - } |
|
32 | + parent::__construct($message, $code, $previous, $path); |
|
33 | + } |
|
34 | 34 | } |
@@ -19,16 +19,16 @@ |
||
19 | 19 | */ |
20 | 20 | class FileNotFoundException extends IOException |
21 | 21 | { |
22 | - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) |
|
22 | + public function __construct( string $message = null, int $code = 0, \Throwable $previous = null, string $path = null ) |
|
23 | 23 | { |
24 | - if (null === $message) { |
|
25 | - if (null === $path) { |
|
24 | + if ( null === $message ) { |
|
25 | + if ( null === $path ) { |
|
26 | 26 | $message = 'File could not be found.'; |
27 | 27 | } else { |
28 | - $message = sprintf('File "%s" could not be found.', $path); |
|
28 | + $message = sprintf( 'File "%s" could not be found.', $path ); |
|
29 | 29 | } |
30 | 30 | } |
31 | 31 | |
32 | - parent::__construct($message, $code, $previous, $path); |
|
32 | + parent::__construct( $message, $code, $previous, $path ); |
|
33 | 33 | } |
34 | 34 | } |
@@ -17,10 +17,8 @@ |
||
17 | 17 | * @author Fabien Potencier <[email protected]> |
18 | 18 | * @author Christian Gärtner <[email protected]> |
19 | 19 | */ |
20 | -class FileNotFoundException extends IOException |
|
21 | -{ |
|
22 | - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) |
|
23 | - { |
|
20 | +class FileNotFoundException extends IOException { |
|
21 | + public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) { |
|
24 | 22 | if (null === $message) { |
25 | 23 | if (null === $path) { |
26 | 24 | $message = 'File could not be found.'; |
@@ -16,6 +16,5 @@ |
||
16 | 16 | * |
17 | 17 | * @author Romain Neutron <[email protected]> |
18 | 18 | */ |
19 | -interface ExceptionInterface extends \Throwable |
|
20 | -{ |
|
19 | +interface ExceptionInterface extends \Throwable { |
|
21 | 20 | } |
@@ -20,20 +20,20 @@ |
||
20 | 20 | */ |
21 | 21 | class IOException extends \RuntimeException implements IOExceptionInterface |
22 | 22 | { |
23 | - private $path; |
|
23 | + private $path; |
|
24 | 24 | |
25 | - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) |
|
26 | - { |
|
27 | - $this->path = $path; |
|
25 | + public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) |
|
26 | + { |
|
27 | + $this->path = $path; |
|
28 | 28 | |
29 | - parent::__construct($message, $code, $previous); |
|
30 | - } |
|
29 | + parent::__construct($message, $code, $previous); |
|
30 | + } |
|
31 | 31 | |
32 | - /** |
|
33 | - * {@inheritdoc} |
|
34 | - */ |
|
35 | - public function getPath() |
|
36 | - { |
|
37 | - return $this->path; |
|
38 | - } |
|
32 | + /** |
|
33 | + * {@inheritdoc} |
|
34 | + */ |
|
35 | + public function getPath() |
|
36 | + { |
|
37 | + return $this->path; |
|
38 | + } |
|
39 | 39 | } |
@@ -22,11 +22,11 @@ |
||
22 | 22 | { |
23 | 23 | private $path; |
24 | 24 | |
25 | - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) |
|
25 | + public function __construct( string $message, int $code = 0, \Throwable $previous = null, string $path = null ) |
|
26 | 26 | { |
27 | 27 | $this->path = $path; |
28 | 28 | |
29 | - parent::__construct($message, $code, $previous); |
|
29 | + parent::__construct( $message, $code, $previous ); |
|
30 | 30 | } |
31 | 31 | |
32 | 32 | /** |
@@ -18,12 +18,10 @@ discard block |
||
18 | 18 | * @author Christian Gärtner <[email protected]> |
19 | 19 | * @author Fabien Potencier <[email protected]> |
20 | 20 | */ |
21 | -class IOException extends \RuntimeException implements IOExceptionInterface |
|
22 | -{ |
|
21 | +class IOException extends \RuntimeException implements IOExceptionInterface { |
|
23 | 22 | private $path; |
24 | 23 | |
25 | - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) |
|
26 | - { |
|
24 | + public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) { |
|
27 | 25 | $this->path = $path; |
28 | 26 | |
29 | 27 | parent::__construct($message, $code, $previous); |
@@ -32,8 +30,7 @@ discard block |
||
32 | 30 | /** |
33 | 31 | * {@inheritdoc} |
34 | 32 | */ |
35 | - public function getPath() |
|
36 | - { |
|
33 | + public function getPath() { |
|
37 | 34 | return $this->path; |
38 | 35 | } |
39 | 36 | } |
@@ -18,10 +18,10 @@ |
||
18 | 18 | */ |
19 | 19 | interface IOExceptionInterface extends ExceptionInterface |
20 | 20 | { |
21 | - /** |
|
22 | - * Returns the associated path for the exception. |
|
23 | - * |
|
24 | - * @return string|null The path |
|
25 | - */ |
|
26 | - public function getPath(); |
|
21 | + /** |
|
22 | + * Returns the associated path for the exception. |
|
23 | + * |
|
24 | + * @return string|null The path |
|
25 | + */ |
|
26 | + public function getPath(); |
|
27 | 27 | } |
@@ -16,8 +16,7 @@ |
||
16 | 16 | * |
17 | 17 | * @author Christian Gärtner <[email protected]> |
18 | 18 | */ |
19 | -interface IOExceptionInterface extends ExceptionInterface |
|
20 | -{ |
|
19 | +interface IOExceptionInterface extends ExceptionInterface { |
|
21 | 20 | /** |
22 | 21 | * Returns the associated path for the exception. |
23 | 22 | * |