Completed
Push — develop ( 32764c...cb3cfa )
by
unknown
20:26
created
vendor/symfony/console/ConsoleEvents.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -23,50 +23,50 @@
 block discarded – undo
23 23
  */
24 24
 final class ConsoleEvents
25 25
 {
26
-    /**
27
-     * The COMMAND event allows you to attach listeners before any command is
28
-     * executed by the console. It also allows you to modify the command, input and output
29
-     * before they are handed to the command.
30
-     *
31
-     * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
32
-     */
33
-    public const COMMAND = 'console.command';
26
+	/**
27
+	 * The COMMAND event allows you to attach listeners before any command is
28
+	 * executed by the console. It also allows you to modify the command, input and output
29
+	 * before they are handed to the command.
30
+	 *
31
+	 * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
32
+	 */
33
+	public const COMMAND = 'console.command';
34 34
 
35
-    /**
36
-     * The SIGNAL event allows you to perform some actions
37
-     * after the command execution was interrupted.
38
-     *
39
-     * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent")
40
-     */
41
-    public const SIGNAL = 'console.signal';
35
+	/**
36
+	 * The SIGNAL event allows you to perform some actions
37
+	 * after the command execution was interrupted.
38
+	 *
39
+	 * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent")
40
+	 */
41
+	public const SIGNAL = 'console.signal';
42 42
 
43
-    /**
44
-     * The TERMINATE event allows you to attach listeners after a command is
45
-     * executed by the console.
46
-     *
47
-     * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
48
-     */
49
-    public const TERMINATE = 'console.terminate';
43
+	/**
44
+	 * The TERMINATE event allows you to attach listeners after a command is
45
+	 * executed by the console.
46
+	 *
47
+	 * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
48
+	 */
49
+	public const TERMINATE = 'console.terminate';
50 50
 
51
-    /**
52
-     * The ERROR event occurs when an uncaught exception or error appears.
53
-     *
54
-     * This event allows you to deal with the exception/error or
55
-     * to modify the thrown exception.
56
-     *
57
-     * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
58
-     */
59
-    public const ERROR = 'console.error';
51
+	/**
52
+	 * The ERROR event occurs when an uncaught exception or error appears.
53
+	 *
54
+	 * This event allows you to deal with the exception/error or
55
+	 * to modify the thrown exception.
56
+	 *
57
+	 * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
58
+	 */
59
+	public const ERROR = 'console.error';
60 60
 
61
-    /**
62
-     * Event aliases.
63
-     *
64
-     * These aliases can be consumed by RegisterListenersPass.
65
-     */
66
-    public const ALIASES = [
67
-        ConsoleCommandEvent::class => self::COMMAND,
68
-        ConsoleErrorEvent::class => self::ERROR,
69
-        ConsoleSignalEvent::class => self::SIGNAL,
70
-        ConsoleTerminateEvent::class => self::TERMINATE,
71
-    ];
61
+	/**
62
+	 * Event aliases.
63
+	 *
64
+	 * These aliases can be consumed by RegisterListenersPass.
65
+	 */
66
+	public const ALIASES = [
67
+		ConsoleCommandEvent::class => self::COMMAND,
68
+		ConsoleErrorEvent::class => self::ERROR,
69
+		ConsoleSignalEvent::class => self::SIGNAL,
70
+		ConsoleTerminateEvent::class => self::TERMINATE,
71
+	];
72 72
 }
Please login to merge, or discard this patch.
vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -29,120 +29,120 @@
 block discarded – undo
29 29
  */
30 30
 class AddConsoleCommandPass implements CompilerPassInterface
31 31
 {
32
-    private $commandLoaderServiceId;
33
-    private $commandTag;
34
-    private $noPreloadTag;
35
-    private $privateTagName;
36
-
37
-    public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload', string $privateTagName = 'container.private')
38
-    {
39
-        if (0 < \func_num_args()) {
40
-            trigger_deprecation('symfony/console', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
41
-        }
42
-
43
-        $this->commandLoaderServiceId = $commandLoaderServiceId;
44
-        $this->commandTag = $commandTag;
45
-        $this->noPreloadTag = $noPreloadTag;
46
-        $this->privateTagName = $privateTagName;
47
-    }
48
-
49
-    public function process(ContainerBuilder $container)
50
-    {
51
-        $commandServices = $container->findTaggedServiceIds($this->commandTag, true);
52
-        $lazyCommandMap = [];
53
-        $lazyCommandRefs = [];
54
-        $serviceIds = [];
55
-
56
-        foreach ($commandServices as $id => $tags) {
57
-            $definition = $container->getDefinition($id);
58
-            $definition->addTag($this->noPreloadTag);
59
-            $class = $container->getParameterBag()->resolveValue($definition->getClass());
60
-
61
-            if (isset($tags[0]['command'])) {
62
-                $aliases = $tags[0]['command'];
63
-            } else {
64
-                if (!$r = $container->getReflectionClass($class)) {
65
-                    throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
66
-                }
67
-                if (!$r->isSubclassOf(Command::class)) {
68
-                    throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
69
-                }
70
-                $aliases = $class::getDefaultName();
71
-            }
72
-
73
-            $aliases = explode('|', $aliases ?? '');
74
-            $commandName = array_shift($aliases);
75
-
76
-            if ($isHidden = '' === $commandName) {
77
-                $commandName = array_shift($aliases);
78
-            }
79
-
80
-            if (null === $commandName) {
81
-                if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag($this->privateTagName)) {
82
-                    $commandId = 'console.command.public_alias.'.$id;
83
-                    $container->setAlias($commandId, $id)->setPublic(true);
84
-                    $id = $commandId;
85
-                }
86
-                $serviceIds[] = $id;
87
-
88
-                continue;
89
-            }
90
-
91
-            $description = $tags[0]['description'] ?? null;
92
-
93
-            unset($tags[0]);
94
-            $lazyCommandMap[$commandName] = $id;
95
-            $lazyCommandRefs[$id] = new TypedReference($id, $class);
96
-
97
-            foreach ($aliases as $alias) {
98
-                $lazyCommandMap[$alias] = $id;
99
-            }
100
-
101
-            foreach ($tags as $tag) {
102
-                if (isset($tag['command'])) {
103
-                    $aliases[] = $tag['command'];
104
-                    $lazyCommandMap[$tag['command']] = $id;
105
-                }
106
-
107
-                $description = $description ?? $tag['description'] ?? null;
108
-            }
109
-
110
-            $definition->addMethodCall('setName', [$commandName]);
111
-
112
-            if ($aliases) {
113
-                $definition->addMethodCall('setAliases', [$aliases]);
114
-            }
115
-
116
-            if ($isHidden) {
117
-                $definition->addMethodCall('setHidden', [true]);
118
-            }
119
-
120
-            if (!$description) {
121
-                if (!$r = $container->getReflectionClass($class)) {
122
-                    throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
123
-                }
124
-                if (!$r->isSubclassOf(Command::class)) {
125
-                    throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
126
-                }
127
-                $description = $class::getDefaultDescription();
128
-            }
129
-
130
-            if ($description) {
131
-                $definition->addMethodCall('setDescription', [$description]);
132
-
133
-                $container->register('.'.$id.'.lazy', LazyCommand::class)
134
-                    ->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);
135
-
136
-                $lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy');
137
-            }
138
-        }
139
-
140
-        $container
141
-            ->register($this->commandLoaderServiceId, ContainerCommandLoader::class)
142
-            ->setPublic(true)
143
-            ->addTag($this->noPreloadTag)
144
-            ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);
145
-
146
-        $container->setParameter('console.command.ids', $serviceIds);
147
-    }
32
+	private $commandLoaderServiceId;
33
+	private $commandTag;
34
+	private $noPreloadTag;
35
+	private $privateTagName;
36
+
37
+	public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload', string $privateTagName = 'container.private')
38
+	{
39
+		if (0 < \func_num_args()) {
40
+			trigger_deprecation('symfony/console', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
41
+		}
42
+
43
+		$this->commandLoaderServiceId = $commandLoaderServiceId;
44
+		$this->commandTag = $commandTag;
45
+		$this->noPreloadTag = $noPreloadTag;
46
+		$this->privateTagName = $privateTagName;
47
+	}
48
+
49
+	public function process(ContainerBuilder $container)
50
+	{
51
+		$commandServices = $container->findTaggedServiceIds($this->commandTag, true);
52
+		$lazyCommandMap = [];
53
+		$lazyCommandRefs = [];
54
+		$serviceIds = [];
55
+
56
+		foreach ($commandServices as $id => $tags) {
57
+			$definition = $container->getDefinition($id);
58
+			$definition->addTag($this->noPreloadTag);
59
+			$class = $container->getParameterBag()->resolveValue($definition->getClass());
60
+
61
+			if (isset($tags[0]['command'])) {
62
+				$aliases = $tags[0]['command'];
63
+			} else {
64
+				if (!$r = $container->getReflectionClass($class)) {
65
+					throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
66
+				}
67
+				if (!$r->isSubclassOf(Command::class)) {
68
+					throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
69
+				}
70
+				$aliases = $class::getDefaultName();
71
+			}
72
+
73
+			$aliases = explode('|', $aliases ?? '');
74
+			$commandName = array_shift($aliases);
75
+
76
+			if ($isHidden = '' === $commandName) {
77
+				$commandName = array_shift($aliases);
78
+			}
79
+
80
+			if (null === $commandName) {
81
+				if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag($this->privateTagName)) {
82
+					$commandId = 'console.command.public_alias.'.$id;
83
+					$container->setAlias($commandId, $id)->setPublic(true);
84
+					$id = $commandId;
85
+				}
86
+				$serviceIds[] = $id;
87
+
88
+				continue;
89
+			}
90
+
91
+			$description = $tags[0]['description'] ?? null;
92
+
93
+			unset($tags[0]);
94
+			$lazyCommandMap[$commandName] = $id;
95
+			$lazyCommandRefs[$id] = new TypedReference($id, $class);
96
+
97
+			foreach ($aliases as $alias) {
98
+				$lazyCommandMap[$alias] = $id;
99
+			}
100
+
101
+			foreach ($tags as $tag) {
102
+				if (isset($tag['command'])) {
103
+					$aliases[] = $tag['command'];
104
+					$lazyCommandMap[$tag['command']] = $id;
105
+				}
106
+
107
+				$description = $description ?? $tag['description'] ?? null;
108
+			}
109
+
110
+			$definition->addMethodCall('setName', [$commandName]);
111
+
112
+			if ($aliases) {
113
+				$definition->addMethodCall('setAliases', [$aliases]);
114
+			}
115
+
116
+			if ($isHidden) {
117
+				$definition->addMethodCall('setHidden', [true]);
118
+			}
119
+
120
+			if (!$description) {
121
+				if (!$r = $container->getReflectionClass($class)) {
122
+					throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
123
+				}
124
+				if (!$r->isSubclassOf(Command::class)) {
125
+					throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
126
+				}
127
+				$description = $class::getDefaultDescription();
128
+			}
129
+
130
+			if ($description) {
131
+				$definition->addMethodCall('setDescription', [$description]);
132
+
133
+				$container->register('.'.$id.'.lazy', LazyCommand::class)
134
+					->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);
135
+
136
+				$lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy');
137
+			}
138
+		}
139
+
140
+		$container
141
+			->register($this->commandLoaderServiceId, ContainerCommandLoader::class)
142
+			->setPublic(true)
143
+			->addTag($this->noPreloadTag)
144
+			->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);
145
+
146
+		$container->setParameter('console.command.ids', $serviceIds);
147
+	}
148 148
 }
