@@ -20,16 +20,16 @@ |
||
| 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 | } |
@@ -17,23 +17,23 @@ |
||
| 17 | 17 | #[\Attribute(\Attribute::TARGET_CLASS)] |
| 18 | 18 | class AsCommand |
| 19 | 19 | { |
| 20 | - public function __construct( |
|
| 21 | - public string $name, |
|
| 22 | - public ?string $description = null, |
|
| 23 | - array $aliases = [], |
|
| 24 | - bool $hidden = false, |
|
| 25 | - ) { |
|
| 26 | - if (!$hidden && !$aliases) { |
|
| 27 | - return; |
|
| 28 | - } |
|
| 20 | + public function __construct( |
|
| 21 | + public string $name, |
|
| 22 | + public ?string $description = null, |
|
| 23 | + array $aliases = [], |
|
| 24 | + bool $hidden = false, |
|
| 25 | + ) { |
|
| 26 | + if (!$hidden && !$aliases) { |
|
| 27 | + return; |
|
| 28 | + } |
|
| 29 | 29 | |
| 30 | - $name = explode('|', $name); |
|
| 31 | - $name = array_merge($name, $aliases); |
|
| 30 | + $name = explode('|', $name); |
|
| 31 | + $name = array_merge($name, $aliases); |
|
| 32 | 32 | |
| 33 | - if ($hidden && '' !== $name[0]) { |
|
| 34 | - array_unshift($name, ''); |
|
| 35 | - } |
|
| 33 | + if ($hidden && '' !== $name[0]) { |
|
| 34 | + array_unshift($name, ''); |
|
| 35 | + } |
|
| 36 | 36 | |
| 37 | - $this->name = implode('|', $name); |
|
| 38 | - } |
|
| 37 | + $this->name = implode('|', $name); |
|
| 38 | + } |
|
| 39 | 39 | } |
@@ -28,314 +28,314 @@ |
||
| 28 | 28 | */ |
| 29 | 29 | class TextDescriptor extends Descriptor |
| 30 | 30 | { |
| 31 | - /** |
|
| 32 | - * {@inheritdoc} |
|
| 33 | - */ |
|
| 34 | - protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 35 | - { |
|
| 36 | - if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { |
|
| 37 | - $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault())); |
|
| 38 | - } else { |
|
| 39 | - $default = ''; |
|
| 40 | - } |
|
| 41 | - |
|
| 42 | - $totalWidth = $options['total_width'] ?? Helper::width($argument->getName()); |
|
| 43 | - $spacingWidth = $totalWidth - \strlen($argument->getName()); |
|
| 44 | - |
|
| 45 | - $this->writeText(sprintf(' <info>%s</info> %s%s%s', |
|
| 46 | - $argument->getName(), |
|
| 47 | - str_repeat(' ', $spacingWidth), |
|
| 48 | - // + 4 = 2 spaces before <info>, 2 spaces after </info> |
|
| 49 | - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), |
|
| 50 | - $default |
|
| 51 | - ), $options); |
|
| 52 | - } |
|
| 53 | - |
|
| 54 | - /** |
|
| 55 | - * {@inheritdoc} |
|
| 56 | - */ |
|
| 57 | - protected function describeInputOption(InputOption $option, array $options = []) |
|
| 58 | - { |
|
| 59 | - if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { |
|
| 60 | - $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault())); |
|
| 61 | - } else { |
|
| 62 | - $default = ''; |
|
| 63 | - } |
|
| 64 | - |
|
| 65 | - $value = ''; |
|
| 66 | - if ($option->acceptValue()) { |
|
| 67 | - $value = '='.strtoupper($option->getName()); |
|
| 68 | - |
|
| 69 | - if ($option->isValueOptional()) { |
|
| 70 | - $value = '['.$value.']'; |
|
| 71 | - } |
|
| 72 | - } |
|
| 73 | - |
|
| 74 | - $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]); |
|
| 75 | - $synopsis = sprintf('%s%s', |
|
| 76 | - $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', |
|
| 77 | - sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value) |
|
| 78 | - ); |
|
| 79 | - |
|
| 80 | - $spacingWidth = $totalWidth - Helper::width($synopsis); |
|
| 81 | - |
|
| 82 | - $this->writeText(sprintf(' <info>%s</info> %s%s%s%s', |
|
| 83 | - $synopsis, |
|
| 84 | - str_repeat(' ', $spacingWidth), |
|
| 85 | - // + 4 = 2 spaces before <info>, 2 spaces after </info> |
|
| 86 | - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), |
|
| 87 | - $default, |
|
| 88 | - $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '' |
|
| 89 | - ), $options); |
|
| 90 | - } |
|
| 91 | - |
|
| 92 | - /** |
|
| 93 | - * {@inheritdoc} |
|
| 94 | - */ |
|
| 95 | - protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 96 | - { |
|
| 97 | - $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); |
|
| 98 | - foreach ($definition->getArguments() as $argument) { |
|
| 99 | - $totalWidth = max($totalWidth, Helper::width($argument->getName())); |
|
| 100 | - } |
|
| 101 | - |
|
| 102 | - if ($definition->getArguments()) { |
|
| 103 | - $this->writeText('<comment>Arguments:</comment>', $options); |
|
| 104 | - $this->writeText("\n"); |
|
| 105 | - foreach ($definition->getArguments() as $argument) { |
|
| 106 | - $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); |
|
| 107 | - $this->writeText("\n"); |
|
| 108 | - } |
|
| 109 | - } |
|
| 110 | - |
|
| 111 | - if ($definition->getArguments() && $definition->getOptions()) { |
|
| 112 | - $this->writeText("\n"); |
|
| 113 | - } |
|
| 114 | - |
|
| 115 | - if ($definition->getOptions()) { |
|
| 116 | - $laterOptions = []; |
|
| 117 | - |
|
| 118 | - $this->writeText('<comment>Options:</comment>', $options); |
|
| 119 | - foreach ($definition->getOptions() as $option) { |
|
| 120 | - if (\strlen($option->getShortcut() ?? '') > 1) { |
|
| 121 | - $laterOptions[] = $option; |
|
| 122 | - continue; |
|
| 123 | - } |
|
| 124 | - $this->writeText("\n"); |
|
| 125 | - $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); |
|
| 126 | - } |
|
| 127 | - foreach ($laterOptions as $option) { |
|
| 128 | - $this->writeText("\n"); |
|
| 129 | - $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); |
|
| 130 | - } |
|
| 131 | - } |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - /** |
|
| 135 | - * {@inheritdoc} |
|
| 136 | - */ |
|
| 137 | - protected function describeCommand(Command $command, array $options = []) |
|
| 138 | - { |
|
| 139 | - $command->mergeApplicationDefinition(false); |
|
| 140 | - |
|
| 141 | - if ($description = $command->getDescription()) { |
|
| 142 | - $this->writeText('<comment>Description:</comment>', $options); |
|
| 143 | - $this->writeText("\n"); |
|
| 144 | - $this->writeText(' '.$description); |
|
| 145 | - $this->writeText("\n\n"); |
|
| 146 | - } |
|
| 147 | - |
|
| 148 | - $this->writeText('<comment>Usage:</comment>', $options); |
|
| 149 | - foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { |
|
| 150 | - $this->writeText("\n"); |
|
| 151 | - $this->writeText(' '.OutputFormatter::escape($usage), $options); |
|
| 152 | - } |
|
| 153 | - $this->writeText("\n"); |
|
| 154 | - |
|
| 155 | - $definition = $command->getDefinition(); |
|
| 156 | - if ($definition->getOptions() || $definition->getArguments()) { |
|
| 157 | - $this->writeText("\n"); |
|
| 158 | - $this->describeInputDefinition($definition, $options); |
|
| 159 | - $this->writeText("\n"); |
|
| 160 | - } |
|
| 161 | - |
|
| 162 | - $help = $command->getProcessedHelp(); |
|
| 163 | - if ($help && $help !== $description) { |
|
| 164 | - $this->writeText("\n"); |
|
| 165 | - $this->writeText('<comment>Help:</comment>', $options); |
|
| 166 | - $this->writeText("\n"); |
|
| 167 | - $this->writeText(' '.str_replace("\n", "\n ", $help), $options); |
|
| 168 | - $this->writeText("\n"); |
|
| 169 | - } |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * {@inheritdoc} |
|
| 174 | - */ |
|
| 175 | - protected function describeApplication(Application $application, array $options = []) |
|
| 176 | - { |
|
| 177 | - $describedNamespace = $options['namespace'] ?? null; |
|
| 178 | - $description = new ApplicationDescription($application, $describedNamespace); |
|
| 179 | - |
|
| 180 | - if (isset($options['raw_text']) && $options['raw_text']) { |
|
| 181 | - $width = $this->getColumnWidth($description->getCommands()); |
|
| 182 | - |
|
| 183 | - foreach ($description->getCommands() as $command) { |
|
| 184 | - $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); |
|
| 185 | - $this->writeText("\n"); |
|
| 186 | - } |
|
| 187 | - } else { |
|
| 188 | - if ('' != $help = $application->getHelp()) { |
|
| 189 | - $this->writeText("$help\n\n", $options); |
|
| 190 | - } |
|
| 191 | - |
|
| 192 | - $this->writeText("<comment>Usage:</comment>\n", $options); |
|
| 193 | - $this->writeText(" command [options] [arguments]\n\n", $options); |
|
| 194 | - |
|
| 195 | - $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); |
|
| 196 | - |
|
| 197 | - $this->writeText("\n"); |
|
| 198 | - $this->writeText("\n"); |
|
| 199 | - |
|
| 200 | - $commands = $description->getCommands(); |
|
| 201 | - $namespaces = $description->getNamespaces(); |
|
| 202 | - if ($describedNamespace && $namespaces) { |
|
| 203 | - // make sure all alias commands are included when describing a specific namespace |
|
| 204 | - $describedNamespaceInfo = reset($namespaces); |
|
| 205 | - foreach ($describedNamespaceInfo['commands'] as $name) { |
|
| 206 | - $commands[$name] = $description->getCommand($name); |
|
| 207 | - } |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - // calculate max. width based on available commands per namespace |
|
| 211 | - $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { |
|
| 212 | - return array_intersect($namespace['commands'], array_keys($commands)); |
|
| 213 | - }, array_values($namespaces))))); |
|
| 214 | - |
|
| 215 | - if ($describedNamespace) { |
|
| 216 | - $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options); |
|
| 217 | - } else { |
|
| 218 | - $this->writeText('<comment>Available commands:</comment>', $options); |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - foreach ($namespaces as $namespace) { |
|
| 222 | - $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { |
|
| 223 | - return isset($commands[$name]); |
|
| 224 | - }); |
|
| 225 | - |
|
| 226 | - if (!$namespace['commands']) { |
|
| 227 | - continue; |
|
| 228 | - } |
|
| 229 | - |
|
| 230 | - if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { |
|
| 231 | - $this->writeText("\n"); |
|
| 232 | - $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options); |
|
| 233 | - } |
|
| 234 | - |
|
| 235 | - foreach ($namespace['commands'] as $name) { |
|
| 236 | - $this->writeText("\n"); |
|
| 237 | - $spacingWidth = $width - Helper::width($name); |
|
| 238 | - $command = $commands[$name]; |
|
| 239 | - $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; |
|
| 240 | - $this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); |
|
| 241 | - } |
|
| 242 | - } |
|
| 243 | - |
|
| 244 | - $this->writeText("\n"); |
|
| 245 | - } |
|
| 246 | - } |
|
| 247 | - |
|
| 248 | - /** |
|
| 249 | - * {@inheritdoc} |
|
| 250 | - */ |
|
| 251 | - private function writeText(string $content, array $options = []) |
|
| 252 | - { |
|
| 253 | - $this->write( |
|
| 254 | - isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, |
|
| 255 | - isset($options['raw_output']) ? !$options['raw_output'] : true |
|
| 256 | - ); |
|
| 257 | - } |
|
| 258 | - |
|
| 259 | - /** |
|
| 260 | - * Formats command aliases to show them in the command description. |
|
| 261 | - */ |
|
| 262 | - private function getCommandAliasesText(Command $command): string |
|
| 263 | - { |
|
| 264 | - $text = ''; |
|
| 265 | - $aliases = $command->getAliases(); |
|
| 266 | - |
|
| 267 | - if ($aliases) { |
|
| 268 | - $text = '['.implode('|', $aliases).'] '; |
|
| 269 | - } |
|
| 270 | - |
|
| 271 | - return $text; |
|
| 272 | - } |
|
| 273 | - |
|
| 274 | - /** |
|
| 275 | - * Formats input option/argument default value. |
|
| 276 | - * |
|
| 277 | - * @param mixed $default |
|
| 278 | - */ |
|
| 279 | - private function formatDefaultValue($default): string |
|
| 280 | - { |
|
| 281 | - if (\INF === $default) { |
|
| 282 | - return 'INF'; |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - if (\is_string($default)) { |
|
| 286 | - $default = OutputFormatter::escape($default); |
|
| 287 | - } elseif (\is_array($default)) { |
|
| 288 | - foreach ($default as $key => $value) { |
|
| 289 | - if (\is_string($value)) { |
|
| 290 | - $default[$key] = OutputFormatter::escape($value); |
|
| 291 | - } |
|
| 292 | - } |
|
| 293 | - } |
|
| 294 | - |
|
| 295 | - return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); |
|
| 296 | - } |
|
| 297 | - |
|
| 298 | - /** |
|
| 299 | - * @param array<Command|string> $commands |
|
| 300 | - */ |
|
| 301 | - private function getColumnWidth(array $commands): int |
|
| 302 | - { |
|
| 303 | - $widths = []; |
|
| 304 | - |
|
| 305 | - foreach ($commands as $command) { |
|
| 306 | - if ($command instanceof Command) { |
|
| 307 | - $widths[] = Helper::width($command->getName()); |
|
| 308 | - foreach ($command->getAliases() as $alias) { |
|
| 309 | - $widths[] = Helper::width($alias); |
|
| 310 | - } |
|
| 311 | - } else { |
|
| 312 | - $widths[] = Helper::width($command); |
|
| 313 | - } |
|
| 314 | - } |
|
| 315 | - |
|
| 316 | - return $widths ? max($widths) + 2 : 0; |
|
| 317 | - } |
|
| 318 | - |
|
| 319 | - /** |
|
| 320 | - * @param InputOption[] $options |
|
| 321 | - */ |
|
| 322 | - private function calculateTotalWidthForOptions(array $options): int |
|
| 323 | - { |
|
| 324 | - $totalWidth = 0; |
|
| 325 | - foreach ($options as $option) { |
|
| 326 | - // "-" + shortcut + ", --" + name |
|
| 327 | - $nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName()); |
|
| 328 | - if ($option->isNegatable()) { |
|
| 329 | - $nameLength += 6 + Helper::width($option->getName()); // |--no- + name |
|
| 330 | - } elseif ($option->acceptValue()) { |
|
| 331 | - $valueLength = 1 + Helper::width($option->getName()); // = + value |
|
| 332 | - $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] |
|
| 333 | - |
|
| 334 | - $nameLength += $valueLength; |
|
| 335 | - } |
|
| 336 | - $totalWidth = max($totalWidth, $nameLength); |
|
| 337 | - } |
|
| 338 | - |
|
| 339 | - return $totalWidth; |
|
| 340 | - } |
|
| 31 | + /** |
|
| 32 | + * {@inheritdoc} |
|
| 33 | + */ |
|
| 34 | + protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 35 | + { |
|
| 36 | + if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { |
|
| 37 | + $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault())); |
|
| 38 | + } else { |
|
| 39 | + $default = ''; |
|
| 40 | + } |
|
| 41 | + |
|
| 42 | + $totalWidth = $options['total_width'] ?? Helper::width($argument->getName()); |
|
| 43 | + $spacingWidth = $totalWidth - \strlen($argument->getName()); |
|
| 44 | + |
|
| 45 | + $this->writeText(sprintf(' <info>%s</info> %s%s%s', |
|
| 46 | + $argument->getName(), |
|
| 47 | + str_repeat(' ', $spacingWidth), |
|
| 48 | + // + 4 = 2 spaces before <info>, 2 spaces after </info> |
|
| 49 | + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), |
|
| 50 | + $default |
|
| 51 | + ), $options); |
|
| 52 | + } |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * {@inheritdoc} |
|
| 56 | + */ |
|
| 57 | + protected function describeInputOption(InputOption $option, array $options = []) |
|
| 58 | + { |
|
| 59 | + if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { |
|
| 60 | + $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault())); |
|
| 61 | + } else { |
|
| 62 | + $default = ''; |
|
| 63 | + } |
|
| 64 | + |
|
| 65 | + $value = ''; |
|
| 66 | + if ($option->acceptValue()) { |
|
| 67 | + $value = '='.strtoupper($option->getName()); |
|
| 68 | + |
|
| 69 | + if ($option->isValueOptional()) { |
|
| 70 | + $value = '['.$value.']'; |
|
| 71 | + } |
|
| 72 | + } |
|
| 73 | + |
|
| 74 | + $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]); |
|
| 75 | + $synopsis = sprintf('%s%s', |
|
| 76 | + $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', |
|
| 77 | + sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value) |
|
| 78 | + ); |
|
| 79 | + |
|
| 80 | + $spacingWidth = $totalWidth - Helper::width($synopsis); |
|
| 81 | + |
|
| 82 | + $this->writeText(sprintf(' <info>%s</info> %s%s%s%s', |
|
| 83 | + $synopsis, |
|
| 84 | + str_repeat(' ', $spacingWidth), |
|
| 85 | + // + 4 = 2 spaces before <info>, 2 spaces after </info> |
|
| 86 | + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), |
|
| 87 | + $default, |
|
| 88 | + $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '' |
|
| 89 | + ), $options); |
|
| 90 | + } |
|
| 91 | + |
|
| 92 | + /** |
|
| 93 | + * {@inheritdoc} |
|
| 94 | + */ |
|
| 95 | + protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 96 | + { |
|
| 97 | + $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); |
|
| 98 | + foreach ($definition->getArguments() as $argument) { |
|
| 99 | + $totalWidth = max($totalWidth, Helper::width($argument->getName())); |
|
| 100 | + } |
|
| 101 | + |
|
| 102 | + if ($definition->getArguments()) { |
|
| 103 | + $this->writeText('<comment>Arguments:</comment>', $options); |
|
| 104 | + $this->writeText("\n"); |
|
| 105 | + foreach ($definition->getArguments() as $argument) { |
|
| 106 | + $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); |
|
| 107 | + $this->writeText("\n"); |
|
| 108 | + } |
|
| 109 | + } |
|
| 110 | + |
|
| 111 | + if ($definition->getArguments() && $definition->getOptions()) { |
|
| 112 | + $this->writeText("\n"); |
|
| 113 | + } |
|
| 114 | + |
|
| 115 | + if ($definition->getOptions()) { |
|
| 116 | + $laterOptions = []; |
|
| 117 | + |
|
| 118 | + $this->writeText('<comment>Options:</comment>', $options); |
|
| 119 | + foreach ($definition->getOptions() as $option) { |
|
| 120 | + if (\strlen($option->getShortcut() ?? '') > 1) { |
|
| 121 | + $laterOptions[] = $option; |
|
| 122 | + continue; |
|
| 123 | + } |
|
| 124 | + $this->writeText("\n"); |
|
| 125 | + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); |
|
| 126 | + } |
|
| 127 | + foreach ($laterOptions as $option) { |
|
| 128 | + $this->writeText("\n"); |
|
| 129 | + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); |
|
| 130 | + } |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + /** |
|
| 135 | + * {@inheritdoc} |
|
| 136 | + */ |
|
| 137 | + protected function describeCommand(Command $command, array $options = []) |
|
| 138 | + { |
|
| 139 | + $command->mergeApplicationDefinition(false); |
|
| 140 | + |
|
| 141 | + if ($description = $command->getDescription()) { |
|
| 142 | + $this->writeText('<comment>Description:</comment>', $options); |
|
| 143 | + $this->writeText("\n"); |
|
| 144 | + $this->writeText(' '.$description); |
|
| 145 | + $this->writeText("\n\n"); |
|
| 146 | + } |
|
| 147 | + |
|
| 148 | + $this->writeText('<comment>Usage:</comment>', $options); |
|
| 149 | + foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { |
|
| 150 | + $this->writeText("\n"); |
|
| 151 | + $this->writeText(' '.OutputFormatter::escape($usage), $options); |
|
| 152 | + } |
|
| 153 | + $this->writeText("\n"); |
|
| 154 | + |
|
| 155 | + $definition = $command->getDefinition(); |
|
| 156 | + if ($definition->getOptions() || $definition->getArguments()) { |
|
| 157 | + $this->writeText("\n"); |
|
| 158 | + $this->describeInputDefinition($definition, $options); |
|
| 159 | + $this->writeText("\n"); |
|
| 160 | + } |
|
| 161 | + |
|
| 162 | + $help = $command->getProcessedHelp(); |
|
| 163 | + if ($help && $help !== $description) { |
|
| 164 | + $this->writeText("\n"); |
|
| 165 | + $this->writeText('<comment>Help:</comment>', $options); |
|
| 166 | + $this->writeText("\n"); |
|
| 167 | + $this->writeText(' '.str_replace("\n", "\n ", $help), $options); |
|
| 168 | + $this->writeText("\n"); |
|
| 169 | + } |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * {@inheritdoc} |
|
| 174 | + */ |
|
| 175 | + protected function describeApplication(Application $application, array $options = []) |
|
| 176 | + { |
|
| 177 | + $describedNamespace = $options['namespace'] ?? null; |
|
| 178 | + $description = new ApplicationDescription($application, $describedNamespace); |
|
| 179 | + |
|
| 180 | + if (isset($options['raw_text']) && $options['raw_text']) { |
|
| 181 | + $width = $this->getColumnWidth($description->getCommands()); |
|
| 182 | + |
|
| 183 | + foreach ($description->getCommands() as $command) { |
|
| 184 | + $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); |
|
| 185 | + $this->writeText("\n"); |
|
| 186 | + } |
|
| 187 | + } else { |
|
| 188 | + if ('' != $help = $application->getHelp()) { |
|
| 189 | + $this->writeText("$help\n\n", $options); |
|
| 190 | + } |
|
| 191 | + |
|
| 192 | + $this->writeText("<comment>Usage:</comment>\n", $options); |
|
| 193 | + $this->writeText(" command [options] [arguments]\n\n", $options); |
|
| 194 | + |
|
| 195 | + $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); |
|
| 196 | + |
|
| 197 | + $this->writeText("\n"); |
|
| 198 | + $this->writeText("\n"); |
|
| 199 | + |
|
| 200 | + $commands = $description->getCommands(); |
|
| 201 | + $namespaces = $description->getNamespaces(); |
|
| 202 | + if ($describedNamespace && $namespaces) { |
|
| 203 | + // make sure all alias commands are included when describing a specific namespace |
|
| 204 | + $describedNamespaceInfo = reset($namespaces); |
|
| 205 | + foreach ($describedNamespaceInfo['commands'] as $name) { |
|
| 206 | + $commands[$name] = $description->getCommand($name); |
|
| 207 | + } |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + // calculate max. width based on available commands per namespace |
|
| 211 | + $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { |
|
| 212 | + return array_intersect($namespace['commands'], array_keys($commands)); |
|
| 213 | + }, array_values($namespaces))))); |
|
| 214 | + |
|
| 215 | + if ($describedNamespace) { |
|
| 216 | + $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options); |
|
| 217 | + } else { |
|
| 218 | + $this->writeText('<comment>Available commands:</comment>', $options); |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + foreach ($namespaces as $namespace) { |
|
| 222 | + $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { |
|
| 223 | + return isset($commands[$name]); |
|
| 224 | + }); |
|
| 225 | + |
|
| 226 | + if (!$namespace['commands']) { |
|
| 227 | + continue; |
|
| 228 | + } |
|
| 229 | + |
|
| 230 | + if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { |
|
| 231 | + $this->writeText("\n"); |
|
| 232 | + $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options); |
|
| 233 | + } |
|
| 234 | + |
|
| 235 | + foreach ($namespace['commands'] as $name) { |
|
| 236 | + $this->writeText("\n"); |
|
| 237 | + $spacingWidth = $width - Helper::width($name); |
|
| 238 | + $command = $commands[$name]; |
|
| 239 | + $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; |
|
| 240 | + $this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); |
|
| 241 | + } |
|
| 242 | + } |
|
| 243 | + |
|
| 244 | + $this->writeText("\n"); |
|
| 245 | + } |
|
| 246 | + } |
|
| 247 | + |
|
| 248 | + /** |
|
| 249 | + * {@inheritdoc} |
|
| 250 | + */ |
|
| 251 | + private function writeText(string $content, array $options = []) |
|
| 252 | + { |
|
| 253 | + $this->write( |
|
| 254 | + isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, |
|
| 255 | + isset($options['raw_output']) ? !$options['raw_output'] : true |
|
| 256 | + ); |
|
| 257 | + } |
|
| 258 | + |
|
| 259 | + /** |
|
| 260 | + * Formats command aliases to show them in the command description. |
|
| 261 | + */ |
|
| 262 | + private function getCommandAliasesText(Command $command): string |
|
| 263 | + { |
|
| 264 | + $text = ''; |
|
| 265 | + $aliases = $command->getAliases(); |
|
| 266 | + |
|
| 267 | + if ($aliases) { |
|
| 268 | + $text = '['.implode('|', $aliases).'] '; |
|
| 269 | + } |
|
| 270 | + |
|
| 271 | + return $text; |
|
| 272 | + } |
|
| 273 | + |
|
| 274 | + /** |
|
| 275 | + * Formats input option/argument default value. |
|
| 276 | + * |
|
| 277 | + * @param mixed $default |
|
| 278 | + */ |
|
| 279 | + private function formatDefaultValue($default): string |
|
| 280 | + { |
|
| 281 | + if (\INF === $default) { |
|
| 282 | + return 'INF'; |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + if (\is_string($default)) { |
|
| 286 | + $default = OutputFormatter::escape($default); |
|
| 287 | + } elseif (\is_array($default)) { |
|
| 288 | + foreach ($default as $key => $value) { |
|
| 289 | + if (\is_string($value)) { |
|
| 290 | + $default[$key] = OutputFormatter::escape($value); |
|
| 291 | + } |
|
| 292 | + } |
|
| 293 | + } |
|
| 294 | + |
|
| 295 | + return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); |
|
| 296 | + } |
|
| 297 | + |
|
| 298 | + /** |
|
| 299 | + * @param array<Command|string> $commands |
|
| 300 | + */ |
|
| 301 | + private function getColumnWidth(array $commands): int |
|
| 302 | + { |
|
| 303 | + $widths = []; |
|
| 304 | + |
|
| 305 | + foreach ($commands as $command) { |
|
| 306 | + if ($command instanceof Command) { |
|
| 307 | + $widths[] = Helper::width($command->getName()); |
|
| 308 | + foreach ($command->getAliases() as $alias) { |
|
| 309 | + $widths[] = Helper::width($alias); |
|
| 310 | + } |
|
| 311 | + } else { |
|
| 312 | + $widths[] = Helper::width($command); |
|
| 313 | + } |
|
| 314 | + } |
|
| 315 | + |
|
| 316 | + return $widths ? max($widths) + 2 : 0; |
|
| 317 | + } |
|
| 318 | + |
|
| 319 | + /** |
|
| 320 | + * @param InputOption[] $options |
|
| 321 | + */ |
|
| 322 | + private function calculateTotalWidthForOptions(array $options): int |
|
| 323 | + { |
|
| 324 | + $totalWidth = 0; |
|
| 325 | + foreach ($options as $option) { |
|
| 326 | + // "-" + shortcut + ", --" + name |
|
| 327 | + $nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName()); |
|
| 328 | + if ($option->isNegatable()) { |
|
| 329 | + $nameLength += 6 + Helper::width($option->getName()); // |--no- + name |
|
| 330 | + } elseif ($option->acceptValue()) { |
|
| 331 | + $valueLength = 1 + Helper::width($option->getName()); // = + value |
|
| 332 | + $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] |
|
| 333 | + |
|
| 334 | + $nameLength += $valueLength; |
|
| 335 | + } |
|
| 336 | + $totalWidth = max($totalWidth, $nameLength); |
|
| 337 | + } |
|
| 338 | + |
|
| 339 | + return $totalWidth; |
|
| 340 | + } |
|
| 341 | 341 | } |
@@ -28,179 +28,179 @@ |
||
| 28 | 28 | */ |
| 29 | 29 | class MarkdownDescriptor extends Descriptor |
| 30 | 30 | { |
| 31 | - /** |
|
| 32 | - * {@inheritdoc} |
|
| 33 | - */ |
|
| 34 | - public function describe(OutputInterface $output, object $object, array $options = []) |
|
| 35 | - { |
|
| 36 | - $decorated = $output->isDecorated(); |
|
| 37 | - $output->setDecorated(false); |
|
| 38 | - |
|
| 39 | - parent::describe($output, $object, $options); |
|
| 40 | - |
|
| 41 | - $output->setDecorated($decorated); |
|
| 42 | - } |
|
| 43 | - |
|
| 44 | - /** |
|
| 45 | - * {@inheritdoc} |
|
| 46 | - */ |
|
| 47 | - protected function write(string $content, bool $decorated = true) |
|
| 48 | - { |
|
| 49 | - parent::write($content, $decorated); |
|
| 50 | - } |
|
| 51 | - |
|
| 52 | - /** |
|
| 53 | - * {@inheritdoc} |
|
| 54 | - */ |
|
| 55 | - protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 56 | - { |
|
| 57 | - $this->write( |
|
| 58 | - '#### `'.($argument->getName() ?: '<none>')."`\n\n" |
|
| 59 | - .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') |
|
| 60 | - .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" |
|
| 61 | - .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" |
|
| 62 | - .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' |
|
| 63 | - ); |
|
| 64 | - } |
|
| 65 | - |
|
| 66 | - /** |
|
| 67 | - * {@inheritdoc} |
|
| 68 | - */ |
|
| 69 | - protected function describeInputOption(InputOption $option, array $options = []) |
|
| 70 | - { |
|
| 71 | - $name = '--'.$option->getName(); |
|
| 72 | - if ($option->isNegatable()) { |
|
| 73 | - $name .= '|--no-'.$option->getName(); |
|
| 74 | - } |
|
| 75 | - if ($option->getShortcut()) { |
|
| 76 | - $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - $this->write( |
|
| 80 | - '#### `'.$name.'`'."\n\n" |
|
| 81 | - .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') |
|
| 82 | - .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" |
|
| 83 | - .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" |
|
| 84 | - .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" |
|
| 85 | - .'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n" |
|
| 86 | - .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' |
|
| 87 | - ); |
|
| 88 | - } |
|
| 89 | - |
|
| 90 | - /** |
|
| 91 | - * {@inheritdoc} |
|
| 92 | - */ |
|
| 93 | - protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 94 | - { |
|
| 95 | - if ($showArguments = \count($definition->getArguments()) > 0) { |
|
| 96 | - $this->write('### Arguments'); |
|
| 97 | - foreach ($definition->getArguments() as $argument) { |
|
| 98 | - $this->write("\n\n"); |
|
| 99 | - if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { |
|
| 100 | - $this->write($describeInputArgument); |
|
| 101 | - } |
|
| 102 | - } |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - if (\count($definition->getOptions()) > 0) { |
|
| 106 | - if ($showArguments) { |
|
| 107 | - $this->write("\n\n"); |
|
| 108 | - } |
|
| 109 | - |
|
| 110 | - $this->write('### Options'); |
|
| 111 | - foreach ($definition->getOptions() as $option) { |
|
| 112 | - $this->write("\n\n"); |
|
| 113 | - if (null !== $describeInputOption = $this->describeInputOption($option)) { |
|
| 114 | - $this->write($describeInputOption); |
|
| 115 | - } |
|
| 116 | - } |
|
| 117 | - } |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - /** |
|
| 121 | - * {@inheritdoc} |
|
| 122 | - */ |
|
| 123 | - protected function describeCommand(Command $command, array $options = []) |
|
| 124 | - { |
|
| 125 | - if ($options['short'] ?? false) { |
|
| 126 | - $this->write( |
|
| 127 | - '`'.$command->getName()."`\n" |
|
| 128 | - .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" |
|
| 129 | - .($command->getDescription() ? $command->getDescription()."\n\n" : '') |
|
| 130 | - .'### Usage'."\n\n" |
|
| 131 | - .array_reduce($command->getAliases(), function ($carry, $usage) { |
|
| 132 | - return $carry.'* `'.$usage.'`'."\n"; |
|
| 133 | - }) |
|
| 134 | - ); |
|
| 135 | - |
|
| 136 | - return; |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - $command->mergeApplicationDefinition(false); |
|
| 140 | - |
|
| 141 | - $this->write( |
|
| 142 | - '`'.$command->getName()."`\n" |
|
| 143 | - .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" |
|
| 144 | - .($command->getDescription() ? $command->getDescription()."\n\n" : '') |
|
| 145 | - .'### Usage'."\n\n" |
|
| 146 | - .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { |
|
| 147 | - return $carry.'* `'.$usage.'`'."\n"; |
|
| 148 | - }) |
|
| 149 | - ); |
|
| 150 | - |
|
| 151 | - if ($help = $command->getProcessedHelp()) { |
|
| 152 | - $this->write("\n"); |
|
| 153 | - $this->write($help); |
|
| 154 | - } |
|
| 155 | - |
|
| 156 | - $definition = $command->getDefinition(); |
|
| 157 | - if ($definition->getOptions() || $definition->getArguments()) { |
|
| 158 | - $this->write("\n\n"); |
|
| 159 | - $this->describeInputDefinition($definition); |
|
| 160 | - } |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - /** |
|
| 164 | - * {@inheritdoc} |
|
| 165 | - */ |
|
| 166 | - protected function describeApplication(Application $application, array $options = []) |
|
| 167 | - { |
|
| 168 | - $describedNamespace = $options['namespace'] ?? null; |
|
| 169 | - $description = new ApplicationDescription($application, $describedNamespace); |
|
| 170 | - $title = $this->getApplicationTitle($application); |
|
| 171 | - |
|
| 172 | - $this->write($title."\n".str_repeat('=', Helper::width($title))); |
|
| 173 | - |
|
| 174 | - foreach ($description->getNamespaces() as $namespace) { |
|
| 175 | - if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { |
|
| 176 | - $this->write("\n\n"); |
|
| 177 | - $this->write('**'.$namespace['id'].':**'); |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - $this->write("\n\n"); |
|
| 181 | - $this->write(implode("\n", array_map(function ($commandName) use ($description) { |
|
| 182 | - return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); |
|
| 183 | - }, $namespace['commands']))); |
|
| 184 | - } |
|
| 185 | - |
|
| 186 | - foreach ($description->getCommands() as $command) { |
|
| 187 | - $this->write("\n\n"); |
|
| 188 | - if (null !== $describeCommand = $this->describeCommand($command, $options)) { |
|
| 189 | - $this->write($describeCommand); |
|
| 190 | - } |
|
| 191 | - } |
|
| 192 | - } |
|
| 193 | - |
|
| 194 | - private function getApplicationTitle(Application $application): string |
|
| 195 | - { |
|
| 196 | - if ('UNKNOWN' !== $application->getName()) { |
|
| 197 | - if ('UNKNOWN' !== $application->getVersion()) { |
|
| 198 | - return sprintf('%s %s', $application->getName(), $application->getVersion()); |
|
| 199 | - } |
|
| 200 | - |
|
| 201 | - return $application->getName(); |
|
| 202 | - } |
|
| 203 | - |
|
| 204 | - return 'Console Tool'; |
|
| 205 | - } |
|
| 31 | + /** |
|
| 32 | + * {@inheritdoc} |
|
| 33 | + */ |
|
| 34 | + public function describe(OutputInterface $output, object $object, array $options = []) |
|
| 35 | + { |
|
| 36 | + $decorated = $output->isDecorated(); |
|
| 37 | + $output->setDecorated(false); |
|
| 38 | + |
|
| 39 | + parent::describe($output, $object, $options); |
|
| 40 | + |
|
| 41 | + $output->setDecorated($decorated); |
|
| 42 | + } |
|
| 43 | + |
|
| 44 | + /** |
|
| 45 | + * {@inheritdoc} |
|
| 46 | + */ |
|
| 47 | + protected function write(string $content, bool $decorated = true) |
|
| 48 | + { |
|
| 49 | + parent::write($content, $decorated); |
|
| 50 | + } |
|
| 51 | + |
|
| 52 | + /** |
|
| 53 | + * {@inheritdoc} |
|
| 54 | + */ |
|
| 55 | + protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 56 | + { |
|
| 57 | + $this->write( |
|
| 58 | + '#### `'.($argument->getName() ?: '<none>')."`\n\n" |
|
| 59 | + .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') |
|
| 60 | + .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" |
|
| 61 | + .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" |
|
| 62 | + .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' |
|
| 63 | + ); |
|
| 64 | + } |
|
| 65 | + |
|
| 66 | + /** |
|
| 67 | + * {@inheritdoc} |
|
| 68 | + */ |
|
| 69 | + protected function describeInputOption(InputOption $option, array $options = []) |
|
| 70 | + { |
|
| 71 | + $name = '--'.$option->getName(); |
|
| 72 | + if ($option->isNegatable()) { |
|
| 73 | + $name .= '|--no-'.$option->getName(); |
|
| 74 | + } |
|
| 75 | + if ($option->getShortcut()) { |
|
| 76 | + $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + $this->write( |
|
| 80 | + '#### `'.$name.'`'."\n\n" |
|
| 81 | + .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') |
|
| 82 | + .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" |
|
| 83 | + .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" |
|
| 84 | + .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" |
|
| 85 | + .'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n" |
|
| 86 | + .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' |
|
| 87 | + ); |
|
| 88 | + } |
|
| 89 | + |
|
| 90 | + /** |
|
| 91 | + * {@inheritdoc} |
|
| 92 | + */ |
|
| 93 | + protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 94 | + { |
|
| 95 | + if ($showArguments = \count($definition->getArguments()) > 0) { |
|
| 96 | + $this->write('### Arguments'); |
|
| 97 | + foreach ($definition->getArguments() as $argument) { |
|
| 98 | + $this->write("\n\n"); |
|
| 99 | + if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { |
|
| 100 | + $this->write($describeInputArgument); |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + if (\count($definition->getOptions()) > 0) { |
|
| 106 | + if ($showArguments) { |
|
| 107 | + $this->write("\n\n"); |
|
| 108 | + } |
|
| 109 | + |
|
| 110 | + $this->write('### Options'); |
|
| 111 | + foreach ($definition->getOptions() as $option) { |
|
| 112 | + $this->write("\n\n"); |
|
| 113 | + if (null !== $describeInputOption = $this->describeInputOption($option)) { |
|
| 114 | + $this->write($describeInputOption); |
|
| 115 | + } |
|
| 116 | + } |
|
| 117 | + } |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + /** |
|
| 121 | + * {@inheritdoc} |
|
| 122 | + */ |
|
| 123 | + protected function describeCommand(Command $command, array $options = []) |
|
| 124 | + { |
|
| 125 | + if ($options['short'] ?? false) { |
|
| 126 | + $this->write( |
|
| 127 | + '`'.$command->getName()."`\n" |
|
| 128 | + .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" |
|
| 129 | + .($command->getDescription() ? $command->getDescription()."\n\n" : '') |
|
| 130 | + .'### Usage'."\n\n" |
|
| 131 | + .array_reduce($command->getAliases(), function ($carry, $usage) { |
|
| 132 | + return $carry.'* `'.$usage.'`'."\n"; |
|
| 133 | + }) |
|
| 134 | + ); |
|
| 135 | + |
|
| 136 | + return; |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + $command->mergeApplicationDefinition(false); |
|
| 140 | + |
|
| 141 | + $this->write( |
|
| 142 | + '`'.$command->getName()."`\n" |
|
| 143 | + .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" |
|
| 144 | + .($command->getDescription() ? $command->getDescription()."\n\n" : '') |
|
| 145 | + .'### Usage'."\n\n" |
|
| 146 | + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { |
|
| 147 | + return $carry.'* `'.$usage.'`'."\n"; |
|
| 148 | + }) |
|
| 149 | + ); |
|
| 150 | + |
|
| 151 | + if ($help = $command->getProcessedHelp()) { |
|
| 152 | + $this->write("\n"); |
|
| 153 | + $this->write($help); |
|
| 154 | + } |
|
| 155 | + |
|
| 156 | + $definition = $command->getDefinition(); |
|
| 157 | + if ($definition->getOptions() || $definition->getArguments()) { |
|
| 158 | + $this->write("\n\n"); |
|
| 159 | + $this->describeInputDefinition($definition); |
|
| 160 | + } |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + /** |
|
| 164 | + * {@inheritdoc} |
|
| 165 | + */ |
|
| 166 | + protected function describeApplication(Application $application, array $options = []) |
|
| 167 | + { |
|
| 168 | + $describedNamespace = $options['namespace'] ?? null; |
|
| 169 | + $description = new ApplicationDescription($application, $describedNamespace); |
|
| 170 | + $title = $this->getApplicationTitle($application); |
|
| 171 | + |
|
| 172 | + $this->write($title."\n".str_repeat('=', Helper::width($title))); |
|
| 173 | + |
|
| 174 | + foreach ($description->getNamespaces() as $namespace) { |
|
| 175 | + if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { |
|
| 176 | + $this->write("\n\n"); |
|
| 177 | + $this->write('**'.$namespace['id'].':**'); |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + $this->write("\n\n"); |
|
| 181 | + $this->write(implode("\n", array_map(function ($commandName) use ($description) { |
|
| 182 | + return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); |
|
| 183 | + }, $namespace['commands']))); |
|
| 184 | + } |
|
| 185 | + |
|
| 186 | + foreach ($description->getCommands() as $command) { |
|
| 187 | + $this->write("\n\n"); |
|
| 188 | + if (null !== $describeCommand = $this->describeCommand($command, $options)) { |
|
| 189 | + $this->write($describeCommand); |
|
| 190 | + } |
|
| 191 | + } |
|
| 192 | + } |
|
| 193 | + |
|
| 194 | + private function getApplicationTitle(Application $application): string |
|
| 195 | + { |
|
| 196 | + if ('UNKNOWN' !== $application->getName()) { |
|
| 197 | + if ('UNKNOWN' !== $application->getVersion()) { |
|
| 198 | + return sprintf('%s %s', $application->getName(), $application->getVersion()); |
|
| 199 | + } |
|
| 200 | + |
|
| 201 | + return $application->getName(); |
|
| 202 | + } |
|
| 203 | + |
|
| 204 | + return 'Console Tool'; |
|
| 205 | + } |
|
| 206 | 206 | } |
@@ -26,69 +26,69 @@ |
||
| 26 | 26 | */ |
| 27 | 27 | abstract class Descriptor implements DescriptorInterface |
| 28 | 28 | { |
| 29 | - /** |
|
| 30 | - * @var OutputInterface |
|
| 31 | - */ |
|
| 32 | - protected $output; |
|
| 29 | + /** |
|
| 30 | + * @var OutputInterface |
|
| 31 | + */ |
|
| 32 | + protected $output; |
|
| 33 | 33 | |
| 34 | - /** |
|
| 35 | - * {@inheritdoc} |
|
| 36 | - */ |
|
| 37 | - public function describe(OutputInterface $output, object $object, array $options = []) |
|
| 38 | - { |
|
| 39 | - $this->output = $output; |
|
| 34 | + /** |
|
| 35 | + * {@inheritdoc} |
|
| 36 | + */ |
|
| 37 | + public function describe(OutputInterface $output, object $object, array $options = []) |
|
| 38 | + { |
|
| 39 | + $this->output = $output; |
|
| 40 | 40 | |
| 41 | - switch (true) { |
|
| 42 | - case $object instanceof InputArgument: |
|
| 43 | - $this->describeInputArgument($object, $options); |
|
| 44 | - break; |
|
| 45 | - case $object instanceof InputOption: |
|
| 46 | - $this->describeInputOption($object, $options); |
|
| 47 | - break; |
|
| 48 | - case $object instanceof InputDefinition: |
|
| 49 | - $this->describeInputDefinition($object, $options); |
|
| 50 | - break; |
|
| 51 | - case $object instanceof Command: |
|
| 52 | - $this->describeCommand($object, $options); |
|
| 53 | - break; |
|
| 54 | - case $object instanceof Application: |
|
| 55 | - $this->describeApplication($object, $options); |
|
| 56 | - break; |
|
| 57 | - default: |
|
| 58 | - throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))); |
|
| 59 | - } |
|
| 60 | - } |
|
| 41 | + switch (true) { |
|
| 42 | + case $object instanceof InputArgument: |
|
| 43 | + $this->describeInputArgument($object, $options); |
|
| 44 | + break; |
|
| 45 | + case $object instanceof InputOption: |
|
| 46 | + $this->describeInputOption($object, $options); |
|
| 47 | + break; |
|
| 48 | + case $object instanceof InputDefinition: |
|
| 49 | + $this->describeInputDefinition($object, $options); |
|
| 50 | + break; |
|
| 51 | + case $object instanceof Command: |
|
| 52 | + $this->describeCommand($object, $options); |
|
| 53 | + break; |
|
| 54 | + case $object instanceof Application: |
|
| 55 | + $this->describeApplication($object, $options); |
|
| 56 | + break; |
|
| 57 | + default: |
|
| 58 | + throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))); |
|
| 59 | + } |
|
| 60 | + } |
|
| 61 | 61 | |
| 62 | - /** |
|
| 63 | - * Writes content to output. |
|
| 64 | - */ |
|
| 65 | - protected function write(string $content, bool $decorated = false) |
|
| 66 | - { |
|
| 67 | - $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); |
|
| 68 | - } |
|
| 62 | + /** |
|
| 63 | + * Writes content to output. |
|
| 64 | + */ |
|
| 65 | + protected function write(string $content, bool $decorated = false) |
|
| 66 | + { |
|
| 67 | + $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); |
|
| 68 | + } |
|
| 69 | 69 | |
| 70 | - /** |
|
| 71 | - * Describes an InputArgument instance. |
|
| 72 | - */ |
|
| 73 | - abstract protected function describeInputArgument(InputArgument $argument, array $options = []); |
|
| 70 | + /** |
|
| 71 | + * Describes an InputArgument instance. |
|
| 72 | + */ |
|
| 73 | + abstract protected function describeInputArgument(InputArgument $argument, array $options = []); |
|
| 74 | 74 | |
| 75 | - /** |
|
| 76 | - * Describes an InputOption instance. |
|
| 77 | - */ |
|
| 78 | - abstract protected function describeInputOption(InputOption $option, array $options = []); |
|
| 75 | + /** |
|
| 76 | + * Describes an InputOption instance. |
|
| 77 | + */ |
|
| 78 | + abstract protected function describeInputOption(InputOption $option, array $options = []); |
|
| 79 | 79 | |
| 80 | - /** |
|
| 81 | - * Describes an InputDefinition instance. |
|
| 82 | - */ |
|
| 83 | - abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); |
|
| 80 | + /** |
|
| 81 | + * Describes an InputDefinition instance. |
|
| 82 | + */ |
|
| 83 | + abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); |
|
| 84 | 84 | |
| 85 | - /** |
|
| 86 | - * Describes a Command instance. |
|
| 87 | - */ |
|
| 88 | - abstract protected function describeCommand(Command $command, array $options = []); |
|
| 85 | + /** |
|
| 86 | + * Describes a Command instance. |
|
| 87 | + */ |
|
| 88 | + abstract protected function describeCommand(Command $command, array $options = []); |
|
| 89 | 89 | |
| 90 | - /** |
|
| 91 | - * Describes an Application instance. |
|
| 92 | - */ |
|
| 93 | - abstract protected function describeApplication(Application $application, array $options = []); |
|
| 90 | + /** |
|
| 91 | + * Describes an Application instance. |
|
| 92 | + */ |
|
| 93 | + abstract protected function describeApplication(Application $application, array $options = []); |
|
| 94 | 94 | } |
@@ -26,222 +26,222 @@ |
||
| 26 | 26 | */ |
| 27 | 27 | class XmlDescriptor extends Descriptor |
| 28 | 28 | { |
| 29 | - public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument |
|
| 30 | - { |
|
| 31 | - $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 32 | - $dom->appendChild($definitionXML = $dom->createElement('definition')); |
|
| 33 | - |
|
| 34 | - $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); |
|
| 35 | - foreach ($definition->getArguments() as $argument) { |
|
| 36 | - $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); |
|
| 37 | - } |
|
| 38 | - |
|
| 39 | - $definitionXML->appendChild($optionsXML = $dom->createElement('options')); |
|
| 40 | - foreach ($definition->getOptions() as $option) { |
|
| 41 | - $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); |
|
| 42 | - } |
|
| 43 | - |
|
| 44 | - return $dom; |
|
| 45 | - } |
|
| 46 | - |
|
| 47 | - public function getCommandDocument(Command $command, bool $short = false): \DOMDocument |
|
| 48 | - { |
|
| 49 | - $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 50 | - $dom->appendChild($commandXML = $dom->createElement('command')); |
|
| 51 | - |
|
| 52 | - $commandXML->setAttribute('id', $command->getName()); |
|
| 53 | - $commandXML->setAttribute('name', $command->getName()); |
|
| 54 | - $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); |
|
| 55 | - |
|
| 56 | - $commandXML->appendChild($usagesXML = $dom->createElement('usages')); |
|
| 57 | - |
|
| 58 | - $commandXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 59 | - $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); |
|
| 60 | - |
|
| 61 | - if ($short) { |
|
| 62 | - foreach ($command->getAliases() as $usage) { |
|
| 63 | - $usagesXML->appendChild($dom->createElement('usage', $usage)); |
|
| 64 | - } |
|
| 65 | - } else { |
|
| 66 | - $command->mergeApplicationDefinition(false); |
|
| 67 | - |
|
| 68 | - foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { |
|
| 69 | - $usagesXML->appendChild($dom->createElement('usage', $usage)); |
|
| 70 | - } |
|
| 71 | - |
|
| 72 | - $commandXML->appendChild($helpXML = $dom->createElement('help')); |
|
| 73 | - $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); |
|
| 74 | - |
|
| 75 | - $definitionXML = $this->getInputDefinitionDocument($command->getDefinition()); |
|
| 76 | - $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - return $dom; |
|
| 80 | - } |
|
| 81 | - |
|
| 82 | - public function getApplicationDocument(Application $application, string $namespace = null, bool $short = false): \DOMDocument |
|
| 83 | - { |
|
| 84 | - $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 85 | - $dom->appendChild($rootXml = $dom->createElement('symfony')); |
|
| 86 | - |
|
| 87 | - if ('UNKNOWN' !== $application->getName()) { |
|
| 88 | - $rootXml->setAttribute('name', $application->getName()); |
|
| 89 | - if ('UNKNOWN' !== $application->getVersion()) { |
|
| 90 | - $rootXml->setAttribute('version', $application->getVersion()); |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - $rootXml->appendChild($commandsXML = $dom->createElement('commands')); |
|
| 95 | - |
|
| 96 | - $description = new ApplicationDescription($application, $namespace, true); |
|
| 97 | - |
|
| 98 | - if ($namespace) { |
|
| 99 | - $commandsXML->setAttribute('namespace', $namespace); |
|
| 100 | - } |
|
| 101 | - |
|
| 102 | - foreach ($description->getCommands() as $command) { |
|
| 103 | - $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short)); |
|
| 104 | - } |
|
| 105 | - |
|
| 106 | - if (!$namespace) { |
|
| 107 | - $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); |
|
| 108 | - |
|
| 109 | - foreach ($description->getNamespaces() as $namespaceDescription) { |
|
| 110 | - $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); |
|
| 111 | - $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); |
|
| 112 | - |
|
| 113 | - foreach ($namespaceDescription['commands'] as $name) { |
|
| 114 | - $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); |
|
| 115 | - $commandXML->appendChild($dom->createTextNode($name)); |
|
| 116 | - } |
|
| 117 | - } |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - return $dom; |
|
| 121 | - } |
|
| 122 | - |
|
| 123 | - /** |
|
| 124 | - * {@inheritdoc} |
|
| 125 | - */ |
|
| 126 | - protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 127 | - { |
|
| 128 | - $this->writeDocument($this->getInputArgumentDocument($argument)); |
|
| 129 | - } |
|
| 130 | - |
|
| 131 | - /** |
|
| 132 | - * {@inheritdoc} |
|
| 133 | - */ |
|
| 134 | - protected function describeInputOption(InputOption $option, array $options = []) |
|
| 135 | - { |
|
| 136 | - $this->writeDocument($this->getInputOptionDocument($option)); |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - /** |
|
| 140 | - * {@inheritdoc} |
|
| 141 | - */ |
|
| 142 | - protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 143 | - { |
|
| 144 | - $this->writeDocument($this->getInputDefinitionDocument($definition)); |
|
| 145 | - } |
|
| 146 | - |
|
| 147 | - /** |
|
| 148 | - * {@inheritdoc} |
|
| 149 | - */ |
|
| 150 | - protected function describeCommand(Command $command, array $options = []) |
|
| 151 | - { |
|
| 152 | - $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false)); |
|
| 153 | - } |
|
| 154 | - |
|
| 155 | - /** |
|
| 156 | - * {@inheritdoc} |
|
| 157 | - */ |
|
| 158 | - protected function describeApplication(Application $application, array $options = []) |
|
| 159 | - { |
|
| 160 | - $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false)); |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - /** |
|
| 164 | - * Appends document children to parent node. |
|
| 165 | - */ |
|
| 166 | - private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) |
|
| 167 | - { |
|
| 168 | - foreach ($importedParent->childNodes as $childNode) { |
|
| 169 | - $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); |
|
| 170 | - } |
|
| 171 | - } |
|
| 172 | - |
|
| 173 | - /** |
|
| 174 | - * Writes DOM document. |
|
| 175 | - */ |
|
| 176 | - private function writeDocument(\DOMDocument $dom) |
|
| 177 | - { |
|
| 178 | - $dom->formatOutput = true; |
|
| 179 | - $this->write($dom->saveXML()); |
|
| 180 | - } |
|
| 181 | - |
|
| 182 | - private function getInputArgumentDocument(InputArgument $argument): \DOMDocument |
|
| 183 | - { |
|
| 184 | - $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 185 | - |
|
| 186 | - $dom->appendChild($objectXML = $dom->createElement('argument')); |
|
| 187 | - $objectXML->setAttribute('name', $argument->getName()); |
|
| 188 | - $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); |
|
| 189 | - $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); |
|
| 190 | - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 191 | - $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); |
|
| 192 | - |
|
| 193 | - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); |
|
| 194 | - $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); |
|
| 195 | - foreach ($defaults as $default) { |
|
| 196 | - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); |
|
| 197 | - $defaultXML->appendChild($dom->createTextNode($default)); |
|
| 198 | - } |
|
| 199 | - |
|
| 200 | - return $dom; |
|
| 201 | - } |
|
| 202 | - |
|
| 203 | - private function getInputOptionDocument(InputOption $option): \DOMDocument |
|
| 204 | - { |
|
| 205 | - $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 206 | - |
|
| 207 | - $dom->appendChild($objectXML = $dom->createElement('option')); |
|
| 208 | - $objectXML->setAttribute('name', '--'.$option->getName()); |
|
| 209 | - $pos = strpos($option->getShortcut() ?? '', '|'); |
|
| 210 | - if (false !== $pos) { |
|
| 211 | - $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); |
|
| 212 | - $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); |
|
| 213 | - } else { |
|
| 214 | - $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); |
|
| 215 | - } |
|
| 216 | - $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); |
|
| 217 | - $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); |
|
| 218 | - $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); |
|
| 219 | - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 220 | - $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); |
|
| 221 | - |
|
| 222 | - if ($option->acceptValue()) { |
|
| 223 | - $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); |
|
| 224 | - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); |
|
| 225 | - |
|
| 226 | - if (!empty($defaults)) { |
|
| 227 | - foreach ($defaults as $default) { |
|
| 228 | - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); |
|
| 229 | - $defaultXML->appendChild($dom->createTextNode($default)); |
|
| 230 | - } |
|
| 231 | - } |
|
| 232 | - } |
|
| 233 | - |
|
| 234 | - if ($option->isNegatable()) { |
|
| 235 | - $dom->appendChild($objectXML = $dom->createElement('option')); |
|
| 236 | - $objectXML->setAttribute('name', '--no-'.$option->getName()); |
|
| 237 | - $objectXML->setAttribute('shortcut', ''); |
|
| 238 | - $objectXML->setAttribute('accept_value', 0); |
|
| 239 | - $objectXML->setAttribute('is_value_required', 0); |
|
| 240 | - $objectXML->setAttribute('is_multiple', 0); |
|
| 241 | - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 242 | - $descriptionXML->appendChild($dom->createTextNode('Negate the "--'.$option->getName().'" option')); |
|
| 243 | - } |
|
| 244 | - |
|
| 245 | - return $dom; |
|
| 246 | - } |
|
| 29 | + public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument |
|
| 30 | + { |
|
| 31 | + $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 32 | + $dom->appendChild($definitionXML = $dom->createElement('definition')); |
|
| 33 | + |
|
| 34 | + $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); |
|
| 35 | + foreach ($definition->getArguments() as $argument) { |
|
| 36 | + $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); |
|
| 37 | + } |
|
| 38 | + |
|
| 39 | + $definitionXML->appendChild($optionsXML = $dom->createElement('options')); |
|
| 40 | + foreach ($definition->getOptions() as $option) { |
|
| 41 | + $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); |
|
| 42 | + } |
|
| 43 | + |
|
| 44 | + return $dom; |
|
| 45 | + } |
|
| 46 | + |
|
| 47 | + public function getCommandDocument(Command $command, bool $short = false): \DOMDocument |
|
| 48 | + { |
|
| 49 | + $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 50 | + $dom->appendChild($commandXML = $dom->createElement('command')); |
|
| 51 | + |
|
| 52 | + $commandXML->setAttribute('id', $command->getName()); |
|
| 53 | + $commandXML->setAttribute('name', $command->getName()); |
|
| 54 | + $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); |
|
| 55 | + |
|
| 56 | + $commandXML->appendChild($usagesXML = $dom->createElement('usages')); |
|
| 57 | + |
|
| 58 | + $commandXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 59 | + $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); |
|
| 60 | + |
|
| 61 | + if ($short) { |
|
| 62 | + foreach ($command->getAliases() as $usage) { |
|
| 63 | + $usagesXML->appendChild($dom->createElement('usage', $usage)); |
|
| 64 | + } |
|
| 65 | + } else { |
|
| 66 | + $command->mergeApplicationDefinition(false); |
|
| 67 | + |
|
| 68 | + foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { |
|
| 69 | + $usagesXML->appendChild($dom->createElement('usage', $usage)); |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + $commandXML->appendChild($helpXML = $dom->createElement('help')); |
|
| 73 | + $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); |
|
| 74 | + |
|
| 75 | + $definitionXML = $this->getInputDefinitionDocument($command->getDefinition()); |
|
| 76 | + $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + return $dom; |
|
| 80 | + } |
|
| 81 | + |
|
| 82 | + public function getApplicationDocument(Application $application, string $namespace = null, bool $short = false): \DOMDocument |
|
| 83 | + { |
|
| 84 | + $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 85 | + $dom->appendChild($rootXml = $dom->createElement('symfony')); |
|
| 86 | + |
|
| 87 | + if ('UNKNOWN' !== $application->getName()) { |
|
| 88 | + $rootXml->setAttribute('name', $application->getName()); |
|
| 89 | + if ('UNKNOWN' !== $application->getVersion()) { |
|
| 90 | + $rootXml->setAttribute('version', $application->getVersion()); |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + $rootXml->appendChild($commandsXML = $dom->createElement('commands')); |
|
| 95 | + |
|
| 96 | + $description = new ApplicationDescription($application, $namespace, true); |
|
| 97 | + |
|
| 98 | + if ($namespace) { |
|
| 99 | + $commandsXML->setAttribute('namespace', $namespace); |
|
| 100 | + } |
|
| 101 | + |
|
| 102 | + foreach ($description->getCommands() as $command) { |
|
| 103 | + $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short)); |
|
| 104 | + } |
|
| 105 | + |
|
| 106 | + if (!$namespace) { |
|
| 107 | + $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); |
|
| 108 | + |
|
| 109 | + foreach ($description->getNamespaces() as $namespaceDescription) { |
|
| 110 | + $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); |
|
| 111 | + $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); |
|
| 112 | + |
|
| 113 | + foreach ($namespaceDescription['commands'] as $name) { |
|
| 114 | + $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); |
|
| 115 | + $commandXML->appendChild($dom->createTextNode($name)); |
|
| 116 | + } |
|
| 117 | + } |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + return $dom; |
|
| 121 | + } |
|
| 122 | + |
|
| 123 | + /** |
|
| 124 | + * {@inheritdoc} |
|
| 125 | + */ |
|
| 126 | + protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 127 | + { |
|
| 128 | + $this->writeDocument($this->getInputArgumentDocument($argument)); |
|
| 129 | + } |
|
| 130 | + |
|
| 131 | + /** |
|
| 132 | + * {@inheritdoc} |
|
| 133 | + */ |
|
| 134 | + protected function describeInputOption(InputOption $option, array $options = []) |
|
| 135 | + { |
|
| 136 | + $this->writeDocument($this->getInputOptionDocument($option)); |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + /** |
|
| 140 | + * {@inheritdoc} |
|
| 141 | + */ |
|
| 142 | + protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 143 | + { |
|
| 144 | + $this->writeDocument($this->getInputDefinitionDocument($definition)); |
|
| 145 | + } |
|
| 146 | + |
|
| 147 | + /** |
|
| 148 | + * {@inheritdoc} |
|
| 149 | + */ |
|
| 150 | + protected function describeCommand(Command $command, array $options = []) |
|
| 151 | + { |
|
| 152 | + $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false)); |
|
| 153 | + } |
|
| 154 | + |
|
| 155 | + /** |
|
| 156 | + * {@inheritdoc} |
|
| 157 | + */ |
|
| 158 | + protected function describeApplication(Application $application, array $options = []) |
|
| 159 | + { |
|
| 160 | + $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false)); |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + /** |
|
| 164 | + * Appends document children to parent node. |
|
| 165 | + */ |
|
| 166 | + private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) |
|
| 167 | + { |
|
| 168 | + foreach ($importedParent->childNodes as $childNode) { |
|
| 169 | + $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); |
|
| 170 | + } |
|
| 171 | + } |
|
| 172 | + |
|
| 173 | + /** |
|
| 174 | + * Writes DOM document. |
|
| 175 | + */ |
|
| 176 | + private function writeDocument(\DOMDocument $dom) |
|
| 177 | + { |
|
| 178 | + $dom->formatOutput = true; |
|
| 179 | + $this->write($dom->saveXML()); |
|
| 180 | + } |
|
| 181 | + |
|
| 182 | + private function getInputArgumentDocument(InputArgument $argument): \DOMDocument |
|
| 183 | + { |
|
| 184 | + $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 185 | + |
|
| 186 | + $dom->appendChild($objectXML = $dom->createElement('argument')); |
|
| 187 | + $objectXML->setAttribute('name', $argument->getName()); |
|
| 188 | + $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); |
|
| 189 | + $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); |
|
| 190 | + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 191 | + $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); |
|
| 192 | + |
|
| 193 | + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); |
|
| 194 | + $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); |
|
| 195 | + foreach ($defaults as $default) { |
|
| 196 | + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); |
|
| 197 | + $defaultXML->appendChild($dom->createTextNode($default)); |
|
| 198 | + } |
|
| 199 | + |
|
| 200 | + return $dom; |
|
| 201 | + } |
|
| 202 | + |
|
| 203 | + private function getInputOptionDocument(InputOption $option): \DOMDocument |
|
| 204 | + { |
|
| 205 | + $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
| 206 | + |
|
| 207 | + $dom->appendChild($objectXML = $dom->createElement('option')); |
|
| 208 | + $objectXML->setAttribute('name', '--'.$option->getName()); |
|
| 209 | + $pos = strpos($option->getShortcut() ?? '', '|'); |
|
| 210 | + if (false !== $pos) { |
|
| 211 | + $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); |
|
| 212 | + $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); |
|
| 213 | + } else { |
|
| 214 | + $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); |
|
| 215 | + } |
|
| 216 | + $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); |
|
| 217 | + $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); |
|
| 218 | + $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); |
|
| 219 | + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 220 | + $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); |
|
| 221 | + |
|
| 222 | + if ($option->acceptValue()) { |
|
| 223 | + $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); |
|
| 224 | + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); |
|
| 225 | + |
|
| 226 | + if (!empty($defaults)) { |
|
| 227 | + foreach ($defaults as $default) { |
|
| 228 | + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); |
|
| 229 | + $defaultXML->appendChild($dom->createTextNode($default)); |
|
| 230 | + } |
|
| 231 | + } |
|
| 232 | + } |
|
| 233 | + |
|
| 234 | + if ($option->isNegatable()) { |
|
| 235 | + $dom->appendChild($objectXML = $dom->createElement('option')); |
|
| 236 | + $objectXML->setAttribute('name', '--no-'.$option->getName()); |
|
| 237 | + $objectXML->setAttribute('shortcut', ''); |
|
| 238 | + $objectXML->setAttribute('accept_value', 0); |
|
| 239 | + $objectXML->setAttribute('is_value_required', 0); |
|
| 240 | + $objectXML->setAttribute('is_multiple', 0); |
|
| 241 | + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); |
|
| 242 | + $descriptionXML->appendChild($dom->createTextNode('Negate the "--'.$option->getName().'" option')); |
|
| 243 | + } |
|
| 244 | + |
|
| 245 | + return $dom; |
|
| 246 | + } |
|
| 247 | 247 | } |
@@ -20,5 +20,5 @@ |
||
| 20 | 20 | */ |
| 21 | 21 | interface DescriptorInterface |
| 22 | 22 | { |
| 23 | - public function describe(OutputInterface $output, object $object, array $options = []); |
|
| 23 | + public function describe(OutputInterface $output, object $object, array $options = []); |
|
| 24 | 24 | } |
@@ -26,156 +26,156 @@ |
||
| 26 | 26 | */ |
| 27 | 27 | class JsonDescriptor extends Descriptor |
| 28 | 28 | { |
| 29 | - /** |
|
| 30 | - * {@inheritdoc} |
|
| 31 | - */ |
|
| 32 | - protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 33 | - { |
|
| 34 | - $this->writeData($this->getInputArgumentData($argument), $options); |
|
| 35 | - } |
|
| 36 | - |
|
| 37 | - /** |
|
| 38 | - * {@inheritdoc} |
|
| 39 | - */ |
|
| 40 | - protected function describeInputOption(InputOption $option, array $options = []) |
|
| 41 | - { |
|
| 42 | - $this->writeData($this->getInputOptionData($option), $options); |
|
| 43 | - if ($option->isNegatable()) { |
|
| 44 | - $this->writeData($this->getInputOptionData($option, true), $options); |
|
| 45 | - } |
|
| 46 | - } |
|
| 47 | - |
|
| 48 | - /** |
|
| 49 | - * {@inheritdoc} |
|
| 50 | - */ |
|
| 51 | - protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 52 | - { |
|
| 53 | - $this->writeData($this->getInputDefinitionData($definition), $options); |
|
| 54 | - } |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * {@inheritdoc} |
|
| 58 | - */ |
|
| 59 | - protected function describeCommand(Command $command, array $options = []) |
|
| 60 | - { |
|
| 61 | - $this->writeData($this->getCommandData($command, $options['short'] ?? false), $options); |
|
| 62 | - } |
|
| 63 | - |
|
| 64 | - /** |
|
| 65 | - * {@inheritdoc} |
|
| 66 | - */ |
|
| 67 | - protected function describeApplication(Application $application, array $options = []) |
|
| 68 | - { |
|
| 69 | - $describedNamespace = $options['namespace'] ?? null; |
|
| 70 | - $description = new ApplicationDescription($application, $describedNamespace, true); |
|
| 71 | - $commands = []; |
|
| 72 | - |
|
| 73 | - foreach ($description->getCommands() as $command) { |
|
| 74 | - $commands[] = $this->getCommandData($command, $options['short'] ?? false); |
|
| 75 | - } |
|
| 76 | - |
|
| 77 | - $data = []; |
|
| 78 | - if ('UNKNOWN' !== $application->getName()) { |
|
| 79 | - $data['application']['name'] = $application->getName(); |
|
| 80 | - if ('UNKNOWN' !== $application->getVersion()) { |
|
| 81 | - $data['application']['version'] = $application->getVersion(); |
|
| 82 | - } |
|
| 83 | - } |
|
| 84 | - |
|
| 85 | - $data['commands'] = $commands; |
|
| 86 | - |
|
| 87 | - if ($describedNamespace) { |
|
| 88 | - $data['namespace'] = $describedNamespace; |
|
| 89 | - } else { |
|
| 90 | - $data['namespaces'] = array_values($description->getNamespaces()); |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - $this->writeData($data, $options); |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - /** |
|
| 97 | - * Writes data as json. |
|
| 98 | - */ |
|
| 99 | - private function writeData(array $data, array $options) |
|
| 100 | - { |
|
| 101 | - $flags = $options['json_encoding'] ?? 0; |
|
| 102 | - |
|
| 103 | - $this->write(json_encode($data, $flags)); |
|
| 104 | - } |
|
| 105 | - |
|
| 106 | - private function getInputArgumentData(InputArgument $argument): array |
|
| 107 | - { |
|
| 108 | - return [ |
|
| 109 | - 'name' => $argument->getName(), |
|
| 110 | - 'is_required' => $argument->isRequired(), |
|
| 111 | - 'is_array' => $argument->isArray(), |
|
| 112 | - 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), |
|
| 113 | - 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), |
|
| 114 | - ]; |
|
| 115 | - } |
|
| 116 | - |
|
| 117 | - private function getInputOptionData(InputOption $option, bool $negated = false): array |
|
| 118 | - { |
|
| 119 | - return $negated ? [ |
|
| 120 | - 'name' => '--no-'.$option->getName(), |
|
| 121 | - 'shortcut' => '', |
|
| 122 | - 'accept_value' => false, |
|
| 123 | - 'is_value_required' => false, |
|
| 124 | - 'is_multiple' => false, |
|
| 125 | - 'description' => 'Negate the "--'.$option->getName().'" option', |
|
| 126 | - 'default' => false, |
|
| 127 | - ] : [ |
|
| 128 | - 'name' => '--'.$option->getName(), |
|
| 129 | - 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', |
|
| 130 | - 'accept_value' => $option->acceptValue(), |
|
| 131 | - 'is_value_required' => $option->isValueRequired(), |
|
| 132 | - 'is_multiple' => $option->isArray(), |
|
| 133 | - 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), |
|
| 134 | - 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), |
|
| 135 | - ]; |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - private function getInputDefinitionData(InputDefinition $definition): array |
|
| 139 | - { |
|
| 140 | - $inputArguments = []; |
|
| 141 | - foreach ($definition->getArguments() as $name => $argument) { |
|
| 142 | - $inputArguments[$name] = $this->getInputArgumentData($argument); |
|
| 143 | - } |
|
| 144 | - |
|
| 145 | - $inputOptions = []; |
|
| 146 | - foreach ($definition->getOptions() as $name => $option) { |
|
| 147 | - $inputOptions[$name] = $this->getInputOptionData($option); |
|
| 148 | - if ($option->isNegatable()) { |
|
| 149 | - $inputOptions['no-'.$name] = $this->getInputOptionData($option, true); |
|
| 150 | - } |
|
| 151 | - } |
|
| 152 | - |
|
| 153 | - return ['arguments' => $inputArguments, 'options' => $inputOptions]; |
|
| 154 | - } |
|
| 155 | - |
|
| 156 | - private function getCommandData(Command $command, bool $short = false): array |
|
| 157 | - { |
|
| 158 | - $data = [ |
|
| 159 | - 'name' => $command->getName(), |
|
| 160 | - 'description' => $command->getDescription(), |
|
| 161 | - ]; |
|
| 162 | - |
|
| 163 | - if ($short) { |
|
| 164 | - $data += [ |
|
| 165 | - 'usage' => $command->getAliases(), |
|
| 166 | - ]; |
|
| 167 | - } else { |
|
| 168 | - $command->mergeApplicationDefinition(false); |
|
| 169 | - |
|
| 170 | - $data += [ |
|
| 171 | - 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), |
|
| 172 | - 'help' => $command->getProcessedHelp(), |
|
| 173 | - 'definition' => $this->getInputDefinitionData($command->getDefinition()), |
|
| 174 | - ]; |
|
| 175 | - } |
|
| 176 | - |
|
| 177 | - $data['hidden'] = $command->isHidden(); |
|
| 178 | - |
|
| 179 | - return $data; |
|
| 180 | - } |
|
| 29 | + /** |
|
| 30 | + * {@inheritdoc} |
|
| 31 | + */ |
|
| 32 | + protected function describeInputArgument(InputArgument $argument, array $options = []) |
|
| 33 | + { |
|
| 34 | + $this->writeData($this->getInputArgumentData($argument), $options); |
|
| 35 | + } |
|
| 36 | + |
|
| 37 | + /** |
|
| 38 | + * {@inheritdoc} |
|
| 39 | + */ |
|
| 40 | + protected function describeInputOption(InputOption $option, array $options = []) |
|
| 41 | + { |
|
| 42 | + $this->writeData($this->getInputOptionData($option), $options); |
|
| 43 | + if ($option->isNegatable()) { |
|
| 44 | + $this->writeData($this->getInputOptionData($option, true), $options); |
|
| 45 | + } |
|
| 46 | + } |
|
| 47 | + |
|
| 48 | + /** |
|
| 49 | + * {@inheritdoc} |
|
| 50 | + */ |
|
| 51 | + protected function describeInputDefinition(InputDefinition $definition, array $options = []) |
|
| 52 | + { |
|
| 53 | + $this->writeData($this->getInputDefinitionData($definition), $options); |
|
| 54 | + } |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * {@inheritdoc} |
|
| 58 | + */ |
|
| 59 | + protected function describeCommand(Command $command, array $options = []) |
|
| 60 | + { |
|
| 61 | + $this->writeData($this->getCommandData($command, $options['short'] ?? false), $options); |
|
| 62 | + } |
|
| 63 | + |
|
| 64 | + /** |
|
| 65 | + * {@inheritdoc} |
|
| 66 | + */ |
|
| 67 | + protected function describeApplication(Application $application, array $options = []) |
|
| 68 | + { |
|
| 69 | + $describedNamespace = $options['namespace'] ?? null; |
|
| 70 | + $description = new ApplicationDescription($application, $describedNamespace, true); |
|
| 71 | + $commands = []; |
|
| 72 | + |
|
| 73 | + foreach ($description->getCommands() as $command) { |
|
| 74 | + $commands[] = $this->getCommandData($command, $options['short'] ?? false); |
|
| 75 | + } |
|
| 76 | + |
|
| 77 | + $data = []; |
|
| 78 | + if ('UNKNOWN' !== $application->getName()) { |
|
| 79 | + $data['application']['name'] = $application->getName(); |
|
| 80 | + if ('UNKNOWN' !== $application->getVersion()) { |
|
| 81 | + $data['application']['version'] = $application->getVersion(); |
|
| 82 | + } |
|
| 83 | + } |
|
| 84 | + |
|
| 85 | + $data['commands'] = $commands; |
|
| 86 | + |
|
| 87 | + if ($describedNamespace) { |
|
| 88 | + $data['namespace'] = $describedNamespace; |
|
| 89 | + } else { |
|
| 90 | + $data['namespaces'] = array_values($description->getNamespaces()); |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + $this->writeData($data, $options); |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + /** |
|
| 97 | + * Writes data as json. |
|
| 98 | + */ |
|
| 99 | + private function writeData(array $data, array $options) |
|
| 100 | + { |
|
| 101 | + $flags = $options['json_encoding'] ?? 0; |
|
| 102 | + |
|
| 103 | + $this->write(json_encode($data, $flags)); |
|
| 104 | + } |
|
| 105 | + |
|
| 106 | + private function getInputArgumentData(InputArgument $argument): array |
|
| 107 | + { |
|
| 108 | + return [ |
|
| 109 | + 'name' => $argument->getName(), |
|
| 110 | + 'is_required' => $argument->isRequired(), |
|
| 111 | + 'is_array' => $argument->isArray(), |
|
| 112 | + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), |
|
| 113 | + 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), |
|
| 114 | + ]; |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + private function getInputOptionData(InputOption $option, bool $negated = false): array |
|
| 118 | + { |
|
| 119 | + return $negated ? [ |
|
| 120 | + 'name' => '--no-'.$option->getName(), |
|
| 121 | + 'shortcut' => '', |
|
| 122 | + 'accept_value' => false, |
|
| 123 | + 'is_value_required' => false, |
|
| 124 | + 'is_multiple' => false, |
|
| 125 | + 'description' => 'Negate the "--'.$option->getName().'" option', |
|
| 126 | + 'default' => false, |
|
| 127 | + ] : [ |
|
| 128 | + 'name' => '--'.$option->getName(), |
|
| 129 | + 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', |
|
| 130 | + 'accept_value' => $option->acceptValue(), |
|
| 131 | + 'is_value_required' => $option->isValueRequired(), |
|
| 132 | + 'is_multiple' => $option->isArray(), |
|
| 133 | + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), |
|
| 134 | + 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), |
|
| 135 | + ]; |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + private function getInputDefinitionData(InputDefinition $definition): array |
|
| 139 | + { |
|
| 140 | + $inputArguments = []; |
|
| 141 | + foreach ($definition->getArguments() as $name => $argument) { |
|
| 142 | + $inputArguments[$name] = $this->getInputArgumentData($argument); |
|
| 143 | + } |
|
| 144 | + |
|
| 145 | + $inputOptions = []; |
|
| 146 | + foreach ($definition->getOptions() as $name => $option) { |
|
| 147 | + $inputOptions[$name] = $this->getInputOptionData($option); |
|
| 148 | + if ($option->isNegatable()) { |
|
| 149 | + $inputOptions['no-'.$name] = $this->getInputOptionData($option, true); |
|
| 150 | + } |
|
| 151 | + } |
|
| 152 | + |
|
| 153 | + return ['arguments' => $inputArguments, 'options' => $inputOptions]; |
|
| 154 | + } |
|
| 155 | + |
|
| 156 | + private function getCommandData(Command $command, bool $short = false): array |
|
| 157 | + { |
|
| 158 | + $data = [ |
|
| 159 | + 'name' => $command->getName(), |
|
| 160 | + 'description' => $command->getDescription(), |
|
| 161 | + ]; |
|
| 162 | + |
|
| 163 | + if ($short) { |
|
| 164 | + $data += [ |
|
| 165 | + 'usage' => $command->getAliases(), |
|
| 166 | + ]; |
|
| 167 | + } else { |
|
| 168 | + $command->mergeApplicationDefinition(false); |
|
| 169 | + |
|
| 170 | + $data += [ |
|
| 171 | + 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), |
|
| 172 | + 'help' => $command->getProcessedHelp(), |
|
| 173 | + 'definition' => $this->getInputDefinitionData($command->getDefinition()), |
|
| 174 | + ]; |
|
| 175 | + } |
|
| 176 | + |
|
| 177 | + $data['hidden'] = $command->isHidden(); |
|
| 178 | + |
|
| 179 | + return $data; |
|
| 180 | + } |
|
| 181 | 181 | } |
@@ -20,80 +20,80 @@ |
||
| 20 | 20 | */ |
| 21 | 21 | class GithubActionReporter |
| 22 | 22 | { |
| 23 | - private $output; |
|
| 23 | + private $output; |
|
| 24 | 24 | |
| 25 | - /** |
|
| 26 | - * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85 |
|
| 27 | - */ |
|
| 28 | - private const ESCAPED_DATA = [ |
|
| 29 | - '%' => '%25', |
|
| 30 | - "\r" => '%0D', |
|
| 31 | - "\n" => '%0A', |
|
| 32 | - ]; |
|
| 25 | + /** |
|
| 26 | + * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85 |
|
| 27 | + */ |
|
| 28 | + private const ESCAPED_DATA = [ |
|
| 29 | + '%' => '%25', |
|
| 30 | + "\r" => '%0D', |
|
| 31 | + "\n" => '%0A', |
|
| 32 | + ]; |
|
| 33 | 33 | |
| 34 | - /** |
|
| 35 | - * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94 |
|
| 36 | - */ |
|
| 37 | - private const ESCAPED_PROPERTIES = [ |
|
| 38 | - '%' => '%25', |
|
| 39 | - "\r" => '%0D', |
|
| 40 | - "\n" => '%0A', |
|
| 41 | - ':' => '%3A', |
|
| 42 | - ',' => '%2C', |
|
| 43 | - ]; |
|
| 34 | + /** |
|
| 35 | + * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94 |
|
| 36 | + */ |
|
| 37 | + private const ESCAPED_PROPERTIES = [ |
|
| 38 | + '%' => '%25', |
|
| 39 | + "\r" => '%0D', |
|
| 40 | + "\n" => '%0A', |
|
| 41 | + ':' => '%3A', |
|
| 42 | + ',' => '%2C', |
|
| 43 | + ]; |
|
| 44 | 44 | |
| 45 | - public function __construct(OutputInterface $output) |
|
| 46 | - { |
|
| 47 | - $this->output = $output; |
|
| 48 | - } |
|
| 45 | + public function __construct(OutputInterface $output) |
|
| 46 | + { |
|
| 47 | + $this->output = $output; |
|
| 48 | + } |
|
| 49 | 49 | |
| 50 | - public static function isGithubActionEnvironment(): bool |
|
| 51 | - { |
|
| 52 | - return false !== getenv('GITHUB_ACTIONS'); |
|
| 53 | - } |
|
| 50 | + public static function isGithubActionEnvironment(): bool |
|
| 51 | + { |
|
| 52 | + return false !== getenv('GITHUB_ACTIONS'); |
|
| 53 | + } |
|
| 54 | 54 | |
| 55 | - /** |
|
| 56 | - * Output an error using the Github annotations format. |
|
| 57 | - * |
|
| 58 | - * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message |
|
| 59 | - */ |
|
| 60 | - public function error(string $message, string $file = null, int $line = null, int $col = null): void |
|
| 61 | - { |
|
| 62 | - $this->log('error', $message, $file, $line, $col); |
|
| 63 | - } |
|
| 55 | + /** |
|
| 56 | + * Output an error using the Github annotations format. |
|
| 57 | + * |
|
| 58 | + * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message |
|
| 59 | + */ |
|
| 60 | + public function error(string $message, string $file = null, int $line = null, int $col = null): void |
|
| 61 | + { |
|
| 62 | + $this->log('error', $message, $file, $line, $col); |
|
| 63 | + } |
|
| 64 | 64 | |
| 65 | - /** |
|
| 66 | - * Output a warning using the Github annotations format. |
|
| 67 | - * |
|
| 68 | - * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message |
|
| 69 | - */ |
|
| 70 | - public function warning(string $message, string $file = null, int $line = null, int $col = null): void |
|
| 71 | - { |
|
| 72 | - $this->log('warning', $message, $file, $line, $col); |
|
| 73 | - } |
|
| 65 | + /** |
|
| 66 | + * Output a warning using the Github annotations format. |
|
| 67 | + * |
|
| 68 | + * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message |
|
| 69 | + */ |
|
| 70 | + public function warning(string $message, string $file = null, int $line = null, int $col = null): void |
|
| 71 | + { |
|
| 72 | + $this->log('warning', $message, $file, $line, $col); |
|
| 73 | + } |
|
| 74 | 74 | |
| 75 | - /** |
|
| 76 | - * Output a debug log using the Github annotations format. |
|
| 77 | - * |
|
| 78 | - * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message |
|
| 79 | - */ |
|
| 80 | - public function debug(string $message, string $file = null, int $line = null, int $col = null): void |
|
| 81 | - { |
|
| 82 | - $this->log('debug', $message, $file, $line, $col); |
|
| 83 | - } |
|
| 75 | + /** |
|
| 76 | + * Output a debug log using the Github annotations format. |
|
| 77 | + * |
|
| 78 | + * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message |
|
| 79 | + */ |
|
| 80 | + public function debug(string $message, string $file = null, int $line = null, int $col = null): void |
|
| 81 | + { |
|
| 82 | + $this->log('debug', $message, $file, $line, $col); |
|
| 83 | + } |
|
| 84 | 84 | |
| 85 | - private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void |
|
| 86 | - { |
|
| 87 | - // Some values must be encoded. |
|
| 88 | - $message = strtr($message, self::ESCAPED_DATA); |
|
| 85 | + private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void |
|
| 86 | + { |
|
| 87 | + // Some values must be encoded. |
|
| 88 | + $message = strtr($message, self::ESCAPED_DATA); |
|
| 89 | 89 | |
| 90 | - if (!$file) { |
|
| 91 | - // No file provided, output the message solely: |
|
| 92 | - $this->output->writeln(sprintf('::%s::%s', $type, $message)); |
|
| 90 | + if (!$file) { |
|
| 91 | + // No file provided, output the message solely: |
|
| 92 | + $this->output->writeln(sprintf('::%s::%s', $type, $message)); |
|
| 93 | 93 | |
| 94 | - return; |
|
| 95 | - } |
|
| 94 | + return; |
|
| 95 | + } |
|
| 96 | 96 | |
| 97 | - $this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); |
|
| 98 | - } |
|
| 97 | + $this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); |
|
| 98 | + } |
|
| 99 | 99 | } |