Chris@0: getName(); Chris@0: } Chris@0: } Chris@0: parent::__construct($name); Chris@0: if ($commandInfo && $commandInfo->hasAnnotation('command')) { Chris@0: $this->setCommandInfo($commandInfo); Chris@0: $this->setCommandOptions($commandInfo); Chris@0: } Chris@0: } Chris@0: Chris@0: public function setCommandCallback($commandCallback) Chris@0: { Chris@0: $this->commandCallback = $commandCallback; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function setCommandProcessor($commandProcessor) Chris@0: { Chris@0: $this->commandProcessor = $commandProcessor; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function commandProcessor() Chris@0: { Chris@0: // If someone is using an AnnotatedCommand, and is NOT getting Chris@0: // it from an AnnotatedCommandFactory OR not correctly injecting Chris@0: // a command processor via setCommandProcessor() (ideally via the Chris@0: // DI container), then we'll just give each annotated command its Chris@0: // own command processor. This is not ideal; preferably, there would Chris@0: // only be one instance of the command processor in the application. Chris@0: if (!isset($this->commandProcessor)) { Chris@0: $this->commandProcessor = new CommandProcessor(new HookManager()); Chris@0: } Chris@0: return $this->commandProcessor; Chris@0: } Chris@0: Chris@0: public function getReturnType() Chris@0: { Chris@0: return $this->returnType; Chris@0: } Chris@0: Chris@0: public function setReturnType($returnType) Chris@0: { Chris@0: $this->returnType = $returnType; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function getAnnotationData() Chris@0: { Chris@0: return $this->annotationData; Chris@0: } Chris@0: Chris@0: public function setAnnotationData($annotationData) Chris@0: { Chris@0: $this->annotationData = $annotationData; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function getTopics() Chris@0: { Chris@0: return $this->topics; Chris@0: } Chris@0: Chris@0: public function setTopics($topics) Chris@0: { Chris@0: $this->topics = $topics; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function setCommandInfo($commandInfo) Chris@0: { Chris@0: $this->setDescription($commandInfo->getDescription()); Chris@0: $this->setHelp($commandInfo->getHelp()); Chris@0: $this->setAliases($commandInfo->getAliases()); Chris@0: $this->setAnnotationData($commandInfo->getAnnotations()); Chris@0: $this->setTopics($commandInfo->getTopics()); Chris@0: foreach ($commandInfo->getExampleUsages() as $usage => $description) { Chris@0: $this->addUsageOrExample($usage, $description); Chris@0: } Chris@0: $this->setCommandArguments($commandInfo); Chris@0: $this->setReturnType($commandInfo->getReturnType()); Chris@0: // Hidden commands available since Symfony 3.2 Chris@0: // http://symfony.com/doc/current/console/hide_commands.html Chris@0: if (method_exists($this, 'setHidden')) { Chris@0: $this->setHidden($commandInfo->getHidden()); Chris@0: } Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function getExampleUsages() Chris@0: { Chris@0: return $this->examples; Chris@0: } Chris@0: Chris@0: protected function addUsageOrExample($usage, $description) Chris@0: { Chris@0: $this->addUsage($usage); Chris@0: if (!empty($description)) { Chris@0: $this->examples[$usage] = $description; Chris@0: } Chris@0: } Chris@0: Chris@0: public function helpAlter(\DomDocument $originalDom) Chris@0: { Chris@17: return HelpDocumentBuilder::alter($originalDom, $this); Chris@0: } Chris@0: Chris@0: protected function setCommandArguments($commandInfo) Chris@0: { Chris@17: $this->injectedClasses = $commandInfo->getInjectedClasses(); Chris@0: $this->setCommandArgumentsFromParameters($commandInfo); Chris@0: return $this; Chris@0: } Chris@0: Chris@0: protected function setCommandArgumentsFromParameters($commandInfo) Chris@0: { Chris@0: $args = $commandInfo->arguments()->getValues(); Chris@0: foreach ($args as $name => $defaultValue) { Chris@0: $description = $commandInfo->arguments()->getDescription($name); Chris@0: $hasDefault = $commandInfo->arguments()->hasDefault($name); Chris@0: $parameterMode = $this->getCommandArgumentMode($hasDefault, $defaultValue); Chris@0: $this->addArgument($name, $parameterMode, $description, $defaultValue); Chris@0: } Chris@0: return $this; Chris@0: } Chris@0: Chris@0: protected function getCommandArgumentMode($hasDefault, $defaultValue) Chris@0: { Chris@0: if (!$hasDefault) { Chris@0: return InputArgument::REQUIRED; Chris@0: } Chris@0: if (is_array($defaultValue)) { Chris@0: return InputArgument::IS_ARRAY; Chris@0: } Chris@0: return InputArgument::OPTIONAL; Chris@0: } Chris@0: Chris@0: public function setCommandOptions($commandInfo, $automaticOptions = []) Chris@0: { Chris@0: $inputOptions = $commandInfo->inputOptions(); Chris@0: Chris@0: $this->addOptions($inputOptions + $automaticOptions, $automaticOptions); Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function addOptions($inputOptions, $automaticOptions = []) Chris@0: { Chris@0: foreach ($inputOptions as $name => $inputOption) { Chris@0: $description = $inputOption->getDescription(); Chris@0: Chris@0: if (empty($description) && isset($automaticOptions[$name])) { Chris@0: $description = $automaticOptions[$name]->getDescription(); Chris@0: $inputOption = static::inputOptionSetDescription($inputOption, $description); Chris@0: } Chris@0: $this->getDefinition()->addOption($inputOption); Chris@0: } Chris@0: } Chris@0: Chris@0: protected static function inputOptionSetDescription($inputOption, $description) Chris@0: { Chris@0: // Recover the 'mode' value, because Symfony is stubborn Chris@0: $mode = 0; Chris@0: if ($inputOption->isValueRequired()) { Chris@0: $mode |= InputOption::VALUE_REQUIRED; Chris@0: } Chris@0: if ($inputOption->isValueOptional()) { Chris@0: $mode |= InputOption::VALUE_OPTIONAL; Chris@0: } Chris@0: if ($inputOption->isArray()) { Chris@0: $mode |= InputOption::VALUE_IS_ARRAY; Chris@0: } Chris@0: if (!$mode) { Chris@0: $mode = InputOption::VALUE_NONE; Chris@0: } Chris@0: Chris@0: $inputOption = new InputOption( Chris@0: $inputOption->getName(), Chris@0: $inputOption->getShortcut(), Chris@0: $mode, Chris@0: $description, Chris@0: $inputOption->getDefault() Chris@0: ); Chris@0: return $inputOption; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns all of the hook names that may be called for this command. Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: public function getNames() Chris@0: { Chris@0: return HookManager::getNames($this, $this->commandCallback); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Add any options to this command that are defined by hook implementations Chris@0: */ Chris@0: public function optionsHook() Chris@0: { Chris@0: $this->commandProcessor()->optionsHook( Chris@0: $this, Chris@0: $this->getNames(), Chris@0: $this->annotationData Chris@0: ); Chris@0: } Chris@0: Chris@0: public function optionsHookForHookAnnotations($commandInfoList) Chris@0: { Chris@0: foreach ($commandInfoList as $commandInfo) { Chris@0: $inputOptions = $commandInfo->inputOptions(); Chris@0: $this->addOptions($inputOptions); Chris@0: foreach ($commandInfo->getExampleUsages() as $usage => $description) { Chris@0: if (!in_array($usage, $this->getUsages())) { Chris@0: $this->addUsageOrExample($usage, $description); Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function interact(InputInterface $input, OutputInterface $output) Chris@0: { Chris@0: $this->commandProcessor()->interact( Chris@0: $input, Chris@0: $output, Chris@0: $this->getNames(), Chris@0: $this->annotationData Chris@0: ); Chris@0: } Chris@0: Chris@0: protected function initialize(InputInterface $input, OutputInterface $output) Chris@0: { Chris@0: // Allow the hook manager a chance to provide configuration values, Chris@0: // if there are any registered hooks to do that. Chris@0: $this->commandProcessor()->initializeHook($input, $this->getNames(), $this->annotationData); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function execute(InputInterface $input, OutputInterface $output) Chris@0: { Chris@0: // Validate, run, process, alter, handle results. Chris@0: return $this->commandProcessor()->process( Chris@0: $output, Chris@0: $this->getNames(), Chris@0: $this->commandCallback, Chris@0: $this->createCommandData($input, $output) Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * This function is available for use by a class that may Chris@0: * wish to extend this class rather than use annotations to Chris@0: * define commands. Using this technique does allow for the Chris@0: * use of annotations to define hooks. Chris@0: */ Chris@0: public function processResults(InputInterface $input, OutputInterface $output, $results) Chris@0: { Chris@0: $commandData = $this->createCommandData($input, $output); Chris@0: $commandProcessor = $this->commandProcessor(); Chris@0: $names = $this->getNames(); Chris@0: $results = $commandProcessor->processResults( Chris@0: $names, Chris@0: $results, Chris@0: $commandData Chris@0: ); Chris@0: return $commandProcessor->handleResults( Chris@0: $output, Chris@0: $names, Chris@0: $results, Chris@0: $commandData Chris@0: ); Chris@0: } Chris@0: Chris@0: protected function createCommandData(InputInterface $input, OutputInterface $output) Chris@0: { Chris@0: $commandData = new CommandData( Chris@0: $this->annotationData, Chris@0: $input, Chris@0: $output Chris@0: ); Chris@0: Chris@17: // Fetch any classes (e.g. InputInterface / OutputInterface) that Chris@17: // this command's callback wants passed as a parameter and inject Chris@17: // it into the command data. Chris@17: $this->commandProcessor()->injectIntoCommandData($commandData, $this->injectedClasses); Chris@0: Chris@0: // Allow the commandData to cache the list of options with Chris@0: // special default values ('null' and 'true'), as these will Chris@0: // need special handling. @see CommandData::options(). Chris@0: $commandData->cacheSpecialDefaults($this->getDefinition()); Chris@0: Chris@0: return $commandData; Chris@0: } Chris@0: }