Please login to merge, or discard this patch.
vendor/symfony/string/UnicodeString.php 1 patch
Indentation   +342 added lines, -342 removed lines patch added patch discarded remove patch
@@ -32,346 +32,346 @@
 block discarded – undo
32 32
  */
33 33
 class UnicodeString extends AbstractUnicodeString
34 34
 {
35
-    public function __construct(string $string = '')
36
-    {
37
-        $this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string);
38
-
39
-        if (false === $this->string) {
40
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
41
-        }
42
-    }
43
-
44
-    public function append(string ...$suffix): AbstractString
45
-    {
46
-        $str = clone $this;
47
-        $str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix));
48
-        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
49
-
50
-        if (false === $str->string) {
51
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
52
-        }
53
-
54
-        return $str;
55
-    }
56
-
57
-    public function chunk(int $length = 1): array
58
-    {
59
-        if (1 > $length) {
60
-            throw new InvalidArgumentException('The chunk length must be greater than zero.');
61
-        }
62
-
63
-        if ('' === $this->string) {
64
-            return [];
65
-        }
66
-
67
-        $rx = '/(';
68
-        while (65535 < $length) {
69
-            $rx .= '\X{65535}';
70
-            $length -= 65535;
71
-        }
72
-        $rx .= '\X{'.$length.'})/u';
73
-
74
-        $str = clone $this;
75
-        $chunks = [];
76
-
77
-        foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
78
-            $str->string = $chunk;
79
-            $chunks[] = clone $str;
80
-        }
81
-
82
-        return $chunks;
83
-    }
84
-
85
-    public function endsWith($suffix): bool
86
-    {
87
-        if ($suffix instanceof AbstractString) {
88
-            $suffix = $suffix->string;
89
-        } elseif (\is_array($suffix) || $suffix instanceof \Traversable) {
90
-            return parent::endsWith($suffix);
91
-        } else {
92
-            $suffix = (string) $suffix;
93
-        }
94
-
95
-        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
96
-        normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form);
97
-
98
-        if ('' === $suffix || false === $suffix) {
99
-            return false;
100
-        }
101
-
102
-        if ($this->ignoreCase) {
103
-            return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8');
104
-        }
105
-
106
-        return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix));
107
-    }
108
-
109
-    public function equalsTo($string): bool
110
-    {
111
-        if ($string instanceof AbstractString) {
112
-            $string = $string->string;
113
-        } elseif (\is_array($string) || $string instanceof \Traversable) {
114
-            return parent::equalsTo($string);
115
-        } else {
116
-            $string = (string) $string;
117
-        }
118
-
119
-        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
120
-        normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form);
121
-
122
-        if ('' !== $string && false !== $string && $this->ignoreCase) {
123
-            return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
124
-        }
125
-
126
-        return $string === $this->string;
127
-    }
128
-
129
-    public function indexOf($needle, int $offset = 0): ?int
130
-    {
131
-        if ($needle instanceof AbstractString) {
132
-            $needle = $needle->string;
133
-        } elseif (\is_array($needle) || $needle instanceof \Traversable) {
134
-            return parent::indexOf($needle, $offset);
135
-        } else {
136
-            $needle = (string) $needle;
137
-        }
138
-
139
-        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
140
-        normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);
141
-
142
-        if ('' === $needle || false === $needle) {
143
-            return null;
144
-        }
145
-
146
-        try {
147
-            $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset);
148
-        } catch (\ValueError $e) {
149
-            return null;
150
-        }
151
-
152
-        return false === $i ? null : $i;
153
-    }
154
-
155
-    public function indexOfLast($needle, int $offset = 0): ?int
156
-    {
157
-        if ($needle instanceof AbstractString) {
158
-            $needle = $needle->string;
159
-        } elseif (\is_array($needle) || $needle instanceof \Traversable) {
160
-            return parent::indexOfLast($needle, $offset);
161
-        } else {
162
-            $needle = (string) $needle;
163
-        }
164
-
165
-        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
166
-        normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);
167
-
168
-        if ('' === $needle || false === $needle) {
169
-            return null;
170
-        }
171
-
172
-        $string = $this->string;
173
-
174
-        if (0 > $offset) {
175
-            // workaround https://bugs.php.net/74264
176
-            if (0 > $offset += grapheme_strlen($needle)) {
177
-                $string = grapheme_substr($string, 0, $offset);
178
-            }
179
-            $offset = 0;
180
-        }
181
-
182
-        $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset);
183
-
184
-        return false === $i ? null : $i;
185
-    }
186
-
187
-    public function join(array $strings, string $lastGlue = null): AbstractString
188
-    {
189
-        $str = parent::join($strings, $lastGlue);
190
-        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
191
-
192
-        return $str;
193
-    }
194
-
195
-    public function length(): int
196
-    {
197
-        return grapheme_strlen($this->string);
198
-    }
199
-
200
-    /**
201
-     * @return static
202
-     */
203
-    public function normalize(int $form = self::NFC): parent
204
-    {
205
-        $str = clone $this;
206
-
207
-        if (\in_array($form, [self::NFC, self::NFKC], true)) {
208
-            normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form);
209
-        } elseif (!\in_array($form, [self::NFD, self::NFKD], true)) {
210
-            throw new InvalidArgumentException('Unsupported normalization form.');
211
-        } elseif (!normalizer_is_normalized($str->string, $form)) {
212
-            $str->string = normalizer_normalize($str->string, $form);
213
-            $str->ignoreCase = null;
214
-        }
215
-
216
-        return $str;
217
-    }
218
-
219
-    public function prepend(string ...$prefix): AbstractString
220
-    {
221
-        $str = clone $this;
222
-        $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string;
223
-        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
224
-
225
-        if (false === $str->string) {
226
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
227
-        }
228
-
229
-        return $str;
230
-    }
231
-
232
-    public function replace(string $from, string $to): AbstractString
233
-    {
234
-        $str = clone $this;
235
-        normalizer_is_normalized($from) ?: $from = normalizer_normalize($from);
236
-
237
-        if ('' !== $from && false !== $from) {
238
-            $tail = $str->string;
239
-            $result = '';
240
-            $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
241
-
242
-            while ('' !== $tail && false !== $i = $indexOf($tail, $from)) {
243
-                $slice = grapheme_substr($tail, 0, $i);
244
-                $result .= $slice.$to;
245
-                $tail = substr($tail, \strlen($slice) + \strlen($from));
246
-            }
247
-
248
-            $str->string = $result.$tail;
249
-            normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
250
-
251
-            if (false === $str->string) {
252
-                throw new InvalidArgumentException('Invalid UTF-8 string.');
253
-            }
254
-        }
255
-
256
-        return $str;
257
-    }
258
-
259
-    public function replaceMatches(string $fromRegexp, $to): AbstractString
260
-    {
261
-        $str = parent::replaceMatches($fromRegexp, $to);
262
-        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
263
-
264
-        return $str;
265
-    }
266
-
267
-    public function slice(int $start = 0, int $length = null): AbstractString
268
-    {
269
-        $str = clone $this;
270
-
271
-        if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) {
272
-            $start = 0;
273
-        }
274
-        $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647);
275
-
276
-        return $str;
277
-    }
278
-
279
-    public function splice(string $replacement, int $start = 0, int $length = null): AbstractString
280
-    {
281
-        $str = clone $this;
282
-
283
-        if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) {
284
-            $start = 0;
285
-        }
286
-        $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0;
287
-        $length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length;
288
-        $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647);
289
-        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
290
-
291
-        if (false === $str->string) {
292
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
293
-        }
294
-
295
-        return $str;
296
-    }
297
-
298
-    public function split(string $delimiter, int $limit = null, int $flags = null): array
299
-    {
300
-        if (1 > $limit = $limit ?? 2147483647) {
301
-            throw new InvalidArgumentException('Split limit must be a positive integer.');
302
-        }
303
-
304
-        if ('' === $delimiter) {
305
-            throw new InvalidArgumentException('Split delimiter is empty.');
306
-        }
307
-
308
-        if (null !== $flags) {
309
-            return parent::split($delimiter.'u', $limit, $flags);
310
-        }
311
-
312
-        normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter);
313
-
314
-        if (false === $delimiter) {
315
-            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
316
-        }
317
-
318
-        $str = clone $this;
319
-        $tail = $this->string;
320
-        $chunks = [];
321
-        $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
322
-
323
-        while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) {
324
-            $str->string = grapheme_substr($tail, 0, $i);
325
-            $chunks[] = clone $str;
326
-            $tail = substr($tail, \strlen($str->string) + \strlen($delimiter));
327
-            --$limit;
328
-        }
329
-
330
-        $str->string = $tail;
331
-        $chunks[] = clone $str;
332
-
333
-        return $chunks;
334
-    }
335
-
336
-    public function startsWith($prefix): bool
337
-    {
338
-        if ($prefix instanceof AbstractString) {
339
-            $prefix = $prefix->string;
340
-        } elseif (\is_array($prefix) || $prefix instanceof \Traversable) {
341
-            return parent::startsWith($prefix);
342
-        } else {
343
-            $prefix = (string) $prefix;
344
-        }
345
-
346
-        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
347
-        normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form);
348
-
349
-        if ('' === $prefix || false === $prefix) {
350
-            return false;
351
-        }
352
-
353
-        if ($this->ignoreCase) {
354
-            return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8');
355
-        }
356
-
357
-        return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES);
358
-    }
359
-
360
-    public function __wakeup()
361
-    {
362
-        if (!\is_string($this->string)) {
363
-            throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
364
-        }
365
-
366
-        normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
367
-    }
368
-
369
-    public function __clone()
370
-    {
371
-        if (null === $this->ignoreCase) {
372
-            normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
373
-        }
374
-
375
-        $this->ignoreCase = false;
376
-    }
35
+	public function __construct(string $string = '')
36
+	{
37
+		$this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string);
38
+
39
+		if (false === $this->string) {
40
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
41
+		}
42
+	}
43
+
44
+	public function append(string ...$suffix): AbstractString
45
+	{
46
+		$str = clone $this;
47
+		$str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix));
48
+		normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
49
+
50
+		if (false === $str->string) {
51
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
52
+		}
53
+
54
+		return $str;
55
+	}
56
+
57
+	public function chunk(int $length = 1): array
58
+	{
59
+		if (1 > $length) {
60
+			throw new InvalidArgumentException('The chunk length must be greater than zero.');
61
+		}
62
+
63
+		if ('' === $this->string) {
64
+			return [];
65
+		}
66
+
67
+		$rx = '/(';
68
+		while (65535 < $length) {
69
+			$rx .= '\X{65535}';
70
+			$length -= 65535;
71
+		}
72
+		$rx .= '\X{'.$length.'})/u';
73
+
74
+		$str = clone $this;
75
+		$chunks = [];
76
+
77
+		foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
78
+			$str->string = $chunk;
79
+			$chunks[] = clone $str;
80
+		}
81
+
82
+		return $chunks;
83
+	}
84
+
85
+	public function endsWith($suffix): bool
86
+	{
87
+		if ($suffix instanceof AbstractString) {
88
+			$suffix = $suffix->string;
89
+		} elseif (\is_array($suffix) || $suffix instanceof \Traversable) {
90
+			return parent::endsWith($suffix);
91
+		} else {
92
+			$suffix = (string) $suffix;
93
+		}
94
+
95
+		$form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
96
+		normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form);
97
+
98
+		if ('' === $suffix || false === $suffix) {
99
+			return false;
100
+		}
101
+
102
+		if ($this->ignoreCase) {
103
+			return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8');
104
+		}
105
+
106
+		return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix));
107
+	}
108
+
109
+	public function equalsTo($string): bool
110
+	{
111
+		if ($string instanceof AbstractString) {
112
+			$string = $string->string;
113
+		} elseif (\is_array($string) || $string instanceof \Traversable) {
114
+			return parent::equalsTo($string);
115
+		} else {
116
+			$string = (string) $string;
117
+		}
118
+
119
+		$form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
120
+		normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form);
121
+
122
+		if ('' !== $string && false !== $string && $this->ignoreCase) {
123
+			return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
124
+		}
125
+
126
+		return $string === $this->string;
127
+	}
128
+
129
+	public function indexOf($needle, int $offset = 0): ?int
130
+	{
131
+		if ($needle instanceof AbstractString) {
132
+			$needle = $needle->string;
133
+		} elseif (\is_array($needle) || $needle instanceof \Traversable) {
134
+			return parent::indexOf($needle, $offset);
135
+		} else {
136
+			$needle = (string) $needle;
137
+		}
138
+
139
+		$form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
140
+		normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);
141
+
142
+		if ('' === $needle || false === $needle) {
143
+			return null;
144
+		}
145
+
146
+		try {
147
+			$i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset);
148
+		} catch (\ValueError $e) {
149
+			return null;
150
+		}
151
+
152
+		return false === $i ? null : $i;
153
+	}
154
+
155
+	public function indexOfLast($needle, int $offset = 0): ?int
156
+	{
157
+		if ($needle instanceof AbstractString) {
158
+			$needle = $needle->string;
159
+		} elseif (\is_array($needle) || $needle instanceof \Traversable) {
160
+			return parent::indexOfLast($needle, $offset);
161
+		} else {
162
+			$needle = (string) $needle;
163
+		}
164
+
165
+		$form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
166
+		normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);
167
+
168
+		if ('' === $needle || false === $needle) {
169
+			return null;
170
+		}
171
+
172
+		$string = $this->string;
173
+
174
+		if (0 > $offset) {
175
+			// workaround https://bugs.php.net/74264
176
+			if (0 > $offset += grapheme_strlen($needle)) {
177
+				$string = grapheme_substr($string, 0, $offset);
178
+			}
179
+			$offset = 0;
180
+		}
181
+
182
+		$i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset);
183
+
184
+		return false === $i ? null : $i;
185
+	}
186
+
187
+	public function join(array $strings, string $lastGlue = null): AbstractString
188
+	{
189
+		$str = parent::join($strings, $lastGlue);
190
+		normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
191
+
192
+		return $str;
193
+	}
194
+
195
+	public function length(): int
196
+	{
197
+		return grapheme_strlen($this->string);
198
+	}
199
+
200
+	/**
201
+	 * @return static
202
+	 */
203
+	public function normalize(int $form = self::NFC): parent
204
+	{
205
+		$str = clone $this;
206
+
207
+		if (\in_array($form, [self::NFC, self::NFKC], true)) {
208
+			normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form);
209
+		} elseif (!\in_array($form, [self::NFD, self::NFKD], true)) {
210
+			throw new InvalidArgumentException('Unsupported normalization form.');
211
+		} elseif (!normalizer_is_normalized($str->string, $form)) {
212
+			$str->string = normalizer_normalize($str->string, $form);
213
+			$str->ignoreCase = null;
214
+		}
215
+
216
+		return $str;
217
+	}
218
+
219
+	public function prepend(string ...$prefix): AbstractString
220
+	{
221
+		$str = clone $this;
222
+		$str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string;
223
+		normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
224
+
225
+		if (false === $str->string) {
226
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
227
+		}
228
+
229
+		return $str;
230
+	}
231
+
232
+	public function replace(string $from, string $to): AbstractString
233
+	{
234
+		$str = clone $this;
235
+		normalizer_is_normalized($from) ?: $from = normalizer_normalize($from);
236
+
237
+		if ('' !== $from && false !== $from) {
238
+			$tail = $str->string;
239
+			$result = '';
240
+			$indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
241
+
242
+			while ('' !== $tail && false !== $i = $indexOf($tail, $from)) {
243
+				$slice = grapheme_substr($tail, 0, $i);
244
+				$result .= $slice.$to;
245
+				$tail = substr($tail, \strlen($slice) + \strlen($from));
246
+			}
247
+
248
+			$str->string = $result.$tail;
249
+			normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
250
+
251
+			if (false === $str->string) {
252
+				throw new InvalidArgumentException('Invalid UTF-8 string.');
253
+			}
254
+		}
255
+
256
+		return $str;
257
+	}
258
+
259
+	public function replaceMatches(string $fromRegexp, $to): AbstractString
260
+	{
261
+		$str = parent::replaceMatches($fromRegexp, $to);
262
+		normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
263
+
264
+		return $str;
265
+	}
266
+
267
+	public function slice(int $start = 0, int $length = null): AbstractString
268
+	{
269
+		$str = clone $this;
270
+
271
+		if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) {
272
+			$start = 0;
273
+		}
274
+		$str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647);
275
+
276
+		return $str;
277
+	}
278
+
279
+	public function splice(string $replacement, int $start = 0, int $length = null): AbstractString
280
+	{
281
+		$str = clone $this;
282
+
283
+		if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) {
284
+			$start = 0;
285
+		}
286
+		$start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0;
287
+		$length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length;
288
+		$str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647);
289
+		normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);
290
+
291
+		if (false === $str->string) {
292
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
293
+		}
294
+
295
+		return $str;
296
+	}
297
+
298
+	public function split(string $delimiter, int $limit = null, int $flags = null): array
299
+	{
300
+		if (1 > $limit = $limit ?? 2147483647) {
301
+			throw new InvalidArgumentException('Split limit must be a positive integer.');
302
+		}
303
+
304
+		if ('' === $delimiter) {
305
+			throw new InvalidArgumentException('Split delimiter is empty.');
306
+		}
307
+
308
+		if (null !== $flags) {
309
+			return parent::split($delimiter.'u', $limit, $flags);
310
+		}
311
+
312
+		normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter);
313
+
314
+		if (false === $delimiter) {
315
+			throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
316
+		}
317
+
318
+		$str = clone $this;
319
+		$tail = $this->string;
320
+		$chunks = [];
321
+		$indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
322
+
323
+		while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) {
324
+			$str->string = grapheme_substr($tail, 0, $i);
325
+			$chunks[] = clone $str;
326
+			$tail = substr($tail, \strlen($str->string) + \strlen($delimiter));
327
+			--$limit;
328
+		}
329
+
330
+		$str->string = $tail;
331
+		$chunks[] = clone $str;
332
+
333
+		return $chunks;
334
+	}
335
+
336
+	public function startsWith($prefix): bool
337
+	{
338
+		if ($prefix instanceof AbstractString) {
339
+			$prefix = $prefix->string;
340
+		} elseif (\is_array($prefix) || $prefix instanceof \Traversable) {
341
+			return parent::startsWith($prefix);
342
+		} else {
343
+			$prefix = (string) $prefix;
344
+		}
345
+
346
+		$form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
347
+		normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form);
348
+
349
+		if ('' === $prefix || false === $prefix) {
350
+			return false;
351
+		}
352
+
353
+		if ($this->ignoreCase) {
354
+			return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8');
355
+		}
356
+
357
+		return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES);
358
+	}
359
+
360
+	public function __wakeup()
361
+	{
362
+		if (!\is_string($this->string)) {
363
+			throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
364
+		}
365
+
366
+		normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
367
+	}
368
+
369
+	public function __clone()
370
+	{
371
+		if (null === $this->ignoreCase) {
372
+			normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
373
+		}
374
+
375
+		$this->ignoreCase = false;
376
+	}
377 377
 }
