123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710 |
- <?php
- namespace Symfony\Component\Console\Command;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Attribute\AsCommand;
- use Symfony\Component\Console\Completion\CompletionInput;
- use Symfony\Component\Console\Completion\CompletionSuggestions;
- use Symfony\Component\Console\Exception\ExceptionInterface;
- use Symfony\Component\Console\Exception\InvalidArgumentException;
- use Symfony\Component\Console\Exception\LogicException;
- use Symfony\Component\Console\Helper\HelperSet;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class Command
- {
-
- public const SUCCESS = 0;
- public const FAILURE = 1;
- public const INVALID = 2;
-
- protected static $defaultName;
-
- protected static $defaultDescription;
- private $application;
- private $name;
- private $processTitle;
- private $aliases = [];
- private $definition;
- private $hidden = false;
- private $help = '';
- private $description = '';
- private $fullDefinition;
- private $ignoreValidationErrors = false;
- private $code;
- private $synopsis = [];
- private $usages = [];
- private $helperSet;
-
- public static function getDefaultName()
- {
- $class = static::class;
- if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
- return $attribute[0]->newInstance()->name;
- }
- $r = new \ReflectionProperty($class, 'defaultName');
- return $class === $r->class ? static::$defaultName : null;
- }
- public static function getDefaultDescription(): ?string
- {
- $class = static::class;
- if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
- return $attribute[0]->newInstance()->description;
- }
- $r = new \ReflectionProperty($class, 'defaultDescription');
- return $class === $r->class ? static::$defaultDescription : null;
- }
-
- public function __construct(string $name = null)
- {
- $this->definition = new InputDefinition();
- if (null === $name && null !== $name = static::getDefaultName()) {
- $aliases = explode('|', $name);
- if ('' === $name = array_shift($aliases)) {
- $this->setHidden(true);
- $name = array_shift($aliases);
- }
- $this->setAliases($aliases);
- }
- if (null !== $name) {
- $this->setName($name);
- }
- if ('' === $this->description) {
- $this->setDescription(static::getDefaultDescription() ?? '');
- }
- $this->configure();
- }
-
- public function ignoreValidationErrors()
- {
- $this->ignoreValidationErrors = true;
- }
- public function setApplication(Application $application = null)
- {
- $this->application = $application;
- if ($application) {
- $this->setHelperSet($application->getHelperSet());
- } else {
- $this->helperSet = null;
- }
- $this->fullDefinition = null;
- }
- public function setHelperSet(HelperSet $helperSet)
- {
- $this->helperSet = $helperSet;
- }
-
- public function getHelperSet()
- {
- return $this->helperSet;
- }
-
- public function getApplication()
- {
- return $this->application;
- }
-
- public function isEnabled()
- {
- return true;
- }
-
- protected function configure()
- {
- }
-
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- throw new LogicException('You must override the execute() method in the concrete command class.');
- }
-
- protected function interact(InputInterface $input, OutputInterface $output)
- {
- }
-
- protected function initialize(InputInterface $input, OutputInterface $output)
- {
- }
-
- public function run(InputInterface $input, OutputInterface $output)
- {
-
- $this->mergeApplicationDefinition();
-
- try {
- $input->bind($this->getDefinition());
- } catch (ExceptionInterface $e) {
- if (!$this->ignoreValidationErrors) {
- throw $e;
- }
- }
- $this->initialize($input, $output);
- if (null !== $this->processTitle) {
- if (\function_exists('cli_set_process_title')) {
- if (!@cli_set_process_title($this->processTitle)) {
- if ('Darwin' === \PHP_OS) {
- $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
- } else {
- cli_set_process_title($this->processTitle);
- }
- }
- } elseif (\function_exists('setproctitle')) {
- setproctitle($this->processTitle);
- } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
- $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
- }
- }
- if ($input->isInteractive()) {
- $this->interact($input, $output);
- }
-
-
-
- if ($input->hasArgument('command') && null === $input->getArgument('command')) {
- $input->setArgument('command', $this->getName());
- }
- $input->validate();
- if ($this->code) {
- $statusCode = ($this->code)($input, $output);
- } else {
- $statusCode = $this->execute($input, $output);
- if (!\is_int($statusCode)) {
- throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode)));
- }
- }
- return is_numeric($statusCode) ? (int) $statusCode : 0;
- }
-
- public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
- {
- }
-
- public function setCode(callable $code)
- {
- if ($code instanceof \Closure) {
- $r = new \ReflectionFunction($code);
- if (null === $r->getClosureThis()) {
- set_error_handler(static function () {});
- try {
- if ($c = \Closure::bind($code, $this)) {
- $code = $c;
- }
- } finally {
- restore_error_handler();
- }
- }
- }
- $this->code = $code;
- return $this;
- }
-
- public function mergeApplicationDefinition(bool $mergeArgs = true)
- {
- if (null === $this->application) {
- return;
- }
- $this->fullDefinition = new InputDefinition();
- $this->fullDefinition->setOptions($this->definition->getOptions());
- $this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());
- if ($mergeArgs) {
- $this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
- $this->fullDefinition->addArguments($this->definition->getArguments());
- } else {
- $this->fullDefinition->setArguments($this->definition->getArguments());
- }
- }
-
- public function setDefinition($definition)
- {
- if ($definition instanceof InputDefinition) {
- $this->definition = $definition;
- } else {
- $this->definition->setDefinition($definition);
- }
- $this->fullDefinition = null;
- return $this;
- }
-
- public function getDefinition()
- {
- return $this->fullDefinition ?? $this->getNativeDefinition();
- }
-
- public function getNativeDefinition()
- {
- if (null === $this->definition) {
- throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
- }
- return $this->definition;
- }
-
- public function addArgument(string $name, int $mode = null, string $description = '', $default = null)
- {
- $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
- if (null !== $this->fullDefinition) {
- $this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default));
- }
- return $this;
- }
-
- public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
- {
- $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
- if (null !== $this->fullDefinition) {
- $this->fullDefinition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
- }
- return $this;
- }
-
- public function setName(string $name)
- {
- $this->validateName($name);
- $this->name = $name;
- return $this;
- }
-
- public function setProcessTitle(string $title)
- {
- $this->processTitle = $title;
- return $this;
- }
-
- public function getName()
- {
- return $this->name;
- }
-
- public function setHidden(bool $hidden )
- {
- $this->hidden = $hidden;
- return $this;
- }
-
- public function isHidden()
- {
- return $this->hidden;
- }
-
- public function setDescription(string $description)
- {
- $this->description = $description;
- return $this;
- }
-
- public function getDescription()
- {
- return $this->description;
- }
-
- public function setHelp(string $help)
- {
- $this->help = $help;
- return $this;
- }
-
- public function getHelp()
- {
- return $this->help;
- }
-
- public function getProcessedHelp()
- {
- $name = $this->name;
- $isSingleCommand = $this->application && $this->application->isSingleCommand();
- $placeholders = [
- '%command.name%',
- '%command.full_name%',
- ];
- $replacements = [
- $name,
- $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name,
- ];
- return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
- }
-
- public function setAliases(iterable $aliases)
- {
- $list = [];
- foreach ($aliases as $alias) {
- $this->validateName($alias);
- $list[] = $alias;
- }
- $this->aliases = \is_array($aliases) ? $aliases : $list;
- return $this;
- }
-
- public function getAliases()
- {
- return $this->aliases;
- }
-
- public function getSynopsis(bool $short = false)
- {
- $key = $short ? 'short' : 'long';
- if (!isset($this->synopsis[$key])) {
- $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
- }
- return $this->synopsis[$key];
- }
-
- public function addUsage(string $usage)
- {
- if (!str_starts_with($usage, $this->name)) {
- $usage = sprintf('%s %s', $this->name, $usage);
- }
- $this->usages[] = $usage;
- return $this;
- }
-
- public function getUsages()
- {
- return $this->usages;
- }
-
- public function getHelper(string $name)
- {
- if (null === $this->helperSet) {
- throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
- }
- return $this->helperSet->get($name);
- }
-
- private function validateName(string $name)
- {
- if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
- throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
- }
- }
- }
|