Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\Console\Descriptor; Chris@0: Chris@0: use Symfony\Component\Console\Application; Chris@0: use Symfony\Component\Console\Command\Command; Chris@0: use Symfony\Component\Console\Formatter\OutputFormatter; Chris@0: use Symfony\Component\Console\Helper\Helper; Chris@0: use Symfony\Component\Console\Input\InputArgument; Chris@0: use Symfony\Component\Console\Input\InputDefinition; Chris@0: use Symfony\Component\Console\Input\InputOption; Chris@0: Chris@0: /** Chris@0: * Text descriptor. Chris@0: * Chris@0: * @author Jean-François Simon Chris@0: * Chris@0: * @internal Chris@0: */ Chris@0: class TextDescriptor extends Descriptor Chris@0: { Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function describeInputArgument(InputArgument $argument, array $options = array()) Chris@0: { Chris@0: if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { Chris@0: $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); Chris@0: } else { Chris@0: $default = ''; Chris@0: } Chris@0: Chris@0: $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); Chris@0: $spacingWidth = $totalWidth - strlen($argument->getName()); Chris@0: Chris@0: $this->writeText(sprintf(' %s %s%s%s', Chris@0: $argument->getName(), Chris@0: str_repeat(' ', $spacingWidth), Chris@0: // + 4 = 2 spaces before , 2 spaces after Chris@0: preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), Chris@0: $default Chris@0: ), $options); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function describeInputOption(InputOption $option, array $options = array()) Chris@0: { Chris@0: if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { Chris@0: $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); Chris@0: } else { Chris@0: $default = ''; Chris@0: } Chris@0: Chris@0: $value = ''; Chris@0: if ($option->acceptValue()) { Chris@0: $value = '='.strtoupper($option->getName()); Chris@0: Chris@0: if ($option->isValueOptional()) { Chris@0: $value = '['.$value.']'; Chris@0: } Chris@0: } Chris@0: Chris@0: $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option)); Chris@0: $synopsis = sprintf('%s%s', Chris@0: $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', Chris@0: sprintf('--%s%s', $option->getName(), $value) Chris@0: ); Chris@0: Chris@0: $spacingWidth = $totalWidth - Helper::strlen($synopsis); Chris@0: Chris@0: $this->writeText(sprintf(' %s %s%s%s%s', Chris@0: $synopsis, Chris@0: str_repeat(' ', $spacingWidth), Chris@0: // + 4 = 2 spaces before , 2 spaces after Chris@0: preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), Chris@0: $default, Chris@0: $option->isArray() ? ' (multiple values allowed)' : '' Chris@0: ), $options); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function describeInputDefinition(InputDefinition $definition, array $options = array()) Chris@0: { Chris@0: $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); Chris@0: foreach ($definition->getArguments() as $argument) { Chris@0: $totalWidth = max($totalWidth, Helper::strlen($argument->getName())); Chris@0: } Chris@0: Chris@0: if ($definition->getArguments()) { Chris@0: $this->writeText('Arguments:', $options); Chris@0: $this->writeText("\n"); Chris@0: foreach ($definition->getArguments() as $argument) { Chris@0: $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth))); Chris@0: $this->writeText("\n"); Chris@0: } Chris@0: } Chris@0: Chris@0: if ($definition->getArguments() && $definition->getOptions()) { Chris@0: $this->writeText("\n"); Chris@0: } Chris@0: Chris@0: if ($definition->getOptions()) { Chris@0: $laterOptions = array(); Chris@0: Chris@0: $this->writeText('Options:', $options); Chris@0: foreach ($definition->getOptions() as $option) { Chris@0: if (strlen($option->getShortcut()) > 1) { Chris@0: $laterOptions[] = $option; Chris@0: continue; Chris@0: } Chris@0: $this->writeText("\n"); Chris@0: $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth))); Chris@0: } Chris@0: foreach ($laterOptions as $option) { Chris@0: $this->writeText("\n"); Chris@0: $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth))); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function describeCommand(Command $command, array $options = array()) Chris@0: { Chris@0: $command->getSynopsis(true); Chris@0: $command->getSynopsis(false); Chris@0: $command->mergeApplicationDefinition(false); Chris@0: Chris@0: $this->writeText('Usage:', $options); Chris@0: foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) { Chris@0: $this->writeText("\n"); Chris@0: $this->writeText(' '.$usage, $options); Chris@0: } Chris@0: $this->writeText("\n"); Chris@0: Chris@0: $definition = $command->getNativeDefinition(); Chris@0: if ($definition->getOptions() || $definition->getArguments()) { Chris@0: $this->writeText("\n"); Chris@0: $this->describeInputDefinition($definition, $options); Chris@0: $this->writeText("\n"); Chris@0: } Chris@0: Chris@0: if ($help = $command->getProcessedHelp()) { Chris@0: $this->writeText("\n"); Chris@0: $this->writeText('Help:', $options); Chris@0: $this->writeText("\n"); Chris@0: $this->writeText(' '.str_replace("\n", "\n ", $help), $options); Chris@0: $this->writeText("\n"); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function describeApplication(Application $application, array $options = array()) Chris@0: { Chris@0: $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; Chris@0: $description = new ApplicationDescription($application, $describedNamespace); Chris@0: Chris@0: if (isset($options['raw_text']) && $options['raw_text']) { Chris@0: $width = $this->getColumnWidth($description->getCommands()); Chris@0: Chris@0: foreach ($description->getCommands() as $command) { Chris@0: $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); Chris@0: $this->writeText("\n"); Chris@0: } Chris@0: } else { Chris@0: if ('' != $help = $application->getHelp()) { Chris@0: $this->writeText("$help\n\n", $options); Chris@0: } Chris@0: Chris@0: $this->writeText("Usage:\n", $options); Chris@0: $this->writeText(" command [options] [arguments]\n\n", $options); Chris@0: Chris@0: $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); Chris@0: Chris@0: $this->writeText("\n"); Chris@0: $this->writeText("\n"); Chris@0: Chris@0: $width = $this->getColumnWidth($description->getCommands()); Chris@0: Chris@0: if ($describedNamespace) { Chris@0: $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); Chris@0: } else { Chris@0: $this->writeText('Available commands:', $options); Chris@0: } Chris@0: Chris@0: // add commands by namespace Chris@0: $commands = $description->getCommands(); Chris@0: Chris@0: foreach ($description->getNamespaces() as $namespace) { Chris@0: if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { Chris@0: $this->writeText("\n"); Chris@0: $this->writeText(' '.$namespace['id'].'', $options); Chris@0: } Chris@0: Chris@0: foreach ($namespace['commands'] as $name) { Chris@0: if (isset($commands[$name])) { Chris@0: $this->writeText("\n"); Chris@0: $spacingWidth = $width - Helper::strlen($name); Chris@0: $command = $commands[$name]; Chris@0: $commandAliases = $this->getCommandAliasesText($command); Chris@0: $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: $this->writeText("\n"); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: private function writeText($content, array $options = array()) Chris@0: { Chris@0: $this->write( Chris@0: isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, Chris@0: isset($options['raw_output']) ? !$options['raw_output'] : true Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Formats command aliases to show them in the command description. Chris@0: * Chris@0: * @param Command $command Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: private function getCommandAliasesText($command) Chris@0: { Chris@0: $text = ''; Chris@0: $aliases = $command->getAliases(); Chris@0: Chris@0: if ($aliases) { Chris@0: $text = '['.implode('|', $aliases).'] '; Chris@0: } Chris@0: Chris@0: return $text; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Formats input option/argument default value. Chris@0: * Chris@0: * @param mixed $default Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: private function formatDefaultValue($default) Chris@0: { Chris@0: if (is_string($default)) { Chris@0: $default = OutputFormatter::escape($default); Chris@0: } elseif (is_array($default)) { Chris@0: foreach ($default as $key => $value) { Chris@0: if (is_string($value)) { Chris@0: $default[$key] = OutputFormatter::escape($value); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param Command[] $commands Chris@0: * Chris@0: * @return int Chris@0: */ Chris@0: private function getColumnWidth(array $commands) Chris@0: { Chris@0: $widths = array(); Chris@0: Chris@0: foreach ($commands as $command) { Chris@0: $widths[] = Helper::strlen($command->getName()); Chris@0: foreach ($command->getAliases() as $alias) { Chris@0: $widths[] = Helper::strlen($alias); Chris@0: } Chris@0: } Chris@0: Chris@0: return max($widths) + 2; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param InputOption[] $options Chris@0: * Chris@0: * @return int Chris@0: */ Chris@0: private function calculateTotalWidthForOptions($options) Chris@0: { Chris@0: $totalWidth = 0; Chris@0: foreach ($options as $option) { Chris@0: // "-" + shortcut + ", --" + name Chris@0: $nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName()); Chris@0: Chris@0: if ($option->acceptValue()) { Chris@0: $valueLength = 1 + Helper::strlen($option->getName()); // = + value Chris@0: $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] Chris@0: Chris@0: $nameLength += $valueLength; Chris@0: } Chris@0: $totalWidth = max($totalWidth, $nameLength); Chris@0: } Chris@0: Chris@0: return $totalWidth; Chris@0: } Chris@0: }