Please login to merge, or discard this patch.
vendor/symfony/string/LazyString.php 1 patch
Indentation   +143 added lines, -143 removed lines patch added patch discarded remove patch
@@ -18,147 +18,147 @@
 block discarded – undo
18 18
  */
19 19
 class LazyString implements \Stringable, \JsonSerializable
20 20
 {
21
-    private $value;
22
-
23
-    /**
24
-     * @param callable|array $callback A callable or a [Closure, method] lazy-callable
25
-     *
26
-     * @return static
27
-     */
28
-    public static function fromCallable($callback, ...$arguments): self
29
-    {
30
-        if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) {
31
-            throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, get_debug_type($callback)));
32
-        }
33
-
34
-        $lazyString = new static();
35
-        $lazyString->value = static function () use (&$callback, &$arguments, &$value): string {
36
-            if (null !== $arguments) {
37
-                if (!\is_callable($callback)) {
38
-                    $callback[0] = $callback[0]();
39
-                    $callback[1] = $callback[1] ?? '__invoke';
40
-                }
41
-                $value = $callback(...$arguments);
42
-                $callback = self::getPrettyName($callback);
43
-                $arguments = null;
44
-            }
45
-
46
-            return $value ?? '';
47
-        };
48
-
49
-        return $lazyString;
50
-    }
51
-
52
-    /**
53
-     * @param string|int|float|bool|\Stringable $value
54
-     *
55
-     * @return static
56
-     */
57
-    public static function fromStringable($value): self
58
-    {
59
-        if (!self::isStringable($value)) {
60
-            throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, get_debug_type($value)));
61
-        }
62
-
63
-        if (\is_object($value)) {
64
-            return static::fromCallable([$value, '__toString']);
65
-        }
66
-
67
-        $lazyString = new static();
68
-        $lazyString->value = (string) $value;
69
-
70
-        return $lazyString;
71
-    }
72
-
73
-    /**
74
-     * Tells whether the provided value can be cast to string.
75
-     */
76
-    final public static function isStringable($value): bool
77
-    {
78
-        return \is_string($value) || $value instanceof self || (\is_object($value) ? method_exists($value, '__toString') : is_scalar($value));
79
-    }
80
-
81
-    /**
82
-     * Casts scalars and stringable objects to strings.
83
-     *
84
-     * @param object|string|int|float|bool $value
85
-     *
86
-     * @throws \TypeError When the provided value is not stringable
87
-     */
88
-    final public static function resolve($value): string
89
-    {
90
-        return $value;
91
-    }
92
-
93
-    /**
94
-     * @return string
95
-     */
96
-    public function __toString()
97
-    {
98
-        if (\is_string($this->value)) {
99
-            return $this->value;
100
-        }
101
-
102
-        try {
103
-            return $this->value = ($this->value)();
104
-        } catch (\Throwable $e) {
105
-            if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) {
106
-                $type = explode(', ', $e->getMessage());
107
-                $type = substr(array_pop($type), 0, -\strlen(' returned'));
108
-                $r = new \ReflectionFunction($this->value);
109
-                $callback = $r->getStaticVariables()['callback'];
110
-
111
-                $e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
112
-            }
113
-
114
-            if (\PHP_VERSION_ID < 70400) {
115
-                // leverage the ErrorHandler component with graceful fallback when it's not available
116
-                return trigger_error($e, \E_USER_ERROR);
117
-            }
118
-
119
-            throw $e;
120
-        }
121
-    }
122
-
123
-    public function __sleep(): array
124
-    {
125
-        $this->__toString();
126
-
127
-        return ['value'];
128
-    }
129
-
130
-    public function jsonSerialize(): string
131
-    {
132
-        return $this->__toString();
133
-    }
134
-
135
-    private function __construct()
136
-    {
137
-    }
138
-
139
-    private static function getPrettyName(callable $callback): string
140
-    {
141
-        if (\is_string($callback)) {
142
-            return $callback;
143
-        }
144
-
145
-        if (\is_array($callback)) {
146
-            $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0];
147
-            $method = $callback[1];
148
-        } elseif ($callback instanceof \Closure) {
149
-            $r = new \ReflectionFunction($callback);
150
-
151
-            if (false !== strpos($r->name, '{closure}') || !$class = $r->getClosureScopeClass()) {
152
-                return $r->name;
153
-            }
154
-
155
-            $class = $class->name;
156
-            $method = $r->name;
157
-        } else {
158
-            $class = get_debug_type($callback);
159
-            $method = '__invoke';
160
-        }
161
-
162
-        return $class.'::'.$method;
163
-    }
21
+	private $value;
22
+
23
+	/**
24
+	 * @param callable|array $callback A callable or a [Closure, method] lazy-callable
25
+	 *
26
+	 * @return static
27
+	 */
28
+	public static function fromCallable($callback, ...$arguments): self
29
+	{
30
+		if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) {
31
+			throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, get_debug_type($callback)));
32
+		}
33
+
34
+		$lazyString = new static();
35
+		$lazyString->value = static function () use (&$callback, &$arguments, &$value): string {
36
+			if (null !== $arguments) {
37
+				if (!\is_callable($callback)) {
38
+					$callback[0] = $callback[0]();
39
+					$callback[1] = $callback[1] ?? '__invoke';
40
+				}
41
+				$value = $callback(...$arguments);
42
+				$callback = self::getPrettyName($callback);
43
+				$arguments = null;
44
+			}
45
+
46
+			return $value ?? '';
47
+		};
48
+
49
+		return $lazyString;
50
+	}
51
+
52
+	/**
53
+	 * @param string|int|float|bool|\Stringable $value
54
+	 *
55
+	 * @return static
56
+	 */
57
+	public static function fromStringable($value): self
58
+	{
59
+		if (!self::isStringable($value)) {
60
+			throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, get_debug_type($value)));
61
+		}
62
+
63
+		if (\is_object($value)) {
64
+			return static::fromCallable([$value, '__toString']);
65
+		}
66
+
67
+		$lazyString = new static();
68
+		$lazyString->value = (string) $value;
69
+
70
+		return $lazyString;
71
+	}
72
+
73
+	/**
74
+	 * Tells whether the provided value can be cast to string.
75
+	 */
76
+	final public static function isStringable($value): bool
77
+	{
78
+		return \is_string($value) || $value instanceof self || (\is_object($value) ? method_exists($value, '__toString') : is_scalar($value));
79
+	}
80
+
81
+	/**
82
+	 * Casts scalars and stringable objects to strings.
83
+	 *
84
+	 * @param object|string|int|float|bool $value
85
+	 *
86
+	 * @throws \TypeError When the provided value is not stringable
87
+	 */
88
+	final public static function resolve($value): string
89
+	{
90
+		return $value;
91
+	}
92
+
93
+	/**
94
+	 * @return string
95
+	 */
96
+	public function __toString()
97
+	{
98
+		if (\is_string($this->value)) {
99
+			return $this->value;
100
+		}
101
+
102
+		try {
103
+			return $this->value = ($this->value)();
104
+		} catch (\Throwable $e) {
105
+			if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) {
106
+				$type = explode(', ', $e->getMessage());
107
+				$type = substr(array_pop($type), 0, -\strlen(' returned'));
108
+				$r = new \ReflectionFunction($this->value);
109
+				$callback = $r->getStaticVariables()['callback'];
110
+
111
+				$e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
112
+			}
113
+
114
+			if (\PHP_VERSION_ID < 70400) {
115
+				// leverage the ErrorHandler component with graceful fallback when it's not available
116
+				return trigger_error($e, \E_USER_ERROR);
117
+			}
118
+
119
+			throw $e;
120
+		}
121
+	}
122
+
123
+	public function __sleep(): array
124
+	{
125
+		$this->__toString();
126
+
127
+		return ['value'];
128
+	}
129
+
130
+	public function jsonSerialize(): string
131
+	{
132
+		return $this->__toString();
133
+	}
134
+
135
+	private function __construct()
136
+	{
137
+	}
138
+
139
+	private static function getPrettyName(callable $callback): string
140
+	{
141
+		if (\is_string($callback)) {
142
+			return $callback;
143
+		}
144
+
145
+		if (\is_array($callback)) {
146
+			$class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0];
147
+			$method = $callback[1];
148
+		} elseif ($callback instanceof \Closure) {
149
+			$r = new \ReflectionFunction($callback);
150
+
151
+			if (false !== strpos($r->name, '{closure}') || !$class = $r->getClosureScopeClass()) {
152
+				return $r->name;
153
+			}
154
+
155
+			$class = $class->name;
156
+			$method = $r->name;
157
+		} else {
158
+			$class = get_debug_type($callback);
159
+			$method = '__invoke';
160
+		}
161
+
162
+		return $class.'::'.$method;
163
+	}
164 164
 }
