1<?php 2 3/* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Symfony\Component\Console\Descriptor; 13 14use Symfony\Component\Console\Application; 15use Symfony\Component\Console\Command\Command; 16use Symfony\Component\Console\Input\InputArgument; 17use Symfony\Component\Console\Input\InputDefinition; 18use Symfony\Component\Console\Input\InputOption; 19 20/** 21 * JSON descriptor. 22 * 23 * @author Jean-François Simon <contact@jfsimon.fr> 24 * 25 * @internal 26 */ 27class JsonDescriptor extends Descriptor 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 } 44 45 /** 46 * {@inheritdoc} 47 */ 48 protected function describeInputDefinition(InputDefinition $definition, array $options = []) 49 { 50 $this->writeData($this->getInputDefinitionData($definition), $options); 51 } 52 53 /** 54 * {@inheritdoc} 55 */ 56 protected function describeCommand(Command $command, array $options = []) 57 { 58 $this->writeData($this->getCommandData($command), $options); 59 } 60 61 /** 62 * {@inheritdoc} 63 */ 64 protected function describeApplication(Application $application, array $options = []) 65 { 66 $describedNamespace = $options['namespace'] ?? null; 67 $description = new ApplicationDescription($application, $describedNamespace, true); 68 $commands = []; 69 70 foreach ($description->getCommands() as $command) { 71 $commands[] = $this->getCommandData($command); 72 } 73 74 $data = []; 75 if ('UNKNOWN' !== $application->getName()) { 76 $data['application']['name'] = $application->getName(); 77 if ('UNKNOWN' !== $application->getVersion()) { 78 $data['application']['version'] = $application->getVersion(); 79 } 80 } 81 82 $data['commands'] = $commands; 83 84 if ($describedNamespace) { 85 $data['namespace'] = $describedNamespace; 86 } else { 87 $data['namespaces'] = array_values($description->getNamespaces()); 88 } 89 90 $this->writeData($data, $options); 91 } 92 93 /** 94 * Writes data as json. 95 */ 96 private function writeData(array $data, array $options) 97 { 98 $flags = $options['json_encoding'] ?? 0; 99 100 $this->write(json_encode($data, $flags)); 101 } 102 103 private function getInputArgumentData(InputArgument $argument): array 104 { 105 return [ 106 'name' => $argument->getName(), 107 'is_required' => $argument->isRequired(), 108 'is_array' => $argument->isArray(), 109 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), 110 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), 111 ]; 112 } 113 114 private function getInputOptionData(InputOption $option): array 115 { 116 return [ 117 'name' => '--'.$option->getName(), 118 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', 119 'accept_value' => $option->acceptValue(), 120 'is_value_required' => $option->isValueRequired(), 121 'is_multiple' => $option->isArray(), 122 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), 123 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), 124 ]; 125 } 126 127 private function getInputDefinitionData(InputDefinition $definition): array 128 { 129 $inputArguments = []; 130 foreach ($definition->getArguments() as $name => $argument) { 131 $inputArguments[$name] = $this->getInputArgumentData($argument); 132 } 133 134 $inputOptions = []; 135 foreach ($definition->getOptions() as $name => $option) { 136 $inputOptions[$name] = $this->getInputOptionData($option); 137 } 138 139 return ['arguments' => $inputArguments, 'options' => $inputOptions]; 140 } 141 142 private function getCommandData(Command $command): array 143 { 144 $command->mergeApplicationDefinition(false); 145 146 return [ 147 'name' => $command->getName(), 148 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), 149 'description' => $command->getDescription(), 150 'help' => $command->getProcessedHelp(), 151 'definition' => $this->getInputDefinitionData($command->getDefinition()), 152 'hidden' => $command->isHidden(), 153 ]; 154 } 155} 156