Completed
Push — develop ( 316159...00443b )
by Zack
20:22
created
vendor/symfony/console/CommandLoader/ContainerCommandLoader.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -21,43 +21,43 @@
 block discarded – undo
21 21
  */
22 22
 class ContainerCommandLoader implements CommandLoaderInterface
23 23
 {
24
-    private $container;
25
-    private $commandMap;
26
-
27
-    /**
28
-     * @param array $commandMap An array with command names as keys and service ids as values
29
-     */
30
-    public function __construct(ContainerInterface $container, array $commandMap)
31
-    {
32
-        $this->container = $container;
33
-        $this->commandMap = $commandMap;
34
-    }
35
-
36
-    /**
37
-     * {@inheritdoc}
38
-     */
39
-    public function get(string $name)
40
-    {
41
-        if (!$this->has($name)) {
42
-            throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
43
-        }
44
-
45
-        return $this->container->get($this->commandMap[$name]);
46
-    }
47
-
48
-    /**
49
-     * {@inheritdoc}
50
-     */
51
-    public function has(string $name)
52
-    {
53
-        return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
54
-    }
55
-
56
-    /**
57
-     * {@inheritdoc}
58
-     */
59
-    public function getNames()
60
-    {
61
-        return array_keys($this->commandMap);
62
-    }
24
+	private $container;
25
+	private $commandMap;
26
+
27
+	/**
28
+	 * @param array $commandMap An array with command names as keys and service ids as values
29
+	 */
30
+	public function __construct(ContainerInterface $container, array $commandMap)
31
+	{
32
+		$this->container = $container;
33
+		$this->commandMap = $commandMap;
34
+	}
35
+
36
+	/**
37
+	 * {@inheritdoc}
38
+	 */
39
+	public function get(string $name)
40
+	{
41
+		if (!$this->has($name)) {
42
+			throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
43
+		}
44
+
45
+		return $this->container->get($this->commandMap[$name]);
46
+	}
47
+
48
+	/**
49
+	 * {@inheritdoc}
50
+	 */
51
+	public function has(string $name)
52
+	{
53
+		return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
54
+	}
55
+
56
+	/**
57
+	 * {@inheritdoc}
58
+	 */
59
+	public function getNames()
60
+	{
61
+		return array_keys($this->commandMap);
62
+	}
63 63
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Color.php 1 patch
Indentation   +159 added lines, -159 removed lines patch added patch discarded remove patch
@@ -18,163 +18,163 @@
 block discarded – undo
18 18
  */
19 19
 final class Color
20 20
 {
21
-    private const COLORS = [
22
-        'black' => 0,
23
-        'red' => 1,
24
-        'green' => 2,
25
-        'yellow' => 3,
26
-        'blue' => 4,
27
-        'magenta' => 5,
28
-        'cyan' => 6,
29
-        'white' => 7,
30
-        'default' => 9,
31
-    ];
32
-
33
-    private const BRIGHT_COLORS = [
34
-        'gray' => 0,
35
-        'bright-red' => 1,
36
-        'bright-green' => 2,
37
-        'bright-yellow' => 3,
38
-        'bright-blue' => 4,
39
-        'bright-magenta' => 5,
40
-        'bright-cyan' => 6,
41
-        'bright-white' => 7,
42
-    ];
43
-
44
-    private const AVAILABLE_OPTIONS = [
45
-        'bold' => ['set' => 1, 'unset' => 22],
46
-        'underscore' => ['set' => 4, 'unset' => 24],
47
-        'blink' => ['set' => 5, 'unset' => 25],
48
-        'reverse' => ['set' => 7, 'unset' => 27],
49
-        'conceal' => ['set' => 8, 'unset' => 28],
50
-    ];
51
-
52
-    private $foreground;
53
-    private $background;
54
-    private $options = [];
55
-
56
-    public function __construct(string $foreground = '', string $background = '', array $options = [])
57
-    {
58
-        $this->foreground = $this->parseColor($foreground);
59
-        $this->background = $this->parseColor($background, true);
60
-
61
-        foreach ($options as $option) {
62
-            if (!isset(self::AVAILABLE_OPTIONS[$option])) {
63
-                throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS))));
64
-            }
65
-
66
-            $this->options[$option] = self::AVAILABLE_OPTIONS[$option];
67
-        }
68
-    }
69
-
70
-    public function apply(string $text): string
71
-    {
72
-        return $this->set().$text.$this->unset();
73
-    }
74
-
75
-    public function set(): string
76
-    {
77
-        $setCodes = [];
78
-        if ('' !== $this->foreground) {
79
-            $setCodes[] = $this->foreground;
80
-        }
81
-        if ('' !== $this->background) {
82
-            $setCodes[] = $this->background;
83
-        }
84
-        foreach ($this->options as $option) {
85
-            $setCodes[] = $option['set'];
86
-        }
87
-        if (0 === \count($setCodes)) {
88
-            return '';
89
-        }
90
-
91
-        return sprintf("\033[%sm", implode(';', $setCodes));
92
-    }
93
-
94
-    public function unset(): string
95
-    {
96
-        $unsetCodes = [];
97
-        if ('' !== $this->foreground) {
98
-            $unsetCodes[] = 39;
99
-        }
100
-        if ('' !== $this->background) {
101
-            $unsetCodes[] = 49;
102
-        }
103
-        foreach ($this->options as $option) {
104
-            $unsetCodes[] = $option['unset'];
105
-        }
106
-        if (0 === \count($unsetCodes)) {
107
-            return '';
108
-        }
109
-
110
-        return sprintf("\033[%sm", implode(';', $unsetCodes));
111
-    }
112
-
113
-    private function parseColor(string $color, bool $background = false): string
114
-    {
115
-        if ('' === $color) {
116
-            return '';
117
-        }
118
-
119
-        if ('#' === $color[0]) {
120
-            $color = substr($color, 1);
121
-
122
-            if (3 === \strlen($color)) {
123
-                $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2];
124
-            }
125
-
126
-            if (6 !== \strlen($color)) {
127
-                throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color));
128
-            }
129
-
130
-            return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color));
131
-        }
132
-
133
-        if (isset(self::COLORS[$color])) {
134
-            return ($background ? '4' : '3').self::COLORS[$color];
135
-        }
136
-
137
-        if (isset(self::BRIGHT_COLORS[$color])) {
138
-            return ($background ? '10' : '9').self::BRIGHT_COLORS[$color];
139
-        }
140
-
141
-        throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
142
-    }
143
-
144
-    private function convertHexColorToAnsi(int $color): string
145
-    {
146
-        $r = ($color >> 16) & 255;
147
-        $g = ($color >> 8) & 255;
148
-        $b = $color & 255;
149
-
150
-        // see https://github.com/termstandard/colors/ for more information about true color support
151
-        if ('truecolor' !== getenv('COLORTERM')) {
152
-            return (string) $this->degradeHexColorToAnsi($r, $g, $b);
153
-        }
154
-
155
-        return sprintf('8;2;%d;%d;%d', $r, $g, $b);
156
-    }
157
-
158
-    private function degradeHexColorToAnsi(int $r, int $g, int $b): int
159
-    {
160
-        if (0 === round($this->getSaturation($r, $g, $b) / 50)) {
161
-            return 0;
162
-        }
163
-
164
-        return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255);
165
-    }
166
-
167
-    private function getSaturation(int $r, int $g, int $b): int
168
-    {
169
-        $r = $r / 255;
170
-        $g = $g / 255;
171
-        $b = $b / 255;
172
-        $v = max($r, $g, $b);
173
-
174
-        if (0 === $diff = $v - min($r, $g, $b)) {
175
-            return 0;
176
-        }
177
-
178
-        return (int) $diff * 100 / $v;
179
-    }
21
+	private const COLORS = [
22
+		'black' => 0,
23
+		'red' => 1,
24
+		'green' => 2,
25
+		'yellow' => 3,
26
+		'blue' => 4,
27
+		'magenta' => 5,
28
+		'cyan' => 6,
29
+		'white' => 7,
30
+		'default' => 9,
31
+	];
32
+
33
+	private const BRIGHT_COLORS = [
34
+		'gray' => 0,
35
+		'bright-red' => 1,
36
+		'bright-green' => 2,
37
+		'bright-yellow' => 3,
38
+		'bright-blue' => 4,
39
+		'bright-magenta' => 5,
40
+		'bright-cyan' => 6,
41
+		'bright-white' => 7,
42
+	];
43
+
44
+	private const AVAILABLE_OPTIONS = [
45
+		'bold' => ['set' => 1, 'unset' => 22],
46
+		'underscore' => ['set' => 4, 'unset' => 24],
47
+		'blink' => ['set' => 5, 'unset' => 25],
48
+		'reverse' => ['set' => 7, 'unset' => 27],
49
+		'conceal' => ['set' => 8, 'unset' => 28],
50
+	];
51
+
52
+	private $foreground;
53
+	private $background;
54
+	private $options = [];
55
+
56
+	public function __construct(string $foreground = '', string $background = '', array $options = [])
57
+	{
58
+		$this->foreground = $this->parseColor($foreground);
59
+		$this->background = $this->parseColor($background, true);
60
+
61
+		foreach ($options as $option) {
62
+			if (!isset(self::AVAILABLE_OPTIONS[$option])) {
63
+				throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS))));
64
+			}
65
+
66
+			$this->options[$option] = self::AVAILABLE_OPTIONS[$option];
67
+		}
68
+	}
69
+
70
+	public function apply(string $text): string
71
+	{
72
+		return $this->set().$text.$this->unset();
73
+	}
74
+
75
+	public function set(): string
76
+	{
77
+		$setCodes = [];
78
+		if ('' !== $this->foreground) {
79
+			$setCodes[] = $this->foreground;
80
+		}
81
+		if ('' !== $this->background) {
82
+			$setCodes[] = $this->background;
83
+		}
84
+		foreach ($this->options as $option) {
85
+			$setCodes[] = $option['set'];
86
+		}
87
+		if (0 === \count($setCodes)) {
88
+			return '';
89
+		}
90
+
91
+		return sprintf("\033[%sm", implode(';', $setCodes));
92
+	}
93
+
94
+	public function unset(): string
95
+	{
96
+		$unsetCodes = [];
97
+		if ('' !== $this->foreground) {
98
+			$unsetCodes[] = 39;
99
+		}
100
+		if ('' !== $this->background) {
101
+			$unsetCodes[] = 49;
102
+		}
103
+		foreach ($this->options as $option) {
104
+			$unsetCodes[] = $option['unset'];
105
+		}
106
+		if (0 === \count($unsetCodes)) {
107
+			return '';
108
+		}
109
+
110
+		return sprintf("\033[%sm", implode(';', $unsetCodes));
111
+	}
112
+
113
+	private function parseColor(string $color, bool $background = false): string
114
+	{
115
+		if ('' === $color) {
116
+			return '';
117
+		}
118
+
119
+		if ('#' === $color[0]) {
120
+			$color = substr($color, 1);
121
+
122
+			if (3 === \strlen($color)) {
123
+				$color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2];
124
+			}
125
+
126
+			if (6 !== \strlen($color)) {
127
+				throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color));
128
+			}
129
+
130
+			return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color));
131
+		}
132
+
133
+		if (isset(self::COLORS[$color])) {
134
+			return ($background ? '4' : '3').self::COLORS[$color];
135
+		}
136
+
137
+		if (isset(self::BRIGHT_COLORS[$color])) {
138
+			return ($background ? '10' : '9').self::BRIGHT_COLORS[$color];
139
+		}
140
+
141
+		throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
142
+	}
143
+
144
+	private function convertHexColorToAnsi(int $color): string
145
+	{
146
+		$r = ($color >> 16) & 255;
147
+		$g = ($color >> 8) & 255;
148
+		$b = $color & 255;
149
+
150
+		// see https://github.com/termstandard/colors/ for more information about true color support
151
+		if ('truecolor' !== getenv('COLORTERM')) {
152
+			return (string) $this->degradeHexColorToAnsi($r, $g, $b);
153
+		}
154
+
155
+		return sprintf('8;2;%d;%d;%d', $r, $g, $b);
156
+	}
157
+
158
+	private function degradeHexColorToAnsi(int $r, int $g, int $b): int
159
+	{
160
+		if (0 === round($this->getSaturation($r, $g, $b) / 50)) {
161
+			return 0;
162
+		}
163
+
164
+		return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255);
165
+	}
166
+
167
+	private function getSaturation(int $r, int $g, int $b): int
168
+	{
169
+		$r = $r / 255;
170
+		$g = $g / 255;
171
+		$b = $b / 255;
172
+		$v = max($r, $g, $b);
173
+
174
+		if (0 === $diff = $v - min($r, $g, $b)) {
175
+			return 0;
176
+		}
177
+
178
+		return (int) $diff * 100 / $v;
179
+	}
180 180
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Application.php 1 patch
Indentation   +1170 added lines, -1170 removed lines patch added patch discarded remove patch
@@ -66,1174 +66,1174 @@
 block discarded – undo