Please login to merge, or discard this patch.
vendor/symfony/string/Resources/functions.php 1 patch
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -12,27 +12,27 @@
 block discarded – undo
12 12
 namespace Symfony\Component\String;
13 13
 
14 14
 if (!\function_exists(u::class)) {
15
-    function u(?string $string = ''): UnicodeString
16
-    {
17
-        return new UnicodeString($string ?? '');
18
-    }
15
+	function u(?string $string = ''): UnicodeString
16
+	{
17
+		return new UnicodeString($string ?? '');
18
+	}
19 19
 }
20 20
 
21 21
 if (!\function_exists(b::class)) {
22
-    function b(?string $string = ''): ByteString
23
-    {
24
-        return new ByteString($string ?? '');
25
-    }
22
+	function b(?string $string = ''): ByteString
23
+	{
24
+		return new ByteString($string ?? '');
25
+	}
26 26
 }
27 27
 
28 28
 if (!\function_exists(s::class)) {
29
-    /**
30
-     * @return UnicodeString|ByteString
31
-     */
32
-    function s(?string $string = ''): AbstractString
33
-    {
34
-        $string = $string ?? '';
29
+	/**
30
+	 * @return UnicodeString|ByteString
31
+	 */
32
+	function s(?string $string = ''): AbstractString
33
+	{
34
+		$string = $string ?? '';
35 35
 
36
-        return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string);
37
-    }
36
+		return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string);
37
+	}
38 38
 }
