MarkdownDescriptor.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Console\Descriptor;
  11. use Symfony\Component\Console\Application;
  12. use Symfony\Component\Console\Command\Command;
  13. use Symfony\Component\Console\Helper\Helper;
  14. use Symfony\Component\Console\Input\InputArgument;
  15. use Symfony\Component\Console\Input\InputDefinition;
  16. use Symfony\Component\Console\Input\InputOption;
  17. use Symfony\Component\Console\Output\OutputInterface;
  18. /**
  19. * Markdown descriptor.
  20. *
  21. * @author Jean-François Simon <contact@jfsimon.fr>
  22. *
  23. * @internal
  24. */
  25. class MarkdownDescriptor extends Descriptor
  26. {
  27. /**
  28. * {@inheritdoc}
  29. */
  30. public function describe(OutputInterface $output, $object, array $options = [])
  31. {
  32. $decorated = $output->isDecorated();
  33. $output->setDecorated(false);
  34. parent::describe($output, $object, $options);
  35. $output->setDecorated($decorated);
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. protected function write(string $content, bool $decorated = true)
  41. {
  42. parent::write($content, $decorated);
  43. }
  44. /**
  45. * {@inheritdoc}
  46. */
  47. protected function describeInputArgument(InputArgument $argument, array $options = [])
  48. {
  49. $this->write(
  50. '#### `'.($argument->getName() ?: '<none>')."`\n\n"
  51. .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '')
  52. .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
  53. .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
  54. .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
  55. );
  56. }
  57. /**
  58. * {@inheritdoc}
  59. */
  60. protected function describeInputOption(InputOption $option, array $options = [])
  61. {
  62. $name = '--'.$option->getName();
  63. if ($option->getShortcut()) {
  64. $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).'';
  65. }
  66. $this->write(
  67. '#### `'.$name.'`'."\n\n"
  68. .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '')
  69. .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
  70. .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
  71. .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
  72. .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
  73. );
  74. }
  75. /**
  76. * {@inheritdoc}
  77. */
  78. protected function describeInputDefinition(InputDefinition $definition, array $options = [])
  79. {
  80. if ($showArguments = \count($definition->getArguments()) > 0) {
  81. $this->write('### Arguments');
  82. foreach ($definition->getArguments() as $argument) {
  83. $this->write("\n\n");
  84. if (null !== $describeInputArgument = $this->describeInputArgument($argument)) {
  85. $this->write($describeInputArgument);
  86. }
  87. }
  88. }
  89. if (\count($definition->getOptions()) > 0) {
  90. if ($showArguments) {
  91. $this->write("\n\n");
  92. }
  93. $this->write('### Options');
  94. foreach ($definition->getOptions() as $option) {
  95. $this->write("\n\n");
  96. if (null !== $describeInputOption = $this->describeInputOption($option)) {
  97. $this->write($describeInputOption);
  98. }
  99. }
  100. }
  101. }
  102. /**
  103. * {@inheritdoc}
  104. */
  105. protected function describeCommand(Command $command, array $options = [])
  106. {
  107. $command->mergeApplicationDefinition(false);
  108. $this->write(
  109. '`'.$command->getName()."`\n"
  110. .str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n"
  111. .($command->getDescription() ? $command->getDescription()."\n\n" : '')
  112. .'### Usage'."\n\n"
  113. .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
  114. return $carry.'* `'.$usage.'`'."\n";
  115. })
  116. );
  117. if ($help = $command->getProcessedHelp()) {
  118. $this->write("\n");
  119. $this->write($help);
  120. }
  121. $definition = $command->getDefinition();
  122. if ($definition->getOptions() || $definition->getArguments()) {
  123. $this->write("\n\n");
  124. $this->describeInputDefinition($definition);
  125. }
  126. }
  127. /**
  128. * {@inheritdoc}
  129. */
  130. protected function describeApplication(Application $application, array $options = [])
  131. {
  132. $describedNamespace = $options['namespace'] ?? null;
  133. $description = new ApplicationDescription($application, $describedNamespace);
  134. $title = $this->getApplicationTitle($application);
  135. $this->write($title."\n".str_repeat('=', Helper::strlen($title)));
  136. foreach ($description->getNamespaces() as $namespace) {
  137. if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
  138. $this->write("\n\n");
  139. $this->write('**'.$namespace['id'].':**');
  140. }
  141. $this->write("\n\n");
  142. $this->write(implode("\n", array_map(function ($commandName) use ($description) {
  143. return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName()));
  144. }, $namespace['commands'])));
  145. }
  146. foreach ($description->getCommands() as $command) {
  147. $this->write("\n\n");
  148. if (null !== $describeCommand = $this->describeCommand($command)) {
  149. $this->write($describeCommand);
  150. }
  151. }
  152. }
  153. private function getApplicationTitle(Application $application): string
  154. {
  155. if ('UNKNOWN' !== $application->getName()) {
  156. if ('UNKNOWN' !== $application->getVersion()) {
  157. return sprintf('%s %s', $application->getName(), $application->getVersion());
  158. }
  159. return $application->getName();
  160. }
  161. return 'Console Tool';
  162. }
  163. }