66 66
  */
67 67
 class Application implements ResetInterface
68 68
 {
69
-    private $commands = [];
70
-    private $wantHelps = false;
71
-    private $runningCommand;
72
-    private $name;
73
-    private $version;
74
-    private $commandLoader;
75
-    private $catchExceptions = true;
76
-    private $autoExit = true;
77
-    private $definition;
78
-    private $helperSet;
79
-    private $dispatcher;
80
-    private $terminal;
81
-    private $defaultCommand;
82
-    private $singleCommand = false;
83
-    private $initialized;
84
-    private $signalRegistry;
85
-    private $signalsToDispatchEvent = [];
86
-
87
-    public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN')
88
-    {
89
-        $this->name = $name;
90
-        $this->version = $version;
91
-        $this->terminal = new Terminal();
92
-        $this->defaultCommand = 'list';
93
-        if (\defined('SIGINT') && SignalRegistry::isSupported()) {
94
-            $this->signalRegistry = new SignalRegistry();
95
-            $this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2];
96
-        }
97
-    }
98
-
99
-    /**
100
-     * @final
101
-     */
102
-    public function setDispatcher(EventDispatcherInterface $dispatcher)
103
-    {
104
-        $this->dispatcher = $dispatcher;
105
-    }
106
-
107
-    public function setCommandLoader(CommandLoaderInterface $commandLoader)
108
-    {
109
-        $this->commandLoader = $commandLoader;
110
-    }
111
-
112
-    public function getSignalRegistry(): SignalRegistry
113
-    {
114
-        if (!$this->signalRegistry) {
115
-            throw new RuntimeException('Signals are not supported. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
116
-        }
117
-
118
-        return $this->signalRegistry;
119
-    }
120
-
121
-    public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent)
122
-    {
123
-        $this->signalsToDispatchEvent = $signalsToDispatchEvent;
124
-    }
125
-
126
-    /**
127
-     * Runs the current application.
128
-     *
129
-     * @return int 0 if everything went fine, or an error code
130
-     *
131
-     * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
132
-     */
133
-    public function run(InputInterface $input = null, OutputInterface $output = null)
134
-    {
135
-        if (\function_exists('putenv')) {
136
-            @putenv('LINES='.$this->terminal->getHeight());
137
-            @putenv('COLUMNS='.$this->terminal->getWidth());
138
-        }
139
-
140
-        if (null === $input) {
141
-            $input = new ArgvInput();
142
-        }
143
-
144
-        if (null === $output) {
145
-            $output = new ConsoleOutput();
146
-        }
147
-
148
-        $renderException = function (\Throwable $e) use ($output) {
149
-            if ($output instanceof ConsoleOutputInterface) {
150
-                $this->renderThrowable($e, $output->getErrorOutput());
151
-            } else {
152
-                $this->renderThrowable($e, $output);
153
-            }
154
-        };
155
-        if ($phpHandler = set_exception_handler($renderException)) {
156
-            restore_exception_handler();
157
-            if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
158
-                $errorHandler = true;
159
-            } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
160
-                $phpHandler[0]->setExceptionHandler($errorHandler);
161
-            }
162
-        }
163
-
164
-        $this->configureIO($input, $output);
165
-
166
-        try {
167
-            $exitCode = $this->doRun($input, $output);
168
-        } catch (\Exception $e) {
169
-            if (!$this->catchExceptions) {
170
-                throw $e;
171
-            }
172
-
173
-            $renderException($e);
174
-
175
-            $exitCode = $e->getCode();
176
-            if (is_numeric($exitCode)) {
177
-                $exitCode = (int) $exitCode;
178
-                if (0 === $exitCode) {
179
-                    $exitCode = 1;
180
-                }
181
-            } else {
182
-                $exitCode = 1;
183
-            }
184
-        } finally {
185
-            // if the exception handler changed, keep it
186
-            // otherwise, unregister $renderException
187
-            if (!$phpHandler) {
188
-                if (set_exception_handler($renderException) === $renderException) {
189
-                    restore_exception_handler();
190
-                }
191
-                restore_exception_handler();
192
-            } elseif (!$errorHandler) {
193
-                $finalHandler = $phpHandler[0]->setExceptionHandler(null);
194
-                if ($finalHandler !== $renderException) {
195
-                    $phpHandler[0]->setExceptionHandler($finalHandler);
196
-                }
197
-            }
198
-        }
199
-
200
-        if ($this->autoExit) {
201
-            if ($exitCode > 255) {
202
-                $exitCode = 255;
203
-            }
204
-
205
-            exit($exitCode);
206
-        }
207
-
208
-        return $exitCode;
209
-    }
210
-
211
-    /**
212
-     * Runs the current application.
213
-     *
214
-     * @return int 0 if everything went fine, or an error code
215
-     */
216
-    public function doRun(InputInterface $input, OutputInterface $output)
217
-    {
218
-        if (true === $input->hasParameterOption(['--version', '-V'], true)) {
219
-            $output->writeln($this->getLongVersion());
220
-
221
-            return 0;
222
-        }
223
-
224
-        try {
225
-            // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
226
-            $input->bind($this->getDefinition());
227
-        } catch (ExceptionInterface $e) {
228
-            // Errors must be ignored, full binding/validation happens later when the command is known.
229
-        }
230
-
231
-        $name = $this->getCommandName($input);
232
-        if (true === $input->hasParameterOption(['--help', '-h'], true)) {
233
-            if (!$name) {
234
-                $name = 'help';
235
-                $input = new ArrayInput(['command_name' => $this->defaultCommand]);
236
-            } else {
237
-                $this->wantHelps = true;
238
-            }
239
-        }
240
-
241
-        if (!$name) {
242
-            $name = $this->defaultCommand;
243
-            $definition = $this->getDefinition();
244
-            $definition->setArguments(array_merge(
245
-                $definition->getArguments(),
246
-                [
247
-                    'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
248
-                ]
249
-            ));
250
-        }
251
-
252
-        try {
253
-            $this->runningCommand = null;
254
-            // the command name MUST be the first element of the input
255
-            $command = $this->find($name);
256
-        } catch (\Throwable $e) {
257
-            if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) {
258
-                if (null !== $this->dispatcher) {
259
-                    $event = new ConsoleErrorEvent($input, $output, $e);
260
-                    $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
261
-
262
-                    if (0 === $event->getExitCode()) {
263
-                        return 0;
264
-                    }
265
-
266
-                    $e = $event->getError();
267
-                }
268
-
269
-                throw $e;
270
-            }
271
-
272
-            $alternative = $alternatives[0];
273
-
274
-            $style = new SymfonyStyle($input, $output);
275
-            $style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error');
276
-            if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) {
277
-                if (null !== $this->dispatcher) {
278
-                    $event = new ConsoleErrorEvent($input, $output, $e);
279
-                    $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
280
-
281
-                    return $event->getExitCode();
282
-                }
283
-
284
-                return 1;
285
-            }
286
-
287
-            $command = $this->find($alternative);
288
-        }
289
-
290
-        if ($command instanceof LazyCommand) {
291
-            $command = $command->getCommand();
292
-        }
293
-
294
-        $this->runningCommand = $command;
295
-        $exitCode = $this->doRunCommand($command, $input, $output);
296
-        $this->runningCommand = null;
297
-
298
-        return $exitCode;
299
-    }
300
-
301
-    /**
302
-     * {@inheritdoc}
303
-     */
304
-    public function reset()
305
-    {
306
-    }
307
-
308
-    public function setHelperSet(HelperSet $helperSet)
309
-    {
310
-        $this->helperSet = $helperSet;
311
-    }
312
-
313
-    /**
314
-     * Get the helper set associated with the command.
315
-     *
316
-     * @return HelperSet The HelperSet instance associated with this command
317
-     */
318
-    public function getHelperSet()
319
-    {
320
-        if (!$this->helperSet) {
321
-            $this->helperSet = $this->getDefaultHelperSet();
322
-        }
323
-
324
-        return $this->helperSet;
325
-    }
326
-
327
-    public function setDefinition(InputDefinition $definition)
328
-    {
329
-        $this->definition = $definition;
330
-    }
331
-
332
-    /**
333
-     * Gets the InputDefinition related to this Application.
334
-     *
335
-     * @return InputDefinition The InputDefinition instance
336
-     */
337
-    public function getDefinition()
338
-    {
339
-        if (!$this->definition) {
340
-            $this->definition = $this->getDefaultInputDefinition();
341
-        }
342
-
343
-        if ($this->singleCommand) {
344
-            $inputDefinition = $this->definition;
345
-            $inputDefinition->setArguments();
346
-
347
-            return $inputDefinition;
348
-        }
349
-
350
-        return $this->definition;
351
-    }
352
-
353
-    /**
354
-     * Gets the help message.
355
-     *
356
-     * @return string A help message
357
-     */
358
-    public function getHelp()
359
-    {
360
-        return $this->getLongVersion();
361
-    }
362
-
363
-    /**
364
-     * Gets whether to catch exceptions or not during commands execution.
365
-     *
366
-     * @return bool Whether to catch exceptions or not during commands execution
367
-     */
368
-    public function areExceptionsCaught()
369
-    {
370
-        return $this->catchExceptions;
371
-    }
372
-
373
-    /**
374
-     * Sets whether to catch exceptions or not during commands execution.
375
-     */
376
-    public function setCatchExceptions(bool $boolean)
377
-    {
378
-        $this->catchExceptions = $boolean;
379
-    }
380
-
381
-    /**
382
-     * Gets whether to automatically exit after a command execution or not.
383
-     *
384
-     * @return bool Whether to automatically exit after a command execution or not
385
-     */
386
-    public function isAutoExitEnabled()
387
-    {
388
-        return $this->autoExit;
389
-    }
390
-
391
-    /**
392
-     * Sets whether to automatically exit after a command execution or not.
393
-     */
394
-    public function setAutoExit(bool $boolean)
395
-    {
396
-        $this->autoExit = $boolean;
397
-    }
398
-
399
-    /**
400
-     * Gets the name of the application.
401
-     *
402
-     * @return string The application name
403
-     */
404
-    public function getName()
405
-    {
406
-        return $this->name;
407
-    }
408
-
409
-    /**
410
-     * Sets the application name.
411
-     **/
412
-    public function setName(string $name)
413
-    {
414
-        $this->name = $name;
415
-    }
416
-
417
-    /**
418
-     * Gets the application version.
419
-     *
420
-     * @return string The application version
421
-     */
422
-    public function getVersion()
423
-    {
424
-        return $this->version;
425
-    }
426
-
427
-    /**
428
-     * Sets the application version.
429
-     */
430
-    public function setVersion(string $version)
431
-    {
432
-        $this->version = $version;
433
-    }
434
-
435
-    /**
436
-     * Returns the long version of the application.
437
-     *
438
-     * @return string The long application version
439
-     */
440
-    public function getLongVersion()
441
-    {
442
-        if ('UNKNOWN' !== $this->getName()) {
443
-            if ('UNKNOWN' !== $this->getVersion()) {
444
-                return sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion());
445
-            }
446
-
447
-            return $this->getName();
448
-        }
449
-
450
-        return 'Console Tool';
451
-    }
452
-
453
-    /**
454
-     * Registers a new command.
455
-     *
456
-     * @return Command The newly created command
457
-     */
458
-    public function register(string $name)
459
-    {
460
-        return $this->add(new Command($name));
461
-    }
462
-
463
-    /**
464
-     * Adds an array of command objects.
465
-     *
466
-     * If a Command is not enabled it will not be added.
467
-     *
468
-     * @param Command[] $commands An array of commands
469
-     */
470
-    public function addCommands(array $commands)
471
-    {
472
-        foreach ($commands as $command) {
473
-            $this->add($command);
474
-        }
475
-    }
476
-
477
-    /**
478
-     * Adds a command object.
479
-     *
480
-     * If a command with the same name already exists, it will be overridden.
481
-     * If the command is not enabled it will not be added.
482
-     *
483
-     * @return Command|null The registered command if enabled or null
484
-     */
485
-    public function add(Command $command)
486
-    {
487
-        $this->init();
488
-
489
-        $command->setApplication($this);
490
-
491
-        if (!$command->isEnabled()) {
492
-            $command->setApplication(null);
493
-
494
-            return null;
495
-        }
496
-
497
-        if (!$command instanceof LazyCommand) {
498
-            // Will throw if the command is not correctly initialized.
499
-            $command->getDefinition();
500
-        }
501
-
502
-        if (!$command->getName()) {
503
-            throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command)));
504
-        }
505
-
506
-        $this->commands[$command->getName()] = $command;
507
-
508
-        foreach ($command->getAliases() as $alias) {
509
-            $this->commands[$alias] = $command;
510
-        }
511
-
512
-        return $command;
513
-    }
514
-
515
-    /**
516
-     * Returns a registered command by name or alias.
517
-     *
518
-     * @return Command A Command object
519
-     *
520
-     * @throws CommandNotFoundException When given command name does not exist
521
-     */
522
-    public function get(string $name)
523
-    {
524
-        $this->init();
525
-
526
-        if (!$this->has($name)) {
527
-            throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
528
-        }
529
-
530
-        // When the command has a different name than the one used at the command loader level
531
-        if (!isset($this->commands[$name])) {
532
-            throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name));
533
-        }
534
-
535
-        $command = $this->commands[$name];
536
-
537
-        if ($this->wantHelps) {
538
-            $this->wantHelps = false;
539
-
540
-            $helpCommand = $this->get('help');
541
-            $helpCommand->setCommand($command);
542
-
543
-            return $helpCommand;
544
-        }
545
-
546
-        return $command;
547
-    }
548
-
549
-    /**
550
-     * Returns true if the command exists, false otherwise.
551
-     *
552
-     * @return bool true if the command exists, false otherwise
553
-     */
554
-    public function has(string $name)
555
-    {
556
-        $this->init();
557
-
558
-        return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name)));
559
-    }
560
-
561
-    /**
562
-     * Returns an array of all unique namespaces used by currently registered commands.
563
-     *
564
-     * It does not return the global namespace which always exists.
565
-     *
566
-     * @return string[] An array of namespaces
567
-     */
568
-    public function getNamespaces()
569
-    {
570
-        $namespaces = [];
571
-        foreach ($this->all() as $command) {
572
-            if ($command->isHidden()) {
573
-                continue;
574
-            }
575
-
576
-            $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
577
-
578
-            foreach ($command->getAliases() as $alias) {
579
-                $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
580
-            }
581
-        }
582
-
583
-        return array_values(array_unique(array_filter($namespaces)));
584
-    }
585
-
586
-    /**
587
-     * Finds a registered namespace by a name or an abbreviation.
588
-     *
589
-     * @return string A registered namespace
590
-     *
591
-     * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous
592
-     */
593
-    public function findNamespace(string $namespace)
594
-    {
595
-        $allNamespaces = $this->getNamespaces();
596
-        $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))).'[^:]*';
597
-        $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
598
-
599
-        if (empty($namespaces)) {
600
-            $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
601
-
602
-            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
603
-                if (1 == \count($alternatives)) {
604
-                    $message .= "\n\nDid you mean this?\n    ";
605
-                } else {
606
-                    $message .= "\n\nDid you mean one of these?\n    ";
607
-                }
608
-
609
-                $message .= implode("\n    ", $alternatives);
610
-            }
611
-
612
-            throw new NamespaceNotFoundException($message, $alternatives);
613
-        }
614
-
615
-        $exact = \in_array($namespace, $namespaces, true);
616
-        if (\count($namespaces) > 1 && !$exact) {
617
-            throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
618
-        }
619
-
620
-        return $exact ? $namespace : reset($namespaces);
621
-    }
622
-
623
-    /**
624
-     * Finds a command by name or alias.
625
-     *
626
-     * Contrary to get, this command tries to find the best
627
-     * match if you give it an abbreviation of a name or alias.
628
-     *
629
-     * @return Command A Command instance
630
-     *
631
-     * @throws CommandNotFoundException When command name is incorrect or ambiguous
632
-     */
633
-    public function find(string $name)
634
-    {
635
-        $this->init();
636
-
637
-        $aliases = [];
638
-
639
-        foreach ($this->commands as $command) {
640
-            foreach ($command->getAliases() as $alias) {
641
-                if (!$this->has($alias)) {
642
-                    $this->commands[$alias] = $command;
643
-                }
644
-            }
645
-        }
646
-
647
-        if ($this->has($name)) {
648
-            return $this->get($name);
649
-        }
650
-
651
-        $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
652
-        $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))).'[^:]*';
653
-        $commands = preg_grep('{^'.$expr.'}', $allCommands);
654
-
655
-        if (empty($commands)) {
656
-            $commands = preg_grep('{^'.$expr.'}i', $allCommands);
657
-        }
658
-
659
-        // if no commands matched or we just matched namespaces
660
-        if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) {
661
-            if (false !== $pos = strrpos($name, ':')) {
662
-                // check if a namespace exists and contains commands
663
-                $this->findNamespace(substr($name, 0, $pos));
664
-            }
665
-
666
-            $message = sprintf('Command "%s" is not defined.', $name);
667
-
668
-            if ($alternatives = $this->findAlternatives($name, $allCommands)) {
669
-                // remove hidden commands
670
-                $alternatives = array_filter($alternatives, function ($name) {
671
-                    return !$this->get($name)->isHidden();
672
-                });
673
-
674
-                if (1 == \count($alternatives)) {
675
-                    $message .= "\n\nDid you mean this?\n    ";
676
-                } else {
677
-                    $message .= "\n\nDid you mean one of these?\n    ";
678
-                }
679
-                $message .= implode("\n    ", $alternatives);
680
-            }
681
-
682
-            throw new CommandNotFoundException($message, array_values($alternatives));
683
-        }
684
-
685
-        // filter out aliases for commands which are already on the list
686
-        if (\count($commands) > 1) {
687
-            $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
688
-            $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) {
689
-                if (!$commandList[$nameOrAlias] instanceof Command) {
690
-                    $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
691
-                }
692
-
693
-                $commandName = $commandList[$nameOrAlias]->getName();
694
-
695
-                $aliases[$nameOrAlias] = $commandName;
696
-
697
-                return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
698
-            }));
699
-        }
700
-
701
-        if (\count($commands) > 1) {
702
-            $usableWidth = $this->terminal->getWidth() - 10;
703
-            $abbrevs = array_values($commands);
704
-            $maxLen = 0;
705
-            foreach ($abbrevs as $abbrev) {
706
-                $maxLen = max(Helper::width($abbrev), $maxLen);
707
-            }
708
-            $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) {
709
-                if ($commandList[$cmd]->isHidden()) {
710
-                    unset($commands[array_search($cmd, $commands)]);
711
-
712
-                    return false;
713
-                }
714
-
715
-                $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription();
716
-
717
-                return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev;
718
-            }, array_values($commands));
719
-
720
-            if (\count($commands) > 1) {
721
-                $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs));
722
-
723
-                throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands));
724
-            }
725
-        }
726
-
727
-        $command = $this->get(reset($commands));
728
-
729
-        if ($command->isHidden()) {
730
-            throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
731
-        }
732
-
733
-        return $command;
734
-    }
735
-
736
-    /**
737
-     * Gets the commands (registered in the given namespace if provided).
738
-     *
739
-     * The array keys are the full names and the values the command instances.
740
-     *
741
-     * @return Command[] An array of Command instances
742
-     */
743
-    public function all(string $namespace = null)
744
-    {
745
-        $this->init();
746
-
747
-        if (null === $namespace) {
748
-            if (!$this->commandLoader) {
749
-                return $this->commands;
750
-            }
751
-
752
-            $commands = $this->commands;
753
-            foreach ($this->commandLoader->getNames() as $name) {
754
-                if (!isset($commands[$name]) && $this->has($name)) {
755
-                    $commands[$name] = $this->get($name);
756
-                }
757
-            }
758
-
759
-            return $commands;
760
-        }
761
-
762
-        $commands = [];
763
-        foreach ($this->commands as $name => $command) {
764
-            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
765
-                $commands[$name] = $command;
766
-            }
767
-        }
768
-
769
-        if ($this->commandLoader) {
770
-            foreach ($this->commandLoader->getNames() as $name) {
771
-                if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) {
772
-                    $commands[$name] = $this->get($name);
773
-                }
774
-            }
775
-        }
776
-
777
-        return $commands;
778
-    }
779
-
780
-    /**
781
-     * Returns an array of possible abbreviations given a set of names.
782
-     *
783
-     * @return string[][] An array of abbreviations
784
-     */
785
-    public static function getAbbreviations(array $names)
786
-    {
787
-        $abbrevs = [];
788
-        foreach ($names as $name) {
789
-            for ($len = \strlen($name); $len > 0; --$len) {
790
-                $abbrev = substr($name, 0, $len);
791
-                $abbrevs[$abbrev][] = $name;
792
-            }
793
-        }
794
-
795
-        return $abbrevs;
796
-    }
797
-
798
-    public function renderThrowable(\Throwable $e, OutputInterface $output): void
799
-    {
800
-        $output->writeln('', OutputInterface::VERBOSITY_QUIET);
801
-
802
-        $this->doRenderThrowable($e, $output);
803
-
804
-        if (null !== $this->runningCommand) {
805
-            $output->writeln(sprintf('<info>%s</info>', OutputFormatter::escape(sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET);
806
-            $output->writeln('', OutputInterface::VERBOSITY_QUIET);
807
-        }
808
-    }
809
-
810
-    protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void
811
-    {
812
-        do {
813
-            $message = trim($e->getMessage());
814
-            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
815
-                $class = get_debug_type($e);
816
-                $title = sprintf('  [%s%s]  ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
817
-                $len = Helper::width($title);
818
-            } else {
819
-                $len = 0;
820
-            }
821
-
822
-            if (str_contains($message, "@anonymous\0")) {
823
-                $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
824
-                    return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
825
-                }, $message);
826
-            }
827
-
828
-            $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX;
829
-            $lines = [];
830
-            foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) {
831
-                foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
832
-                    // pre-format lines to get the right string length
833
-                    $lineLength = Helper::width($line) + 4;
834
-                    $lines[] = [$line, $lineLength];
835
-
836
-                    $len = max($lineLength, $len);
837
-                }
838
-            }
839
-
840
-            $messages = [];
841
-            if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
842
-                $messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
843
-            }
844
-            $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
845
-            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
846
-                $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::width($title))));
847
-            }
848
-            foreach ($lines as $line) {
849
-                $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
850
-            }
851
-            $messages[] = $emptyLine;
852
-            $messages[] = '';
853
-
854
-            $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
855
-
856
-            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
857
-                $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
858
-
859
-                // exception related properties
860
-                $trace = $e->getTrace();
861
-
862
-                array_unshift($trace, [
863
-                    'function' => '',
864
-                    'file' => $e->getFile() ?: 'n/a',
865
-                    'line' => $e->getLine() ?: 'n/a',
866
-                    'args' => [],
867
-                ]);
868
-
869
-                for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
870
-                    $class = $trace[$i]['class'] ?? '';
871
-                    $type = $trace[$i]['type'] ?? '';
872
-                    $function = $trace[$i]['function'] ?? '';
873
-                    $file = $trace[$i]['file'] ?? 'n/a';
874
-                    $line = $trace[$i]['line'] ?? 'n/a';
875
-
876
-                    $output->writeln(sprintf(' %s%s at <info>%s:%s</info>', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET);
877
-                }
878
-
879
-                $output->writeln('', OutputInterface::VERBOSITY_QUIET);
880
-            }
881
-        } while ($e = $e->getPrevious());
882
-    }
883
-
884
-    /**
885
-     * Configures the input and output instances based on the user arguments and options.
886
-     */
887
-    protected function configureIO(InputInterface $input, OutputInterface $output)
888
-    {
889
-        if (true === $input->hasParameterOption(['--ansi'], true)) {
890
-            $output->setDecorated(true);
891
-        } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) {
892
-            $output->setDecorated(false);
893
-        }
894
-
895
-        if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) {
896
-            $input->setInteractive(false);
897
-        }
898
-
899
-        switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
900
-            case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break;
901
-            case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break;
902
-            case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break;
903
-            case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break;
904
-            default: $shellVerbosity = 0; break;
905
-        }
906
-
907
-        if (true === $input->hasParameterOption(['--quiet', '-q'], true)) {
908
-            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
909
-            $shellVerbosity = -1;
910
-        } else {
911
-            if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) {
912
-                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
913
-                $shellVerbosity = 3;
914
-            } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) {
915
-                $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
916
-                $shellVerbosity = 2;
917
-            } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) {
918
-                $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
919
-                $shellVerbosity = 1;
920
-            }
921
-        }
922
-
923
-        if (-1 === $shellVerbosity) {
924
-            $input->setInteractive(false);
925
-        }
926
-
927
-        if (\function_exists('putenv')) {
928
-            @putenv('SHELL_VERBOSITY='.$shellVerbosity);
929
-        }
930
-        $_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
931
-        $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
932
-    }
933
-
934
-    /**
935
-     * Runs the current command.
936
-     *
937
-     * If an event dispatcher has been attached to the application,
938
-     * events are also dispatched during the life-cycle of the command.
939
-     *
940
-     * @return int 0 if everything went fine, or an error code
941
-     */
942
-    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
943
-    {
944
-        foreach ($command->getHelperSet() as $helper) {
945
-            if ($helper instanceof InputAwareInterface) {
946
-                $helper->setInput($input);
947
-            }
948
-        }
949
-
950
-        if ($command instanceof SignalableCommandInterface && ($this->signalsToDispatchEvent || $command->getSubscribedSignals())) {
951
-            if (!$this->signalRegistry) {
952
-                throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
953
-            }
954
-
955
-            if ($this->dispatcher) {
956
-                foreach ($this->signalsToDispatchEvent as $signal) {
957
-                    $event = new ConsoleSignalEvent($command, $input, $output, $signal);
958
-
959
-                    $this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) {
960
-                        $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
961
-
962
-                        // No more handlers, we try to simulate PHP default behavior
963
-                        if (!$hasNext) {
964
-                            if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) {
965
-                                exit(0);
966
-                            }
967
-                        }
968
-                    });
969
-                }
970
-            }
971
-
972
-            foreach ($command->getSubscribedSignals() as $signal) {
973
-                $this->signalRegistry->register($signal, [$command, 'handleSignal']);
974
-            }
975
-        }
976
-
977
-        if (null === $this->dispatcher) {
978
-            return $command->run($input, $output);
979
-        }
980
-
981
-        // bind before the console.command event, so the listeners have access to input options/arguments
982
-        try {
983
-            $command->mergeApplicationDefinition();
984
-            $input->bind($command->getDefinition());
985
-        } catch (ExceptionInterface $e) {
986
-            // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
987
-        }
988
-
989
-        $event = new ConsoleCommandEvent($command, $input, $output);
990
-        $e = null;
991
-
992
-        try {
993
-            $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND);
994
-
995
-            if ($event->commandShouldRun()) {
996
-                $exitCode = $command->run($input, $output);
997
-            } else {
998
-                $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
999
-            }
1000
-        } catch (\Throwable $e) {
1001
-            $event = new ConsoleErrorEvent($input, $output, $e, $command);
1002
-            $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
1003
-            $e = $event->getError();
1004
-
1005
-            if (0 === $exitCode = $event->getExitCode()) {
1006
-                $e = null;
1007
-            }
1008
-        }
1009
-
1010
-        $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
1011
-        $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);
1012
-
1013
-        if (null !== $e) {
1014
-            throw $e;
1015
-        }
1016
-
1017
-        return $event->getExitCode();
1018
-    }
1019
-
1020
-    /**
1021
-     * Gets the name of the command based on input.
1022
-     *
1023
-     * @return string|null
1024
-     */
1025
-    protected function getCommandName(InputInterface $input)
1026
-    {
1027
-        return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument();
1028
-    }
1029
-
1030
-    /**
1031
-     * Gets the default input definition.
1032
-     *
1033
-     * @return InputDefinition An InputDefinition instance
1034
-     */
1035
-    protected function getDefaultInputDefinition()
1036
-    {
1037
-        return new InputDefinition([
1038
-            new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
1039
-            new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the <info>'.$this->defaultCommand.'</info> command'),
1040
-            new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
1041
-            new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
1042
-            new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
1043
-            new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', false),
1044
-            new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
1045
-        ]);
1046
-    }
1047
-
1048
-    /**
1049
-     * Gets the default commands that should always be available.
1050
-     *
1051
-     * @return Command[] An array of default Command instances
1052
-     */
1053
-    protected function getDefaultCommands()
1054
-    {
1055
-        return [new HelpCommand(), new ListCommand()];
1056
-    }
1057
-
1058
-    /**
1059
-     * Gets the default helper set with the helpers that should always be available.
1060
-     *
1061
-     * @return HelperSet A HelperSet instance
1062
-     */
1063
-    protected function getDefaultHelperSet()
1064
-    {
1065
-        return new HelperSet([
1066
-            new FormatterHelper(),
1067
-            new DebugFormatterHelper(),
1068
-            new ProcessHelper(),
1069
-            new QuestionHelper(),
1070
-        ]);
1071
-    }
1072
-
1073
-    /**
1074
-     * Returns abbreviated suggestions in string format.
1075
-     */
1076
-    private function getAbbreviationSuggestions(array $abbrevs): string
1077
-    {
1078
-        return '    '.implode("\n    ", $abbrevs);
1079
-    }
1080
-
1081
-    /**
1082
-     * Returns the namespace part of the command name.
1083
-     *
1084
-     * This method is not part of public API and should not be used directly.
1085
-     *
1086
-     * @return string The namespace of the command
1087
-     */
1088
-    public function extractNamespace(string $name, int $limit = null)
1089
-    {
1090
-        $parts = explode(':', $name, -1);
1091
-
1092
-        return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
1093
-    }
1094
-
1095
-    /**
1096
-     * Finds alternative of $name among $collection,
1097
-     * if nothing is found in $collection, try in $abbrevs.
1098
-     *
1099
-     * @return string[] A sorted array of similar string
1100
-     */
1101
-    private function findAlternatives(string $name, iterable $collection): array
1102
-    {
1103
-        $threshold = 1e3;
1104
-        $alternatives = [];
1105
-
1106
-        $collectionParts = [];
1107
-        foreach ($collection as $item) {
1108
-            $collectionParts[$item] = explode(':', $item);
1109
-        }
1110
-
1111
-        foreach (explode(':', $name) as $i => $subname) {
1112
-            foreach ($collectionParts as $collectionName => $parts) {
1113
-                $exists = isset($alternatives[$collectionName]);
1114
-                if (!isset($parts[$i]) && $exists) {
1115
-                    $alternatives[$collectionName] += $threshold;
1116
-                    continue;
1117
-                } elseif (!isset($parts[$i])) {
1118
-                    continue;
1119
-                }
1120
-
1121
-                $lev = levenshtein($subname, $parts[$i]);
1122
-                if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) {
1123
-                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
1124
-                } elseif ($exists) {
1125
-                    $alternatives[$collectionName] += $threshold;
1126
-                }
1127
-            }
1128
-        }
1129
-
1130
-        foreach ($collection as $item) {
1131
-            $lev = levenshtein($name, $item);
1132
-            if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) {
1133
-                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
1134
-            }
1135
-        }
1136
-
1137
-        $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
1138
-        ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE);
1139
-
1140
-        return array_keys($alternatives);
1141
-    }
1142
-
1143
-    /**
1144
-     * Sets the default Command name.
1145
-     *
1146
-     * @return self
1147
-     */
1148
-    public function setDefaultCommand(string $commandName, bool $isSingleCommand = false)
1149
-    {
1150
-        $this->defaultCommand = explode('|', ltrim($commandName, '|'))[0];
1151
-
1152
-        if ($isSingleCommand) {
1153
-            // Ensure the command exist
1154
-            $this->find($commandName);
1155
-
1156
-            $this->singleCommand = true;
1157
-        }
1158
-
1159
-        return $this;
1160
-    }
1161
-
1162
-    /**
1163
-     * @internal
1164
-     */
1165
-    public function isSingleCommand(): bool
1166
-    {
1167
-        return $this->singleCommand;
1168
-    }
1169
-
1170
-    private function splitStringByWidth(string $string, int $width): array
1171
-    {
1172
-        // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
1173
-        // additionally, array_slice() is not enough as some character has doubled width.
1174
-        // we need a function to split string not by character count but by string width
1175
-        if (false === $encoding = mb_detect_encoding($string, null, true)) {
1176
-            return str_split($string, $width);
1177
-        }
1178
-
1179
-        $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
1180
-        $lines = [];
1181
-        $line = '';
1182
-
1183
-        $offset = 0;
1184
-        while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) {
1185
-            $offset += \strlen($m[0]);
1186
-
1187
-            foreach (preg_split('//u', $m[0]) as $char) {
1188
-                // test if $char could be appended to current line
1189
-                if (mb_strwidth($line.$char, 'utf8') <= $width) {
1190
-                    $line .= $char;
1191
-                    continue;
1192
-                }
1193
-                // if not, push current line to array and make new line
1194
-                $lines[] = str_pad($line, $width);
1195
-                $line = $char;
1196
-            }
1197
-        }
1198
-
1199
-        $lines[] = \count($lines) ? str_pad($line, $width) : $line;
1200
-
1201
-        mb_convert_variables($encoding, 'utf8', $lines);
1202
-
1203
-        return $lines;
1204
-    }
1205
-
1206
-    /**
1207
-     * Returns all namespaces of the command name.
1208
-     *
1209
-     * @return string[] The namespaces of the command
1210
-     */
1211
-    private function extractAllNamespaces(string $name): array
1212
-    {
1213
-        // -1 as third argument is needed to skip the command short name when exploding
1214
-        $parts = explode(':', $name, -1);
1215
-        $namespaces = [];
1216
-
1217
-        foreach ($parts as $part) {
1218
-            if (\count($namespaces)) {
1219
-                $namespaces[] = end($namespaces).':'.$part;
1220
-            } else {
1221
-                $namespaces[] = $part;
1222
-            }
1223
-        }
1224
-
1225
-        return $namespaces;
1226
-    }
1227
-
1228
-    private function init()
1229
-    {
1230
-        if ($this->initialized) {
1231
-            return;
1232
-        }
1233
-        $this->initialized = true;
1234
-
1235
-        foreach ($this->getDefaultCommands() as $command) {
1236
-            $this->add($command);
1237
-        }
1238
-    }
69
+	private $commands = [];
70
+	private $wantHelps = false;
71
+	private $runningCommand;
72
+	private $name;
73
+	private $version;
74
+	private $commandLoader;
75
+	private $catchExceptions = true;
76
+	private $autoExit = true;
77
+	private $definition;
78
+	private $helperSet;
79
+	private $dispatcher;
80
+	private $terminal;
81
+	private $defaultCommand;
82
+	private $singleCommand = false;
83
+	private $initialized;
84
+	private $signalRegistry;
85
+	private $signalsToDispatchEvent = [];
86
+
87
+	public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN')
88
+	{
89
+		$this->name = $name;
90
+		$this->version = $version;
91
+		$this->terminal = new Terminal();
92
+		$this->defaultCommand = 'list';
93
+		if (\defined('SIGINT') && SignalRegistry::isSupported()) {
94
+			$this->signalRegistry = new SignalRegistry();
95
+			$this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2];
96
+		}
97
+	}
98
+
99
+	/**
100
+	 * @final
101
+	 */
102
+	public function setDispatcher(EventDispatcherInterface $dispatcher)
103
+	{
104
+		$this->dispatcher = $dispatcher;
105
+	}
106
+
107
+	public function setCommandLoader(CommandLoaderInterface $commandLoader)
108
+	{
109
+		$this->commandLoader = $commandLoader;
110
+	}
111
+
112
+	public function getSignalRegistry(): SignalRegistry
113
+	{
114
+		if (!$this->signalRegistry) {
115
+			throw new RuntimeException('Signals are not supported. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
116
+		}
117
+
118
+		return $this->signalRegistry;
119
+	}
120
+
121
+	public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent)
122
+	{
123
+		$this->signalsToDispatchEvent = $signalsToDispatchEvent;
124
+	}
125
+
126
+	/**
127
+	 * Runs the current application.
128
+	 *
129
+	 * @return int 0 if everything went fine, or an error code
130
+	 *
131
+	 * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
132
+	 */
133
+	public function run(InputInterface $input = null, OutputInterface $output = null)
134
+	{
135
+		if (\function_exists('putenv')) {
136
+			@putenv('LINES='.$this->terminal->getHeight());
137
+			@putenv('COLUMNS='.$this->terminal->getWidth());
138
+		}
139
+
140
+		if (null === $input) {
141
+			$input = new ArgvInput();
142
+		}
143
+
144
+		if (null === $output) {
145
+			$output = new ConsoleOutput();
146
+		}
147
+
148
+		$renderException = function (\Throwable $e) use ($output) {
149
+			if ($output instanceof ConsoleOutputInterface) {
150
+				$this->renderThrowable($e, $output->getErrorOutput());
151
+			} else {
152
+				$this->renderThrowable($e, $output);
153
+			}
154
+		};
155
+		if ($phpHandler = set_exception_handler($renderException)) {
156
+			restore_exception_handler();
157
+			if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
158
+				$errorHandler = true;
159
+			} elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
160
+				$phpHandler[0]->setExceptionHandler($errorHandler);
161
+			}
162
+		}
163
+
164
+		$this->configureIO($input, $output);
165
+
166
+		try {
167
+			$exitCode = $this->doRun($input, $output);
168
+		} catch (\Exception $e) {
169
+			if (!$this->catchExceptions) {
170
+				throw $e;
171
+			}
172
+
173
+			$renderException($e);
174
+
175
+			$exitCode = $e->getCode();
176
+			if (is_numeric($exitCode)) {
177
+				$exitCode = (int) $exitCode;
178
+				if (0 === $exitCode) {
179
+					$exitCode = 1;
180
+				}
181
+			} else {
182
+				$exitCode = 1;
183
+			}
184
+		} finally {
185
+			// if the exception handler changed, keep it
186
+			// otherwise, unregister $renderException
187
+			if (!$phpHandler) {
188
+				if (set_exception_handler($renderException) === $renderException) {
189
+					restore_exception_handler();
190
+				}
191
+				restore_exception_handler();
192
+			} elseif (!$errorHandler) {
193
+				$finalHandler = $phpHandler[0]->setExceptionHandler(null);
194
+				if ($finalHandler !== $renderException) {
195
+					$phpHandler[0]->setExceptionHandler($finalHandler);
196
+				}
197
+			}
198
+		}
199
+
200
+		if ($this->autoExit) {
201
+			if ($exitCode > 255) {
202
+				$exitCode = 255;
203
+			}
204
+
205
+			exit($exitCode);
206
+		}
207
+
208
+		return $exitCode;
209
+	}
210
+
211
+	/**
212
+	 * Runs the current application.
213
+	 *
214
+	 * @return int 0 if everything went fine, or an error code
215
+	 */
216
+	public function doRun(InputInterface $input, OutputInterface $output)
217
+	{
218
+		if (true === $input->hasParameterOption(['--version', '-V'], true)) {
219
+			$output->writeln($this->getLongVersion());
220
+
221
+			return 0;
222
+		}
223
+
224
+		try {
225
+			// Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
226
+			$input->bind($this->getDefinition());
227
+		} catch (ExceptionInterface $e) {
228
+			// Errors must be ignored, full binding/validation happens later when the command is known.
229
+		}
230
+
231
+		$name = $this->getCommandName($input);
232
+		if (true === $input->hasParameterOption(['--help', '-h'], true)) {
233
+			if (!$name) {
234
+				$name = 'help';
235
+				$input = new ArrayInput(['command_name' => $this->defaultCommand]);
236
+			} else {
237
+				$this->wantHelps = true;
238
+			}
239
+		}
240
+
241
+		if (!$name) {
242
+			$name = $this->defaultCommand;
243
+			$definition = $this->getDefinition();
244
+			$definition->setArguments(array_merge(
245
+				$definition->getArguments(),
246
+				[
247
+					'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
248
+				]
249
+			));
250
+		}
251
+
252
+		try {
253
+			$this->runningCommand = null;
254
+			// the command name MUST be the first element of the input
255
+			$command = $this->find($name);
256
+		} catch (\Throwable $e) {
257
+			if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) {
258
+				if (null !== $this->dispatcher) {
259
+					$event = new ConsoleErrorEvent($input, $output, $e);
260
+					$this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
261
+
262
+					if (0 === $event->getExitCode()) {
263
+						return 0;
264
+					}
265
+
266
+					$e = $event->getError();
267
+				}
268
+
269
+				throw $e;
270
+			}
271
+
272
+			$alternative = $alternatives[0];
273
+
274
+			$style = new SymfonyStyle($input, $output);
275
+			$style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error');
276
+			if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) {
277
+				if (null !== $this->dispatcher) {
278
+					$event = new ConsoleErrorEvent($input, $output, $e);
279
+					$this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
280
+
281
+					return $event->getExitCode();
282
+				}
283
+
284
+				return 1;
285
+			}
286
+
287
+			$command = $this->find($alternative);
288
+		}
289
+
290
+		if ($command instanceof LazyCommand) {
291
+			$command = $command->getCommand();
292
+		}
293
+
294
+		$this->runningCommand = $command;
295
+		$exitCode = $this->doRunCommand($command, $input, $output);
296
+		$this->runningCommand = null;
297
+
298
+		return $exitCode;
299
+	}
300
+
301
+	/**
302
+	 * {@inheritdoc}
303
+	 */
304
+	public function reset()
305
+	{
306
+	}
307
+
308
+	public function setHelperSet(HelperSet $helperSet)
309
+	{
310
+		$this->helperSet = $helperSet;
311
+	}
312
+
313
+	/**
314
+	 * Get the helper set associated with the command.
315
+	 *
316
+	 * @return HelperSet The HelperSet instance associated with this command
317
+	 */
318
+	public function getHelperSet()
319
+	{
320
+		if (!$this->helperSet) {
321
+			$this->helperSet = $this->getDefaultHelperSet();
322
+		}
323
+
324
+		return $this->helperSet;
325
+	}
326
+
327
+	public function setDefinition(InputDefinition $definition)
328
+	{
329
+		$this->definition = $definition;
330
+	}
331
+
332
+	/**
333
+	 * Gets the InputDefinition related to this Application.
334
+	 *
335
+	 * @return InputDefinition The InputDefinition instance
336
+	 */
337
+	public function getDefinition()
338
+	{
339
+		if (!$this->definition) {
340
+			$this->definition = $this->getDefaultInputDefinition();
341
+		}
342
+
343
+		if ($this->singleCommand) {
344
+			$inputDefinition = $this->definition;
345
+			$inputDefinition->setArguments();
346
+
347
+			return $inputDefinition;
348
+		}
349
+
350
+		return $this->definition;
351
+	}
352
+
353
+	/**
354
+	 * Gets the help message.
355
+	 *
356
+	 * @return string A help message
357
+	 */
358
+	public function getHelp()
359
+	{
360
+		return $this->getLongVersion();
361
+	}
362
+
363
+	/**
364
+	 * Gets whether to catch exceptions or not during commands execution.
365
+	 *
366
+	 * @return bool Whether to catch exceptions or not during commands execution
367
+	 */
368
+	public function areExceptionsCaught()
369
+	{
370
+		return $this->catchExceptions;
371
+	}
372
+
373
+	/**
374
+	 * Sets whether to catch exceptions or not during commands execution.
375
+	 */
376
+	public function setCatchExceptions(bool $boolean)
377
+	{
378
+		$this->catchExceptions = $boolean;
379
+	}
380
+
381
+	/**
382
+	 * Gets whether to automatically exit after a command execution or not.
383
+	 *
384
+	 * @return bool Whether to automatically exit after a command execution or not
385
+	 */
386
+	public function isAutoExitEnabled()
387
+	{
388
+		return $this->autoExit;
389
+	}
390
+
391
+	/**
392
+	 * Sets whether to automatically exit after a command execution or not.
393
+	 */
394
+	public function setAutoExit(bool $boolean)
395
+	{
396
+		$this->autoExit = $boolean;
397
+	}
398
+
399
+	/**
400
+	 * Gets the name of the application.
401
+	 *
402
+	 * @return string The application name
403
+	 */
404
+	public function getName()
405
+	{
406
+		return $this->name;
407
+	}
408
+
409
+	/**
410
+	 * Sets the application name.
411
+	 **/
412
+	public function setName(string $name)
413
+	{
414
+		$this->name = $name;
415
+	}
416
+
417
+	/**
418
+	 * Gets the application version.
419
+	 *
420
+	 * @return string The application version
421
+	 */
422
+	public function getVersion()
423
+	{
424
+		return $this->version;
425
+	}
426
+
427
+	/**
428
+	 * Sets the application version.
429
+	 */
430
+	public function setVersion(string $version)
431
+	{
432
+		$this->version = $version;
433
+	}
434
+
435
+	/**
436
+	 * Returns the long version of the application.
437
+	 *
438
+	 * @return string The long application version
439
+	 */
440
+	public function getLongVersion()
441
+	{
442
+		if ('UNKNOWN' !== $this->getName()) {
443
+			if ('UNKNOWN' !== $this->getVersion()) {
444
+				return sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion());
445
+			}
446
+
447
+			return $this->getName();
448
+		}
449
+
450
+		return 'Console Tool';
451
+	}
452
+
453
+	/**
454
+	 * Registers a new command.
455
+	 *
456
+	 * @return Command The newly created command
457
+	 */
458
+	public function register(string $name)
459
+	{
460
+		return $this->add(new Command($name));
461
+	}
462
+
463
+	/**
464
+	 * Adds an array of command objects.
465
+	 *
466
+	 * If a Command is not enabled it will not be added.
467
+	 *
468
+	 * @param Command[] $commands An array of commands
469
+	 */
470
+	public function addCommands(array $commands)
471
+	{
472
+		foreach ($commands as $command) {
473
+			$this->add($command);
474
+		}
475
+	}
476
+
477
+	/**
478
+	 * Adds a command object.
479
+	 *
480
+	 * If a command with the same name already exists, it will be overridden.
481
+	 * If the command is not enabled it will not be added.
482
+	 *
483
+	 * @return Command|null The registered command if enabled or null
484
+	 */
485
+	public function add(Command $command)
486
+	{
487
+		$this->init();
488
+
489
+		$command->setApplication($this);
490
+
491
+		if (!$command->isEnabled()) {
492
+			$command->setApplication(null);
493
+
494
+			return null;
495
+		}
496
+
497
+		if (!$command instanceof LazyCommand) {
498
+			// Will throw if the command is not correctly initialized.
499
+			$command->getDefinition();
500
+		}
501
+
502
+		if (!$command->getName()) {
503
+			throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command)));
504
+		}
505
+
506
+		$this->commands[$command->getName()] = $command;
507
+
508
+		foreach ($command->getAliases() as $alias) {
509
+			$this->commands[$alias] = $command;
510
+		}
511
+
512
+		return $command;
513
+	}
514
+
515
+	/**
516
+	 * Returns a registered command by name or alias.
517
+	 *
518
+	 * @return Command A Command object
519
+	 *
520
+	 * @throws CommandNotFoundException When given command name does not exist
521
+	 */
522
+	public function get(string $name)
523
+	{
524
+		$this->init();
525
+
526
+		if (!$this->has($name)) {
527
+			throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
528
+		}
529
+
530
+		// When the command has a different name than the one used at the command loader level
531
+		if (!isset($this->commands[$name])) {
532
+			throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name));
533
+		}
534
+
535
+		$command = $this->commands[$name];
536
+
537
+		if ($this->wantHelps) {
538
+			$this->wantHelps = false;
539
+
540
+			$helpCommand = $this->get('help');
541
+			$helpCommand->setCommand($command);
542
+
543
+			return $helpCommand;
544
+		}
545
+
546
+		return $command;
547
+	}
548
+
549
+	/**
550
+	 * Returns true if the command exists, false otherwise.
551
+	 *
552
+	 * @return bool true if the command exists, false otherwise
553
+	 */
554
+	public function has(string $name)
555
+	{
556
+		$this->init();
557
+
558
+		return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name)));
559
+	}
560
+
561
+	/**
562
+	 * Returns an array of all unique namespaces used by currently registered commands.
563
+	 *
564
+	 * It does not return the global namespace which always exists.
565
+	 *
566
+	 * @return string[] An array of namespaces
567
+	 */
568
+	public function getNamespaces()
569
+	{
570
+		$namespaces = [];
571
+		foreach ($this->all() as $command) {
572
+			if ($command->isHidden()) {
573
+				continue;
574
+			}
575
+
576
+			$namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
577
+
578
+			foreach ($command->getAliases() as $alias) {
579
+				$namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
580
+			}
581
+		}
582
+
583
+		return array_values(array_unique(array_filter($namespaces)));
584
+	}
585
+
586
+	/**
587
+	 * Finds a registered namespace by a name or an abbreviation.
588
+	 *
589
+	 * @return string A registered namespace
590
+	 *
591
+	 * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous
592
+	 */
593
+	public function findNamespace(string $namespace)
594
+	{
595
+		$allNamespaces = $this->getNamespaces();
596
+		$expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))).'[^:]*';
597
+		$namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
598
+
599
+		if (empty($namespaces)) {
600
+			$message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
601
+
602
+			if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
603
+				if (1 == \count($alternatives)) {
604
+					$message .= "\n\nDid you mean this?\n    ";
605
+				} else {
606
+					$message .= "\n\nDid you mean one of these?\n    ";
607
+				}
608
+
609
+				$message .= implode("\n    ", $alternatives);
610
+			}
611
+
612
+			throw new NamespaceNotFoundException($message, $alternatives);
613
+		}
614
+
615
+		$exact = \in_array($namespace, $namespaces, true);
616
+		if (\count($namespaces) > 1 && !$exact) {
617
+			throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
618
+		}
619
+
620
+		return $exact ? $namespace : reset($namespaces);
621
+	}
622
+
623
+	/**
624
+	 * Finds a command by name or alias.
625
+	 *
626
+	 * Contrary to get, this command tries to find the best
627
+	 * match if you give it an abbreviation of a name or alias.
628
+	 *
629
+	 * @return Command A Command instance
630
+	 *
631
+	 * @throws CommandNotFoundException When command name is incorrect or ambiguous
632
+	 */
633
+	public function find(string $name)
634
+	{
635
+		$this->init();
636
+
637
+		$aliases = [];
638
+
639
+		foreach ($this->commands as $command) {
640
+			foreach ($command->getAliases() as $alias) {
641
+				if (!$this->has($alias)) {
642
+					$this->commands[$alias] = $command;
643
+				}
644
+			}
645
+		}
646
+
647
+		if ($this->has($name)) {
648
+			return $this->get($name);
649
+		}
650
+
651
+		$allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
652
+		$expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))).'[^:]*';
653
+		$commands = preg_grep('{^'.$expr.'}', $allCommands);
654
+
655
+		if (empty($commands)) {
656
+			$commands = preg_grep('{^'.$expr.'}i', $allCommands);
657
+		}
658
+
659
+		// if no commands matched or we just matched namespaces
660
+		if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) {
661
+			if (false !== $pos = strrpos($name, ':')) {
662
+				// check if a namespace exists and contains commands
663
+				$this->findNamespace(substr($name, 0, $pos));
664
+			}
665
+
666
+			$message = sprintf('Command "%s" is not defined.', $name);
667
+
668
+			if ($alternatives = $this->findAlternatives($name, $allCommands)) {
669
+				// remove hidden commands
670
+				$alternatives = array_filter($alternatives, function ($name) {
671
+					return !$this->get($name)->isHidden();
672
+				});
673
+
674
+				if (1 == \count($alternatives)) {
675
+					$message .= "\n\nDid you mean this?\n    ";
676
+				} else {
677
+					$message .= "\n\nDid you mean one of these?\n    ";
678
+				}
679
+				$message .= implode("\n    ", $alternatives);
680
+			}
681
+
682
+			throw new CommandNotFoundException($message, array_values($alternatives));
683
+		}
684
+
685
+		// filter out aliases for commands which are already on the list
686
+		if (\count($commands) > 1) {
687
+			$commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
688
+			$commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) {
689
+				if (!$commandList[$nameOrAlias] instanceof Command) {
690
+					$commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
691
+				}
692
+
693
+				$commandName = $commandList[$nameOrAlias]->getName();
694
+
695
+				$aliases[$nameOrAlias] = $commandName;
696
+
697
+				return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
698
+			}));
699
+		}
700
+
701
+		if (\count($commands) > 1) {
702
+			$usableWidth = $this->terminal->getWidth() - 10;
703
+			$abbrevs = array_values($commands);
704
+			$maxLen = 0;
705
+			foreach ($abbrevs as $abbrev) {
706
+				$maxLen = max(Helper::width($abbrev), $maxLen);
707
+			}
708
+			$abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) {
709
+				if ($commandList[$cmd]->isHidden()) {
710
+					unset($commands[array_search($cmd, $commands)]);
711
+
712
+					return false;
713
+				}
714
+
715
+				$abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription();
716
+
717
+				return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev;
718
+			}, array_values($commands));
719
+
720
+			if (\count($commands) > 1) {
721
+				$suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs));
722
+
723
+				throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands));
724
+			}
725
+		}
726
+
727
+		$command = $this->get(reset($commands));
728
+
729
+		if ($command->isHidden()) {
730
+			throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
731
+		}
732
+
733
+		return $command;
734
+	}
735
+
736
+	/**
737
+	 * Gets the commands (registered in the given namespace if provided).
738
+	 *
739
+	 * The array keys are the full names and the values the command instances.
740
+	 *
741
+	 * @return Command[] An array of Command instances
742
+	 */
743
+	public function all(string $namespace = null)
744
+	{
745
+		$this->init();
746
+
747
+		if (null === $namespace) {
748
+			if (!$this->commandLoader) {
749
+				return $this->commands;
750
+			}
751
+
752
+			$commands = $this->commands;
753
+			foreach ($this->commandLoader->getNames() as $name) {
754
+				if (!isset($commands[$name]) && $this->has($name)) {
755
+					$commands[$name] = $this->get($name);
756
+				}
757
+			}
758
+
759
+			return $commands;
760
+		}
761
+
762
+		$commands = [];
763
+		foreach ($this->commands as $name => $command) {
764
+			if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
765
+				$commands[$name] = $command;
766
+			}
767
+		}
768
+
769
+		if ($this->commandLoader) {
770
+			foreach ($this->commandLoader->getNames() as $name) {
771
+				if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) {
772
+					$commands[$name] = $this->get($name);
773
+				}
774
+			}
775
+		}
776
+
777
+		return $commands;
778
+	}
779
+
780
+	/**
781
+	 * Returns an array of possible abbreviations given a set of names.
782
+	 *
783
+	 * @return string[][] An array of abbreviations
784
+	 */
785
+	public static function getAbbreviations(array $names)
786
+	{
787
+		$abbrevs = [];
788
+		foreach ($names as $name) {
789
+			for ($len = \strlen($name); $len > 0; --$len) {
790
+				$abbrev = substr($name, 0, $len);
791
+				$abbrevs[$abbrev][] = $name;
792
+			}
793
+		}
794
+
795
+		return $abbrevs;
796
+	}
797
+
798
+	public function renderThrowable(\Throwable $e, OutputInterface $output): void
799
+	{
800
+		$output->writeln('', OutputInterface::VERBOSITY_QUIET);
801
+
802
+		$this->doRenderThrowable($e, $output);
803
+
804
+		if (null !== $this->runningCommand) {
805
+			$output->writeln(sprintf('<info>%s</info>', OutputFormatter::escape(sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET);
806
+			$output->writeln('', OutputInterface::VERBOSITY_QUIET);
807
+		}
808
+	}
809
+
810
+	protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void
811
+	{
812
+		do {
813
+			$message = trim($e->getMessage());
814
+			if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
815
+				$class = get_debug_type($e);
816
+				$title = sprintf('  [%s%s]  ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
817
+				$len = Helper::width($title);
818
+			} else {
819
+				$len = 0;
820
+			}
821
+
822
+			if (str_contains($message, "@anonymous\0")) {
823
+				$message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
824
+					return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
825
+				}, $message);
826
+			}
827
+
828
+			$width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX;
829
+			$lines = [];
830
+			foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) {
831
+				foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
832
+					// pre-format lines to get the right string length
833
+					$lineLength = Helper::width($line) + 4;
834
+					$lines[] = [$line, $lineLength];
835
+
836
+					$len = max($lineLength, $len);
837
+				}
838
+			}
839
+
840
+			$messages = [];
841
+			if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
842
+				$messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
843
+			}
844
+			$messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
845
+			if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
846
+				$messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::width($title))));
847
+			}
848
+			foreach ($lines as $line) {
849
+				$messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
850
+			}
851
+			$messages[] = $emptyLine;
852
+			$messages[] = '';
853
+
854
+			$output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
855
+
856
+			if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
857
+				$output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
858
+
859
+				// exception related properties
860
+				$trace = $e->getTrace();
861
+
862
+				array_unshift($trace, [
863
+					'function' => '',
864
+					'file' => $e->getFile() ?: 'n/a',
865
+					'line' => $e->getLine() ?: 'n/a',
866
+					'args' => [],
867
+				]);
868
+
869
+				for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
870
+					$class = $trace[$i]['class'] ?? '';
871
+					$type = $trace[$i]['type'] ?? '';
872
+					$function = $trace[$i]['function'] ?? '';
873
+					$file = $trace[$i]['file'] ?? 'n/a';
874
+					$line = $trace[$i]['line'] ?? 'n/a';
875
+
876
+					$output->writeln(sprintf(' %s%s at <info>%s:%s</info>', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET);
877
+				}
878
+
879
+				$output->writeln('', OutputInterface::VERBOSITY_QUIET);
880
+			}
881
+		} while ($e = $e->getPrevious());
882
+	}
883
+
884
+	/**
885
+	 * Configures the input and output instances based on the user arguments and options.
886
+	 */
887
+	protected function configureIO(InputInterface $input, OutputInterface $output)
888
+	{
889
+		if (true === $input->hasParameterOption(['--ansi'], true)) {
890
+			$output->setDecorated(true);
891
+		} elseif (true === $input->hasParameterOption(['--no-ansi'], true)) {
892
+			$output->setDecorated(false);
893
+		}
894
+
895
+		if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) {
896
+			$input->setInteractive(false);
897
+		}
898
+
899
+		switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
900
+			case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break;
901
+			case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break;
902
+			case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break;
903
+			case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break;
904
+			default: $shellVerbosity = 0; break;
905
+		}
906
+
907
+		if (true === $input->hasParameterOption(['--quiet', '-q'], true)) {
908
+			$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
909
+			$shellVerbosity = -1;
910
+		} else {
911
+			if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) {
912
+				$output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
913
+				$shellVerbosity = 3;
914
+			} elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) {
915
+				$output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
916
+				$shellVerbosity = 2;
917
+			} elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) {
918
+				$output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
919
+				$shellVerbosity = 1;
920
+			}
921
+		}
922
+
923
+		if (-1 === $shellVerbosity) {
924
+			$input->setInteractive(false);
925
+		}
926
+
927
+		if (\function_exists('putenv')) {
928
+			@putenv('SHELL_VERBOSITY='.$shellVerbosity);
929
+		}
930
+		$_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
931
+		$_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
932
+	}
933
+
934
+	/**
935
+	 * Runs the current command.
936
+	 *
937
+	 * If an event dispatcher has been attached to the application,
938
+	 * events are also dispatched during the life-cycle of the command.
939
+	 *
940
+	 * @return int 0 if everything went fine, or an error code
941
+	 */
942
+	protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
943
+	{
944
+		foreach ($command->getHelperSet() as $helper) {
945
+			if ($helper instanceof InputAwareInterface) {
946
+				$helper->setInput($input);
947
+			}
948
+		}
949
+
950
+		if ($command instanceof SignalableCommandInterface && ($this->signalsToDispatchEvent || $command->getSubscribedSignals())) {
951
+			if (!$this->signalRegistry) {
952
+				throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
953
+			}
954
+
955
+			if ($this->dispatcher) {
956
+				foreach ($this->signalsToDispatchEvent as $signal) {
957
+					$event = new ConsoleSignalEvent($command, $input, $output, $signal);
958
+
959
+					$this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) {
960
+						$this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
961
+
962
+						// No more handlers, we try to simulate PHP default behavior
963
+						if (!$hasNext) {
964
+							if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) {
965
+								exit(0);
966
+							}
967
+						}
968
+					});
969
+				}
970
+			}
971
+
972
+			foreach ($command->getSubscribedSignals() as $signal) {
973
+				$this->signalRegistry->register($signal, [$command, 'handleSignal']);
974
+			}
975
+		}
976
+
977
+		if (null === $this->dispatcher) {
978
+			return $command->run($input, $output);
979
+		}
980
+
981
+		// bind before the console.command event, so the listeners have access to input options/arguments
982
+		try {
983
+			$command->mergeApplicationDefinition();
984
+			$input->bind($command->getDefinition());
985
+		} catch (ExceptionInterface $e) {
986
+			// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
987
+		}
988
+
989
+		$event = new ConsoleCommandEvent($command, $input, $output);
990
+		$e = null;
991
+
992
+		try {
993
+			$this->dispatcher->dispatch($event, ConsoleEvents::COMMAND);
994
+
995
+			if ($event->commandShouldRun()) {
996
+				$exitCode = $command->run($input, $output);
997
+			} else {
998
+				$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
999
+			}
1000
+		} catch (\Throwable $e) {
1001
+			$event = new ConsoleErrorEvent($input, $output, $e, $command);
1002
+			$this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
1003
+			$e = $event->getError();
1004
+
1005
+			if (0 === $exitCode = $event->getExitCode()) {
1006
+				$e = null;
1007
+			}
1008
+		}
1009
+
1010
+		$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
1011
+		$this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);
1012
+
1013
+		if (null !== $e) {
1014
+			throw $e;
1015
+		}
1016
+
1017
+		return $event->getExitCode();
1018
+	}
1019
+
1020
+	/**
1021
+	 * Gets the name of the command based on input.
1022
+	 *
1023
+	 * @return string|null
1024
+	 */
1025
+	protected function getCommandName(InputInterface $input)
1026
+	{
1027
+		return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument();
1028
+	}
1029
+
1030
+	/**
1031
+	 * Gets the default input definition.
1032
+	 *
1033
+	 * @return InputDefinition An InputDefinition instance
1034
+	 */
1035
+	protected function getDefaultInputDefinition()
1036
+	{
1037
+		return new InputDefinition([
1038
+			new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
1039
+			new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the <info>'.$this->defaultCommand.'</info> command'),
1040
+			new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
1041
+			new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
1042
+			new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
1043
+			new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', false),
1044
+			new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
1045
+		]);
1046
+	}
1047
+
1048
+	/**
1049
+	 * Gets the default commands that should always be available.
1050
+	 *
1051
+	 * @return Command[] An array of default Command instances
1052
+	 */
1053
+	protected function getDefaultCommands()
1054
+	{
1055
+		return [new HelpCommand(), new ListCommand()];
1056
+	}
1057
+
1058
+	/**
1059
+	 * Gets the default helper set with the helpers that should always be available.
1060
+	 *
1061
+	 * @return HelperSet A HelperSet instance
1062
+	 */
1063
+	protected function getDefaultHelperSet()
1064
+	{
1065
+		return new HelperSet([
1066
+			new FormatterHelper(),
1067
+			new DebugFormatterHelper(),
1068
+			new ProcessHelper(),
1069
+			new QuestionHelper(),
1070
+		]);
1071
+	}
1072
+
1073
+	/**
1074
+	 * Returns abbreviated suggestions in string format.
1075
+	 */
1076
+	private function getAbbreviationSuggestions(array $abbrevs): string
1077
+	{
1078
+		return '    '.implode("\n    ", $abbrevs);
1079
+	}
1080
+
1081
+	/**
1082
+	 * Returns the namespace part of the command name.
1083
+	 *
1084
+	 * This method is not part of public API and should not be used directly.
1085
+	 *
1086
+	 * @return string The namespace of the command
1087
+	 */
1088
+	public function extractNamespace(string $name, int $limit = null)
1089
+	{
1090
+		$parts = explode(':', $name, -1);
1091
+
1092
+		return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
1093
+	}
1094
+
1095
+	/**
1096
+	 * Finds alternative of $name among $collection,
1097
+	 * if nothing is found in $collection, try in $abbrevs.
1098
+	 *
1099
+	 * @return string[] A sorted array of similar string
1100
+	 */
1101
+	private function findAlternatives(string $name, iterable $collection): array
1102
+	{
1103
+		$threshold = 1e3;
1104
+		$alternatives = [];
1105
+
1106
+		$collectionParts = [];
1107
+		foreach ($collection as $item) {
1108
+			$collectionParts[$item] = explode(':', $item);
1109
+		}
1110
+
1111
+		foreach (explode(':', $name) as $i => $subname) {
1112
+			foreach ($collectionParts as $collectionName => $parts) {
1113
+				$exists = isset($alternatives[$collectionName]);
1114
+				if (!isset($parts[$i]) && $exists) {
1115
+					$alternatives[$collectionName] += $threshold;
1116
+					continue;
1117
+				} elseif (!isset($parts[$i])) {
1118
+					continue;
1119
+				}
1120
+
1121
+				$lev = levenshtein($subname, $parts[$i]);
1122
+				if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) {
1123
+					$alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
1124
+				} elseif ($exists) {
1125
+					$alternatives[$collectionName] += $threshold;
1126
+				}
1127
+			}
1128
+		}
1129
+
1130
+		foreach ($collection as $item) {
1131
+			$lev = levenshtein($name, $item);
1132
+			if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) {
1133
+				$alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
1134
+			}
1135
+		}
1136
+
1137
+		$alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
1138
+		ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE);
1139
+
1140
+		return array_keys($alternatives);
1141
+	}
1142
+
1143
+	/**
1144
+	 * Sets the default Command name.
1145
+	 *
1146
+	 * @return self
1147
+	 */
1148
+	public function setDefaultCommand(string $commandName, bool $isSingleCommand = false)
1149
+	{
1150
+		$this->defaultCommand = explode('|', ltrim($commandName, '|'))[0];
1151
+
1152
+		if ($isSingleCommand) {
1153
+			// Ensure the command exist
1154
+			$this->find($commandName);
1155
+
1156
+			$this->singleCommand = true;
1157
+		}
1158
+
1159
+		return $this;
1160
+	}
1161
+
1162
+	/**
1163
+	 * @internal
1164
+	 */
1165
+	public function isSingleCommand(): bool
1166
+	{
1167
+		return $this->singleCommand;
1168
+	}
1169
+
1170
+	private function splitStringByWidth(string $string, int $width): array
1171
+	{
1172
+		// str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
1173
+		// additionally, array_slice() is not enough as some character has doubled width.
1174
+		// we need a function to split string not by character count but by string width
1175
+		if (false === $encoding = mb_detect_encoding($string, null, true)) {
1176
+			return str_split($string, $width);
1177
+		}
1178
+
1179
+		$utf8String = mb_convert_encoding($string, 'utf8', $encoding);
1180
+		$lines = [];
1181
+		$line = '';
1182
+
1183
+		$offset = 0;
1184
+		while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) {
1185
+			$offset += \strlen($m[0]);
1186
+
1187
+			foreach (preg_split('//u', $m[0]) as $char) {
1188
+				// test if $char could be appended to current line
1189
+				if (mb_strwidth($line.$char, 'utf8') <= $width) {
1190
+					$line .= $char;
1191
+					continue;
1192
+				}
1193
+				// if not, push current line to array and make new line
1194
+				$lines[] = str_pad($line, $width);
1195
+				$line = $char;
1196
+			}
1197
+		}
1198
+
1199
+		$lines[] = \count($lines) ? str_pad($line, $width) : $line;
1200
+
1201
+		mb_convert_variables($encoding, 'utf8', $lines);
1202
+
1203
+		return $lines;
1204
+	}
1205
+
1206
+	/**
1207
+	 * Returns all namespaces of the command name.
1208
+	 *
1209
+	 * @return string[] The namespaces of the command
1210
+	 */
1211
+	private function extractAllNamespaces(string $name): array
1212
+	{
1213
+		// -1 as third argument is needed to skip the command short name when exploding
1214
+		$parts = explode(':', $name, -1);
1215
+		$namespaces = [];
1216
+
1217
+		foreach ($parts as $part) {
1218
+			if (\count($namespaces)) {
1219
+				$namespaces[] = end($namespaces).':'.$part;
1220
+			} else {
1221
+				$namespaces[] = $part;
1222
+			}
1223
+		}
1224
+
1225
+		return $namespaces;
1226
+	}
1227
+
1228
+	private function init()
1229
+	{
1230
+		if ($this->initialized) {
1231
+			return;
1232
+		}
1233
+		$this->initialized = true;
1234
+
1235
+		foreach ($this->getDefaultCommands() as $command) {
1236
+			$this->add($command);
1237
+		}
1238
+	}
1239 1239
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Terminal.php 1 patch
Indentation   +158 added lines, -158 removed lines patch added patch discarded remove patch
@@ -13,162 +13,162 @@
 block discarded – undo
