This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Components/Console/Command/Command.php

515 lines
13 KiB
PHP
Raw Normal View History

2010-01-04 14:42:28 +00:00
<?php
2010-01-09 11:57:15 +00:00
namespace Symfony\Components\Console\Command;
2010-01-04 14:42:28 +00:00
2010-01-09 11:57:15 +00:00
use Symfony\Components\Console\Input\InputDefinition;
use Symfony\Components\Console\Input\InputOption;
use Symfony\Components\Console\Input\InputArgument;
use Symfony\Components\Console\Input\InputInterface;
use Symfony\Components\Console\Output\OutputInterface;
use Symfony\Components\Console\Application;
2010-01-04 14:42:28 +00:00
/*
* This file is part of the symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Base class for all commands.
2010-01-04 14:42:28 +00:00
*
* @package symfony
* @subpackage console
2010-01-04 14:42:28 +00:00
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Command
2010-01-04 14:42:28 +00:00
{
protected $name;
protected $namespace;
protected $aliases;
protected $definition;
protected $help;
protected $application;
protected $description;
protected $ignoreValidationErrors;
protected $formatter;
protected $applicationDefinitionMerged;
protected $code;
/**
* Constructor.
*
2010-01-11 13:46:11 +00:00
* @param string $name The name of the command
2010-04-04 18:11:32 +01:00
*
* @throws \LogicException When the command name is empty
2010-01-04 14:42:28 +00:00
*/
2010-01-11 13:46:11 +00:00
public function __construct($name = null)
2010-01-04 14:42:28 +00:00
{
$this->definition = new InputDefinition();
2010-01-04 14:42:28 +00:00
$this->ignoreValidationErrors = false;
$this->applicationDefinitionMerged = false;
$this->aliases = array();
if (null !== $name)
{
$this->setName($name);
}
$this->configure();
if (!$this->name)
{
throw new \LogicException('The command name cannot be empty.');
2010-01-04 14:42:28 +00:00
}
}
/**
* Sets the application instance for this command.
2010-01-04 14:42:28 +00:00
*
* @param Application $application An Application instance
*/
public function setApplication(Application $application = null)
{
$this->application = $application;
}
/**
* Configures the current command.
2010-01-04 14:42:28 +00:00
*/
protected function configure()
{
}
/**
* Executes the current command.
2010-01-04 14:42:28 +00:00
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return integer 0 if everything went fine, or an error code
2010-04-04 18:11:32 +01:00
*
* @throws \LogicException When this abstrass class is not implemented
2010-01-04 14:42:28 +00:00
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new \LogicException('You must override the execute() method in the concrete command class.');
2010-01-04 14:42:28 +00:00
}
/**
* Interacts with the user.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
}
/**
* Initializes the command just after the input has been validated.
*
* This is mainly useful when a lot of commands extends one main command
* where some things need to be initialized based on the input arguments and options.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
}
/**
* Runs the command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
2010-01-04 14:42:28 +00:00
public function run(InputInterface $input, OutputInterface $output)
{
// add the application arguments and options
$this->mergeApplicationDefinition();
// bind the input against the command specific arguments/options
2010-01-04 14:42:28 +00:00
try
{
$input->bind($this->definition);
}
catch (\Exception $e)
{
if (!$this->ignoreValidationErrors)
{
throw $e;
}
}
$this->initialize($input, $output);
2010-01-04 14:42:28 +00:00
if ($input->isInteractive())
{
$this->interact($input, $output);
}
$input->validate();
if ($this->code)
{
return call_user_func($this->code, $input, $output);
}
else
{
return $this->execute($input, $output);
}
}
/**
* Sets the code to execute when running this command.
2010-01-04 14:42:28 +00:00
*
* @param \Closure $code A \Closure
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function setCode(\Closure $code)
{
$this->code = $code;
return $this;
}
/**
* Merges the application definition with the command definition.
2010-01-04 14:42:28 +00:00
*/
protected function mergeApplicationDefinition()
{
if (null === $this->application || true === $this->applicationDefinitionMerged)
{
return;
}
$this->definition->setArguments(array_merge(
$this->application->getDefinition()->getArguments(),
$this->definition->getArguments()
));
$this->definition->addOptions($this->application->getDefinition()->getOptions());
$this->applicationDefinitionMerged = true;
}
/**
* Sets an array of argument and option instances.
*
* @param array|Definition $definition An array of argument and option instances or a definition instance
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function setDefinition($definition)
{
if ($definition instanceof InputDefinition)
2010-01-04 14:42:28 +00:00
{
$this->definition = $definition;
}
else
{
$this->definition->setDefinition($definition);
}
$this->applicationDefinitionMerged = false;
return $this;
}
2010-01-14 09:45:37 +00:00
/**
* Gets the InputDefinition attached to this Command.
*
* @return InputDefinition $definition An InputDefinition instance
*/
public function getDefinition()
{
return $this->definition;
}
2010-01-04 14:42:28 +00:00
/**
* Adds an argument.
*
* @param string $name The argument name
* @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
2010-01-04 14:42:28 +00:00
* @param string $description A description text
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
2010-01-04 14:42:28 +00:00
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function addArgument($name, $mode = null, $description = '', $default = null)
{
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
2010-01-04 14:42:28 +00:00
return $this;
}
/**
* Adds an option.
*
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
2010-01-04 14:42:28 +00:00
return $this;
}
/**
* Sets the name of the command.
2010-01-04 14:42:28 +00:00
*
* This method can set both the namespace and the name if
* you separate them by a colon (:)
*
* $command->setName('foo:bar');
2010-01-04 14:42:28 +00:00
*
* @param string $name The command name
2010-01-04 14:42:28 +00:00
*
* @return Command The current instance
2010-04-04 18:11:32 +01:00
*
* @throws \InvalidArgumentException When command name given is empty
2010-01-04 14:42:28 +00:00
*/
public function setName($name)
{
if (false !== $pos = strpos($name, ':'))
{
$namespace = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
}
else
{
$namespace = $this->namespace;
}
if (!$name)
{
throw new \InvalidArgumentException('A command name cannot be empty');
2010-01-04 14:42:28 +00:00
}
$this->namespace = $namespace;
$this->name = $name;
return $this;
}
/**
* Returns the command namespace.
2010-01-04 14:42:28 +00:00
*
* @return string The command namespace
2010-01-04 14:42:28 +00:00
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Returns the command name
2010-01-04 14:42:28 +00:00
*
* @return string The command name
2010-01-04 14:42:28 +00:00
*/
public function getName()
{
return $this->name;
}
/**
* Returns the fully qualified command name.
2010-01-04 14:42:28 +00:00
*
* @return string The fully qualified command name
2010-01-04 14:42:28 +00:00
*/
public function getFullName()
{
return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName();
}
/**
* Sets the description for the command.
2010-01-04 14:42:28 +00:00
*
* @param string $description The description for the command
2010-01-04 14:42:28 +00:00
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Returns the description for the command.
2010-01-04 14:42:28 +00:00
*
* @return string The description for the command
2010-01-04 14:42:28 +00:00
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets the help for the command.
2010-01-04 14:42:28 +00:00
*
* @param string $help The help for the command
2010-01-04 14:42:28 +00:00
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function setHelp($help)
{
$this->help = $help;
return $this;
}
/**
* Returns the help for the command.
2010-01-04 14:42:28 +00:00
*
* @return string The help for the command
2010-01-04 14:42:28 +00:00
*/
public function getHelp()
{
return $this->help;
}
/**
* Sets the aliases for the command.
2010-01-04 14:42:28 +00:00
*
* @param array $aliases An array of aliases for the command
2010-01-04 14:42:28 +00:00
*
* @return Command The current instance
2010-01-04 14:42:28 +00:00
*/
public function setAliases($aliases)
{
$this->aliases = $aliases;
return $this;
}
/**
* Returns the aliases for the command.
2010-01-04 14:42:28 +00:00
*
* @return array An array of aliases for the command
2010-01-04 14:42:28 +00:00
*/
public function getAliases()
{
return $this->aliases;
}
/**
* Returns the synopsis for the command.
2010-01-04 14:42:28 +00:00
*
* @return string The synopsis
*/
public function getSynopsis()
{
return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis());
2010-01-04 14:42:28 +00:00
}
/**
2010-01-11 13:46:11 +00:00
* Gets a helper instance by name.
2010-01-04 14:42:28 +00:00
*
2010-01-11 13:46:11 +00:00
* @param string $name The helper name
2010-01-04 14:42:28 +00:00
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
2010-01-04 14:42:28 +00:00
*/
2010-01-11 13:46:11 +00:00
protected function getHelper($name)
2010-01-04 14:42:28 +00:00
{
2010-01-11 13:46:11 +00:00
return $this->application->getHelperSet()->get($name);
2010-01-04 14:42:28 +00:00
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
public function __get($name)
{
return $this->application->getHelperSet()->get($name);
}
2010-01-04 14:42:28 +00:00
/**
* Returns a text representation of the command.
2010-01-04 14:42:28 +00:00
*
* @return string A string representing the command
2010-01-04 14:42:28 +00:00
*/
public function asText()
{
$messages = array(
'<comment>Usage:</comment>',
' '.$this->getSynopsis(),
2010-01-04 14:42:28 +00:00
'',
);
if ($this->getAliases())
{
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
}
$messages[] = $this->definition->asText();
if ($help = $this->getHelp())
{
$messages[] = '<comment>Help:</comment>';
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n";
}
return implode("\n", $messages);
}
/**
* Returns an XML representation of the command.
2010-01-04 14:42:28 +00:00
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the command
2010-01-04 14:42:28 +00:00
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($commandXML = $dom->createElement('command'));
$commandXML->setAttribute('id', $this->getFullName());
$commandXML->setAttribute('namespace', $this->getNamespace() ? $this->getNamespace() : '_global');
$commandXML->setAttribute('name', $this->getName());
2010-01-04 14:42:28 +00:00
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
2010-01-04 14:42:28 +00:00
$usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
2010-01-04 14:42:28 +00:00
$descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription()))));
$commandXML->appendChild($helpXML = $dom->createElement('help'));
2010-01-04 14:42:28 +00:00
$help = $this->help;
$helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help))));
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
2010-01-04 14:42:28 +00:00
foreach ($this->getAliases() as $alias)
{
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
$aliasXML->appendChild($dom->createTextNode($alias));
}
$definition = $this->definition->asXml(true);
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
2010-01-04 14:42:28 +00:00
return $asDom ? $dom : $dom->saveXml();
}
}