[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <[email protected]> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\Console\Command; 13 14 use Symfony\Component\Console\Completion\CompletionInput; 15 use Symfony\Component\Console\Completion\CompletionSuggestions; 16 use Symfony\Component\Console\Completion\Output\BashCompletionOutput; 17 use Symfony\Component\Console\Completion\Output\CompletionOutputInterface; 18 use Symfony\Component\Console\Exception\CommandNotFoundException; 19 use Symfony\Component\Console\Exception\ExceptionInterface; 20 use Symfony\Component\Console\Input\InputInterface; 21 use Symfony\Component\Console\Input\InputOption; 22 use Symfony\Component\Console\Output\OutputInterface; 23 24 /** 25 * Responsible for providing the values to the shell completion. 26 * 27 * @author Wouter de Jong <[email protected]> 28 */ 29 final class CompleteCommand extends Command 30 { 31 protected static $defaultName = '|_complete'; 32 protected static $defaultDescription = 'Internal command to provide shell completion suggestions'; 33 34 private $completionOutputs; 35 36 private $isDebug = false; 37 38 /** 39 * @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value 40 */ 41 public function __construct(array $completionOutputs = []) 42 { 43 // must be set before the parent constructor, as the property value is used in configure() 44 $this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class]; 45 46 parent::__construct(); 47 } 48 49 protected function configure(): void 50 { 51 $this 52 ->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")') 53 ->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)') 54 ->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)') 55 ->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'The version of the completion script') 56 ; 57 } 58 59 protected function initialize(InputInterface $input, OutputInterface $output) 60 { 61 $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOLEAN); 62 } 63 64 protected function execute(InputInterface $input, OutputInterface $output): int 65 { 66 try { 67 // uncomment when a bugfix or BC break has been introduced in the shell completion scripts 68 //$version = $input->getOption('symfony'); 69 //if ($version && version_compare($version, 'x.y', '>=')) { 70 // $message = sprintf('Completion script version is not supported ("%s" given, ">=x.y" required).', $version); 71 // $this->log($message); 72 73 // $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.'); 74 75 // return 126; 76 //} 77 78 $shell = $input->getOption('shell'); 79 if (!$shell) { 80 throw new \RuntimeException('The "--shell" option must be set.'); 81 } 82 83 if (!$completionOutput = $this->completionOutputs[$shell] ?? false) { 84 throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs)))); 85 } 86 87 $completionInput = $this->createCompletionInput($input); 88 $suggestions = new CompletionSuggestions(); 89 90 $this->log([ 91 '', 92 '<comment>'.date('Y-m-d H:i:s').'</>', 93 '<info>Input:</> <comment>("|" indicates the cursor position)</>', 94 ' '.(string) $completionInput, 95 '<info>Command:</>', 96 ' '.(string) implode(' ', $_SERVER['argv']), 97 '<info>Messages:</>', 98 ]); 99 100 $command = $this->findCommand($completionInput, $output); 101 if (null === $command) { 102 $this->log(' No command found, completing using the Application class.'); 103 104 $this->getApplication()->complete($completionInput, $suggestions); 105 } elseif ( 106 $completionInput->mustSuggestArgumentValuesFor('command') 107 && $command->getName() !== $completionInput->getCompletionValue() 108 ) { 109 $this->log(' No command found, completing using the Application class.'); 110 111 // expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear") 112 $suggestions->suggestValue($command->getName()); 113 } else { 114 $command->mergeApplicationDefinition(); 115 $completionInput->bind($command->getDefinition()); 116 117 if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) { 118 $this->log(' Completing option names for the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> command.'); 119 120 $suggestions->suggestOptions($command->getDefinition()->getOptions()); 121 } else { 122 $this->log([ 123 ' Completing using the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> class.', 124 ' Completing <comment>'.$completionInput->getCompletionType().'</> for <comment>'.$completionInput->getCompletionName().'</>', 125 ]); 126 if (null !== $compval = $completionInput->getCompletionValue()) { 127 $this->log(' Current value: <comment>'.$compval.'</>'); 128 } 129 130 $command->complete($completionInput, $suggestions); 131 } 132 } 133 134 /** @var CompletionOutputInterface $completionOutput */ 135 $completionOutput = new $completionOutput(); 136 137 $this->log('<info>Suggestions:</>'); 138 if ($options = $suggestions->getOptionSuggestions()) { 139 $this->log(' --'.implode(' --', array_map(function ($o) { return $o->getName(); }, $options))); 140 } elseif ($values = $suggestions->getValueSuggestions()) { 141 $this->log(' '.implode(' ', $values)); 142 } else { 143 $this->log(' <comment>No suggestions were provided</>'); 144 } 145 146 $completionOutput->write($suggestions, $output); 147 } catch (\Throwable $e) { 148 $this->log([ 149 '<error>Error!</error>', 150 (string) $e, 151 ]); 152 153 if ($output->isDebug()) { 154 throw $e; 155 } 156 157 return self::FAILURE; 158 } 159 160 return self::SUCCESS; 161 } 162 163 private function createCompletionInput(InputInterface $input): CompletionInput 164 { 165 $currentIndex = $input->getOption('current'); 166 if (!$currentIndex || !ctype_digit($currentIndex)) { 167 throw new \RuntimeException('The "--current" option must be set and it must be an integer.'); 168 } 169 170 $completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex); 171 172 try { 173 $completionInput->bind($this->getApplication()->getDefinition()); 174 } catch (ExceptionInterface $e) { 175 } 176 177 return $completionInput; 178 } 179 180 private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command 181 { 182 try { 183 $inputName = $completionInput->getFirstArgument(); 184 if (null === $inputName) { 185 return null; 186 } 187 188 return $this->getApplication()->find($inputName); 189 } catch (CommandNotFoundException $e) { 190 } 191 192 return null; 193 } 194 195 private function log($messages): void 196 { 197 if (!$this->isDebug) { 198 return; 199 } 200 201 $commandName = basename($_SERVER['argv'][0]); 202 file_put_contents(sys_get_temp_dir().'/sf_'.$commandName.'.log', implode(\PHP_EOL, (array) $messages).\PHP_EOL, \FILE_APPEND); 203 } 204 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |