[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/console/Command/ -> Command.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   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\Application;
  15  use Symfony\Component\Console\Descriptor\TextDescriptor;
  16  use Symfony\Component\Console\Descriptor\XmlDescriptor;
  17  use Symfony\Component\Console\Exception\ExceptionInterface;
  18  use Symfony\Component\Console\Exception\InvalidArgumentException;
  19  use Symfony\Component\Console\Exception\LogicException;
  20  use Symfony\Component\Console\Helper\HelperSet;
  21  use Symfony\Component\Console\Input\InputArgument;
  22  use Symfony\Component\Console\Input\InputDefinition;
  23  use Symfony\Component\Console\Input\InputInterface;
  24  use Symfony\Component\Console\Input\InputOption;
  25  use Symfony\Component\Console\Output\BufferedOutput;
  26  use Symfony\Component\Console\Output\OutputInterface;
  27  
  28  /**
  29   * Base class for all commands.
  30   *
  31   * @author Fabien Potencier <fabien@symfony.com>
  32   */
  33  class Command
  34  {
  35      private $application;
  36      private $name;
  37      private $processTitle;
  38      private $aliases = array();
  39      private $definition;
  40      private $help;
  41      private $description;
  42      private $ignoreValidationErrors = false;
  43      private $applicationDefinitionMerged = false;
  44      private $applicationDefinitionMergedWithArgs = false;
  45      private $code;
  46      private $synopsis = array();
  47      private $usages = array();
  48      private $helperSet;
  49  
  50      /**
  51       * @param string|null $name The name of the command; passing null means it must be set in configure()
  52       *
  53       * @throws LogicException When the command name is empty
  54       */
  55      public function __construct($name = null)
  56      {
  57          $this->definition = new InputDefinition();
  58  
  59          if (null !== $name) {
  60              $this->setName($name);
  61          }
  62  
  63          $this->configure();
  64  
  65          if (!$this->name) {
  66              throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($this)));
  67          }
  68      }
  69  
  70      /**
  71       * Ignores validation errors.
  72       *
  73       * This is mainly useful for the help command.
  74       */
  75      public function ignoreValidationErrors()
  76      {
  77          $this->ignoreValidationErrors = true;
  78      }
  79  
  80      public function setApplication(Application $application = null)
  81      {
  82          $this->application = $application;
  83          if ($application) {
  84              $this->setHelperSet($application->getHelperSet());
  85          } else {
  86              $this->helperSet = null;
  87          }
  88      }
  89  
  90      public function setHelperSet(HelperSet $helperSet)
  91      {
  92          $this->helperSet = $helperSet;
  93      }
  94  
  95      /**
  96       * Gets the helper set.
  97       *
  98       * @return HelperSet A HelperSet instance
  99       */
 100      public function getHelperSet()
 101      {
 102          return $this->helperSet;
 103      }
 104  
 105      /**
 106       * Gets the application instance for this command.
 107       *
 108       * @return Application An Application instance
 109       */
 110      public function getApplication()
 111      {
 112          return $this->application;
 113      }
 114  
 115      /**
 116       * Checks whether the command is enabled or not in the current environment.
 117       *
 118       * Override this to check for x or y and return false if the command can not
 119       * run properly under the current conditions.
 120       *
 121       * @return bool
 122       */
 123      public function isEnabled()
 124      {
 125          return true;
 126      }
 127  
 128      /**
 129       * Configures the current command.
 130       */
 131      protected function configure()
 132      {
 133      }
 134  
 135      /**
 136       * Executes the current command.
 137       *
 138       * This method is not abstract because you can use this class
 139       * as a concrete class. In this case, instead of defining the
 140       * execute() method, you set the code to execute by passing
 141       * a Closure to the setCode() method.
 142       *
 143       * @return int|null null or 0 if everything went fine, or an error code
 144       *
 145       * @throws LogicException When this abstract method is not implemented
 146       *
 147       * @see setCode()
 148       */
 149      protected function execute(InputInterface $input, OutputInterface $output)
 150      {
 151          throw new LogicException('You must override the execute() method in the concrete command class.');
 152      }
 153  
 154      /**
 155       * Interacts with the user.
 156       *
 157       * This method is executed before the InputDefinition is validated.
 158       * This means that this is the only place where the command can
 159       * interactively ask for values of missing required arguments.
 160       */
 161      protected function interact(InputInterface $input, OutputInterface $output)
 162      {
 163      }
 164  
 165      /**
 166       * Initializes the command after the input has been bound and before the input
 167       * is validated.
 168       *
 169       * This is mainly useful when a lot of commands extends one main command
 170       * where some things need to be initialized based on the input arguments and options.
 171       *
 172       * @see InputInterface::bind()
 173       * @see InputInterface::validate()
 174       */
 175      protected function initialize(InputInterface $input, OutputInterface $output)
 176      {
 177      }
 178  
 179      /**
 180       * Runs the command.
 181       *
 182       * The code to execute is either defined directly with the
 183       * setCode() method or by overriding the execute() method
 184       * in a sub-class.
 185       *
 186       * @return int The command exit code
 187       *
 188       * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}.
 189       *
 190       * @see setCode()
 191       * @see execute()
 192       */
 193      public function run(InputInterface $input, OutputInterface $output)
 194      {
 195          // force the creation of the synopsis before the merge with the app definition
 196          $this->getSynopsis(true);
 197          $this->getSynopsis(false);
 198  
 199          // add the application arguments and options
 200          $this->mergeApplicationDefinition();
 201  
 202          // bind the input against the command specific arguments/options
 203          try {
 204              $input->bind($this->definition);
 205          } catch (ExceptionInterface $e) {
 206              if (!$this->ignoreValidationErrors) {
 207                  throw $e;
 208              }
 209          }
 210  
 211          $this->initialize($input, $output);
 212  
 213          if (null !== $this->processTitle) {
 214              if (\function_exists('cli_set_process_title')) {
 215                  if (!@cli_set_process_title($this->processTitle)) {
 216                      if ('Darwin' === PHP_OS) {
 217                          $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
 218                      } else {
 219                          cli_set_process_title($this->processTitle);
 220                      }
 221                  }
 222              } elseif (\function_exists('setproctitle')) {
 223                  setproctitle($this->processTitle);
 224              } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
 225                  $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
 226              }
 227          }
 228  
 229          if ($input->isInteractive()) {
 230              $this->interact($input, $output);
 231          }
 232  
 233          // The command name argument is often omitted when a command is executed directly with its run() method.
 234          // It would fail the validation if we didn't make sure the command argument is present,
 235          // since it's required by the application.
 236          if ($input->hasArgument('command') && null === $input->getArgument('command')) {
 237              $input->setArgument('command', $this->getName());
 238          }
 239  
 240          $input->validate();
 241  
 242          if ($this->code) {
 243              $statusCode = \call_user_func($this->code, $input, $output);
 244          } else {
 245              $statusCode = $this->execute($input, $output);
 246          }
 247  
 248          return is_numeric($statusCode) ? (int) $statusCode : 0;
 249      }
 250  
 251      /**
 252       * Sets the code to execute when running this command.
 253       *
 254       * If this method is used, it overrides the code defined
 255       * in the execute() method.
 256       *
 257       * @param callable $code A callable(InputInterface $input, OutputInterface $output)
 258       *
 259       * @return $this
 260       *
 261       * @throws InvalidArgumentException
 262       *
 263       * @see execute()
 264       */
 265      public function setCode($code)
 266      {
 267          if (!\is_callable($code)) {
 268              throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
 269          }
 270  
 271          if (\PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
 272              $r = new \ReflectionFunction($code);
 273              if (null === $r->getClosureThis()) {
 274                  if (\PHP_VERSION_ID < 70000) {
 275                      // Bug in PHP5: https://bugs.php.net/bug.php?id=64761
 276                      // This means that we cannot bind static closures and therefore we must
 277                      // ignore any errors here.  There is no way to test if the closure is
 278                      // bindable.
 279                      $code = @\Closure::bind($code, $this);
 280                  } else {
 281                      $code = \Closure::bind($code, $this);
 282                  }
 283              }
 284          }
 285  
 286          $this->code = $code;
 287  
 288          return $this;
 289      }
 290  
 291      /**
 292       * Merges the application definition with the command definition.
 293       *
 294       * This method is not part of public API and should not be used directly.
 295       *
 296       * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
 297       */
 298      public function mergeApplicationDefinition($mergeArgs = true)
 299      {
 300          if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
 301              return;
 302          }
 303  
 304          $this->definition->addOptions($this->application->getDefinition()->getOptions());
 305  
 306          $this->applicationDefinitionMerged = true;
 307  
 308          if ($mergeArgs) {
 309              $currentArguments = $this->definition->getArguments();
 310              $this->definition->setArguments($this->application->getDefinition()->getArguments());
 311              $this->definition->addArguments($currentArguments);
 312  
 313              $this->applicationDefinitionMergedWithArgs = true;
 314          }
 315      }
 316  
 317      /**
 318       * Sets an array of argument and option instances.
 319       *
 320       * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
 321       *
 322       * @return $this
 323       */
 324      public function setDefinition($definition)
 325      {
 326          if ($definition instanceof InputDefinition) {
 327              $this->definition = $definition;
 328          } else {
 329              $this->definition->setDefinition($definition);
 330          }
 331  
 332          $this->applicationDefinitionMerged = false;
 333  
 334          return $this;
 335      }
 336  
 337      /**
 338       * Gets the InputDefinition attached to this Command.
 339       *
 340       * @return InputDefinition An InputDefinition instance
 341       */
 342      public function getDefinition()
 343      {
 344          return $this->definition;
 345      }
 346  
 347      /**
 348       * Gets the InputDefinition to be used to create XML and Text representations of this Command.
 349       *
 350       * Can be overridden to provide the original command representation when it would otherwise
 351       * be changed by merging with the application InputDefinition.
 352       *
 353       * This method is not part of public API and should not be used directly.
 354       *
 355       * @return InputDefinition An InputDefinition instance
 356       */
 357      public function getNativeDefinition()
 358      {
 359          return $this->getDefinition();
 360      }
 361  
 362      /**
 363       * Adds an argument.
 364       *
 365       * @param string               $name        The argument name
 366       * @param int|null             $mode        The argument mode: self::REQUIRED or self::OPTIONAL
 367       * @param string               $description A description text
 368       * @param string|string[]|null $default     The default value (for self::OPTIONAL mode only)
 369       *
 370       * @throws InvalidArgumentException When argument mode is not valid
 371       *
 372       * @return $this
 373       */
 374      public function addArgument($name, $mode = null, $description = '', $default = null)
 375      {
 376          $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
 377  
 378          return $this;
 379      }
 380  
 381      /**
 382       * Adds an option.
 383       *
 384       * @param string                        $name        The option name
 385       * @param string|array                  $shortcut    The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
 386       * @param int|null                      $mode        The option mode: One of the VALUE_* constants
 387       * @param string                        $description A description text
 388       * @param string|string[]|int|bool|null $default     The default value (must be null for self::VALUE_NONE)
 389       *
 390       * @throws InvalidArgumentException If option mode is invalid or incompatible
 391       *
 392       * @return $this
 393       */
 394      public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
 395      {
 396          $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
 397  
 398          return $this;
 399      }
 400  
 401      /**
 402       * Sets the name of the command.
 403       *
 404       * This method can set both the namespace and the name if
 405       * you separate them by a colon (:)
 406       *
 407       *     $command->setName('foo:bar');
 408       *
 409       * @param string $name The command name
 410       *
 411       * @return $this
 412       *
 413       * @throws InvalidArgumentException When the name is invalid
 414       */
 415      public function setName($name)
 416      {
 417          $this->validateName($name);
 418  
 419          $this->name = $name;
 420  
 421          return $this;
 422      }
 423  
 424      /**
 425       * Sets the process title of the command.
 426       *
 427       * This feature should be used only when creating a long process command,
 428       * like a daemon.
 429       *
 430       * PHP 5.5+ or the proctitle PECL library is required
 431       *
 432       * @param string $title The process title
 433       *
 434       * @return $this
 435       */
 436      public function setProcessTitle($title)
 437      {
 438          $this->processTitle = $title;
 439  
 440          return $this;
 441      }
 442  
 443      /**
 444       * Returns the command name.
 445       *
 446       * @return string The command name
 447       */
 448      public function getName()
 449      {
 450          return $this->name;
 451      }
 452  
 453      /**
 454       * Sets the description for the command.
 455       *
 456       * @param string $description The description for the command
 457       *
 458       * @return $this
 459       */
 460      public function setDescription($description)
 461      {
 462          $this->description = $description;
 463  
 464          return $this;
 465      }
 466  
 467      /**
 468       * Returns the description for the command.
 469       *
 470       * @return string The description for the command
 471       */
 472      public function getDescription()
 473      {
 474          return $this->description;
 475      }
 476  
 477      /**
 478       * Sets the help for the command.
 479       *
 480       * @param string $help The help for the command
 481       *
 482       * @return $this
 483       */
 484      public function setHelp($help)
 485      {
 486          $this->help = $help;
 487  
 488          return $this;
 489      }
 490  
 491      /**
 492       * Returns the help for the command.
 493       *
 494       * @return string The help for the command
 495       */
 496      public function getHelp()
 497      {
 498          return $this->help;
 499      }
 500  
 501      /**
 502       * Returns the processed help for the command replacing the %command.name% and
 503       * %command.full_name% patterns with the real values dynamically.
 504       *
 505       * @return string The processed help for the command
 506       */
 507      public function getProcessedHelp()
 508      {
 509          $name = $this->name;
 510  
 511          $placeholders = array(
 512              '%command.name%',
 513              '%command.full_name%',
 514          );
 515          $replacements = array(
 516              $name,
 517              $_SERVER['PHP_SELF'].' '.$name,
 518          );
 519  
 520          return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
 521      }
 522  
 523      /**
 524       * Sets the aliases for the command.
 525       *
 526       * @param string[] $aliases An array of aliases for the command
 527       *
 528       * @return $this
 529       *
 530       * @throws InvalidArgumentException When an alias is invalid
 531       */
 532      public function setAliases($aliases)
 533      {
 534          if (!\is_array($aliases) && !$aliases instanceof \Traversable) {
 535              throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
 536          }
 537  
 538          foreach ($aliases as $alias) {
 539              $this->validateName($alias);
 540          }
 541  
 542          $this->aliases = $aliases;
 543  
 544          return $this;
 545      }
 546  
 547      /**
 548       * Returns the aliases for the command.
 549       *
 550       * @return array An array of aliases for the command
 551       */
 552      public function getAliases()
 553      {
 554          return $this->aliases;
 555      }
 556  
 557      /**
 558       * Returns the synopsis for the command.
 559       *
 560       * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
 561       *
 562       * @return string The synopsis
 563       */
 564      public function getSynopsis($short = false)
 565      {
 566          $key = $short ? 'short' : 'long';
 567  
 568          if (!isset($this->synopsis[$key])) {
 569              $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
 570          }
 571  
 572          return $this->synopsis[$key];
 573      }
 574  
 575      /**
 576       * Add a command usage example.
 577       *
 578       * @param string $usage The usage, it'll be prefixed with the command name
 579       *
 580       * @return $this
 581       */
 582      public function addUsage($usage)
 583      {
 584          if (0 !== strpos($usage, $this->name)) {
 585              $usage = sprintf('%s %s', $this->name, $usage);
 586          }
 587  
 588          $this->usages[] = $usage;
 589  
 590          return $this;
 591      }
 592  
 593      /**
 594       * Returns alternative usages of the command.
 595       *
 596       * @return array
 597       */
 598      public function getUsages()
 599      {
 600          return $this->usages;
 601      }
 602  
 603      /**
 604       * Gets a helper instance by name.
 605       *
 606       * @param string $name The helper name
 607       *
 608       * @return mixed The helper value
 609       *
 610       * @throws LogicException           if no HelperSet is defined
 611       * @throws InvalidArgumentException if the helper is not defined
 612       */
 613      public function getHelper($name)
 614      {
 615          if (null === $this->helperSet) {
 616              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));
 617          }
 618  
 619          return $this->helperSet->get($name);
 620      }
 621  
 622      /**
 623       * Returns a text representation of the command.
 624       *
 625       * @return string A string representing the command
 626       *
 627       * @deprecated since version 2.3, to be removed in 3.0.
 628       */
 629      public function asText()
 630      {
 631          @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
 632  
 633          $descriptor = new TextDescriptor();
 634          $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
 635          $descriptor->describe($output, $this, array('raw_output' => true));
 636  
 637          return $output->fetch();
 638      }
 639  
 640      /**
 641       * Returns an XML representation of the command.
 642       *
 643       * @param bool $asDom Whether to return a DOM or an XML string
 644       *
 645       * @return string|\DOMDocument An XML string representing the command
 646       *
 647       * @deprecated since version 2.3, to be removed in 3.0.
 648       */
 649      public function asXml($asDom = false)
 650      {
 651          @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
 652  
 653          $descriptor = new XmlDescriptor();
 654  
 655          if ($asDom) {
 656              return $descriptor->getCommandDocument($this);
 657          }
 658  
 659          $output = new BufferedOutput();
 660          $descriptor->describe($output, $this);
 661  
 662          return $output->fetch();
 663      }
 664  
 665      /**
 666       * Validates a command name.
 667       *
 668       * It must be non-empty and parts can optionally be separated by ":".
 669       *
 670       * @param string $name
 671       *
 672       * @throws InvalidArgumentException When the name is invalid
 673       */
 674      private function validateName($name)
 675      {
 676          if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
 677              throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
 678          }
 679      }
 680  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1