Please login to merge, or discard this patch.
vendor/symfony/string/CodePointString.php 1 patch
Indentation   +243 added lines, -243 removed lines patch added patch discarded remove patch
@@ -24,247 +24,247 @@
 block discarded – undo
24 24
  */
25 25
 class CodePointString extends AbstractUnicodeString
26 26
 {
27
-    public function __construct(string $string = '')
28
-    {
29
-        if ('' !== $string && !preg_match('//u', $string)) {
30
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
31
-        }
32
-
33
-        $this->string = $string;
34
-    }
35
-
36
-    public function append(string ...$suffix): AbstractString
37
-    {
38
-        $str = clone $this;
39
-        $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix);
40
-
41
-        if (!preg_match('//u', $str->string)) {
42
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
43
-        }
44
-
45
-        return $str;
46
-    }
47
-
48
-    public function chunk(int $length = 1): array
49
-    {
50
-        if (1 > $length) {
51
-            throw new InvalidArgumentException('The chunk length must be greater than zero.');
52
-        }
53
-
54
-        if ('' === $this->string) {
55
-            return [];
56
-        }
57
-
58
-        $rx = '/(';
59
-        while (65535 < $length) {
60
-            $rx .= '.{65535}';
61
-            $length -= 65535;
62
-        }
63
-        $rx .= '.{'.$length.'})/us';
64
-
65
-        $str = clone $this;
66
-        $chunks = [];
67
-
68
-        foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
69
-            $str->string = $chunk;
70
-            $chunks[] = clone $str;
71
-        }
72
-
73
-        return $chunks;
74
-    }
75
-
76
-    public function codePointsAt(int $offset): array
77
-    {
78
-        $str = $offset ? $this->slice($offset, 1) : $this;
79
-
80
-        return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')];
81
-    }
82
-
83
-    public function endsWith($suffix): bool
84
-    {
85
-        if ($suffix instanceof AbstractString) {
86
-            $suffix = $suffix->string;
87
-        } elseif (\is_array($suffix) || $suffix instanceof \Traversable) {
88
-            return parent::endsWith($suffix);
89
-        } else {
90
-            $suffix = (string) $suffix;
91
-        }
92
-
93
-        if ('' === $suffix || !preg_match('//u', $suffix)) {
94
-            return false;
95
-        }
96
-
97
-        if ($this->ignoreCase) {
98
-            return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string);
99
-        }
100
-
101
-        return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix));
102
-    }
103
-
104
-    public function equalsTo($string): bool
105
-    {
106
-        if ($string instanceof AbstractString) {
107
-            $string = $string->string;
108
-        } elseif (\is_array($string) || $string instanceof \Traversable) {
109
-            return parent::equalsTo($string);
110
-        } else {
111
-            $string = (string) $string;
112
-        }
113
-
114
-        if ('' !== $string && $this->ignoreCase) {
115
-            return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
116
-        }
117
-
118
-        return $string === $this->string;
119
-    }
120
-
121
-    public function indexOf($needle, int $offset = 0): ?int
122
-    {
123
-        if ($needle instanceof AbstractString) {
124
-            $needle = $needle->string;
125
-        } elseif (\is_array($needle) || $needle instanceof \Traversable) {
126
-            return parent::indexOf($needle, $offset);
127
-        } else {
128
-            $needle = (string) $needle;
129
-        }
130
-
131
-        if ('' === $needle) {
132
-            return null;
133
-        }
134
-
135
-        $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8');
136
-
137
-        return false === $i ? null : $i;
138
-    }
139
-
140
-    public function indexOfLast($needle, int $offset = 0): ?int
141
-    {
142
-        if ($needle instanceof AbstractString) {
143
-            $needle = $needle->string;
144
-        } elseif (\is_array($needle) || $needle instanceof \Traversable) {
145
-            return parent::indexOfLast($needle, $offset);
146
-        } else {
147
-            $needle = (string) $needle;
148
-        }
149
-
150
-        if ('' === $needle) {
151
-            return null;
152
-        }
153
-
154
-        $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8');
155
-
156
-        return false === $i ? null : $i;
157
-    }
158
-
159
-    public function length(): int
160
-    {
161
-        return mb_strlen($this->string, 'UTF-8');
162
-    }
163
-
164
-    public function prepend(string ...$prefix): AbstractString
165
-    {
166
-        $str = clone $this;
167
-        $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string;
168
-
169
-        if (!preg_match('//u', $str->string)) {
170
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
171
-        }
172
-
173
-        return $str;
174
-    }
175
-
176
-    public function replace(string $from, string $to): AbstractString
177
-    {
178
-        $str = clone $this;
179
-
180
-        if ('' === $from || !preg_match('//u', $from)) {
181
-            return $str;
182
-        }
183
-
184
-        if ('' !== $to && !preg_match('//u', $to)) {
185
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
186
-        }
187
-
188
-        if ($this->ignoreCase) {
189
-            $str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string));
190
-        } else {
191
-            $str->string = str_replace($from, $to, $this->string);
192
-        }
193
-
194
-        return $str;
195
-    }
196
-
197
-    public function slice(int $start = 0, int $length = null): AbstractString
198
-    {
199
-        $str = clone $this;
200
-        $str->string = mb_substr($this->string, $start, $length, 'UTF-8');
201
-
202
-        return $str;
203
-    }
204
-
205
-    public function splice(string $replacement, int $start = 0, int $length = null): AbstractString
206
-    {
207
-        if (!preg_match('//u', $replacement)) {
208
-            throw new InvalidArgumentException('Invalid UTF-8 string.');
209
-        }
210
-
211
-        $str = clone $this;
212
-        $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0;
213
-        $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length;
214
-        $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
215
-
216
-        return $str;
217
-    }
218
-
219
-    public function split(string $delimiter, int $limit = null, int $flags = null): array
220
-    {
221
-        if (1 > $limit = $limit ?? \PHP_INT_MAX) {
222
-            throw new InvalidArgumentException('Split limit must be a positive integer.');
223
-        }
224
-
225
-        if ('' === $delimiter) {
226
-            throw new InvalidArgumentException('Split delimiter is empty.');
227
-        }
228
-
229
-        if (null !== $flags) {
230
-            return parent::split($delimiter.'u', $limit, $flags);
231
-        }
232
-
233
-        if (!preg_match('//u', $delimiter)) {
234
-            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
235
-        }
236
-
237
-        $str = clone $this;
238
-        $chunks = $this->ignoreCase
239
-            ? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit)
240
-            : explode($delimiter, $this->string, $limit);
241
-
242
-        foreach ($chunks as &$chunk) {
243
-            $str->string = $chunk;
244
-            $chunk = clone $str;
245
-        }
246
-
247
-        return $chunks;
248
-    }
249
-
250
-    public function startsWith($prefix): bool
251
-    {
252
-        if ($prefix instanceof AbstractString) {
253
-            $prefix = $prefix->string;
254
-        } elseif (\is_array($prefix) || $prefix instanceof \Traversable) {
255
-            return parent::startsWith($prefix);
256
-        } else {
257
-            $prefix = (string) $prefix;
258
-        }
259
-
260
-        if ('' === $prefix || !preg_match('//u', $prefix)) {
261
-            return false;
262
-        }
263
-
264
-        if ($this->ignoreCase) {
265
-            return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8');
266
-        }
267
-
268
-        return 0 === strncmp($this->string, $prefix, \strlen($prefix));
269
-    }
27
+	public function __construct(string $string = '')
28
+	{
29
+		if ('' !== $string && !preg_match('//u', $string)) {
30
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
31
+		}
32
+
33
+		$this->string = $string;
34
+	}
35
+
36
+	public function append(string ...$suffix): AbstractString
37
+	{
38
+		$str = clone $this;
39
+		$str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix);
40
+
41
+		if (!preg_match('//u', $str->string)) {
42
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
43
+		}
44
+
45
+		return $str;
46
+	}
47
+
48
+	public function chunk(int $length = 1): array
49
+	{
50
+		if (1 > $length) {
51
+			throw new InvalidArgumentException('The chunk length must be greater than zero.');
52
+		}
53
+
54
+		if ('' === $this->string) {
55
+			return [];
56
+		}
57
+
58
+		$rx = '/(';
59
+		while (65535 < $length) {
60
+			$rx .= '.{65535}';
61
+			$length -= 65535;
62
+		}
63
+		$rx .= '.{'.$length.'})/us';
64
+
65
+		$str = clone $this;
66
+		$chunks = [];
67
+
68
+		foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
69
+			$str->string = $chunk;
70
+			$chunks[] = clone $str;
71
+		}
72
+
73
+		return $chunks;
74
+	}
75
+
76
+	public function codePointsAt(int $offset): array
77
+	{
78
+		$str = $offset ? $this->slice($offset, 1) : $this;
79
+
80
+		return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')];
81
+	}
82
+
83
+	public function endsWith($suffix): bool
84
+	{
85
+		if ($suffix instanceof AbstractString) {
86
+			$suffix = $suffix->string;
87
+		} elseif (\is_array($suffix) || $suffix instanceof \Traversable) {
88
+			return parent::endsWith($suffix);
89
+		} else {
90
+			$suffix = (string) $suffix;
91
+		}
92
+
93
+		if ('' === $suffix || !preg_match('//u', $suffix)) {
94
+			return false;
95
+		}
96
+
97
+		if ($this->ignoreCase) {
98
+			return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string);
99
+		}
100
+
101
+		return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix));
102
+	}
103
+
104
+	public function equalsTo($string): bool
105
+	{
106
+		if ($string instanceof AbstractString) {
107
+			$string = $string->string;
108
+		} elseif (\is_array($string) || $string instanceof \Traversable) {
109
+			return parent::equalsTo($string);
110
+		} else {
111
+			$string = (string) $string;
112
+		}
113
+
114
+		if ('' !== $string && $this->ignoreCase) {
115
+			return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
116
+		}
117
+
118
+		return $string === $this->string;
119
+	}
120
+
121
+	public function indexOf($needle, int $offset = 0): ?int
122
+	{
123
+		if ($needle instanceof AbstractString) {
124
+			$needle = $needle->string;
125
+		} elseif (\is_array($needle) || $needle instanceof \Traversable) {
126
+			return parent::indexOf($needle, $offset);
127
+		} else {
128
+			$needle = (string) $needle;
129
+		}
130
+
131
+		if ('' === $needle) {
132
+			return null;
133
+		}
134
+
135
+		$i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8');
136
+
137
+		return false === $i ? null : $i;
138
+	}
139
+
140
+	public function indexOfLast($needle, int $offset = 0): ?int
141
+	{
142
+		if ($needle instanceof AbstractString) {
143
+			$needle = $needle->string;
144
+		} elseif (\is_array($needle) || $needle instanceof \Traversable) {
145
+			return parent::indexOfLast($needle, $offset);
146
+		} else {
147
+			$needle = (string) $needle;
148
+		}
149
+
150
+		if ('' === $needle) {
151
+			return null;
152
+		}
153
+
154
+		$i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8');
155
+
156
+		return false === $i ? null : $i;
157
+	}
158
+
159
+	public function length(): int
160
+	{
161
+		return mb_strlen($this->string, 'UTF-8');
162
+	}
163
+
164
+	public function prepend(string ...$prefix): AbstractString
165
+	{
166
+		$str = clone $this;
167
+		$str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string;
168
+
169
+		if (!preg_match('//u', $str->string)) {
170
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
171
+		}
172
+
173
+		return $str;
174
+	}
175
+
176
+	public function replace(string $from, string $to): AbstractString
177
+	{
178
+		$str = clone $this;
179
+
180
+		if ('' === $from || !preg_match('//u', $from)) {
181
+			return $str;
182
+		}
183
+
184
+		if ('' !== $to && !preg_match('//u', $to)) {
185
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
186
+		}
187
+
188
+		if ($this->ignoreCase) {
189
+			$str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string));
190
+		} else {
191
+			$str->string = str_replace($from, $to, $this->string);
192
+		}
193
+
194
+		return $str;
195
+	}
196
+
197
+	public function slice(int $start = 0, int $length = null): AbstractString
198
+	{
199
+		$str = clone $this;
200
+		$str->string = mb_substr($this->string, $start, $length, 'UTF-8');
201
+
202
+		return $str;
203
+	}
204
+
205
+	public function splice(string $replacement, int $start = 0, int $length = null): AbstractString
206
+	{
207
+		if (!preg_match('//u', $replacement)) {
208
+			throw new InvalidArgumentException('Invalid UTF-8 string.');
209
+		}
210
+
211
+		$str = clone $this;
212
+		$start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0;
213
+		$length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length;
214
+		$str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
215
+
216
+		return $str;
217
+	}
218
+
219
+	public function split(string $delimiter, int $limit = null, int $flags = null): array
220
+	{
221
+		if (1 > $limit = $limit ?? \PHP_INT_MAX) {
222
+			throw new InvalidArgumentException('Split limit must be a positive integer.');
223
+		}
224
+
225
+		if ('' === $delimiter) {
226
+			throw new InvalidArgumentException('Split delimiter is empty.');
227
+		}
228
+
229
+		if (null !== $flags) {
230
+			return parent::split($delimiter.'u', $limit, $flags);
231
+		}
232
+
233
+		if (!preg_match('//u', $delimiter)) {
234
+			throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
235
+		}
236
+
237
+		$str = clone $this;
238
+		$chunks = $this->ignoreCase
239
+			? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit)
240
+			: explode($delimiter, $this->string, $limit);
241
+
242
+		foreach ($chunks as &$chunk) {
243
+			$str->string = $chunk;
244
+			$chunk = clone $str;
245
+		}
246
+
247
+		return $chunks;
248
+	}
249
+
250
+	public function startsWith($prefix): bool
251
+	{
252
+		if ($prefix instanceof AbstractString) {
253
+			$prefix = $prefix->string;
254
+		} elseif (\is_array($prefix) || $prefix instanceof \Traversable) {
255
+			return parent::startsWith($prefix);
256
+		} else {
257
+			$prefix = (string) $prefix;
258
+		}
259
+
260
+		if ('' === $prefix || !preg_match('//u', $prefix)) {
261
+			return false;
262
+		}
263
+
264
+		if ($this->ignoreCase) {
265
+			return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8');
266
+		}
267
+
268
+		return 0 === strncmp($this->string, $prefix, \strlen($prefix));
269
+	}
270 270
 }
