Chris@17: formatterManager = $formatterManager; Chris@17: return $this; Chris@17: } Chris@17: Chris@17: /** Chris@17: * Return the formatter manager Chris@17: * @return FormatterManager Chris@17: */ Chris@17: public function formatterManager() Chris@17: { Chris@17: return $this->formatterManager; Chris@17: } Chris@17: Chris@17: public function setDisplayErrorFunction(callable $fn) Chris@17: { Chris@17: $this->displayErrorFunction = $fn; Chris@17: return $this; Chris@17: } Chris@17: Chris@17: /** Chris@17: * Handle the result output and status code calculation. Chris@17: */ Chris@17: public function handle(OutputInterface $output, $result, CommandData $commandData, $statusCodeDispatcher = null, $extractDispatcher = null) Chris@17: { Chris@17: // A little messy, for backwards compatibility: if the result implements Chris@17: // ExitCodeInterface, then use that as the exit code. If a status code Chris@17: // dispatcher returns a non-zero result, then we will never print a Chris@17: // result. Chris@17: $status = null; Chris@17: if ($result instanceof ExitCodeInterface) { Chris@17: $status = $result->getExitCode(); Chris@17: } elseif (isset($statusCodeDispatcher)) { Chris@17: $status = $statusCodeDispatcher->determineStatusCode($result); Chris@17: if (isset($status) && ($status != 0)) { Chris@17: return $status; Chris@17: } Chris@17: } Chris@17: // 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: if (is_integer($result) && !isset($status)) { Chris@17: return $result; Chris@17: } Chris@17: $status = $this->interpretStatusCode($status); Chris@17: Chris@17: // Get the structured output, the output stream and the formatter Chris@17: $structuredOutput = $result; Chris@17: if (isset($extractDispatcher)) { Chris@17: $structuredOutput = $extractDispatcher->extractOutput($result); Chris@17: } Chris@17: if (($status != 0) && is_string($structuredOutput)) { Chris@17: $output = $this->chooseOutputStream($output, $status); Chris@17: return $this->writeErrorMessage($output, $status, $structuredOutput, $result); Chris@17: } Chris@17: if ($this->dataCanBeFormatted($structuredOutput) && isset($this->formatterManager)) { Chris@17: return $this->writeUsingFormatter($output, $structuredOutput, $commandData, $status); Chris@17: } Chris@17: return $this->writeCommandOutput($output, $structuredOutput, $status); Chris@17: } Chris@17: Chris@17: protected function dataCanBeFormatted($structuredOutput) Chris@17: { Chris@17: if (!isset($this->formatterManager)) { Chris@17: return false; Chris@17: } Chris@17: return Chris@17: is_object($structuredOutput) || Chris@17: is_array($structuredOutput); Chris@17: } Chris@17: Chris@17: /** Chris@17: * Determine the formatter that should be used to render Chris@17: * output. Chris@17: * Chris@17: * If the user specified a format via the --format option, Chris@17: * then always return that. Otherwise, return the default Chris@17: * format, unless --pipe was specified, in which case Chris@17: * return the default pipe format, format-pipe. Chris@17: * Chris@17: * n.b. --pipe is a handy option introduced in Drush 2 Chris@17: * (or perhaps even Drush 1) that indicates that the command Chris@17: * should select the output format that is most appropriate Chris@17: * for use in scripts (e.g. to pipe to another command). Chris@17: * Chris@17: * @return string Chris@17: */ Chris@17: protected function getFormat(FormatterOptions $options) Chris@17: { Chris@17: // In Symfony Console, there is no way for us to differentiate Chris@17: // between the user specifying '--format=table', and the user Chris@17: // not specifying --format when the default value is 'table'. Chris@17: // Therefore, we must make --field always override --format; it Chris@17: // cannot become the default value for --format. Chris@17: if ($options->get('field')) { Chris@17: return 'string'; Chris@17: } Chris@17: $defaults = []; Chris@17: if ($options->get('pipe')) { Chris@17: return $options->get('pipe-format', [], 'tsv'); Chris@17: } Chris@17: return $options->getFormat($defaults); Chris@17: } Chris@17: Chris@17: /** Chris@17: * Determine whether we should use stdout or stderr. Chris@17: */ Chris@17: protected function chooseOutputStream(OutputInterface $output, $status) Chris@17: { Chris@17: // If the status code indicates an error, then print the Chris@17: // result to stderr rather than stdout Chris@17: if ($status && ($output instanceof ConsoleOutputInterface)) { Chris@17: return $output->getErrorOutput(); Chris@17: } Chris@17: return $output; Chris@17: } Chris@17: Chris@17: /** Chris@17: * Call the formatter to output the provided data. Chris@17: */ Chris@17: protected function writeUsingFormatter(OutputInterface $output, $structuredOutput, CommandData $commandData, $status = 0) Chris@17: { Chris@17: $formatterOptions = $commandData->formatterOptions(); Chris@17: $format = $this->getFormat($formatterOptions); Chris@17: $this->formatterManager->write( Chris@17: $output, Chris@17: $format, Chris@17: $structuredOutput, Chris@17: $formatterOptions Chris@17: ); Chris@17: return $status; Chris@17: } Chris@17: Chris@17: /** Chris@17: * Description Chris@17: * @param OutputInterface $output Chris@17: * @param int $status Chris@17: * @param string $structuredOutput Chris@17: * @param mixed $originalResult Chris@17: * @return type Chris@17: */ Chris@17: protected function writeErrorMessage($output, $status, $structuredOutput, $originalResult) Chris@17: { Chris@17: if (isset($this->displayErrorFunction)) { Chris@17: call_user_func($this->displayErrorFunction, $output, $structuredOutput, $status, $originalResult); Chris@17: } else { Chris@17: $this->writeCommandOutput($output, $structuredOutput); Chris@17: } Chris@17: return $status; Chris@17: } Chris@17: Chris@17: /** Chris@17: * If the result object is a string, then print it. Chris@17: */ Chris@17: protected function writeCommandOutput( Chris@17: OutputInterface $output, Chris@17: $structuredOutput, Chris@17: $status = 0 Chris@17: ) { Chris@17: // If there is no formatter, we will print strings, Chris@17: // but can do no more than that. Chris@17: if (is_string($structuredOutput)) { Chris@17: $output->writeln($structuredOutput); Chris@17: } Chris@17: return $status; Chris@17: } Chris@17: Chris@17: /** Chris@17: * If a status code was set, then return it; otherwise, Chris@17: * presume success. Chris@17: */ Chris@17: protected function interpretStatusCode($status) Chris@17: { Chris@17: if (isset($status)) { Chris@17: return $status; Chris@17: } Chris@17: return 0; Chris@17: } Chris@17: }