annotate vendor/consolidation/annotated-command/src/ResultWriter.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@17 1 <?php
Chris@17 2 namespace Consolidation\AnnotatedCommand;
Chris@17 3
Chris@17 4 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ReplaceCommandHookDispatcher;
Chris@17 5 use Symfony\Component\Console\Input\InputInterface;
Chris@17 6 use Symfony\Component\Console\Output\OutputInterface;
Chris@17 7 use Symfony\Component\Console\Output\ConsoleOutputInterface;
Chris@17 8
Chris@17 9 use Consolidation\OutputFormatters\FormatterManager;
Chris@17 10 use Consolidation\OutputFormatters\Options\FormatterOptions;
Chris@17 11 use Consolidation\AnnotatedCommand\Hooks\HookManager;
Chris@17 12 use Consolidation\AnnotatedCommand\Options\PrepareFormatter;
Chris@17 13
Chris@17 14 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher;
Chris@17 15 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\OptionsHookDispatcher;
Chris@17 16 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\InteractHookDispatcher;
Chris@17 17 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ValidateHookDispatcher;
Chris@17 18 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ProcessResultHookDispatcher;
Chris@17 19 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\StatusDeterminerHookDispatcher;
Chris@17 20 use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ExtracterHookDispatcher;
Chris@17 21
Chris@17 22 /**
Chris@17 23 * Write the results of a command. Inject your ResultWriter
Chris@17 24 * into the CommandProcessor.
Chris@17 25 */
Chris@17 26 class ResultWriter
Chris@17 27 {
Chris@17 28 /** var FormatterManager */
Chris@17 29 protected $formatterManager;
Chris@17 30 /** @var callable */
Chris@17 31 protected $displayErrorFunction;
Chris@17 32
Chris@17 33 public function setFormatterManager(FormatterManager $formatterManager)
Chris@17 34 {
Chris@17 35 $this->formatterManager = $formatterManager;
Chris@17 36 return $this;
Chris@17 37 }
Chris@17 38
Chris@17 39 /**
Chris@17 40 * Return the formatter manager
Chris@17 41 * @return FormatterManager
Chris@17 42 */
Chris@17 43 public function formatterManager()
Chris@17 44 {
Chris@17 45 return $this->formatterManager;
Chris@17 46 }
Chris@17 47
Chris@17 48 public function setDisplayErrorFunction(callable $fn)
Chris@17 49 {
Chris@17 50 $this->displayErrorFunction = $fn;
Chris@17 51 return $this;
Chris@17 52 }
Chris@17 53
Chris@17 54 /**
Chris@17 55 * Handle the result output and status code calculation.
Chris@17 56 */
Chris@17 57 public function handle(OutputInterface $output, $result, CommandData $commandData, $statusCodeDispatcher = null, $extractDispatcher = null)
Chris@17 58 {
Chris@17 59 // A little messy, for backwards compatibility: if the result implements
Chris@17 60 // ExitCodeInterface, then use that as the exit code. If a status code
Chris@17 61 // dispatcher returns a non-zero result, then we will never print a
Chris@17 62 // result.
Chris@17 63 $status = null;
Chris@17 64 if ($result instanceof ExitCodeInterface) {
Chris@17 65 $status = $result->getExitCode();
Chris@17 66 } elseif (isset($statusCodeDispatcher)) {
Chris@17 67 $status = $statusCodeDispatcher->determineStatusCode($result);
Chris@17 68 if (isset($status) && ($status != 0)) {
Chris@17 69 return $status;
Chris@17 70 }
Chris@17 71 }
Chris@17 72 // If the result is an integer and no separate status code was provided, then use the result as the status and do no output.
Chris@17 73 if (is_integer($result) && !isset($status)) {
Chris@17 74 return $result;
Chris@17 75 }
Chris@17 76 $status = $this->interpretStatusCode($status);
Chris@17 77
Chris@17 78 // Get the structured output, the output stream and the formatter
Chris@17 79 $structuredOutput = $result;
Chris@17 80 if (isset($extractDispatcher)) {
Chris@17 81 $structuredOutput = $extractDispatcher->extractOutput($result);
Chris@17 82 }
Chris@17 83 if (($status != 0) && is_string($structuredOutput)) {
Chris@17 84 $output = $this->chooseOutputStream($output, $status);
Chris@17 85 return $this->writeErrorMessage($output, $status, $structuredOutput, $result);
Chris@17 86 }
Chris@17 87 if ($this->dataCanBeFormatted($structuredOutput) && isset($this->formatterManager)) {
Chris@17 88 return $this->writeUsingFormatter($output, $structuredOutput, $commandData, $status);
Chris@17 89 }
Chris@17 90 return $this->writeCommandOutput($output, $structuredOutput, $status);
Chris@17 91 }
Chris@17 92
Chris@17 93 protected function dataCanBeFormatted($structuredOutput)
Chris@17 94 {
Chris@17 95 if (!isset($this->formatterManager)) {
Chris@17 96 return false;
Chris@17 97 }
Chris@17 98 return
Chris@17 99 is_object($structuredOutput) ||
Chris@17 100 is_array($structuredOutput);
Chris@17 101 }
Chris@17 102
Chris@17 103 /**
Chris@17 104 * Determine the formatter that should be used to render
Chris@17 105 * output.
Chris@17 106 *
Chris@17 107 * If the user specified a format via the --format option,
Chris@17 108 * then always return that. Otherwise, return the default
Chris@17 109 * format, unless --pipe was specified, in which case
Chris@17 110 * return the default pipe format, format-pipe.
Chris@17 111 *
Chris@17 112 * n.b. --pipe is a handy option introduced in Drush 2
Chris@17 113 * (or perhaps even Drush 1) that indicates that the command
Chris@17 114 * should select the output format that is most appropriate
Chris@17 115 * for use in scripts (e.g. to pipe to another command).
Chris@17 116 *
Chris@17 117 * @return string
Chris@17 118 */
Chris@17 119 protected function getFormat(FormatterOptions $options)
Chris@17 120 {
Chris@17 121 // In Symfony Console, there is no way for us to differentiate
Chris@17 122 // between the user specifying '--format=table', and the user
Chris@17 123 // not specifying --format when the default value is 'table'.
Chris@17 124 // Therefore, we must make --field always override --format; it
Chris@17 125 // cannot become the default value for --format.
Chris@17 126 if ($options->get('field')) {
Chris@17 127 return 'string';
Chris@17 128 }
Chris@17 129 $defaults = [];
Chris@17 130 if ($options->get('pipe')) {
Chris@17 131 return $options->get('pipe-format', [], 'tsv');
Chris@17 132 }
Chris@17 133 return $options->getFormat($defaults);
Chris@17 134 }
Chris@17 135
Chris@17 136 /**
Chris@17 137 * Determine whether we should use stdout or stderr.
Chris@17 138 */
Chris@17 139 protected function chooseOutputStream(OutputInterface $output, $status)
Chris@17 140 {
Chris@17 141 // If the status code indicates an error, then print the
Chris@17 142 // result to stderr rather than stdout
Chris@17 143 if ($status && ($output instanceof ConsoleOutputInterface)) {
Chris@17 144 return $output->getErrorOutput();
Chris@17 145 }
Chris@17 146 return $output;
Chris@17 147 }
Chris@17 148
Chris@17 149 /**
Chris@17 150 * Call the formatter to output the provided data.
Chris@17 151 */
Chris@17 152 protected function writeUsingFormatter(OutputInterface $output, $structuredOutput, CommandData $commandData, $status = 0)
Chris@17 153 {
Chris@17 154 $formatterOptions = $commandData->formatterOptions();
Chris@17 155 $format = $this->getFormat($formatterOptions);
Chris@17 156 $this->formatterManager->write(
Chris@17 157 $output,
Chris@17 158 $format,
Chris@17 159 $structuredOutput,
Chris@17 160 $formatterOptions
Chris@17 161 );
Chris@17 162 return $status;
Chris@17 163 }
Chris@17 164
Chris@17 165 /**
Chris@17 166 * Description
Chris@17 167 * @param OutputInterface $output
Chris@17 168 * @param int $status
Chris@17 169 * @param string $structuredOutput
Chris@17 170 * @param mixed $originalResult
Chris@17 171 * @return type
Chris@17 172 */
Chris@17 173 protected function writeErrorMessage($output, $status, $structuredOutput, $originalResult)
Chris@17 174 {
Chris@17 175 if (isset($this->displayErrorFunction)) {
Chris@17 176 call_user_func($this->displayErrorFunction, $output, $structuredOutput, $status, $originalResult);
Chris@17 177 } else {
Chris@17 178 $this->writeCommandOutput($output, $structuredOutput);
Chris@17 179 }
Chris@17 180 return $status;
Chris@17 181 }
Chris@17 182
Chris@17 183 /**
Chris@17 184 * If the result object is a string, then print it.
Chris@17 185 */
Chris@17 186 protected function writeCommandOutput(
Chris@17 187 OutputInterface $output,
Chris@17 188 $structuredOutput,
Chris@17 189 $status = 0
Chris@17 190 ) {
Chris@17 191 // If there is no formatter, we will print strings,
Chris@17 192 // but can do no more than that.
Chris@17 193 if (is_string($structuredOutput)) {
Chris@17 194 $output->writeln($structuredOutput);
Chris@17 195 }
Chris@17 196 return $status;
Chris@17 197 }
Chris@17 198
Chris@17 199 /**
Chris@17 200 * If a status code was set, then return it; otherwise,
Chris@17 201 * presume success.
Chris@17 202 */
Chris@17 203 protected function interpretStatusCode($status)
Chris@17 204 {
Chris@17 205 if (isset($status)) {
Chris@17 206 return $status;
Chris@17 207 }
Chris@17 208 return 0;
Chris@17 209 }
Chris@17 210 }