Please login to merge, or discard this patch.
vendor/symfony/string/Slugger/SluggerInterface.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -20,8 +20,8 @@
 block discarded – undo
20 20
  */
21 21
 interface SluggerInterface
22 22
 {
23
-    /**
24
-     * Creates a slug for the given string and locale, using appropriate transliteration when needed.
25
-     */
26
-    public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString;
23
+	/**
24
+	 * Creates a slug for the given string and locale, using appropriate transliteration when needed.
25
+	 */
26
+	public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString;
27 27
 }
Please login to merge, or discard this patch.
vendor/symfony/string/Slugger/AsciiSlugger.php 1 patch
Indentation   +157 added lines, -157 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
 use Symfony\Contracts\Translation\LocaleAwareInterface;
17 17
 
18 18
 if (!interface_exists(LocaleAwareInterface::class)) {
19
-    throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".');
19
+	throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".');
20 20
 }
21 21
 
22 22
 /**
@@ -24,160 +24,160 @@  discard block
 block discarded – undo
24 24
  */
25 25
 class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
26 26
 {
27
-    private const LOCALE_TO_TRANSLITERATOR_ID = [
28
-        'am' => 'Amharic-Latin',
29
-        'ar' => 'Arabic-Latin',
30
-        'az' => 'Azerbaijani-Latin',
31
-        'be' => 'Belarusian-Latin',
32
-        'bg' => 'Bulgarian-Latin',
33
-        'bn' => 'Bengali-Latin',
34
-        'de' => 'de-ASCII',
35
-        'el' => 'Greek-Latin',
36
-        'fa' => 'Persian-Latin',
37
-        'he' => 'Hebrew-Latin',
38
-        'hy' => 'Armenian-Latin',
39
-        'ka' => 'Georgian-Latin',
40
-        'kk' => 'Kazakh-Latin',
41
-        'ky' => 'Kirghiz-Latin',
42
-        'ko' => 'Korean-Latin',
43
-        'mk' => 'Macedonian-Latin',
44
-        'mn' => 'Mongolian-Latin',
45
-        'or' => 'Oriya-Latin',
46
-        'ps' => 'Pashto-Latin',
47
-        'ru' => 'Russian-Latin',
48
-        'sr' => 'Serbian-Latin',
49
-        'sr_Cyrl' => 'Serbian-Latin',
50
-        'th' => 'Thai-Latin',
51
-        'tk' => 'Turkmen-Latin',
52
-        'uk' => 'Ukrainian-Latin',
53
-        'uz' => 'Uzbek-Latin',
54
-        'zh' => 'Han-Latin',
55
-    ];
56
-
57
-    private $defaultLocale;
58
-    private $symbolsMap = [
59
-        'en' => ['@' => 'at', '&' => 'and'],
60
-    ];
61
-
62
-    /**
63
-     * Cache of transliterators per locale.
64
-     *
65
-     * @var \Transliterator[]
66
-     */
67
-    private $transliterators = [];
68
-
69
-    /**
70
-     * @param array|\Closure|null $symbolsMap
71
-     */
72
-    public function __construct(string $defaultLocale = null, $symbolsMap = null)
73
-    {
74
-        if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) {
75
-            throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap)));
76
-        }
77
-
78
-        $this->defaultLocale = $defaultLocale;
79
-        $this->symbolsMap = $symbolsMap ?? $this->symbolsMap;
80
-    }
81
-
82
-    /**
83
-     * {@inheritdoc}
84
-     */
85
-    public function setLocale($locale)
86
-    {
87
-        $this->defaultLocale = $locale;
88
-    }
89
-
90
-    /**
91
-     * {@inheritdoc}
92
-     */
93
-    public function getLocale()
94
-    {
95
-        return $this->defaultLocale;
96
-    }
97
-
98
-    /**
99
-     * {@inheritdoc}
100
-     */
101
-    public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString
102
-    {
103
-        $locale = $locale ?? $this->defaultLocale;
104
-
105
-        $transliterator = [];
106
-        if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) {
107
-            // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl)
108
-            $transliterator = ['de-ASCII'];
109
-        } elseif (\function_exists('transliterator_transliterate') && $locale) {
110
-            $transliterator = (array) $this->createTransliterator($locale);
111
-        }
112
-
113
-        if ($this->symbolsMap instanceof \Closure) {
114
-            // If the symbols map is passed as a closure, there is no need to fallback to the parent locale
115
-            // as the closure can just provide substitutions for all locales of interest.
116
-            $symbolsMap = $this->symbolsMap;
117
-            array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) {
118
-                return $symbolsMap($s, $locale);
119
-            });
120
-        }
121
-
122
-        $unicodeString = (new UnicodeString($string))->ascii($transliterator);
123
-
124
-        if (\is_array($this->symbolsMap)) {
125
-            $map = null;
126
-            if (isset($this->symbolsMap[$locale])) {
127
-                $map = $this->symbolsMap[$locale];
128
-            } else {
129
-                $parent = self::getParentLocale($locale);
130
-                if ($parent && isset($this->symbolsMap[$parent])) {
131
-                    $map = $this->symbolsMap[$parent];
132
-                }
133
-            }
134
-            if ($map) {
135
-                foreach ($map as $char => $replace) {
136
-                    $unicodeString = $unicodeString->replace($char, ' '.$replace.' ');
137
-                }
138
-            }
139
-        }
140
-
141
-        return $unicodeString
142
-            ->replaceMatches('/[^A-Za-z0-9]++/', $separator)
143
-            ->trim($separator)
144
-        ;
145
-    }
146
-
147
-    private function createTransliterator(string $locale): ?\Transliterator
148
-    {
149
-        if (\array_key_exists($locale, $this->transliterators)) {
150
-            return $this->transliterators[$locale];
151
-        }
152
-
153
-        // Exact locale supported, cache and return
154
-        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) {
155
-            return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
156
-        }
157
-
158
-        // Locale not supported and no parent, fallback to any-latin
159
-        if (!$parent = self::getParentLocale($locale)) {
160
-            return $this->transliterators[$locale] = null;
161
-        }
162
-
163
-        // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
164
-        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
165
-            $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
166
-        }
167
-
168
-        return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
169
-    }
170
-
171
-    private static function getParentLocale(?string $locale): ?string
172
-    {
173
-        if (!$locale) {
174
-            return null;
175
-        }
176
-        if (false === $str = strrchr($locale, '_')) {
177
-            // no parent locale
178
-            return null;
179
-        }
180
-
181
-        return substr($locale, 0, -\strlen($str));
182
-    }
27
+	private const LOCALE_TO_TRANSLITERATOR_ID = [
28
+		'am' => 'Amharic-Latin',
29
+		'ar' => 'Arabic-Latin',
30
+		'az' => 'Azerbaijani-Latin',
31
+		'be' => 'Belarusian-Latin',
32
+		'bg' => 'Bulgarian-Latin',
33
+		'bn' => 'Bengali-Latin',
34
+		'de' => 'de-ASCII',
35
+		'el' => 'Greek-Latin',
36
+		'fa' => 'Persian-Latin',
37
+		'he' => 'Hebrew-Latin',
38
+		'hy' => 'Armenian-Latin',
39
+		'ka' => 'Georgian-Latin',
40
+		'kk' => 'Kazakh-Latin',
41
+		'ky' => 'Kirghiz-Latin',
42
+		'ko' => 'Korean-Latin',
43
+		'mk' => 'Macedonian-Latin',
44
+		'mn' => 'Mongolian-Latin',
45
+		'or' => 'Oriya-Latin',
46
+		'ps' => 'Pashto-Latin',
47
+		'ru' => 'Russian-Latin',
48
+		'sr' => 'Serbian-Latin',
49
+		'sr_Cyrl' => 'Serbian-Latin',
50
+		'th' => 'Thai-Latin',
51
+		'tk' => 'Turkmen-Latin',
52
+		'uk' => 'Ukrainian-Latin',
53
+		'uz' => 'Uzbek-Latin',
54
+		'zh' => 'Han-Latin',
55
+	];
56
+
57
+	private $defaultLocale;
58
+	private $symbolsMap = [
59
+		'en' => ['@' => 'at', '&' => 'and'],
60
+	];
61
+
62
+	/**
63
+	 * Cache of transliterators per locale.
64
+	 *
65
+	 * @var \Transliterator[]
66
+	 */
67
+	private $transliterators = [];
68
+
69
+	/**
70
+	 * @param array|\Closure|null $symbolsMap
71
+	 */
72
+	public function __construct(string $defaultLocale = null, $symbolsMap = null)
73
+	{
74
+		if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) {
75
+			throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap)));
76
+		}
77
+
78
+		$this->defaultLocale = $defaultLocale;
79
+		$this->symbolsMap = $symbolsMap ?? $this->symbolsMap;
80
+	}
81
+
82
+	/**
83
+	 * {@inheritdoc}
84
+	 */
85
+	public function setLocale($locale)
86
+	{
87
+		$this->defaultLocale = $locale;
88
+	}
89
+
90
+	/**
91
+	 * {@inheritdoc}
92
+	 */
93
+	public function getLocale()
94
+	{
95
+		return $this->defaultLocale;
96
+	}
97
+
98
+	/**
99
+	 * {@inheritdoc}
100
+	 */
101
+	public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString
102
+	{
103
+		$locale = $locale ?? $this->defaultLocale;
104
+
105
+		$transliterator = [];
106
+		if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) {
107
+			// Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl)
108
+			$transliterator = ['de-ASCII'];
109
+		} elseif (\function_exists('transliterator_transliterate') && $locale) {
110
+			$transliterator = (array) $this->createTransliterator($locale);
111
+		}
112
+
113
+		if ($this->symbolsMap instanceof \Closure) {
114
+			// If the symbols map is passed as a closure, there is no need to fallback to the parent locale
115
+			// as the closure can just provide substitutions for all locales of interest.
116
+			$symbolsMap = $this->symbolsMap;
117
+			array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) {
118
+				return $symbolsMap($s, $locale);
119
+			});
120
+		}
121
+
122
+		$unicodeString = (new UnicodeString($string))->ascii($transliterator);
123
+
124
+		if (\is_array($this->symbolsMap)) {
125
+			$map = null;
126
+			if (isset($this->symbolsMap[$locale])) {
127
+				$map = $this->symbolsMap[$locale];
128
+			} else {
129
+				$parent = self::getParentLocale($locale);
130
+				if ($parent && isset($this->symbolsMap[$parent])) {
131
+					$map = $this->symbolsMap[$parent];
132
+				}
133
+			}
134
+			if ($map) {
135
+				foreach ($map as $char => $replace) {
136
+					$unicodeString = $unicodeString->replace($char, ' '.$replace.' ');
137
+				}
138
+			}
139
+		}
140
+
141
+		return $unicodeString
142
+			->replaceMatches('/[^A-Za-z0-9]++/', $separator)
143
+			->trim($separator)
144
+		;
145
+	}
146
+
147
+	private function createTransliterator(string $locale): ?\Transliterator
148
+	{
149
+		if (\array_key_exists($locale, $this->transliterators)) {
150
+			return $this->transliterators[$locale];
151
+		}
152
+
153
+		// Exact locale supported, cache and return
154
+		if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) {
155
+			return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
156
+		}
157
+
158
+		// Locale not supported and no parent, fallback to any-latin
159
+		if (!$parent = self::getParentLocale($locale)) {
160
+			return $this->transliterators[$locale] = null;
161
+		}
162
+
163
+		// Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
164
+		if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
165
+			$transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
166
+		}
167
+
168
+		return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
169
+	}
170
+
171
+	private static function getParentLocale(?string $locale): ?string
172
+	{
173
+		if (!$locale) {
174
+			return null;
175
+		}
176
+		if (false === $str = strrchr($locale, '_')) {
177
+			// no parent locale
178
+			return null;
179
+		}
180
+
181
+		return substr($locale, 0, -\strlen($str));
182
+	}
183 183
 }
Please login to merge, or discard this patch.
vendor/symfony/string/ByteString.php 1 patch
Indentation   +457 added lines, -457 removed lines patch added patch discarded remove patch
@@ -25,14 +25,14 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 }
Please login to merge, or discard this patch.