13 13
 
14 14
 class Terminal
15 15
 {
16
-    private static $width;
17
-    private static $height;
18
-    private static $stty;
19
-
20
-    /**
21
-     * Gets the terminal width.
22
-     *
23
-     * @return int
24
-     */
25
-    public function getWidth()
26
-    {
27
-        $width = getenv('COLUMNS');
28
-        if (false !== $width) {
29
-            return (int) trim($width);
30
-        }
31
-
32
-        if (null === self::$width) {
33
-            self::initDimensions();
34
-        }
35
-
36
-        return self::$width ?: 80;
37
-    }
38
-
39
-    /**
40
-     * Gets the terminal height.
41
-     *
42
-     * @return int
43
-     */
44
-    public function getHeight()
45
-    {
46
-        $height = getenv('LINES');
47
-        if (false !== $height) {
48
-            return (int) trim($height);
49
-        }
50
-
51
-        if (null === self::$height) {
52
-            self::initDimensions();
53
-        }
54
-
55
-        return self::$height ?: 50;
56
-    }
57
-
58
-    /**
59
-     * @internal
60
-     *
61
-     * @return bool
62
-     */
63
-    public static function hasSttyAvailable()
64
-    {
65
-        if (null !== self::$stty) {
66
-            return self::$stty;
67
-        }
68
-
69
-        // skip check if exec function is disabled
70
-        if (!\function_exists('exec')) {
71
-            return false;
72
-        }
73
-
74
-        exec('stty 2>&1', $output, $exitcode);
75
-
76
-        return self::$stty = 0 === $exitcode;
77
-    }
78
-
79
-    private static function initDimensions()
80
-    {
81
-        if ('\\' === \DIRECTORY_SEPARATOR) {
82
-            if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) {
83
-                // extract [w, H] from "wxh (WxH)"
84
-                // or [w, h] from "wxh"
85
-                self::$width = (int) $matches[1];
86
-                self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
87
-            } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) {
88
-                // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash)
89
-                // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT
90
-                self::initDimensionsUsingStty();
91
-            } elseif (null !== $dimensions = self::getConsoleMode()) {
92
-                // extract [w, h] from "wxh"
93
-                self::$width = (int) $dimensions[0];
94
-                self::$height = (int) $dimensions[1];
95
-            }
96
-        } else {
97
-            self::initDimensionsUsingStty();
98
-        }
99
-    }
100
-
101
-    /**
102
-     * Returns whether STDOUT has vt100 support (some Windows 10+ configurations).
103
-     */
104
-    private static function hasVt100Support(): bool
105
-    {
106
-        return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w'));
107
-    }
108
-
109
-    /**
110
-     * Initializes dimensions using the output of an stty columns line.
111
-     */
112
-    private static function initDimensionsUsingStty()
113
-    {
114
-        if ($sttyString = self::getSttyColumns()) {
115
-            if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
116
-                // extract [w, h] from "rows h; columns w;"
117
-                self::$width = (int) $matches[2];
118
-                self::$height = (int) $matches[1];
119
-            } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
120
-                // extract [w, h] from "; h rows; w columns"
121
-                self::$width = (int) $matches[2];
122
-                self::$height = (int) $matches[1];
123
-            }
124
-        }
125
-    }
126
-
127
-    /**
128
-     * Runs and parses mode CON if it's available, suppressing any error output.
129
-     *
130
-     * @return int[]|null An array composed of the width and the height or null if it could not be parsed
131
-     */
132
-    private static function getConsoleMode(): ?array
133
-    {
134
-        $info = self::readFromProcess('mode CON');
135
-
136
-        if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
137
-            return null;
138
-        }
139
-
140
-        return [(int) $matches[2], (int) $matches[1]];
141
-    }
142
-
143
-    /**
144
-     * Runs and parses stty -a if it's available, suppressing any error output.
145
-     */
146
-    private static function getSttyColumns(): ?string
147
-    {
148
-        return self::readFromProcess('stty -a | grep columns');
149
-    }
150
-
151
-    private static function readFromProcess(string $command): ?string
152
-    {
153
-        if (!\function_exists('proc_open')) {
154
-            return null;
155
-        }
156
-
157
-        $descriptorspec = [
158
-            1 => ['pipe', 'w'],
159
-            2 => ['pipe', 'w'],
160
-        ];
161
-
162
-        $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
163
-        if (!\is_resource($process)) {
164
-            return null;
165
-        }
166
-
167
-        $info = stream_get_contents($pipes[1]);
168
-        fclose($pipes[1]);
169
-        fclose($pipes[2]);
170
-        proc_close($process);
171
-
172
-        return $info;
173
-    }
16
+	private static $width;
17
+	private static $height;
18
+	private static $stty;
19
+
20
+	/**
21
+	 * Gets the terminal width.
22
+	 *
23
+	 * @return int
24
+	 */
25
+	public function getWidth()
26
+	{
27
+		$width = getenv('COLUMNS');
28
+		if (false !== $width) {
29
+			return (int) trim($width);
30
+		}
31
+
32
+		if (null === self::$width) {
33
+			self::initDimensions();
34
+		}
35
+
36
+		return self::$width ?: 80;
37
+	}
38
+
39
+	/**
40
+	 * Gets the terminal height.
41
+	 *
42
+	 * @return int
43
+	 */
44
+	public function getHeight()
45
+	{
46
+		$height = getenv('LINES');
47
+		if (false !== $height) {
48
+			return (int) trim($height);
49
+		}
50
+
51
+		if (null === self::$height) {
52
+			self::initDimensions();
53
+		}
54
+
55
+		return self::$height ?: 50;
56
+	}
57
+
58
+	/**
59
+	 * @internal
60
+	 *
61
+	 * @return bool
62
+	 */
63
+	public static function hasSttyAvailable()
64
+	{
65
+		if (null !== self::$stty) {
66
+			return self::$stty;
67
+		}
68
+
69
+		// skip check if exec function is disabled
70
+		if (!\function_exists('exec')) {
71
+			return false;
72
+		}
73
+
74
+		exec('stty 2>&1', $output, $exitcode);
75
+
76
+		return self::$stty = 0 === $exitcode;
77
+	}
78
+
79
+	private static function initDimensions()
80
+	{
81
+		if ('\\' === \DIRECTORY_SEPARATOR) {
82
+			if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) {
83
+				// extract [w, H] from "wxh (WxH)"
84
+				// or [w, h] from "wxh"
85
+				self::$width = (int) $matches[1];
86
+				self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
87
+			} elseif (!self::hasVt100Support() && self::hasSttyAvailable()) {
88
+				// only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash)
89
+				// testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT
90
+				self::initDimensionsUsingStty();
91
+			} elseif (null !== $dimensions = self::getConsoleMode()) {
92
+				// extract [w, h] from "wxh"
93
+				self::$width = (int) $dimensions[0];
94
+				self::$height = (int) $dimensions[1];
95
+			}
96
+		} else {
97
+			self::initDimensionsUsingStty();
98
+		}
99
+	}
100
+
101
+	/**
102
+	 * Returns whether STDOUT has vt100 support (some Windows 10+ configurations).
103
+	 */
104
+	private static function hasVt100Support(): bool
105
+	{
106
+		return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w'));
107
+	}
108
+
109
+	/**
110
+	 * Initializes dimensions using the output of an stty columns line.
111
+	 */
112
+	private static function initDimensionsUsingStty()
113
+	{
114
+		if ($sttyString = self::getSttyColumns()) {
115
+			if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
116
+				// extract [w, h] from "rows h; columns w;"
117
+				self::$width = (int) $matches[2];
118
+				self::$height = (int) $matches[1];
119
+			} elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
120
+				// extract [w, h] from "; h rows; w columns"
121
+				self::$width = (int) $matches[2];
122
+				self::$height = (int) $matches[1];
123
+			}
124
+		}
125
+	}
126
+
127
+	/**
128
+	 * Runs and parses mode CON if it's available, suppressing any error output.
129
+	 *
130
+	 * @return int[]|null An array composed of the width and the height or null if it could not be parsed
131
+	 */
132
+	private static function getConsoleMode(): ?array
133
+	{
134
+		$info = self::readFromProcess('mode CON');
135
+
136
+		if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
137
+			return null;
138
+		}
139
+
140
+		return [(int) $matches[2], (int) $matches[1]];
141
+	}
142
+
143
+	/**
144
+	 * Runs and parses stty -a if it's available, suppressing any error output.
145
+	 */
146
+	private static function getSttyColumns(): ?string
147
+	{
148
+		return self::readFromProcess('stty -a | grep columns');
149
+	}
150
+
151
+	private static function readFromProcess(string $command): ?string
152
+	{
153
+		if (!\function_exists('proc_open')) {
154
+			return null;
155
+		}
156
+
157
+		$descriptorspec = [
158
+			1 => ['pipe', 'w'],
159
+			2 => ['pipe', 'w'],
160
+		];
161
+
162
+		$process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
163
+		if (!\is_resource($process)) {
164
+			return null;
165
+		}
166
+
167
+		$info = stream_get_contents($pipes[1]);
168
+		fclose($pipes[1]);
169
+		fclose($pipes[2]);
170
+		proc_close($process);
171
+
172
+		return $info;
173
+	}
174 174
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Event/ConsoleCommandEvent.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -18,34 +18,34 @@
 block discarded – undo
18 18
  */
19 19
 final class ConsoleCommandEvent extends ConsoleEvent
20 20
 {
21
-    /**
22
-     * The return code for skipped commands, this will also be passed into the terminate event.
23
-     */
24
-    public const RETURN_CODE_DISABLED = 113;
21
+	/**
22
+	 * The return code for skipped commands, this will also be passed into the terminate event.
23
+	 */
24
+	public const RETURN_CODE_DISABLED = 113;
25 25
 
26
-    /**
27
-     * Indicates if the command should be run or skipped.
28
-     */
29
-    private $commandShouldRun = true;
26
+	/**
27
+	 * Indicates if the command should be run or skipped.
28
+	 */
29
+	private $commandShouldRun = true;
30 30
 
31
-    /**
32
-     * Disables the command, so it won't be run.
33
-     */
34
-    public function disableCommand(): bool
35
-    {
36
-        return $this->commandShouldRun = false;
37
-    }
31
+	/**
32
+	 * Disables the command, so it won't be run.
33
+	 */
34
+	public function disableCommand(): bool
35
+	{
36
+		return $this->commandShouldRun = false;
37
+	}
38 38
 
39
-    public function enableCommand(): bool
40
-    {
41
-        return $this->commandShouldRun = true;
42
-    }
39
+	public function enableCommand(): bool
40
+	{
41
+		return $this->commandShouldRun = true;
42
+	}
43 43
 
44
-    /**
45
-     * Returns true if the command is runnable, false otherwise.
46
-     */
47
-    public function commandShouldRun(): bool
48
-    {
49
-        return $this->commandShouldRun;
50
-    }
44
+	/**
45
+	 * Returns true if the command is runnable, false otherwise.
46
+	 */
47
+	public function commandShouldRun(): bool
48
+	{
49
+		return $this->commandShouldRun;
50
+	}
51 51
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Event/ConsoleErrorEvent.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -22,37 +22,37 @@
 block discarded – undo
22 22
  */
23 23
 final class ConsoleErrorEvent extends ConsoleEvent
24 24
 {
25
-    private $error;
26
-    private $exitCode;
27
-
28
-    public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null)
29
-    {
30
-        parent::__construct($command, $input, $output);
31
-
32
-        $this->error = $error;
33
-    }
34
-
35
-    public function getError(): \Throwable
36
-    {
37
-        return $this->error;
38
-    }
39
-
40
-    public function setError(\Throwable $error): void
41
-    {
42
-        $this->error = $error;
43
-    }
44
-
45
-    public function setExitCode(int $exitCode): void
46
-    {
47
-        $this->exitCode = $exitCode;
48
-
49
-        $r = new \ReflectionProperty($this->error, 'code');
50
-        $r->setAccessible(true);
51
-        $r->setValue($this->error, $this->exitCode);
52
-    }
53
-
54
-    public function getExitCode(): int
55
-    {
56
-        return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
57
-    }
25
+	private $error;
26
+	private $exitCode;
27
+
28
+	public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null)
29
+	{
30
+		parent::__construct($command, $input, $output);
31
+
32
+		$this->error = $error;
33
+	}
34
+
35
+	public function getError(): \Throwable
36
+	{
37
+		return $this->error;
38
+	}
39
+
40
+	public function setError(\Throwable $error): void
41
+	{
42
+		$this->error = $error;
43
+	}
44
+
45
+	public function setExitCode(int $exitCode): void
46
+	{
47
+		$this->exitCode = $exitCode;
48
+
49
+		$r = new \ReflectionProperty($this->error, 'code');
50
+		$r->setAccessible(true);
51
+		$r->setValue($this->error, $this->exitCode);
52
+	}
53
+
54
+	public function getExitCode(): int
55
+	{
56
+		return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
57
+	}
58 58
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Event/ConsoleTerminateEvent.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -22,22 +22,22 @@
 block discarded – undo
22 22
  */
23 23
 final class ConsoleTerminateEvent extends ConsoleEvent
24 24
 {
25
-    private $exitCode;
25
+	private $exitCode;
26 26
 
27
-    public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode)
28
-    {
29
-        parent::__construct($command, $input, $output);
27
+	public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode)
28
+	{
29
+		parent::__construct($command, $input, $output);
30 30
 
31
-        $this->setExitCode($exitCode);
32
-    }
31
+		$this->setExitCode($exitCode);
32
+	}
33 33
 
34
-    public function setExitCode(int $exitCode): void
35
-    {
36
-        $this->exitCode = $exitCode;
37
-    }
34
+	public function setExitCode(int $exitCode): void
35
+	{
36
+		$this->exitCode = $exitCode;
37
+	}
38 38
 
39
-    public function getExitCode(): int
40
-    {
41
-        return $this->exitCode;
42
-    }
39
+	public function getExitCode(): int
40
+	{
41
+		return $this->exitCode;
42
+	}
43 43
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Event/ConsoleEvent.php 1 patch
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -23,45 +23,45 @@
 block discarded – undo
23 23
  */
24 24
 class ConsoleEvent extends Event
25 25
 {
26
-    protected $command;
26
+	protected $command;
27 27
 
28
-    private $input;
29
-    private $output;
28
+	private $input;
29
+	private $output;
30 30
 
31
-    public function __construct(?Command $command, InputInterface $input, OutputInterface $output)
32
-    {
33
-        $this->command = $command;
34
-        $this->input = $input;
35
-        $this->output = $output;
36
-    }
31
+	public function __construct(?Command $command, InputInterface $input, OutputInterface $output)
32
+	{
33
+		$this->command = $command;
34
+		$this->input = $input;
35
+		$this->output = $output;
36
+	}
37 37
 
38
-    /**
39
-     * Gets the command that is executed.
40
-     *
41
-     * @return Command|null A Command instance
42
-     */
43
-    public function getCommand()
44
-    {
45
-        return $this->command;
46
-    }
38
+	/**
39
+	 * Gets the command that is executed.
40
+	 *
41
+	 * @return Command|null A Command instance
42
+	 */
43
+	public function getCommand()
44
+	{
45
+		return $this->command;
46
+	}
47 47
 
48
-    /**
49
-     * Gets the input instance.
50
-     *
51
-     * @return InputInterface An InputInterface instance
52
-     */
53
-    public function getInput()
54
-    {
55
-        return $this->input;
56
-    }
48
+	/**
49
+	 * Gets the input instance.
50
+	 *
51
+	 * @return InputInterface An InputInterface instance
52
+	 */
53
+	public function getInput()
54
+	{
55
+		return $this->input;
56
+	}
57 57
 
58
-    /**
59
-     * Gets the output instance.
60
-     *
61
-     * @return OutputInterface An OutputInterface instance
62
-     */
63
-    public function getOutput()
64
-    {
65
-        return $this->output;
66
-    }
58
+	/**
59
+	 * Gets the output instance.
60
+	 *
61
+	 * @return OutputInterface An OutputInterface instance
62
+	 */
63
+	public function getOutput()
64
+	{
65
+		return $this->output;
66
+	}
67 67
 }
Please login to merge, or discard this patch.
vendor/symfony/console/Event/ConsoleSignalEvent.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -20,16 +20,16 @@
 block discarded – undo
20 20
  */
21 21
 final class ConsoleSignalEvent extends ConsoleEvent
22 22
 {
23
-    private $handlingSignal;
23
+	private $handlingSignal;
24 24
 
25
-    public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal)
26
-    {
27
-        parent::__construct($command, $input, $output);
28
-        $this->handlingSignal = $handlingSignal;
29
-    }
25
+	public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal)
26
+	{
27
+		parent::__construct($command, $input, $output);
28
+		$this->handlingSignal = $handlingSignal;
29
+	}
30 30
 
31
-    public function getHandlingSignal(): int
32
-    {
33
-        return $this->handlingSignal;
34
-    }
31
+	public function getHandlingSignal(): int
32
+	{
33
+		return $this->handlingSignal;
34
+	}
35 35
 }
Please login to merge, or discard this patch.