From 45de5c69324018004b83cf1e8f6c35eefff071d2 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Thu, 8 Apr 2010 00:30:11 -0300 Subject: [PATCH 1/4] [2.0] Removed old CLI support. --- lib/Doctrine/Common/CLI/AbstractNamespace.php | 234 --------- lib/Doctrine/Common/CLI/CLIController.php | 306 ----------- lib/Doctrine/Common/CLI/CLIException.php | 59 --- lib/Doctrine/Common/CLI/Configuration.php | 86 ---- lib/Doctrine/Common/CLI/Option.php | 103 ---- lib/Doctrine/Common/CLI/OptionGroup.php | 482 ------------------ .../Common/CLI/Printers/AbstractPrinter.php | 190 ------- .../Common/CLI/Printers/AnsiColorPrinter.php | 214 -------- .../Common/CLI/Printers/NormalPrinter.php | 46 -- lib/Doctrine/Common/CLI/Style.php | 93 ---- lib/Doctrine/Common/CLI/TaskDocumentation.php | 192 ------- lib/Doctrine/Common/CLI/TaskNamespace.php | 251 --------- .../Common/CLI/Tasks/AbstractTask.php | 200 -------- lib/Doctrine/Common/CLI/Tasks/HelpTask.php | 79 --- lib/Doctrine/Common/CLI/Tasks/VersionTask.php | 61 --- .../DBAL/Tools/CLI/Tasks/RunSqlTask.php | 171 ------- .../DBAL/Tools/CLI/Tasks/VersionTask.php | 62 --- .../ORM/Tools/CLI/Tasks/ClearCacheTask.php | 205 -------- .../CLI/Tasks/ConvertDoctrine1SchemaTask.php | 117 ----- .../Tools/CLI/Tasks/ConvertMappingTask.php | 163 ------ .../Tasks/EnsureProductionSettingsTask.php | 78 --- .../Tools/CLI/Tasks/GenerateEntitiesTask.php | 120 ----- .../Tools/CLI/Tasks/GenerateProxiesTask.php | 108 ---- .../CLI/Tasks/GenerateRepositoriesTask.php | 146 ------ .../ORM/Tools/CLI/Tasks/RunDqlTask.php | 147 ------ .../ORM/Tools/CLI/Tasks/SchemaToolTask.php | 224 -------- .../ORM/Tools/CLI/Tasks/VersionTask.php | 62 --- 27 files changed, 4199 deletions(-) delete mode 100644 lib/Doctrine/Common/CLI/AbstractNamespace.php delete mode 100644 lib/Doctrine/Common/CLI/CLIController.php delete mode 100644 lib/Doctrine/Common/CLI/CLIException.php delete mode 100644 lib/Doctrine/Common/CLI/Configuration.php delete mode 100644 lib/Doctrine/Common/CLI/Option.php delete mode 100644 lib/Doctrine/Common/CLI/OptionGroup.php delete mode 100644 lib/Doctrine/Common/CLI/Printers/AbstractPrinter.php delete mode 100644 lib/Doctrine/Common/CLI/Printers/AnsiColorPrinter.php delete mode 100644 lib/Doctrine/Common/CLI/Printers/NormalPrinter.php delete mode 100644 lib/Doctrine/Common/CLI/Style.php delete mode 100644 lib/Doctrine/Common/CLI/TaskDocumentation.php delete mode 100644 lib/Doctrine/Common/CLI/TaskNamespace.php delete mode 100644 lib/Doctrine/Common/CLI/Tasks/AbstractTask.php delete mode 100644 lib/Doctrine/Common/CLI/Tasks/HelpTask.php delete mode 100644 lib/Doctrine/Common/CLI/Tasks/VersionTask.php delete mode 100644 lib/Doctrine/DBAL/Tools/CLI/Tasks/RunSqlTask.php delete mode 100644 lib/Doctrine/DBAL/Tools/CLI/Tasks/VersionTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/ClearCacheTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertDoctrine1SchemaTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertMappingTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/EnsureProductionSettingsTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateEntitiesTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateProxiesTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateRepositoriesTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/RunDqlTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/SchemaToolTask.php delete mode 100644 lib/Doctrine/ORM/Tools/CLI/Tasks/VersionTask.php diff --git a/lib/Doctrine/Common/CLI/AbstractNamespace.php b/lib/Doctrine/Common/CLI/AbstractNamespace.php deleted file mode 100644 index fb552c118..000000000 --- a/lib/Doctrine/Common/CLI/AbstractNamespace.php +++ /dev/null @@ -1,234 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -use Doctrine\Common\Util\Inflector; - -/** - * Abstract CLI Namespace class - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -abstract class AbstractNamespace -{ - /** - * @var Configuration CLI Configuration instance - */ - private $_configuration = null; - - /** - * @var AbstractPrinter CLI Printer instance - */ - private $_printer = null; - - /** - * @var AbstractNamespace CLI Namespace instance - */ - private $_parentNamespace = null; - - /** - * @var array Available namespaces - */ - private $_namespaces = array(); - - /** - * Add a single namespace to CLI. - * Example of inclusion support to a single namespace: - * - * [php] - * $cliOrmNamespace->addNamespace('my-custom-namespace'); - * - * @param string $name CLI Namespace name - * - * @return CliController This object instance - */ - public function addNamespace($name) - { - $name = self::formatName($name); - - if ($this->hasNamespace($name)) { - throw CLIException::cannotOverrideNamespace($name); - } - - return $this->overrideNamespace($name); - } - - /** - * Overrides a namespace to CLI. - * Example of inclusion support to a single namespace: - * - * [php] - * $cli->overrideNamespace('orm'); - * - * @param string $name CLI Namespace name - * - * @return AbstractNamespace Newly created CLI Namespace - */ - public function overrideNamespace($name) - { - $taskNamespace = new TaskNamespace($name); - - $taskNamespace->setParentNamespace($this); - $taskNamespace->setPrinter($this->_printer); - $taskNamespace->setConfiguration($this->_configuration); - - $this->_namespaces[$taskNamespace->getName()] = $taskNamespace; - - return $taskNamespace; - } - - /** - * Retrieve CLI Namespace. - * Example of usage: - * - * [php] - * $cliOrmNamespace = $cli->getNamespace('ORM'); - * - * @param string $name CLI Namespace name - * - * @return TaskNamespace CLI Namespace - */ - public function getNamespace($name) - { - $name = self::formatName($name); - - return isset($this->_namespaces[$name]) - ? $this->_namespaces[$name] : null; - } - - /** - * Check existance of a CLI Namespace - * - * @param string CLI Namespace name - * - * @return boolean TRUE if namespace if defined, false otherwise - */ - public function hasNamespace($name) - { - return ($this->getNamespace($name) !== null); - } - - /** - * Defines the parent CLI Namespace - * - * @return AbstractNamespace - */ - public function setParentNamespace(AbstractNamespace $namespace) - { - $this->_parentNamespace = $namespace; - - return $this; - } - - /** - * Retrieves currently parent CLI Namespace - * - * @return AbstractNamespace - */ - public function getParentNamespace() - { - return $this->_parentNamespace; - } - - /** - * Retrieve all defined CLI Tasks - * - * @return array - */ - public function getAvailableTasks() - { - $tasks = array(); - - foreach ($this->_namespaces as $namespace) { - $tasks = array_merge($tasks, $namespace->getAvailableTasks()); - } - - return $tasks; - } - - /** - * Defines the CLI Output Printer - * - * @param AbstractPrinter $printer CLI Output Printer - * - * @return AbstractNamespace - */ - public function setPrinter(Printers\AbstractPrinter $printer = null) - { - $this->_printer = $printer ?: new Printers\AnsiColorPrinter; - - return $this; - } - - /** - * Retrieves currently used CLI Output Printer - * - * @return AbstractPrinter - */ - public function getPrinter() - { - return $this->_printer; - } - - /** - * Defines the CLI Configuration - * - * #param Configuration $configuration CLI Configuration - * - * @return AbstractNamespace - */ - public function setConfiguration(Configuration $config) - { - $this->_configuration = $config; - - return $this; - } - - /** - * Retrieves currently used CLI Configuration - * - * @return Configuration - */ - public function getConfiguration() - { - return $this->_configuration; - } - - /** - * Formats the CLI Namespace name into a camel-cased name - * - * @param string $name CLI Namespace name - * - * @return string Formatted CLI Namespace name - */ - public static function formatName($name) - { - return Inflector::classify($name); - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/CLIController.php b/lib/Doctrine/Common/CLI/CLIController.php deleted file mode 100644 index d11fc708a..000000000 --- a/lib/Doctrine/Common/CLI/CLIController.php +++ /dev/null @@ -1,306 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -/** - * Generic CLI Controller of Tasks execution - * - * To include a new Task support, create a task: - * - * [php] - * class MyProject\Tools\CLI\Tasks\MyTask extends Doctrine\ORM\Tools\CLI\Tasks\AbstractTask - * { - * public function run(); - * public function basicHelp(); - * public function extendedHelp(); - * public function validate(); - * } - * - * And then, load the namespace assoaicated an include the support to it in your command-line script: - * - * [php] - * $cli = new Doctrine\Common\CLI\CLIController(); - * $cliNS = $cli->getNamespace('custom'); - * $cliNS->addTask('myTask', 'MyProject\Tools\CLI\Tasks\MyTask'); - * - * To execute, just type any classify-able name: - * - * $ cli.php custom:my-task - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class CLIController extends AbstractNamespace -{ - /** - * The CLI processor of tasks - * - * @param Configuration $config - * @param AbstractPrinter $printer CLI Output printer - */ - public function __construct(Configuration $config, Printers\AbstractPrinter $printer = null) - { - $this->setPrinter($printer); - $this->setConfiguration($config); - - // Include core namespaces of tasks - $ns = 'Doctrine\Common\CLI\Tasks'; - $this->addNamespace('Core') - ->addTask('help', $ns . '\HelpTask') - ->addTask('version', $ns . '\VersionTask'); - - $ns = 'Doctrine\ORM\Tools\CLI\Tasks'; - $this->addNamespace('Orm') - ->addTask('clear-cache', $ns . '\ClearCacheTask') - ->addTask('convert-mapping', $ns . '\ConvertMappingTask') - ->addTask('ensure-production-settings', $ns . '\EnsureProductionSettingsTask') - ->addTask('generate-proxies', $ns . '\GenerateProxiesTask') - ->addTask('run-dql', $ns . '\RunDqlTask') - ->addTask('schema-tool', $ns . '\SchemaToolTask') - ->addTask('version', $ns . '\VersionTask') - ->addTask('convert-d1-schema', $ns . '\ConvertDoctrine1SchemaTask') - ->addTask('generate-entities', $ns . '\GenerateEntitiesTask') - ->addTask('generate-repositories', $ns . '\GenerateRepositoriesTask'); - - $ns = 'Doctrine\DBAL\Tools\CLI\Tasks'; - $this->addNamespace('Dbal') - ->addTask('run-sql', $ns . '\RunSqlTask') - ->addTask('version', $ns . '\VersionTask'); - } - - /** - * Add a single task to CLI Core Namespace. This method acts as a delegate. - * Example of inclusion support to a single task: - * - * [php] - * $cli->addTask('my-custom-task', 'MyProject\CLI\Tasks\MyCustomTask'); - * - * @param string $name CLI Task name - * @param string $class CLI Task class (FQCN - Fully Qualified Class Name) - * - * @return CLIController This object instance - */ - public function addTask($name, $class) - { - $this->getNamespace('Core')->addTask($name, $class); - - return $this; - } - - /** - * Processor of CLI Tasks. Handles multiple task calls, instantiate - * respective classes and run them. - * - * @param array $args CLI Arguments - */ - public function run($args = array()) - { - // Remove script file argument - $scriptFile = array_shift($args); - - // If not arguments are defined, include "help" - if (empty($args)) { - array_unshift($args, 'Core:Help'); - } - - // Process all sent arguments - $args = $this->_processArguments($args); - - try { - $this->getPrinter()->writeln('Doctrine Command Line Interface' . PHP_EOL, 'HEADER'); - - // Handle possible multiple tasks on a single command - foreach($args as $taskData) { - $taskName = $taskData['name']; - $taskArguments = $taskData['args']; - - $this->runTask($taskName, $taskArguments); - } - - return true; - } catch (\Exception $e) { - $message = $taskName . ' => ' . $e->getMessage(); - - if (isset($taskArguments['trace']) && $taskArguments['trace']) { - $message .= PHP_EOL . PHP_EOL . $e->getTraceAsString(); - } - - $this->getPrinter()->writeln($message, 'ERROR'); - - return false; - } - } - - /** - * Executes a given CLI Task - * - * @param atring $name CLI Task name - * @param array $args CLI Arguments - */ - public function runTask($name, $args = array()) - { - // Retrieve namespace name, task name and arguments - $taskPath = explode(':', $name); - - // Find the correct namespace where the task is defined - $taskName = array_pop($taskPath); - $taskNamespace = $this->_retrieveTaskNamespace($taskPath); - - $taskNamespace->runTask($taskName, $args); - } - - /** - * Processes arguments and returns a structured hierachy. - * Example: - * - * cli.php foo -abc --option=value bar --option -a=value --optArr=value1,value2 - * - * Returns: - * - * array( - * 0 => array( - * 'name' => 'foo', - * 'args' => array( - * 'a' => true, - * 'b' => true, - * 'c' => true, - * 'option' => 'value', - * ), - * ), - * 1 => array( - * 'name' => 'bar', - * 'args' => array( - * 'option' => true, - * 'a' => 'value', - * 'optArr' => array( - * 'value1', 'value2' - * ), - * ), - * ), - * ) - * - * Based on implementation of Patrick Fisher available at: - * http://pwfisher.com/nucleus/index.php?itemid=45 - * - * @param array $args - * - * @return array - */ - private function _processArguments($args = array()) - { - $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE; - $regex = '/\s*[,]?\s*"([^"]*)"|\s*[,]?\s*([^,]*)/i'; - $preparedArgs = array(); - $out = & $preparedArgs; - - foreach ($args as $arg){ - // --foo --bar=baz - if (substr($arg, 0, 2) == '--'){ - $eqPos = strpos($arg, '='); - - // --foo - if ($eqPos === false){ - $key = substr($arg, 2); - $out[$key] = isset($out[$key]) ? $out[$key] : true; - // --bar=baz - } else { - $key = substr($arg, 2, $eqPos - 2); - $value = substr($arg, $eqPos + 1); - $value = (strpos($value, ' ') !== false) ? $value : array_values(array_filter( - explode(',', $value), function ($v) { return trim($v) != ''; } - )); - $out[$key] = ( ! is_array($value) || empty($value) || (is_array($value) && count($value) > 1)) - ? $value : $value[0]; - } - // -k=value -abc - } else if (substr($arg, 0, 1) == '-'){ - // -k=value - if (substr($arg, 2, 1) == '='){ - $key = substr($arg, 1, 1); - $value = substr($arg, 3); - $value = (strpos($value, ' ') !== false) ? $value : array_values(array_filter( - explode(',', $value), function ($v) { return trim($v) != ''; } - )); - $out[$key] = ( ! is_array($value) || (is_array($value) && count($value) > 1)) - ? $value : $value[0]; - // -abc - } else { - $chars = str_split(substr($arg, 1)); - - foreach ($chars as $char){ - $key = $char; - $out[$key] = isset($out[$key]) ? $out[$key] : true; - } - } - // plain-arg - } else { - $key = count($preparedArgs); - $preparedArgs[$key] = array( - 'name' => $arg, - 'args' => array() - ); - $out = & $preparedArgs[$key]['args']; - } - } - - return $preparedArgs; - } - - /** - * Retrieve the correct namespace given a namespace path - * - * @param array $namespacePath CLI Namespace path - * - * @return AbstractNamespace - */ - private function _retrieveTaskNamespace($namespacePath) - { - $taskNamespace = $this; - $currentNamespacePath = ''; - - // Consider possible missing namespace (ie. "help") and forward to "core" - if (count($namespacePath) == 0) { - $namespacePath = array('Core'); - } - - // Loop through each namespace - foreach ($namespacePath as $namespaceName) { - $taskNamespace = $taskNamespace->getNamespace($namespaceName); - - // If the given namespace returned "null", throw exception - if ($taskNamespace === null) { - throw CLIException::namespaceDoesNotExist($namespaceName, $currentNamespacePath); - } - - $currentNamespacePath = (( ! empty($currentNamespacePath)) ? ':' : '') - . $taskNamespace->getName(); - } - - return $taskNamespace; - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/CLIException.php b/lib/Doctrine/Common/CLI/CLIException.php deleted file mode 100644 index 33b0a609d..000000000 --- a/lib/Doctrine/Common/CLI/CLIException.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -/** - * CLI Exception class - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class CLIException extends \Exception -{ - public static function namespaceDoesNotExist($namespaceName, $namespacePath = '') - { - return new self( - "Namespace '{$namespaceName}' does not exist" . - (( ! empty($namespacePath)) ? " in '{$namespacePath}'." : '.') - ); - } - - public static function taskDoesNotExist($taskName, $namespacePath) - { - return new self("Task '{$taskName}' does not exist in '{$namespacePath}'."); - } - - public static function cannotOverrideTask($taskName) - { - return new self("Task '{$taskName}' cannot be overriden."); - } - - public static function cannotOverrideNamespace($namespace) { - return new self("Namespace '$namespace' cannot be overriden. Call overrideNamespace() directly."); - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Configuration.php b/lib/Doctrine/Common/CLI/Configuration.php deleted file mode 100644 index 99a6ad18e..000000000 --- a/lib/Doctrine/Common/CLI/Configuration.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -/** - * CLI Configuration class - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Configuration -{ - /** - * @var array Configuration attributes - */ - private $_attributes = array(); - - /** - * Defines a new configuration attribute - * - * @param string $name Attribute name - * @param mixed $value Attribute value - * - * @return Configuration This object instance - */ - public function setAttribute($name, $value = null) - { - $this->_attributes[$name] = $value; - - if ($value === null) { - unset($this->_attributes[$name]); - } - - return $this; - } - - /** - * Retrieves a configuration attribute - * - * @param string $name Attribute name - * - * @return mixed Attribute value - */ - public function getAttribute($name) - { - return isset($this->_attributes[$name]) - ? $this->_attributes[$name] : null; - } - - /** - * Checks if configuration attribute is defined - * - * @param string $name Attribute name - * - * @return boolean TRUE if attribute exists, FALSE otherwise - */ - public function hasAttribute($name) - { - return isset($this->_attributes[$name]); - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Option.php b/lib/Doctrine/Common/CLI/Option.php deleted file mode 100644 index d50427f2d..000000000 --- a/lib/Doctrine/Common/CLI/Option.php +++ /dev/null @@ -1,103 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -/** - * CLI Option definition - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Option -{ - /** @var string Option name */ - private $_name; - - /** @var string Option default value */ - private $_defaultValue; - - /** @var string Option description */ - private $description; - - /** - * Constructs a CLI Option - * - * @param string Option name - * @param integer Option type - * @param string Option description - */ - public function __construct($name, $defaultValue, $description) - { - $this->_name = $name; - $this->_defaultValue = $defaultValue; - $this->_description = $description; - } - - /** - * Retrieves the CLI Option name - * - * @return string Option name - */ - public function getName() - { - return $this->_name; - } - - /** - * Retrieves the CLI Option default value - * - * @return mixed Option default value - */ - public function getDefaultValue() - { - return $this->_defaultValue; - } - - /** - * Retrieves the CLI Option description - * - * @return string Option description - */ - public function getDescription() - { - return $this->_description; - } - - /** - * Converts the Option instance into a string representation - * - * @return string CLI Option representation in string - */ - public function __toString() - { - $defaultValue = ( ! is_null($this->_defaultValue)) - ? '=' . (is_array($this->_defaultValue) ? implode(',', $this->_defaultValue) : $this->_defaultValue) - : ''; - - return '--' . $this->_name . $defaultValue; - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/OptionGroup.php b/lib/Doctrine/Common/CLI/OptionGroup.php deleted file mode 100644 index 440d79e1b..000000000 --- a/lib/Doctrine/Common/CLI/OptionGroup.php +++ /dev/null @@ -1,482 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -use Doctrine\Common\CLI\Printers\AbstractPrinter; - -/** - * CLI Option Group definition - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class OptionGroup -{ - /* CLI Option Group CARDINALITY */ - /** - * Defines the cardinality 0..N to CLI Option Group. - * This means options in this group are optional and you can - * define more than one CLI Option on a single command. - */ - const CARDINALITY_0_N = 0; // [...] [...] [...] - - /** - * Defines the cardinality 0..1 to CLI Option Group. - * This means all options in this group are optional and you can - * define only one CLI Option on a single command. - */ - const CARDINALITY_0_1 = 1; // [...|...|...] - - /** - * Defines the cardinality 1..1 to CLI Option Group. - * This means all options in this group are required and you must - * define only one CLI Option on a single command. - */ - const CARDINALITY_1_1 = 2; // (...|...|...) - - /** - * Defines the cardinality 1..N to CLI Option Group. - * This means all options in this group are required and you must - * define at least one CLI Option on a single command. - */ - const CARDINALITY_1_N = 3; // (... ... ...) - - /** - * Defines the cardinality N..N to CLI Option Group. - * This means all options in this group are required and you must - * define all CLI Options on a single command. - */ - const CARDINALITY_N_N = 4; // ... ... ... - - /** - * Defines the cardinality M..N to CLI Option Group. - * This means all options in this group are either required or - * optional and you can CLI Options on a single command. - * This is the option to skip CLI Option validation. - */ - const CARDINALITY_M_N = 5; // ... ... ... - - - /** @var integer Option Group cardinality */ - private $_cadinality; - - /** @var array Option Group list of CLI Options */ - private $_options; - - - /** - * Constructs a new CLI Option Group - * - * @param integer Option Group cardinality - * @param array CLI Option Group options - */ - public function __construct($cardinality, $options = array()) - { - $this->_cardinality = $cardinality; - $this->_options = $options; - } - - /** - * Retrieves the CLI Option Group cardinality - * - * @return integer Option Group cardinality - */ - public function getCardinality() - { - return $this->_cardinality; - } - - /** - * Retrieves the CLI Option Group options - * - * @return array Option Group options - */ - public function getOptions() - { - return $this->_options; - } - - /** - * Cleans the CLI Options inside this CLI Option Group - * - */ - public function clear() - { - $this->_options = array(); - } - - /** - * Includes a new CLI Option to the Option Group - * - * @param Option|OptionGroup CLI Option or CLI Option Group - * @return OptionGroup This object instance - */ - public function addOption($option) - { - if ($option instanceof Option || $option instanceof OptionGroup) { - $this->_options[] = $option; - } - - return $this; - } - - /** - * Formats the CLI Option Group into a single line representation - * - * @param AbstractPrinter CLI Printer - * @return string Single line string representation of CLI Option Group - */ - public function formatPlain(AbstractPrinter $printer) - { - $numOptions = count($this->_options); - - if ($numOptions == 0) { - return ''; - } - - $style = $this->_getGroupOptionStyle(); - $shouldDisplayExtras = ( - $numOptions > 1 || - $this->_cardinality == self::CARDINALITY_0_1 || - $this->_cardinality == self::CARDINALITY_0_N - ); - - $str = ($shouldDisplayExtras) ? $printer->format($this->_startGroupDeclaration(), $style) : ''; - - // Loop through all CLI Options defined in OptionGroup - for ($i = 0; $i < $numOptions; $i++) { - $option = $this->_options[$i]; - - // Check for possible recursive OptionGroup - if ($option instanceof OptionGroup) { - // Simple increase nesting level by calling format recursively - $str .= $option->formatPlain($printer); - } else { - // Expose the option formatted - $str .= $printer->format((string) $option, $style); - } - - // Possibly append content if needed - if ($i < $numOptions - 1) { - $str .= $printer->format($this->_separatorGroupDeclaration(), $style); - } - } - - $str .= ($shouldDisplayExtras) ? $printer->format($this->_endGroupDeclaration(), $style) : ''; - - return $str; - } - - /** - * INTERNAL: - * Defines the start Option Group declaration string - * - * @return string Start Option Group declaration string - */ - private function _startGroupDeclaration() - { - $str = ''; - - // Inspect cardinality of OptionGroup - switch ($this->_cardinality) { - case self::CARDINALITY_0_1: - case self::CARDINALITY_0_N: - $str .= '['; - break; - - case self::CARDINALITY_1_1: - case self::CARDINALITY_1_N: - $str .= '('; - break; - - case self::CARDINALITY_N_N: - case self::CARDINALITY_M_N: - default: - // Does nothing - break; - } - - return $str; - } - - /** - * INTERNAL: - * Defines the separator Option Group declaration string - * - * @return string Separator Option Group declaration string - */ - private function _separatorGroupDeclaration() - { - $str = ''; - - // Inspect cardinality of OptionGroup - switch ($this->_cardinality) { - case self::CARDINALITY_0_1: - case self::CARDINALITY_1_1: - $str .= ' | '; - break; - - case self::CARDINALITY_1_N: - case self::CARDINALITY_N_N: - case self::CARDINALITY_M_N: - $str .= ' '; - break; - - case self::CARDINALITY_0_N: - $str .= '] ['; - break; - - default: - // Does nothing - break; - } - - return $str; - } - - /** - * INTERNAL: - * Defines the end Option Group declaration string - * - * @return string End Option Group declaration string - */ - private function _endGroupDeclaration() - { - $str = ''; - - // Inspect cardinality of OptionGroup - switch ($this->_cardinality) { - case self::CARDINALITY_0_1: - case self::CARDINALITY_0_N: - $str .= ']'; - break; - - case self::CARDINALITY_1_1: - case self::CARDINALITY_1_N: - $str .= ')'; - break; - - case self::CARDINALITY_N_N: - case self::CARDINALITY_M_N: - default: - // Does nothing - break; - } - - return $str; - } - - /** - * INTERNAL: - * Retrieve the Option Group style based on defined cardinality - * - * @return string CLI Style string representation - */ - private function _getGroupOptionStyle() - { - $style = 'NONE'; - - // Inspect cardinality of OptionGroup - switch ($this->_cardinality) { - case self::CARDINALITY_0_1: - case self::CARDINALITY_0_N: - $style = 'OPT_ARG'; - break; - - case self::CARDINALITY_1_1: - case self::CARDINALITY_1_N: - case self::CARDINALITY_N_N: - case self::CARDINALITY_M_N: - $style = 'REQ_ARG'; - break; - - default: - // Does nothing - break; - } - - return $style; - } - - /** - * Formats the CLI Option Group into a multi-line list with respective description - * - * @param AbstractPrinter CLI Printer - * @return string Multi-line string representation of CLI Option Group - */ - public function formatWithDescription(AbstractPrinter $printer) - { - $numOptions = count($this->_options); - - if ($numOptions == 0) { - return 'No available options' . PHP_EOL . PHP_EOL; - } - - $str = ''; - - // Get list of required and optional and max length options - list( - $requiredOptions, $optionalOptions, $maxOptionLength - ) = $this->_getOrganizedOptions( - $this->_options, $this->_cardinality, 0 - ); - - // Array-unique options - $requiredOptions = array_unique($requiredOptions); - $optionalOptions = array_unique($optionalOptions); - - // TODO Sort options alphabetically - - // Displaying required options - for ($i = 0, $l = count($requiredOptions); $i < $l; $i++) { - $str .= $this->_displayOptionWithDescription( - $printer, $requiredOptions[$i], 'REQ_ARG', $maxOptionLength - ); - - // Include extra line breaks between options - $str .= PHP_EOL . PHP_EOL; - } - - // Displaying optional options - for ($i = 0, $l = count($optionalOptions); $i < $l; $i++) { - $str .= $this->_displayOptionWithDescription( - $printer, $optionalOptions[$i], 'OPT_ARG', $maxOptionLength - ); - - // Include extra line breaks between options - $str .= PHP_EOL . PHP_EOL; - } - - return $str; - } - - /** - * Organize the Options into arrays of required and optional options. - * Also define the maximum length of CLI Options. - * - * @param array Array of CLI Option or CLI Option Group - * @param integer Current CLI OptionGroup cardinality - * @param integer Maximum length of CLI Options - * @return array Array containing 3 indexes: required options, optional - * options and maximum length of CLI Options - */ - private function _getOrganizedOptions($options, $cardinality, $maxColumn) - { - // Calculate maximum length and also organize the - // options into required and optional ones - $numOptions = count($options); - $requiredOptions = array(); - $optionalOptions = array(); - - for ($i = 0; $i < $numOptions; $i++) { - $option = $options[$i]; - - // Check for possible recursive OptionGroup - if ($option instanceof OptionGroup) { - // Initialize OptionGroup options - $groupRequiredOptions = array(); - $groupOptionalOptions = array(); - - // Get nested information - list( - $groupRequiredOptions, $groupOptionalOptions, $maxGroupColumn - ) = $this->_getOrganizedOptions( - $option->getOptions(), $option->getCardinality(), $maxColumn - ); - - // Merge nested required and optional options - $requiredOptions = array_merge($requiredOptions, $groupRequiredOptions); - $optionalOptions = array_merge($optionalOptions, $groupOptionalOptions); - - // If OptionGroup length is bigger than the current maximum, update - if ($maxColumn < $maxGroupColumn) { - $maxColumn = $maxGroupColumn; - } - } else { - // Cardinality defines between optional or required options - switch ($cardinality) { - case self::CARDINALITY_0_1: - case self::CARDINALITY_0_N: - $optionalOptions[] = $option; - break; - - case self::CARDINALITY_1_1: - case self::CARDINALITY_1_N: - case self::CARDINALITY_N_N: - case self::CARDINALITY_M_N: - $requiredOptions[] = $option; - break; - - default: - // Does nothing - break; - } - - // Build Option string - $optionStr = (string) $option; - - // + 2 = aditional spaces after option - $length = strlen($optionStr) + 2; - - if ($maxColumn < $length) { - $maxColumn = $length; - } - } - } - - return array($requiredOptions, $optionalOptions, $maxColumn); - } - - /** - * INTERNAL: - * Formats the CLI Option and also include the description - * - * @param AbstractPrinter CLI Printer - * @param Option CLI Option to be formatted - * @param string CLI Style string representation - * @param integer Maximum CLI Option length - * @return string Formats the current CLI Option line(s) - */ - private function _displayOptionWithDescription($printer, $option, $style, $maxOptionLength) - { - // Expose the option formatted - $optionStr = (string) $option; - - // Format Option string - $str = $printer->format($optionStr, $style); - - // Include missing spaces - $str .= str_repeat(' ', $maxOptionLength - strlen($optionStr)); - - // Calculate and display description - $str .= str_replace( - PHP_EOL, PHP_EOL . str_repeat(' ', $maxOptionLength), $option->getDescription() - ); - - return $str; - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Printers/AbstractPrinter.php b/lib/Doctrine/Common/CLI/Printers/AbstractPrinter.php deleted file mode 100644 index 7dd1a7907..000000000 --- a/lib/Doctrine/Common/CLI/Printers/AbstractPrinter.php +++ /dev/null @@ -1,190 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI\Printers; - -use Doctrine\Common\CLI\Style; - -/** - * CLI Output Printer. - * Abstract class responsable to provide basic methods to support output - * styling and excerpt limited by output margin. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -abstract class AbstractPrinter -{ - /** - * @var resource Output Stream - */ - protected $_stream; - - /** - * @var integer Maximum column size - */ - protected $_maxColumnSize; - - /** - * @var array Array of Styles - */ - protected $_styles; - - /** - * Creates an instance of Printer - * - * @param resource $stream Output Stream - */ - public function __construct($stream = STDOUT) - { - $this->_stream = $stream; - $this->_maxColumnSize = 80; - - $this->_initStyles(); - } - - /** - * Initializes Printer Styles - * - */ - protected function _initStyles() - { - // Defines base styles - $this->addStyles(array( - 'ERROR' => new Style(), - 'INFO' => new Style(), - 'COMMENT' => new Style(), - 'HEADER' => new Style(), - 'NONE' => new Style(), - )); - } - - /** - * Add a collection of styles to the Printer. - * To include them, just call the method with the following structure: - * - * [php] - * $printer->addStyles(array( - * 'ERROR' => new Style('BLACK', 'DEFAULT', array('BOLD' => true)), - * ... - * )); - * - * @param array $tasks CLI Tasks to be included - */ - public function addStyles($styles) - { - foreach ($styles as $name => $style) { - $this->addStyle($name, $style); - } - } - - /** - * Add a single Style to Printer. - * Example of inclusion to support a new Style: - * - * [php] - * $printer->addStyle('ERROR', new Style('BLACK', 'DEFAULT', array('BOLD' => true))); - * - * @param string $name Style name - * @param Style $style Style instance - */ - public function addStyle($name, Style $style) - { - $this->_styles[strtoupper($name)] = $style; - } - - /** - * Retrieves a defined Style. - * - * @return Style - */ - public function getStyle($name) - { - if (is_string($name)) { - $name = strtoupper($name); - return isset($this->_styles[$name]) ? $this->_styles[$name] : null; - } - - return $name; - } - - /** - * Sets the maximum column size (defines the CLI margin). - * - * @param integer $maxColumnSize The maximum column size for a message - */ - public function setMaxColumnSize($maxColumnSize) - { - $this->_maxColumnSize = $maxColumnSize; - } - - /** - * Writes to the output stream. - * - * @param string $message Message to be outputted - */ - public function output($message) - { - fwrite($this->_stream, $message); - - return $this; - } - - /** - * Formats message applying the defined style and writes to the output stream. - * - * @param string $message Message to be outputted - * @param mixed $style Optional style to be applied in message - */ - public function write($message, $style = 'NONE') - { - $this->output($this->format($message, $style)); - - return $this; - } - - /** - * Writes a line to the output stream, formatting it by applying the defined style. - * - * @param string $message Message to be outputted - * @param mixed $style Optional style to be applied in message - */ - public function writeln($message, $style = 'NONE') - { - $this->output($this->format($message, $style) . PHP_EOL); - - return $this; - } - - /** - * Formats the given message with the defined style. - * - * @param string $message Message to be formatted - * @param mixed $style Style to be applied in message - * @return string Formatted message - */ - abstract public function format($message, $style); -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Printers/AnsiColorPrinter.php b/lib/Doctrine/Common/CLI/Printers/AnsiColorPrinter.php deleted file mode 100644 index ef78b9ed5..000000000 --- a/lib/Doctrine/Common/CLI/Printers/AnsiColorPrinter.php +++ /dev/null @@ -1,214 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI\Printers; - -use Doctrine\Common\CLI\Style; - -/** - * CLI Output Printer for ANSI Color terminal - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class AnsiColorPrinter extends AbstractPrinter -{ - /** - * @inheritdoc - */ - protected function _initStyles() - { - $this->addStyles(array( - 'HEADER' => new Style('DEFAULT', 'DEFAULT', array('BOLD' => true)), - 'ERROR' => new Style('WHITE', 'RED', array('BOLD' => true)), - 'WARNING' => new Style('DEFAULT', 'YELLOW'), - 'KEYWORD' => new Style('BLUE', 'DEFAULT', array('BOLD' => true)), - 'REQ_ARG' => new Style('MAGENTA', 'DEFAULT', array('BOLD' => true)), - 'OPT_ARG' => new Style('CYAN', 'DEFAULT', array('BOLD' => true)), - 'INFO' => new Style('GREEN', 'DEFAULT', array('BOLD' => true)), - 'COMMENT' => new Style('DEFAULT', 'MAGENTA'), - 'NONE' => new Style(), - )); - } - - /** - * @inheritdoc - */ - public function format($message, $style = 'NONE') - { - if ( ! $this->_supportsColor()) { - return $message; - } - - $style = $this->getStyle($style); - $str = $this->_getForegroundString($style) - . $this->_getBackgroundString($style); - $styleSet = ($str != ''); - - return $str . $message . ($styleSet ? chr(27) . '[0m' : ''); - } - - /** - * Retrieves the ANSI string representation of requested color name - * - * @param Style $style Style - * @return string - */ - protected function _getBackgroundString(Style $style) - { - $background = $style->getBackground(); - - if (empty($background)) { - return ''; - } - - $esc = chr(27); - - switch (strtoupper($background)) { - case 'BLACK': - return $esc . '[40m'; - case 'RED': - return $esc . '[41m'; - case 'GREEN': - return $esc . '[42m'; - case 'YELLOW': - return $esc . '[43m'; - case 'BLUE': - return $esc . '[44m'; - case 'MAGENTA': - return $esc . '[45m'; - case 'CYAN': - return $esc . '[46m'; - case 'WHITE': - return $esc . '[47m'; - case 'DEFAULT': - default: - return $esc . '[48m'; - } - } - - /** - * Retrieves the ANSI string representation of requested color name - * - * @param Style $style Style - * @return string - */ - protected function _getForegroundString(Style $style) - { - $foreground = $style->getForeground(); - - if (empty($foreground)) { - return ''; - } - - $str = chr(27) . '[' . $this->_getOptionsString($style); - - switch (strtoupper($foreground)) { - case 'BLACK': - return $str . '30m'; - case 'RED': - return $str . '31m'; - case 'GREEN': - return $str . '32m'; - case 'YELLOW': - return $str . '33m'; - case 'BLUE': - return $str . '34m'; - case 'MAGENTA': - return $str . '35m'; - case 'CYAN': - return $str . '36m'; - case 'WHITE': - return $str . '37m'; - case 'DEFAULT_FGU': - return $str . '38m'; - case 'DEFAULT': - default: - return $str . '39m'; - } - } - - /** - * Retrieves the ANSI string representation of requested options - * - * @param Style $style Style - * @return string - */ - protected function _getOptionsString(Style $style) - { - $options = $style->getOptions(); - - if (empty($options)) { - return ''; - } - - $str = ''; - - foreach ($options as $name => $value) { - if ($value) { - $name = strtoupper($name); - - switch ($name) { - case 'BOLD': - $str .= '1;'; - break; - case 'HALF': - $str .= '2;'; - break; - case 'UNDERLINE': - $str .= '4;'; - break; - case 'BLINK': - $str .= '5;'; - break; - case 'REVERSE': - $str .= '7;'; - break; - case 'CONCEAL': - $str .= '8;'; - break; - default: - // Ignore unknown option - break; - } - } - } - - return $str; - } - - /** - * Checks if the current Output Stream supports ANSI Colors - * - * @return boolean - */ - private function _supportsColor() - { - return DIRECTORY_SEPARATOR != '\\' && - function_exists('posix_isatty') && - @posix_isatty($this->_stream); - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Printers/NormalPrinter.php b/lib/Doctrine/Common/CLI/Printers/NormalPrinter.php deleted file mode 100644 index 2293be4fe..000000000 --- a/lib/Doctrine/Common/CLI/Printers/NormalPrinter.php +++ /dev/null @@ -1,46 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI\Printers; - -use Doctrine\Common\CLI\Style; - -/** - * CLI Output Printer for Normal terminal - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class NormalPrinter extends AbstractPrinter -{ - /** - * @inheritdoc - */ - public function format($message, $style) - { - return $message; - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Style.php b/lib/Doctrine/Common/CLI/Style.php deleted file mode 100644 index 12a35acb5..000000000 --- a/lib/Doctrine/Common/CLI/Style.php +++ /dev/null @@ -1,93 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -/** - * CLI Output Style - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Style -{ - /** - * @var string Background color - */ - private $_background; - - /** - * @var string Foreground color - */ - private $_foreground; - - /** - * @var array Formatting options - */ - private $_options = array(); - - /** - * @param string $foreground Foreground color name - * @param string $background Background color name - * @param array $options Formatting options - */ - public function __construct($foreground = null, $background = null, $options = array()) - { - $this->_foreground = strtoupper($foreground); - $this->_background = strtoupper($background); - $this->_options = $options; - } - - /** - * Retrieves the foreground color name - * - * @return string - */ - public function getForeground() - { - return $this->_foreground; - } - - /** - * Retrieves the background color name - * - * @return string - */ - public function getBackground() - { - return $this->_background; - } - - /** - * Retrieves the formatting options - * - * @return string - */ - public function getOptions() - { - return $this->_options; - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/TaskDocumentation.php b/lib/Doctrine/Common/CLI/TaskDocumentation.php deleted file mode 100644 index 5cf658ff6..000000000 --- a/lib/Doctrine/Common/CLI/TaskDocumentation.php +++ /dev/null @@ -1,192 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -use Doctrine\Common\CLI\Printers\AbstractPrinter, - Doctrine\Common\CLI\OptionGroup, - Doctrine\Common\CLI\Option; - -/** - * CLI Task documentation - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class TaskDocumentation -{ - /** @var AbstractPrinter CLI Printer */ - private $_printer; - - /** @var AbstractNamespace CLI Namespace */ - private $_namespace; - - /** @var string CLI Task name */ - private $_name; - - /** @var string CLI Task description */ - private $_description; - - /** @var array CLI Task Option Group */ - private $_optionGroup; - - /** - * Constructs a new CLI Task Documentation - * - * @param AbstractNamespace CLI Namespace - */ - public function __construct(AbstractNamespace $namespace) - { - $this->_namespace = $namespace; - $this->_printer = $namespace->getPrinter(); - $this->_optionGroup = new OptionGroup(OptionGroup::CARDINALITY_M_N); - } - - /** - * Retrieves the CLI Namespace - * - * @return AbstractNamespace - */ - public function getNamespace() - { - return $this->_namespace; - } - - /** - * Defines the CLI Task name - * - * @param string Task name - * @return TaskDocumentation This object instance - */ - public function setName($name) - { - $this->_name = $name; - - return $this; - } - - /** - * Retrieves the CLI Task name - * - * @return string Task name - */ - public function getName() - { - return $this->_name; - } - - /** - * Retrieves the full CLI Task name - * - * @return string Task full name - */ - public function getFullName() - { - return $this->getNamespace()->getFullName() . ':' . $this->_name; - } - - /** - * Defines the CLI Task description - * - * @param string Task description - * @return TaskDocumentation This object instance - */ - public function setDescription($description) - { - $this->_description = $description; - - return $this; - } - - /** - * Retrieves the CLI Task description - * - * @var string Task description - */ - public function getDescription() - { - return $this->_description; - } - - /** - * Retrieves the CLI Task Option Group - * - * @return OptionGroup CLI Task Option Group - */ - public function getOptionGroup() - { - return $this->_optionGroup; - } - - /** - * Includes a new CLI Option Group to the CLI Task documentation - * - * @param OptionGroup CLI Option Group - * @return TaskDocumentation This object instance - */ - public function addOption($option) - { - if ($option instanceof OptionGroup) { - $this->_optionGroup->addOption($option); - } - - return $this; - } - - /** - * Retrieves the synopsis of associated CLI Task - * - * @return string CLI Task synopsis - */ - public function getSynopsis() - { - return $this->_printer->format($this->getFullName(), 'KEYWORD') . ' ' - . trim($this->_optionGroup->formatPlain($this->_printer)); - } - - /** - * Retrieve the complete documentation of associated CLI Task - * - * @return string CLI Task complete documentation - */ - public function getCompleteDocumentation() - { - $printer = $this->_printer; - - return $printer->format('Task: ') - . $printer->format($this->getFullName(), 'KEYWORD') - . $printer->format(PHP_EOL) - . $printer->format('Synopsis: ') - . $this->getSynopsis() - . $printer->format(PHP_EOL) - . $printer->format('Description: ') - . $printer->format($this->_description) - . $printer->format(PHP_EOL) - . $printer->format('Options: ') - . $printer->format(PHP_EOL) - . $this->_optionGroup->formatWithDescription($printer); - } -} diff --git a/lib/Doctrine/Common/CLI/TaskNamespace.php b/lib/Doctrine/Common/CLI/TaskNamespace.php deleted file mode 100644 index 9c9936f47..000000000 --- a/lib/Doctrine/Common/CLI/TaskNamespace.php +++ /dev/null @@ -1,251 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI; - -/** - * CLI Namespace class - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class TaskNamespace extends AbstractNamespace -{ - /** - * @var boolean CLI Tasks flag to check if they are already initialized - */ - private $_initialized = false; - - /** - * @var string CLI Namespace full name - */ - private $_fullName = null; - - /** - * @var string CLI Namespace name - */ - private $_name = null; - - /** - * @var array Available tasks - */ - private $_tasks = array(); - - /** - * The CLI namespace - * - * @param string $name CLI Namespace name - */ - public function __construct($name) - { - $this->_name = self::formatName($name); - } - - /** - * Retrieve an instantiated CLI Task by given its name. - * - * @param string $name CLI Task name - * - * @return AbstractTask - */ - public function getTask($name) - { - // Check if task exists in namespace - if ($this->hasTask($name)) { - $taskClass = $this->_tasks[self::formatName($name)]; - - return new $taskClass($this); - } - - throw CLIException::taskDoesNotExist($name, $this->getFullName()); - } - - /** - * Retrieve all CLI Task in this Namespace. - * - * @return array - */ - public function getTasks() - { - return $this->_tasks; - } - - /** - * Retrieve all defined CLI Tasks - * - * @return array - */ - public function getAvailableTasks() - { - $tasks = parent::getAvailableTasks(); - - foreach ($this->_tasks as $taskName => $taskClass) { - $fullName = $this->getFullName() . ':' . $taskName; - - $tasks[$fullName] = $taskClass; - } - - return $tasks; - } - - /** - * Add a single task to CLI Namespace. - * Example of inclusion support to a single task: - * - * [php] - * $cliOrmNamespace->addTask('my-custom-task', 'MyProject\Cli\Tasks\MyCustomTask'); - * - * @param string $name CLI Task name - * @param string $class CLI Task class (FQCN - Fully Qualified Class Name) - * - * @return TaskNamespace This object instance - */ - public function addTask($name, $class) - { - $name = self::formatName($name); - - if ($this->hasTask($name)) { - throw CLIException::cannotOverrideTask($name); - } - - return $this->overrideTask($name, $class); - } - - /** - * Overrides task on CLI Namespace. - * Example of inclusion support to a single task: - * - * [php] - * $cliOrmNamespace->overrideTask('schema-tool', 'MyProject\Cli\Tasks\MyCustomTask'); - * - * @param string $name CLI Task name - * @param string $class CLI Task class (FQCN - Fully Qualified Class Name) - * - * @return TaskNamespace This object instance - */ - public function overrideTask($name, $class) - { - $name = self::formatName($name); - - $this->_tasks[$name] = $class; - - return $this; - } - - /** - * Check existance of a CLI Task - * - * @param string CLI Task name - * - * @return boolean TRUE if CLI Task if defined, false otherwise - */ - public function hasTask($name) - { - $name = self::formatName($name); - - return isset($this->_tasks[$name]); - } - - /** - * Retrieves the CLI Namespace name - * - * @return string CLI Namespace name - */ - public function getName() - { - return $this->_name; - } - - /** - * Retrieves the full CLI Namespace name - * - * @return string CLI Namespace full name - */ - public function getFullName() - { - if ($this->_fullName === null) { - $str = $this->_name; - - while ( - ($parentNamespace = $this->getParentNamespace()) !== null && - ! ($parentNamespace instanceof CliController) - ) { - $str = $parentNamespace->getFullName() . ':' . $str; - } - - $this->_fullName = $str; - } - - return $this->_fullName; - } - - /** - * Effectively instantiate and execute a given CLI Task - * - * @param string $name CLI Task name - * @param array $arguments CLI Task arguments - */ - public function runTask($name, $arguments = array()) - { - try { - $task = $this->getTask($name); - - // Merge global configuration if it exists - if (($globalArgs = $this->getConfiguration()->getAttribute('globalArguments')) !== null) { - $arguments = array_merge($globalArgs, $arguments); - } - - $task->setArguments($arguments); - - if ((isset($arguments['help']) && $arguments['help']) || (isset($arguments['h']) && $arguments['h'])) { - $task->extendedHelp(); // User explicitly asked for help option - } else if (isset($arguments['basic-help']) && $arguments['basic-help']) { - $task->basicHelp(); // User explicitly asked for basic help option - } else if ($task->validate()) { - $task->run(); - } - } catch (CLIException $e) { - $message = $this->getFullName() . ':' . $name . ' => ' . $e->getMessage(); - $printer = $this->getPrinter(); - - // If we want the trace of calls, append to error message - if (isset($arguments['trace']) && $arguments['trace']) { - $message .= PHP_EOL . PHP_EOL . $e->getTraceAsString(); - } - - $printer->writeln($message, 'ERROR'); - - // Unable instantiate task or task is not valid - if (isset($task) && $task !== null) { - $printer->write(PHP_EOL); - $task->basicHelp(); // Fallback of not-valid task arguments - } - - $printer->write(PHP_EOL); - } - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Tasks/AbstractTask.php b/lib/Doctrine/Common/CLI/Tasks/AbstractTask.php deleted file mode 100644 index 28c783b0b..000000000 --- a/lib/Doctrine/Common/CLI/Tasks/AbstractTask.php +++ /dev/null @@ -1,200 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI\Tasks; - -use Doctrine\Common\CLI\AbstractNamespace, - Doctrine\Common\CLI\TaskDocumentation; - -/** - * Base class for CLI Tasks. - * Provides basic methods and requires implementation of methods that - * each task should implement in order to correctly work. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -abstract class AbstractTask -{ - /** - * @var AbstractNamespace CLI Namespace - */ - protected $_printer; - - /** - * @var TaskDocumentation CLI Task Documentation - */ - protected $_documentation; - - /** - * @var array CLI Task arguments - */ - protected $_arguments = array(); - - /** - * Constructor of CLI Task - * - * @param AbstractNamespace CLI Namespace - */ - public function __construct(AbstractNamespace $namespace) - { - $this->_namespace = $namespace; - $this->_documentation = new TaskDocumentation($namespace); - - // Complete the CLI Task Documentation creation - $this->buildDocumentation(); - } - - /** - * Retrieves the CLI Namespace - * - * @return AbstractNamespace - */ - public function getNamespace() - { - return $this->_namespace; - } - - /** - * Retrieves the CLI Task Documentation - * - * @return TaskDocumentation - */ - public function getDocumentation() - { - return $this->_documentation; - } - - /** - * Defines the CLI Task arguments - * - * @param array $arguments CLI Task arguments - * - * @return AbstractTask - */ - public function setArguments(array $arguments = array()) - { - $this->_arguments = $arguments; - - return $this; - } - - /** - * Retrieves the CLI Task arguments - * - * @return array - */ - public function getArguments() - { - return $this->_arguments; - } - - /** - * Retrieves currently used CLI Output Printer - * - * @return AbstractPrinter - */ - public function getPrinter() - { - return $this->_namespace->getPrinter(); - } - - /** - * Retrieves current used CLI Configuration - * - * @return Configuration - */ - public function getConfiguration() - { - return $this->_namespace->getConfiguration(); - } - - /** - * Expose to CLI Output Printer the extended help of the given task. - * This means it should detail all parameters, options and the meaning - * of each one. - * This method is executed when user types in CLI the following command: - * - * [bash] - * ./doctrine task --help - * - */ - public function extendedHelp() - { - $this->getPrinter()->output($this->_documentation->getCompleteDocumentation()); - } - - /** - * Expose to CLI Output Printer the basic help of the given task. - * This means it should only expose the basic task call. It is also - * executed when user calls the global help; so this means it should - * not pollute the Printer. - * Basic help exposure is displayed when task does not pass the validate - * (which means when user does not type the required options or when given - * options are invalid, ie: invalid option), or when user requests to have - * description of all available tasks. - * This method is executed when user uses the following commands: - * - * [bash] - * ./doctrine task --invalid-option - * ./doctrine --help - * - */ - public function basicHelp() - { - $this->getPrinter() - ->output($this->_documentation->getSynopsis()) - ->output(PHP_EOL) - ->output(' ' . $this->_documentation->getDescription()) - ->output(PHP_EOL . PHP_EOL); - } - - /** - * Assures the given arguments matches with required/optional ones. - * This method should be used to introspect arguments to check for - * missing required arguments and also for invalid defined options. - * - * @return boolean - */ - public function validate() - { - // TODO implement DAG here! - return true; - } - - /** - * Safely execution of task. - * Each CLI task should implement this as normal flow execution of - * what is supposed to do. - */ - abstract public function run(); - - /** - * Generate the CLI Task Documentation - */ - abstract public function buildDocumentation(); -} diff --git a/lib/Doctrine/Common/CLI/Tasks/HelpTask.php b/lib/Doctrine/Common/CLI/Tasks/HelpTask.php deleted file mode 100644 index 7e25a00dd..000000000 --- a/lib/Doctrine/Common/CLI/Tasks/HelpTask.php +++ /dev/null @@ -1,79 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI\Tasks; - -use Doctrine\Common\CLI\CLIException; - -/** - * CLI Task to display available commands help - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class HelpTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $doc = $this->getDocumentation(); - $doc->setName('help') - ->setDescription('Exposes helpful information about all available tasks.'); - } - - /** - * @inheritdoc - */ - public function extendedHelp() - { - $this->run(); - } - - /** - * Exposes the available tasks - * - */ - public function run() - { - $this->getPrinter()->writeln('Available Tasks:', 'HEADER')->write(PHP_EOL); - - // Find the CLI Controller - $cliController = $this->getNamespace()->getParentNamespace(); - - // Switch between ALL available tasks and display the basic Help of each one - $availableTasks = $cliController->getAvailableTasks(); - //unset($availableTasks['Core:Help']); - - ksort($availableTasks); - - foreach (array_keys($availableTasks) as $taskName) { - $cliController->runTask($taskName, array('basic-help' => true)); - } - } -} \ No newline at end of file diff --git a/lib/Doctrine/Common/CLI/Tasks/VersionTask.php b/lib/Doctrine/Common/CLI/Tasks/VersionTask.php deleted file mode 100644 index 119d08753..000000000 --- a/lib/Doctrine/Common/CLI/Tasks/VersionTask.php +++ /dev/null @@ -1,61 +0,0 @@ -. - */ - -namespace Doctrine\Common\CLI\Tasks; - -use Doctrine\Common\Version; - -/** - * CLI Task to display the doctrine version - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class VersionTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - // There're no options on this task - $this->getDocumentation()->getOptionGroup()->clear(); - - $doc = $this->getDocumentation(); - $doc->setName('version') - ->setDescription('Displays the current installed Doctrine version.'); - } - - /** - * Displays the current version of Doctrine - * - */ - public function run() - { - $this->getPrinter()->writeln('You are currently running Doctrine ' . Version::VERSION, 'INFO'); - } -} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Tools/CLI/Tasks/RunSqlTask.php b/lib/Doctrine/DBAL/Tools/CLI/Tasks/RunSqlTask.php deleted file mode 100644 index 687f5e071..000000000 --- a/lib/Doctrine/DBAL/Tools/CLI/Tasks/RunSqlTask.php +++ /dev/null @@ -1,171 +0,0 @@ -. - */ - -namespace Doctrine\DBAL\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\CLIException, - Doctrine\Common\Util\Debug, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup; - -/** - * Task for executing arbitrary SQL that can come from a file or directly from - * the command line. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class RunSqlTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $dqlAndFile = new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option( - 'sql', '', 'The SQL to execute.' . PHP_EOL . - 'If defined, --file can not be requested on same task.' - ), - new Option( - 'file', '', 'The path to the file with the SQL to execute.' . PHP_EOL . - 'If defined, --sql can not be requested on same task.' - ) - )); - - $depth = new OptionGroup(OptionGroup::CARDINALITY_0_1, array( - new Option('depth', '', 'Dumping depth of Entities graph.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('run-sql') - ->setDescription('Executes arbitrary SQL from a file or directly from the command line.') - ->getOptionGroup() - ->addOption($dqlAndFile) - ->addOption($depth); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - if ( ! (isset($arguments['sql']) ^ isset($arguments['file']))) { - throw new CLIException('One of --sql or --file required, and only one.'); - } - - return true; - } - - - /** - * Executes the task. - */ - public function run() - { - $arguments = $this->getArguments(); - - if (isset($arguments['file'])) { - $em = $this->getConfiguration()->getAttribute('em'); - $conn = $em->getConnection(); - $printer = $this->getPrinter(); - - $fileNames = (array) $arguments['file']; - - foreach ($fileNames as $fileName) { - if ( ! file_exists($fileName)) { - throw new CLIException(sprintf('The SQL file [%s] does not exist.', $fileName)); - } else if ( ! is_readable($fileName)) { - throw new CLIException(sprintf('The SQL file [%s] does not have read permissions.', $fileName)); - } - - $printer->write('Processing file [' . $fileName . ']... '); - $sql = file_get_contents($fileName); - - if ($conn instanceof \Doctrine\DBAL\Driver\PDOConnection) { - // PDO Drivers - try { - $lines = 0; - - $stmt = $conn->prepare($sql); - $stmt->execute(); - - do { - // Required due to "MySQL has gone away!" issue - $stmt->fetch(); - $stmt->closeCursor(); - - $lines++; - } while ($stmt->nextRowset()); - - $printer->writeln(sprintf('%d statements executed!', $lines)); - } catch (\PDOException $e) { - $printer->writeln('error!') - ->writeln($e->getMessage()); - } - } else { - // Non-PDO Drivers (ie. OCI8 driver) - $stmt = $conn->prepare($sql); - $rs = $stmt->execute(); - - if ($rs) { - $printer->writeln('OK!'); - } else { - $error = $stmt->errorInfo(); - - $printer->writeln('error!') - ->writeln($error['message']); - } - - $stmt->closeCursor(); - } - } - } else if (isset($arguments['sql'])) { - $em = $this->getConfiguration()->getAttribute('em'); - - if (preg_match('/^select/i', $arguments['sql'])) { - $stmt = $em->getConnection()->executeQuery($arguments['sql']); - $resultSet = $stmt->fetchAll(\Doctrine\DBAL\Connection::FETCH_ASSOC); - } else { - $resultSet = $em->getConnection()->executeUpdate($arguments['sql']); - } - - $maxDepth = isset($arguments['depth']) ? $arguments['depth'] : 7; - - Debug::dump($resultSet, $maxDepth); - } - } -} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Tools/CLI/Tasks/VersionTask.php b/lib/Doctrine/DBAL/Tools/CLI/Tasks/VersionTask.php deleted file mode 100644 index 273132d9b..000000000 --- a/lib/Doctrine/DBAL/Tools/CLI/Tasks/VersionTask.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\DBAL\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\Version; - -/** - * CLI Task to display the doctrine version - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class VersionTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - // There're no options on this task - $this->getDocumentation()->getOptionGroup()->clear(); - - $doc = $this->getDocumentation(); - $doc->setName('version') - ->setDescription('Displays the current installed Doctrine version.'); - } - - /** - * Displays the current version of Doctrine - * - */ - public function run() - { - $this->getPrinter()->writeln('You are currently running Doctrine ' . Version::VERSION, 'INFO'); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/ClearCacheTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/ClearCacheTask.php deleted file mode 100644 index 5dcfed081..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/ClearCacheTask.php +++ /dev/null @@ -1,205 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\CliException, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup, - Doctrine\Common\Cache\AbstractDriver; - -/** - * CLI Task to clear the cache of the various cache drivers - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ClearCacheTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $cacheOptions = new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option('query', null, 'Clear the query cache.'), - new Option('metadata', null, 'Clear the metadata cache.'), - new OptionGroup(OptionGroup::CARDINALITY_M_N, array( - new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option('result', null, 'Clear the result cache.') - )), - new OptionGroup(OptionGroup::CARDINALITY_0_N, array( - new Option('id', '', 'The id of the cache entry to delete (accepts * wildcards).'), - new Option('regex', '', 'Delete cache entries that match the given regular expression.'), - new Option('prefix', '', 'Delete cache entries that have the given prefix.'), - new Option('suffix', '', 'Delete cache entries that have the given suffix.') - )) - )) - )); - - $doc = $this->getDocumentation(); - $doc->setName('clear-cache') - ->setDescription('Clear cache from configured query, result and metadata drivers.') - ->getOptionGroup() - ->addOption($cacheOptions); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - - // Check if we have an active EntityManager - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - // When clearing the query cache no need to specify - // id, regex, prefix or suffix. - if ( - (isset($arguments['query']) || isset($arguments['metadata'])) && (isset($arguments['id']) || - isset($arguments['regex']) || isset($arguments['prefix']) || isset($arguments['suffix'])) - ) { - throw new CLIException( - 'When clearing the query or metadata cache do not ' . - 'specify any --id, --regex, --prefix or --suffix.' - ); - } - - return true; - } - - /** - * @inheritdoc - */ - public function run() - { - $arguments = $this->getArguments(); - $printer = $this->getPrinter(); - - $query = isset($arguments['query']); - $result = isset($arguments['result']); - $metadata = isset($arguments['metadata']); - $id = isset($arguments['id']) ? $arguments['id'] : null; - $regex = isset($arguments['regex']) ? $arguments['regex'] : null; - $prefix = isset($arguments['prefix']) ? $arguments['prefix'] : null; - $suffix = isset($arguments['suffix']) ? $arguments['suffix'] : null; - - $all = false; - - if ( ! $query && ! $result && ! $metadata) { - $all = true; - } - - $em = $this->getConfiguration()->getAttribute('em'); - $configuration = $em->getConfiguration(); - - if ($query || $all) { - $this->_doDelete( - 'query', $configuration->getQueryCacheImpl(), $id, $regex, $prefix, $suffix - ); - } - - if ($result || $all) { - $this->_doDelete( - 'result', $configuration->getResultCacheImpl(), $id, $regex, $prefix, $suffix - ); - } - - if ($metadata || $all) { - $this->_doDelete( - 'metadata', $configuration->getMetadataCacheImpl(), $id, $regex, $prefix, $suffix - ); - } - } - - private function _doDelete($type, $cacheDriver, $id, $regex, $prefix, $suffix) - { - $printer = $this->getPrinter(); - - if ( ! $cacheDriver) { - throw new CLIException('No driver has been configured for the ' . $type . ' cache.'); - } - - if ($id) { - $printer->writeln('Clearing ' . $type . ' cache entries that match the id "' . $id . '".', 'INFO'); - - $deleted = $cacheDriver->delete($id); - - if (is_array($deleted)) { - $this->_printDeleted($type, $deleted); - } else if (is_bool($deleted) && $deleted) { - $this->_printDeleted($type, array($id)); - } - } - - if ($regex) { - $printer->writeln('Clearing ' . $type . ' cache entries that match the regular expression ".' . $regex . '"', 'INFO'); - - $this->_printDeleted($type, $cacheDriver->deleteByRegex('/' . $regex. '/')); - } - - if ($prefix) { - $printer->writeln('Clearing ' . $type . ' cache entries that have the prefix "' . $prefix . '".', 'INFO'); - - $this->_printDeleted($type, $cacheDriver->deleteByPrefix($prefix)); - } - - if ($suffix) { - $printer->writeln('Clearing ' . $type . ' cache entries that have the suffix "' . $suffix . '".', 'INFO'); - - $this->_printDeleted($type, $cacheDriver->deleteBySuffix($suffix)); - } - - if ( ! $id && ! $regex && ! $prefix && ! $suffix) { - $printer->writeln('Clearing all ' . $type . ' cache entries.', 'INFO'); - - $this->_printDeleted($type, $cacheDriver->deleteAll()); - } - } - - private function _printDeleted($type, array $ids) - { - $printer = $this->getPrinter(); - - if ( ! empty($ids)) { - foreach ($ids as $id) { - $printer->writeln(' - ' . $id); - } - } else { - throw new CLIException('No ' . $type . ' cache entries found.'); - } - - $printer->write(PHP_EOL); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertDoctrine1SchemaTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertDoctrine1SchemaTask.php deleted file mode 100644 index 42bbfda20..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertDoctrine1SchemaTask.php +++ /dev/null @@ -1,117 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\ORM\Tools\Export\ClassMetadataExporter, - Doctrine\Common\CLI\CliException, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup, - Doctrine\ORM\Tools\ConvertDoctrine1Schema, - Doctrine\ORM\Tools\EntityGenerator; - -/** - * CLI Task to convert a Doctrine 1 schema to a Doctrine 2 mapping file - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConvertDoctrine1SchemaTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $options = new OptionGroup(OptionGroup::CARDINALITY_N_N, array( - new Option('from', '', 'The path to the Doctrine 1 schema.'), - new Option('to', '', 'The Doctrine 2 mapping format to convert to.'), - new Option('dest', '', 'The path to export the converted schema.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('convert-10-schema') - ->setDescription('Converts a Doctrine 1.X schema into a Doctrine 2.X schema.') - ->getOptionGroup() - ->addOption($options); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - - if ( ! isset($arguments['from']) || ! isset($arguments['to']) || ! isset($arguments['dest'])) { - throw new CLIException('You must specify a value for --from, --to and --dest'); - } - - return true; - } - - public function run() - { - $arguments = $this->getArguments(); - $printer = $this->getPrinter(); - - $printer->writeln(sprintf( - 'Converting Doctrine 1 schema at "%s" to the "%s" format', - $printer->format($arguments['from'], 'KEYWORD'), - $printer->format($arguments['to'], 'KEYWORD') - ) - ); - - $cme = new ClassMetadataExporter(); - $exporter = $cme->getExporter($arguments['to'], $arguments['dest']); - - if ($arguments['to'] === 'annotation') { - $entityGenerator = new EntityGenerator(); - $exporter->setEntityGenerator($entityGenerator); - } - - $converter = new ConvertDoctrine1Schema($arguments['from']); - $metadatas = $converter->getMetadatas(); - - foreach ($metadatas as $metadata) { - $printer->writeln( - sprintf('Processing entity "%s"', $printer->format($metadata->name, 'KEYWORD')) - ); - } - - $exporter->setMetadatas($metadatas); - $exporter->export(); - - $printer->writeln(sprintf( - 'Writing Doctrine 2 mapping files to "%s"', - $printer->format($arguments['dest'], 'KEYWORD') - ) - ); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertMappingTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertMappingTask.php deleted file mode 100644 index 962b6fdc7..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/ConvertMappingTask.php +++ /dev/null @@ -1,163 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\CliException, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup, - Doctrine\ORM\Tools\EntityGenerator, - Doctrine\ORM\Tools\Export\ClassMetadataExporter, - Doctrine\ORM\Mapping\Driver\DriverChain, - Doctrine\ORM\Mapping\Driver\AnnotationDriver, - Doctrine\ORM\Mapping\Driver\Driver; - -/** - * CLI Task to convert your mapping information between the various formats - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConvertMappingTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $convertOptions = new OptionGroup(OptionGroup::CARDINALITY_N_N, array( - new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option('from', '', 'The path to the mapping information to convert from (yml, xml, php, annotation).'), - new Option('from-database', null, 'Use this option if you wish to reverse engineer your database to a set of Doctrine mapping files.') - )), - new Option('to', '', 'The format to convert to (yml, xml, php, annotation).'), - new Option('dest', '', 'The path to write the converted mapping information.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('convert-mapping') - ->setDescription('Convert mapping information between supported formats.') - ->getOptionGroup() - ->addOption($convertOptions); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - - if (isset($arguments['from-database']) && $arguments['from-database']) { - $arguments['from'] = 'database'; - - $this->setArguments($arguments); - } - - if (!(isset($arguments['from']) && isset($arguments['to']) && isset($arguments['dest']))) { - throw new CLIException( - 'You must include a value for all three options: --from, --to and --dest.' - ); - } - - if (strtolower($arguments['to']) != 'annotation' && isset($arguments['extend'])) { - throw new CLIException( - 'You can only use the --extend argument when converting to annotations.' - ); - } - - if (strtolower($arguments['from']) == 'database') { - // Check if we have an active EntityManager - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - $config = $em->getConfiguration(); - $config->setMetadataDriverImpl( - new \Doctrine\ORM\Mapping\Driver\DatabaseDriver( - $em->getConnection()->getSchemaManager() - ) - ); - } - - return true; - } - - public function run() - { - $arguments = $this->getArguments(); - $cme = new ClassMetadataExporter(); - $cme->setEntityManager($this->getConfiguration()->getAttribute('em')); - $printer = $this->getPrinter(); - - // Get exporter and configure it - $exporter = $cme->getExporter($arguments['to'], $arguments['dest']); - - if ($arguments['to'] === 'annotation') { - $entityGenerator = new EntityGenerator(); - $exporter->setEntityGenerator($entityGenerator); - - if (isset($arguments['extend']) && $arguments['extend']) { - $entityGenerator->setClassToExtend($arguments['extend']); - } - - if (isset($arguments['num-spaces']) && $arguments['extend']) { - $entityGenerator->setNumSpaces($arguments['num-spaces']); - } - } - - $from = (array) $arguments['from']; - - foreach ($from as $source) { - $cme->addMappingSource($source); - } - - $metadatas = $cme->getMetadatas(); - - foreach ($metadatas as $metadata) { - $printer->writeln( - sprintf('Processing entity "%s"', $printer->format($metadata->name, 'KEYWORD')) - ); - } - - $printer->writeln(''); - $printer->writeln( - sprintf( - 'Exporting "%s" mapping information to "%s"', - $printer->format($arguments['to'], 'KEYWORD'), - $printer->format($arguments['dest'], 'KEYWORD') - ) - ); - - $exporter->setMetadatas($metadatas); - $exporter->export(); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/EnsureProductionSettingsTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/EnsureProductionSettingsTask.php deleted file mode 100644 index effc6e969..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/EnsureProductionSettingsTask.php +++ /dev/null @@ -1,78 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\CLIException; - -/** - * CLI Task to ensure that Doctrine is properly configured for a production environment. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class EnsureProductionSettingsTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $doc = $this->getDocumentation(); - $doc->setName('ensure-production-settings') - ->setDescription('Verify that Doctrine is properly configured for a production environment.'); - } - - /** - * @inheritdoc - */ - public function validate() - { - // Check if we have an active EntityManager - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - return true; - } - - /** - * @inheritdoc - */ - public function run() - { - $em = $this->getConfiguration()->getAttribute('em'); - $em->getConfiguration()->ensureProductionSettings(); - - $this->getPrinter()->writeln('Environment is correctly configured for production.'); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateEntitiesTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateEntitiesTask.php deleted file mode 100644 index 3bc9c5262..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateEntitiesTask.php +++ /dev/null @@ -1,120 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup, - Doctrine\Common\CLI\CLIException, - Doctrine\ORM\Tools\EntityGenerator, - Doctrine\ORM\Tools\ClassMetadataReader; - -/** - * CLI Task to generate entity classes and method stubs from your mapping information. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class GenerateEntitiesTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $options = new OptionGroup(OptionGroup::CARDINALITY_N_N, array( - new Option('from', '', 'The path to mapping information.'), - new Option('dest', '', 'The path to generate your entity classes.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('generate-entities') - ->setDescription('Generate entity classes and method stubs from your mapping information.') - ->getOptionGroup() - ->addOption($options); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - - if ( ! isset($arguments['from']) || ! isset($arguments['dest'])) { - throw new CLIException('You must specify a value for --from and --dest'); - } - - return true; - } - - /** - * @inheritdoc - */ - public function run() - { - $printer = $this->getPrinter(); - $arguments = $this->getArguments(); - $from = $arguments['from']; - $dest = realpath($arguments['dest']); - - $entityGenerator = new EntityGenerator(); - $entityGenerator->setGenerateAnnotations(false); - $entityGenerator->setGenerateStubMethods(true); - $entityGenerator->setRegenerateEntityIfExists(false); - $entityGenerator->setUpdateEntityIfExists(true); - - if (isset($arguments['extend']) && $arguments['extend']) { - $entityGenerator->setClassToExtend($arguments['extend']); - } - - if (isset($arguments['num-spaces']) && $arguments['extend']) { - $entityGenerator->setNumSpaces($arguments['num-spaces']); - } - - $reader = new ClassMetadataReader(); - $reader->setEntityManager($this->getConfiguration()->getAttribute('em')); - $reader->addMappingSource($from); - $metadatas = $reader->getMetadatas(); - - foreach ($metadatas as $metadata) { - $printer->writeln( - sprintf('Processing entity "%s"', $printer->format($metadata->name, 'KEYWORD')) - ); - } - - $entityGenerator->generate($metadatas, $dest); - - $printer->write(PHP_EOL); - $printer->writeln( - sprintf('Entity classes generated to "%s"', - $printer->format($dest, 'KEYWORD') - ) - ); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateProxiesTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateProxiesTask.php deleted file mode 100644 index e1589d59a..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateProxiesTask.php +++ /dev/null @@ -1,108 +0,0 @@ - - * @author Jonathan Wage - * @author Roman Borschel - */ -class GenerateProxiesTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $classDir = new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option('class-dir', '', 'Specified directory where mapping classes are located.') - )); - - $toDir = new OptionGroup(OptionGroup::CARDINALITY_0_1, array( - new Option('to-dir', '', 'Generates the classes in the specified directory.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('generate-proxies') - ->setDescription('Generates proxy classes for entity classes.') - ->getOptionGroup() - ->addOption($classDir) - ->addOption($toDir); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - $metadataDriver = $em->getConfiguration()->getMetadataDriverImpl(); - - if ($metadataDriver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) { - if (isset($arguments['class-dir'])) { - $metadataDriver->addPaths((array) $arguments['class-dir']); - } else { - throw new CLIException( - 'The supplied configuration uses the annotation metadata driver. ' . - "The 'class-dir' argument is required for this driver." - ); - } - } - - return true; - } - - /** - * @inheritdoc - */ - public function run() - { - $arguments = $this->getArguments(); - $printer = $this->getPrinter(); - - $em = $this->getConfiguration()->getAttribute('em'); - $cmf = $em->getMetadataFactory(); - $classes = $cmf->getAllMetadata(); - $factory = $em->getProxyFactory(); - - if (empty($classes)) { - $printer->writeln('No classes to process.', 'INFO'); - } else { - foreach ($classes as $class) { - $printer->writeln( - sprintf('Processing entity "%s"', $printer->format($class->name, 'KEYWORD')) - ); - } - - $factory->generateProxyClasses( - $classes, isset($arguments['to-dir']) ? $arguments['to-dir'] : null - ); - - $printer->writeln(''); - - $printer->writeln( - sprintf('Proxy classes generated to "%s"', - $printer->format(isset($arguments['to-dir']) ? $arguments['to-dir'] : $em->getConfiguration()->getProxyDir(), 'KEYWORD')) - ); - } - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateRepositoriesTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateRepositoriesTask.php deleted file mode 100644 index 5d1e6f53a..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/GenerateRepositoriesTask.php +++ /dev/null @@ -1,146 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup, - Doctrine\Common\CLI\CLIException, - Doctrine\ORM\Tools\ClassMetadataReader; - -/** - * CLI Task to generate repository classes for some mapping information - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class GenerateRepositoriesTask extends ConvertMappingTask -{ - private static $_template = -'; - -use \Doctrine\ORM\EntityRepository; - -/** - * - * - * This class was generated by the Doctrine ORM. Add your own custom - * repository methods below. - */ -class extends EntityRepository -{ -}'; - - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $options = new OptionGroup(OptionGroup::CARDINALITY_N_N, array( - new Option('from', '', 'The path to mapping information.'), - new Option('dest', '', 'The path to generate your repository classes.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('generate-repositories') - ->setDescription('Generate repository classes for some mapping information.') - ->getOptionGroup() - ->addOption($options); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - - if ( ! isset($arguments['from']) || ! isset($arguments['dest'])) { - throw new CLIException('You must specify a value for --from and --dest'); - } - - return true; - } - - public function run() - { - $printer = $this->getPrinter(); - $arguments = $this->getArguments(); - $dest = realpath($arguments['dest']); - - $reader = new ClassMetadataReader(); - $reader->setEntityManager($this->getConfiguration()->getAttribute('em')); - $reader->addMappingSource($arguments['from']); - $metadatas = $reader->getMetadatas(); - - foreach ($metadatas as $metadata) { - if ($metadata->customRepositoryClassName) { - $code = $this->_generateRepositoryClass($metadata->customRepositoryClassName); - $path = $dest . '/' . str_replace('\\', '/', $metadata->customRepositoryClassName) . '.php'; - $dir = dirname($path); - if ( ! is_dir($dir)) { - mkdir($dir, 0777, true); - } - $printer->writeln( - sprintf('Processing entity "%s"', - $printer->format($metadata->customRepositoryClassName, 'KEYWORD') - ) - ); - file_put_contents($path, $code); - } - } - $printer->writeln(''); - $printer->writeln( - sprintf('Entity repository classes generated to "%s"', - $printer->format($dest, 'KEYWORD') - ) - ); - } - - private function _generateRepositoryClass($fullyQualifiedClassName) - { - $namespace = substr($fullyQualifiedClassName, 0, strrpos($fullyQualifiedClassName, '\\')); - - $pos = strrpos($fullyQualifiedClassName, '\\'); - $className = substr($fullyQualifiedClassName, $pos + 1, strlen($fullyQualifiedClassName)); - - $placeHolders = array( - '', - '' - ); - $replacements = array( - $namespace, - $className - ); - $code = str_replace($placeHolders, $replacements, self::$_template); - return $code; - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/RunDqlTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/RunDqlTask.php deleted file mode 100644 index b7aead638..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/RunDqlTask.php +++ /dev/null @@ -1,147 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\CLI\CLIException, - Doctrine\Common\Util\Debug, - Doctrine\Common\CLI\Option, - Doctrine\Common\CLI\OptionGroup, - Doctrine\ORM\Query; - -/** - * Task for executing DQL in passed EntityManager. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class RunDqlTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $dql = new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option('dql', '', 'The DQL to execute.') - )); - - $hydrate = new OptionGroup(OptionGroup::CARDINALITY_0_1, array( - new Option( - 'hydrate', '', - 'Hydration mode of result set.' . PHP_EOL . - 'Should be either: object, array, scalar or single-scalar.' - ) - )); - - $firstResult = new OptionGroup(OptionGroup::CARDINALITY_0_1, array( - new Option('first-result', '', 'The first result in the result set.') - )); - - $maxResults = new OptionGroup(OptionGroup::CARDINALITY_0_1, array( - new Option('max-results', '', 'The maximum number of results in the result set.') - )); - - $depth = new OptionGroup(OptionGroup::CARDINALITY_0_1, array( - new Option('depth', '', 'Dumping depth of Entities graph.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('run-dql') - ->setDescription('Executes arbitrary DQL directly from the command line.') - ->getOptionGroup() - ->addOption($dql) - ->addOption($hydrate) - ->addOption($firstResult) - ->addOption($maxResults) - ->addOption($depth); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - if ( ! isset($arguments['dql'])) { - throw new CLIException('Argument --dql must be defined.'); - } - - if (isset($arguments['hydrate'])) { - $hydrationModeName = 'Doctrine\ORM\Query::HYDRATE_' . strtoupper(str_replace('-', '_', $arguments['hydrate'])); - - if ( ! defined($hydrationModeName)) { - throw new CLIException("Argument --hydrate must be either 'object', 'array', 'scalar' or 'single-scalar'."); - } - } - - if (isset($arguments['first-result']) && ! ctype_digit($arguments['first-result'])) { - throw new CLIException('Argument --first-result must be an integer value.'); - } - - if (isset($arguments['max-results']) && ! ctype_digit($arguments['max-results'])) { - throw new CLIException('Argument --max-results must be an integer value.'); - } - - return true; - } - - /** - * @inheritdoc - */ - public function run() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - $query = $em->createQuery($arguments['dql']); - - $hydrationMode = isset($arguments['hydrate']) - ? constant('Doctrine\ORM\Query::HYDRATE_' . strtoupper(str_replace('-', '_', $arguments['hydrate']))) - : Query::HYDRATE_OBJECT; - - if (isset($arguments['first-result'])) { - $query->setFirstResult($arguments['first-result']); - } - - if (isset($arguments['max-results'])) { - $query->setMaxResults($arguments['max-results']); - } - - $resultSet = $query->getResult($hydrationMode); - $maxDepth = isset($arguments['depth']) ? $arguments['depth'] : 7; - - Debug::dump($resultSet, $maxDepth); - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/SchemaToolTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/SchemaToolTask.php deleted file mode 100644 index 3564a8b01..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/SchemaToolTask.php +++ /dev/null @@ -1,224 +0,0 @@ ---class-dir= - * Specifies the directory where to start looking for mapped classes. - * This argument is required when the annotation metadata driver is used, - * otherwise it has no effect. - * - * --dump-sql - * Specifies that instead of directly executing the SQL statements, - * they should be printed to the standard output. - * - * --create - * Specifies that the schema of the classes should be created. - * - * --drop - * Specifies that the schema of the classes should be dropped. - * - * --update - * Specifies that the schema of the classes should be updated. - * - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision: 3938 $ - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SchemaToolTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - $schemaOption = new OptionGroup(OptionGroup::CARDINALITY_1_1, array( - new Option( - 'create', null, - 'Creates the schema in EntityManager (create tables on Database).' . PHP_EOL . - 'If defined, --drop, --update and --re-create can not be requested on same task.' - ), - new Option( - 'drop', null, - 'Drops the schema of EntityManager (drop tables on Database).' . PHP_EOL . - 'Beware that the complete database is dropped by this command, '.PHP_EOL. - 'even tables that are not relevant to your metadata model.' . PHP_EOL . - 'If defined, --create, --update and --re-create can not be requested on same task.' - ), - new Option( - 'update', null, - 'Updates the schema in EntityManager (update tables on Database).' . PHP_EOL . - 'This command does a save update, which does not delete any tables, sequences or affected foreign keys.' . PHP_EOL . - 'If defined, --create, --drop and --complete-update --re-create can not be requested on same task.' - ), - new Option( - 'complete-update', null, - 'Updates the schema in EntityManager (update tables on Database).' . PHP_EOL . - 'Beware that all assets of the database which are not relevant to the current metadata are dropped by this command.'.PHP_EOL. - 'If defined, --create, --drop and --update --re-create can not be requested on same task.' - ), - new Option( - 're-create', null, - 'Runs --drop then --create to re-create the database.' . PHP_EOL . - 'If defined, --create, --update and --drop can not be requested on same task.' - ) - )); - - $optionalOptions = new OptionGroup(OptionGroup::CARDINALITY_0_N, array( - new Option('dump-sql', null, 'Instead of try to apply generated SQLs into EntityManager, output them.'), - new Option('class-dir', '', 'Optional class directory to fetch for Entities.') - )); - - $doc = $this->getDocumentation(); - $doc->setName('schema-tool') - ->setDescription('Processes the schema and either apply it directly on EntityManager or generate the SQL output.') - ->getOptionGroup() - ->addOption($schemaOption) - ->addOption($optionalOptions); - } - - /** - * @inheritdoc - */ - public function validate() - { - $arguments = $this->getArguments(); - $em = $this->getConfiguration()->getAttribute('em'); - - if ($em === null) { - throw new CLIException( - "Attribute 'em' of CLI Configuration is not defined or it is not a valid EntityManager." - ); - } - - if (isset($arguments['re-create'])) { - $arguments['drop'] = true; - $arguments['create'] = true; - - unset($arguments['re-create']); - - $this->setArguments($arguments); - } - - $isCreate = isset($arguments['create']) && $arguments['create']; - $isDrop = isset($arguments['drop']) && $arguments['drop']; - $isUpdate = isset($arguments['update']) && $arguments['update']; - $isCompleteUpdate = isset($arguments['complete-update']) && $arguments['complete-update']; - - if ($isUpdate && ($isCreate || $isDrop || $isCompleteUpdate)) { - throw new CLIException( - 'You cannot use --update with --create, --drop or --complete-update.' - ); - } - - if ($isCompleteUpdate && ($isCreate || $isDrop || $isUpdate)) { - throw new CLIException('You cannot use --complete-update with --create, --drop or --update.'); - } - - if ( ! ($isCreate || $isDrop || $isUpdate || $isCompleteUpdate)) { - throw new CLIException( - 'You must specify at a minimum one of the options: ' . - '--create, --drop, --update, --re-create or --complete-update.' - ); - } - - $metadataDriver = $em->getConfiguration()->getMetadataDriverImpl(); - - if ($metadataDriver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) { - if (isset($arguments['class-dir'])) { - $metadataDriver->addPaths((array) $arguments['class-dir']); - } else { - throw new CLIException( - 'The supplied configuration uses the annotation metadata driver. ' . - "The 'class-dir' argument is required for this driver." - ); - } - } - - return true; - } - - /** - * @inheritdoc - */ - public function run() - { - $arguments = $this->getArguments(); - $printer = $this->getPrinter(); - - $isCreate = isset($arguments['create']) && $arguments['create']; - $isDrop = isset($arguments['drop']) && $arguments['drop']; - $isUpdate = isset($arguments['update']) && $arguments['update']; - $isCompleteUpdate = isset($arguments['complete-update']) && $arguments['complete-update']; - - $em = $this->getConfiguration()->getAttribute('em'); - - $cmf = $em->getMetadataFactory(); - $classes = $cmf->getAllMetadata(); - - if (empty($classes)) { - $printer->writeln('No classes to process.', 'INFO'); - - return; - } - - $tool = new SchemaTool($em); - - if ($isDrop) { - if (isset($arguments['dump-sql'])) { - foreach ($tool->getDropSchemaSql($classes) as $sql) { - $printer->writeln($sql . ";"); - } - } else { - $printer->writeln('Dropping database schema...', 'INFO'); - $tool->dropSchema($classes); - $printer->writeln('Database schema dropped successfully.', 'INFO'); - } - } - - if ($isCreate) { - if (isset($arguments['dump-sql'])) { - foreach ($tool->getCreateSchemaSql($classes) as $sql) { - $printer->writeln($sql . ";"); - } - } else { - $printer->writeln('Creating database schema...', 'INFO'); - $tool->createSchema($classes); - $printer->writeln('Database schema created successfully.', 'INFO'); - } - } - - if ($isUpdate || $isCompleteUpdate) { - $saveMode = $isUpdate ? true : false; - - if (isset($arguments['dump-sql'])) { - foreach ($tool->getUpdateSchemaSql($classes, $saveMode) as $sql) { - $printer->writeln($sql . ";"); - } - } else { - $printer->writeln('Updating database schema...', 'INFO'); - $tool->updateSchema($classes, $saveMode); - $printer->writeln('Database schema updated successfully.', 'INFO'); - } - } - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/CLI/Tasks/VersionTask.php b/lib/Doctrine/ORM/Tools/CLI/Tasks/VersionTask.php deleted file mode 100644 index e43f5128b..000000000 --- a/lib/Doctrine/ORM/Tools/CLI/Tasks/VersionTask.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\CLI\Tasks; - -use Doctrine\Common\CLI\Tasks\AbstractTask, - Doctrine\Common\Version; - -/** - * CLI Task to display the doctrine version - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class VersionTask extends AbstractTask -{ - /** - * @inheritdoc - */ - public function buildDocumentation() - { - // There're no options on this task - $this->getDocumentation()->getOptionGroup()->clear(); - - $doc = $this->getDocumentation(); - $doc->setName('version') - ->setDescription('Displays the current installed Doctrine version.'); - } - - /** - * Displays the current version of Doctrine - * - */ - public function run() - { - $this->getPrinter()->writeln('You are currently running Doctrine ' . Version::VERSION, 'INFO'); - } -} \ No newline at end of file From 5854bcab11ed8101d0f3c7e798fd669f17abab38 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Thu, 8 Apr 2010 00:47:42 -0300 Subject: [PATCH 2/4] [2.0] Added new Console support --- .../Tools/Console/Command/ImportCommand.php | 127 +++++++++++++ .../Tools/Console/Command/RunSqlCommand.php | 87 +++++++++ .../Tools/Console/Helper/ConnectionHelper.php | 74 ++++++++ .../Command/ClearCache/MetadataCommand.php | 81 +++++++++ .../Command/ClearCache/QueryCommand.php | 81 +++++++++ .../Command/ClearCache/ResultCommand.php | 164 +++++++++++++++++ .../Command/ConvertDoctrine1SchemaCommand.php | 154 ++++++++++++++++ .../Console/Command/ConvertMappingCommand.php | 165 +++++++++++++++++ .../EnsureProductionSettingsCommand.php | 76 ++++++++ .../Command/GenerateEntitiesCommand.php | 167 +++++++++++++++++ .../Command/GenerateProxiesCommand.php | 136 ++++++++++++++ .../Command/GenerateRepositoriesCommand.php | 171 ++++++++++++++++++ .../Tools/Console/Command/RunDqlCommand.php | 124 +++++++++++++ .../Command/SchemaTool/CreateCommand.php | 120 ++++++++++++ .../Command/SchemaTool/DropCommand.php | 121 +++++++++++++ .../Command/SchemaTool/UpdateCommand.php | 129 +++++++++++++ .../Console/Helper/EntityManagerHelper.php | 74 ++++++++ .../ORM/Tools/ConvertDoctrine1Schema.php | 2 +- lib/Doctrine/ORM/Tools/SchemaTool.php | 15 +- tools/sandbox/cli-config.php | 9 +- tools/sandbox/doctrine.php | 32 +++- 21 files changed, 2087 insertions(+), 22 deletions(-) create mode 100644 lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php create mode 100644 lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php create mode 100644 lib/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php create mode 100644 lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php diff --git a/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php b/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php new file mode 100644 index 000000000..8c3dd2b76 --- /dev/null +++ b/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php @@ -0,0 +1,127 @@ +. + */ + +namespace Doctrine\DBAL\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console; + +/** + * Task for executing arbitrary SQL that can come from a file or directly from + * the command line. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ImportCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('dbal:import') + ->setDescription('Import SQL file(s) directly to Database.') + ->setDefinition(array( + new InputArgument( + 'file', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'File path(s) of SQL to be executed.' + ) + )) + ->setHelp(<<getHelper('db')->getConnection(); + + if (($fileNames = $input->getArgument('file')) !== null) { + foreach ((array) $fileNames as $fileName) { + $fileName = realpath($fileName); + + if ( ! file_exists($fileName)) { + throw new \InvalidArgumentException( + sprintf("SQL file '%s' does not exist.", $fileName) + ); + } else if ( ! is_readable($fileName)) { + throw new \InvalidArgumentException( + sprintf("SQL file '%s' does not have read permissions.", $fileName) + ); + } + + $output->write(sprintf("Processing file '%s'... ", $fileName)); + $sql = file_get_contents($fileName); + + if ($conn instanceof \Doctrine\DBAL\Driver\PDOConnection) { + // PDO Drivers + try { + $lines = 0; + + $stmt = $conn->prepare($sql); + $stmt->execute(); + + do { + // Required due to "MySQL has gone away!" issue + $stmt->fetch(); + $stmt->closeCursor(); + + $lines++; + } while ($stmt->nextRowset()); + + $output->write(sprintf('%d statements executed!', $lines) . PHP_EOL); + } catch (\PDOException $e) { + $output->write('error!' . PHP_EOL); + + throw new \RuntimeException($e->getMessage(), $e->getCode(), $e); + } + } else { + // Non-PDO Drivers (ie. OCI8 driver) + $stmt = $conn->prepare($sql); + $rs = $stmt->execute(); + + if ($rs) { + $printer->writeln('OK!'); + } else { + $error = $stmt->errorInfo(); + + $output->write('error!' . PHP_EOL); + + throw new \RuntimeException($error[2], $error[0]); + } + + $stmt->closeCursor(); + } + } + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php b/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php new file mode 100644 index 000000000..6c5ee824e --- /dev/null +++ b/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php @@ -0,0 +1,87 @@ +. + */ + +namespace Doctrine\DBAL\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Task for executing arbitrary SQL that can come from a file or directly from + * the command line. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class RunSqlCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('dbal:run-sql') + ->setDescription('Executes arbitrary SQL directly from the command line.') + ->setDefinition(array( + new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'), + new InputOption('depth', null, InputOption::PARAMETER_REQUIRED, 'Dumping depth of result set.', 7) + )) + ->setHelp(<<getHelper('db')->getConnection(); + + if (($sql = $input->getArgument('sql')) === null) { + throw new \RuntimeException("Argument 'SQL' is required in order to execute this command correctly."); + } + + $depth = $input->getOption('depth'); + + if ( ! is_numeric($depth)) { + throw new \LogicException("Option 'depth' must contains an integer value"); + } + + if (preg_match('/^select/i', $sql)) { + $stmt = $conn->execute($sql); + $resultSet = $stmt->fetchAll(\Doctrine\DBAL\Connection::FETCH_ASSOC); + } else { + $resultSet = $em->getConnection()->executeUpdate($sql); + } + + \Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth); + } +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php b/lib/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php new file mode 100644 index 000000000..bcf6f8d97 --- /dev/null +++ b/lib/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php @@ -0,0 +1,74 @@ +. + */ + +namespace Doctrine\DBAL\Tools\Console\Helper; + +use Symfony\Components\Console\Helper\Helper, + Doctrine\DBAL\Connection; + +/** + * Doctrine CLI Connection Helper. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConnectionHelper extends Helper +{ + /** + * Doctrine Database Connection + * @var Connection + */ + protected $_connection; + + /** + * Constructor + * + * @param Connection $connection Doctrine Database Connection + */ + public function __construct(Connection $connection) + { + $this->_connection = $connection; + } + + /** + * Retrieves Doctrine Database Connection + * + * @return Connection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * @see Helper + */ + public function getName() + { + return 'connection'; + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php new file mode 100644 index 000000000..711bffd2d --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php @@ -0,0 +1,81 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to clear the metadata cache of the various cache drivers. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class MetadataCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:clear-cache:metadata') + ->setDescription('Clear all metadata cache of the various cache drivers.') + ->setDefinition(array()) + ->setHelp(<<getHelper('em')->getEntityManager(); + $cacheDriver = $em->getConfiguration()->getMetadataCacheImpl(); + + if ( ! $cacheDriver) { + throw new \InvalidArgumentException('No Metadata cache driver is configured on given EntityManager.'); + } + + $output->write('Clearing ALL Metadata cache entries' . PHP_EOL); + + $cacheIds = $cacheDriver->deleteAll(); + + if ($cacheIds) { + foreach ($cacheIds as $cacheId) { + $output->write(' - ' . $cacheId . PHP_EOL); + } + } else { + $output->write('No entries to be deleted.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php new file mode 100644 index 000000000..b16fec3eb --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php @@ -0,0 +1,81 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to clear the query cache of the various cache drivers. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class QueryCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:clear-cache:query') + ->setDescription('Clear all query cache of the various cache drivers.') + ->setDefinition(array()) + ->setHelp(<<getHelper('em')->getEntityManager(); + $cacheDriver = $em->getConfiguration()->getQueryCacheImpl(); + + if ( ! $cacheDriver) { + throw new \InvalidArgumentException('No Query cache driver is configured on given EntityManager.'); + } + + $output->write('Clearing ALL Query cache entries' . PHP_EOL); + + $cacheIds = $cacheDriver->deleteAll(); + + if ($cacheIds) { + foreach ($cacheIds as $cacheId) { + $output->write(' - ' . $cacheId . PHP_EOL); + } + } else { + $output->write('No entries to be deleted.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php new file mode 100644 index 000000000..947cac9fb --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php @@ -0,0 +1,164 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to clear the result cache of the various cache drivers. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ResultCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:clear-cache:result') + ->setDescription('Clear result cache of the various cache drivers.') + ->setDefinition(array( + new InputOption( + 'id', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'ID(s) of the cache entry to delete (accepts * wildcards).', array() + ), + new InputOption( + 'regex', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Delete cache entries that match the given regular expression(s).', array() + ), + new InputOption( + 'prefix', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Delete cache entries that have the given prefix(es).', array() + ), + new InputOption( + 'suffix', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Delete cache entries that have the given suffix(es).', array() + ), + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + $cacheDriver = $em->getConfiguration()->getResultCacheImpl(); + + if ( ! $cacheDriver) { + throw new \InvalidArgumentException('No Result cache driver is configured on given EntityManager.'); + } + + $outputed = false; + + // Removing based on --id + if (($ids = $input->getOption('id')) !== null && $ids) { + foreach ($ids as $id) { + $output->write($outputed ? PHP_EOL : ''); + $output->write(sprintf('Clearing Result cache entries that match the id "%s"', $id) . PHP_EOL); + + $deleted = $cacheDriver->delete($id); + + if (is_array($deleted)) { + $this->_printDeleted($deleted); + } else if (is_bool($deleted) && $deleted) { + $this->_printDeleted(array($id)); + } + + $outputed = true; + } + } + + // Removing based on --regex + if (($regex = $input->getOption('regex')) !== null && $regexps) { + foreach($regexps as $regex) { + $output->write($outputed ? PHP_EOL : ''); + $output->write(sprintf('Clearing Result cache entries that match the regular expression "%s"', $regex) . PHP_EOL); + + $this->_printDeleted($cacheDriver->deleteByRegex('/' . $regex. '/')); + + $outputed = true; + } + } + + // Removing based on --prefix + if (($prefixes = $input->getOption('prefix')) !== null & $prefixes) { + foreach ($prefixes as $prefix) { + $output->write($outputed ? PHP_EOL : ''); + $output->write(sprintf('Clearing Result cache entries that have the prefix "%s"', $prefix) . PHP_EOL); + + $this->_printDeleted($cacheDriver->deleteByPrefix($prefix)); + + $outputed = true; + } + } + + // Removing based on --suffix + if (($suffixes = $input->getOption('suffix')) !== null && $suffixes) { + foreach ($suffixes as $suffix) { + $output->write($outputed ? PHP_EOL : ''); + $output->write(sprintf('Clearing Result cache entries that have the suffix "%s"', $suffix) . PHP_EOL); + + $this->_printDeleted($cacheDriver->deleteBySuffix($suffix)); + + $outputed = true; + } + } + + // Removing ALL entries + if ( ! $ids && ! $regexps && ! $prefixes && ! $suffixes) { + $output->write($outputed ? PHP_EOL : ''); + $output->write('Clearing ALL Result cache entries'); + + $this->_printDeleted($cacheDriver->deleteAll()); + + $outputed = true; + } + } + + private function _printDeleted(Console\Output\OutputInterface $output, array $items) + { + if ($items) { + foreach ($items as $item) { + $output->write(' - ' . $item . PHP_EOL); + } + } else { + $output->write('No entries to be deleted.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php new file mode 100644 index 000000000..48ce45fb0 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php @@ -0,0 +1,154 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to convert a Doctrine 1 schema to a Doctrine 2 mapping file. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConvertDoctrine1SchemaCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:convert-d1-schema') + ->setDescription('Converts Doctrine 1.X schema into a Doctrine 2.X schema.') + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of Doctrine 1.X schema information.' + ), + new InputArgument( + 'to-type', InputArgument::REQUIRED, 'The destination Doctrine 2.X mapping type.' + ), + new InputArgument( + 'dest-path', InputArgument::REQUIRED, + 'The path to generate your Doctrine 2.X mapping information.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of Doctrine 1.X schema information.', + array() + ), + new InputOption( + 'extend', null, InputOption::PARAMETER_OPTIONAL, + 'Defines a base class to be extended by generated entity classes.' + ), + new InputOption( + 'num-spaces', null, InputOption::PARAMETER_OPTIONAL, + 'Defines the number of indentation spaces', 4 + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as &$dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 1.X schema directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 1.X schema directory '%s' does not have read permissions.", $dirName) + ); + } + } + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 2.X mapping destination directory '%s' does not exist.", $destPath) + ); + } else if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 2.X mapping destination directory '%s' does not have write permissions.", $destPath) + ); + } + + $toType = $input->getArgument('to-type'); + + $cme = new ClassMetadataExporter(); + $exporter = $cme->getExporter($toType, $destPath); + + if (strtolower($toType) === 'annotation') { + $entityGenerator = new EntityGenerator(); + $exporter->setEntityGenerator($entityGenerator); + + $entityGenerator->setNumSpaces($input->getOption('num-spaces')); + + if (($extend = $input->getOption('extend')) !== null) { + $entityGenerator->setClassToExtend($extend); + } + } + + $converter = new ConvertDoctrine1Schema($fromPaths); + $metadatas = $converter->getMetadatas(); + + if ($metadatas) { + $output->write(PHP_EOL); + + foreach ($metadatas as $metadata) { + $output->write(sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL); + } + + $exporter->setMetadatas($metadatas); + $exporter->export(); + + $output->write(PHP_EOL . sprintf( + 'Converting Doctrine 1.X schema to "%s" mapping type in "%s"', $toType, $destPath + )); + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php new file mode 100644 index 000000000..45bc79714 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php @@ -0,0 +1,165 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to convert your mapping information between the various formats. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConvertMappingCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:convert-mapping') + ->setDescription('Convert mapping information between supported formats.') + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputArgument( + 'to-type', InputArgument::REQUIRED, 'The mapping type to be converted.' + ), + new InputArgument( + 'dest-path', InputArgument::REQUIRED, + 'The path to generate your entities classes.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ), + new InputOption( + 'extend', null, InputOption::PARAMETER_OPTIONAL, + 'Defines a base class to be extended by generated entity classes.' + ), + new InputOption( + 'num-spaces', null, InputOption::PARAMETER_OPTIONAL, + 'Defines the number of indentation spaces', 4 + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + $cme = new ClassMetadataExporter(); + + // Process source directories + $fromPath = $input->getArgument('from-path'); + + if (strtolower($fromPath) !== 'database') { + $fromPaths = array_merge(array($fromPath), $input->getOption('from')); + + foreach ($fromPaths as &$dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $cme->addMappingSource($dirName); + } + } else { + $em->getConfiguration()->setMetadataDriverImpl( + new \Doctrine\ORM\Mapping\Driver\DatabaseDriver( + $em->getConnection()->getSchemaManager() + ) + ); + + $cme->addMappingSource($fromPath); + } + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Mapping destination directory '%s' does not exist.", $destPath) + ); + } else if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Mapping destination directory '%s' does not have write permissions.", $destPath) + ); + } + + $toType = strtolower($input->getArgument('to-type')); + + $exporter = $cme->getExporter($toType, $destPath); + + if ($toType == 'annotation') { + $entityGenerator = new EntityGenerator(); + $exporter->setEntityGenerator($entityGenerator); + + $entityGenerator->setNumSpaces($input->getOption('num-spaces')); + + if (($extend = $input->getOption('extend')) !== null) { + $entityGenerator->setClassToExtend($extend); + } + } + + $metadatas = $cme->getMetadatas(); + + if ($metadatas) { + foreach ($metadatas as $metadata) { + $output->write(sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL); + } + + $exporter->setMetadatas($metadatas); + $exporter->export(); + + $output->write(PHP_EOL . sprintf( + 'Exporting "%s" mapping information to "%s"', $toType, $destPath + )); + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php new file mode 100644 index 000000000..44cdd5688 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php @@ -0,0 +1,76 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to ensure that Doctrine is properly configured for a production environment. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EnsureProductionSettingsCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:ensure-production-settings') + ->setDescription('Verify that Doctrine is properly configured for a production environment.') + ->setDefinition(array( + new InputOption( + 'complete', null, InputOption::PARAMETER_NONE, + 'Flag to also inspect database connection existance.' + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + $em->getConfiguration()->ensureProductionSettings(); + + if ($input->getOption('complete') !== null) { + $em->getConnection()->connect(); + } + + $output->write('Environment is correctly configured for production.'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php new file mode 100644 index 000000000..0cf0230dd --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php @@ -0,0 +1,167 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to generate entity classes and method stubs from your mapping information. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GenerateEntitiesCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:generate-entities') + ->setDescription('Generate entity classes and method stubs from your mapping information.') + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputArgument( + 'dest-path', InputArgument::REQUIRED, 'The path to generate your entity classes.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ), + new InputOption( + 'generate-annotations', null, InputOption::PARAMETER_OPTIONAL, + 'Flag to define if generator should generate annotation metadata on entities.', false + ), + new InputOption( + 'generate-methods', null, InputOption::PARAMETER_OPTIONAL, + 'Flag to define if generator should generate stub methods on entities.', true + ), + new InputOption( + 'regenerate-entities', null, InputOption::PARAMETER_OPTIONAL, + 'Flag to define if generator should regenerate entity if it exists.', false + ), + new InputOption( + 'update-entities', null, InputOption::PARAMETER_OPTIONAL, + 'Flag to define if generator should only update entity if it exists.', true + ), + new InputOption( + 'extend', null, InputOption::PARAMETER_OPTIONAL, + 'Defines a base class to be extended by generated entity classes.' + ), + new InputOption( + 'num-spaces', null, InputOption::PARAMETER_OPTIONAL, + 'Defines the number of indentation spaces', 4 + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + $reader = new ClassMetadataReader(); + $reader->setEntityManager($em); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as $dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $reader->addMappingSource($dirName); + } + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not exist.", $destPath) + ); + } else if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not have write permissions.", $destPath) + ); + } + + // Create EntityGenerator + $entityGenerator = new EntityGenerator(); + + $entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations')); + $entityGenerator->setGenerateStubMethods($input->getOption('generate-methods')); + $entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities')); + $entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities')); + $entityGenerator->setNumSpaces($input->getOption('num-spaces')); + + if (($extend = $input->getOption('extend')) !== null) { + $entityGenerator->setClassToExtend($extend); + } + + // Retrieving ClassMetadatas + $metadatas = $reader->getMetadatas(); + + if ( ! empty($metadatas)) { + foreach ($metadatas as $metadata) { + $output->write( + sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL + ); + } + + // Generating Entities + $entityGenerator->generate($metadatas, $destPath); + + // Outputting information message + $output->write(PHP_EOL . sprintf('Entity classes generated to "%s"', $destPath) . PHP_EOL); + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php new file mode 100644 index 000000000..4b6333b6f --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php @@ -0,0 +1,136 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to (re)generate the proxy classes used by doctrine. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GenerateProxiesCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:generate-proxies') + ->setDescription('Generates proxy classes for entity classes.') + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputArgument( + 'dest-path', InputArgument::OPTIONAL, + 'The path to generate your proxy classes. If none is provided, it will attempt to grab from configuration.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + $reader = new ClassMetadataReader(); + $reader->setEntityManager($em); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as $dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $reader->addMappingSource($dirName); + } + + // Process destination directory + if (($destPath = $input->getArgument('dest-path')) === null) { + $destPath = $em->getConfiguration()->getProxyDir(); + } + + $destPath = realpath($destPath); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Proxies destination directory '%s' does not exist.", $destPath) + ); + } else if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Proxies destination directory '%s' does not have write permissions.", $destPath) + ); + } + + // Retrieving ClassMetadatas + $metadatas = $reader->getMetadatas(); + + if ( ! empty($metadatas)) { + foreach ($metadatas as $metadata) { + $output->write( + sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL + ); + } + + // Generating Proxies + $em->getProxyFactory()->generateProxyClasses($metadatas, $destPath); + + // Outputting information message + $output->write(PHP_EOL . sprintf('Proxy classes generated to "%s"', $destPath) . PHP_EOL); + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php new file mode 100644 index 000000000..1d24fccb3 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php @@ -0,0 +1,171 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to generate repository classes for mapping information. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GenerateRepositoriesCommand extends Console\Command\Command +{ + private static $_template = +'; + +use \Doctrine\ORM\EntityRepository; + +/** + * + * + * This class was generated by the Doctrine ORM. Add your own custom + * repository methods below. + */ +class extends EntityRepository +{ +}'; + + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:generate-repositories') + ->setDescription('Generate repository classes from your mapping information.') + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputArgument( + 'dest-path', InputArgument::REQUIRED, 'The path to generate your repository classes.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + $reader = new ClassMetadataReader(); + $reader->setEntityManager($em); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as $dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $reader->addMappingSource($dirName); + } + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not exist.", $destPath) + ); + } else if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not have write permissions.", $destPath) + ); + } + + // Retrieving ClassMetadatas + $metadatas = $reader->getMetadatas(); + + if ( ! empty($metadatas)) { + $numRepositories = 0; + + foreach ($metadatas as $metadata) { + if ($metadata->customRepositoryClassName) { + $output->write( + sprintf('Processing repository "%s"', $metadata->customRepositoryClassName) . PHP_EOL + ); + + $this->_generateRepositoryClass($metadata, $destPath); + + $numRepositories++; + } + } + + if ($numRepositories) { + // Outputting information message + $output->write(PHP_EOL . sprintf('Repository classes generated to "%s"', $destPath) . PHP_EOL); + } else { + $output->write('No Repository classes were found to be processed.' . PHP_EOL); + } + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } + + private function _generateRepositoryClass($metadata, $destPath) + { + $code = $this->_generateRepositoryClass($metadata->customRepositoryClassName); + + $path = $destPath . DIRECTORY_SEPARATOR + . str_replace('\\', \DIRECTORY_SEPARATOR, $metadata->customRepositoryClassName) . '.php'; + $dir = dirname($path); + + if ( ! is_dir($dir)) { + mkdir($dir, 0777, true); + } + + file_put_contents($path, $code); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php new file mode 100644 index 000000000..c995fba7b --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php @@ -0,0 +1,124 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to execute DQL queries in a given EntityManager. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class RunDqlCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:run-dql') + ->setDescription('Executes arbitrary DQL directly from the command line.') + ->setDefinition(array( + new InputArgument('dql', InputArgument::REQUIRED, 'The DQL to execute.'), + new InputOption( + 'hydrate', null, InputOption::PARAMETER_REQUIRED, + 'Hydration mode of result set. Should be either: object, array, scalar or single-scalar.', + 'object' + ), + new InputOption( + 'first-result', null, InputOption::PARAMETER_REQUIRED, + 'The first result in the result set.' + ), + new InputOption( + 'max-result', null, InputOption::PARAMETER_REQUIRED, + 'The maximum number of results in the result set.' + ), + new InputOption( + 'depth', null, InputOption::PARAMETER_REQUIRED, + 'Dumping depth of Entity graph.', 7 + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + if (($dql = $input->getArgument('dql')) === null) { + throw new \RuntimeException("Argument 'DQL' is required in order to execute this command correctly."); + } + + $depth = $input->getOption('depth'); + + if ( ! is_numeric($depth)) { + throw new \LogicException("Option 'depth' must contains an integer value"); + } + + $hydrationModeName = $input->getOption('hydrate'); + $hydrationMode = 'Doctrine\ORM\Query::HYDRATE_' . strtoupper(str_replace('-', '_', $hydrationModeName)); + + if ( ! defined($hydrationMode)) { + throw new \RuntimeException( + "Hydration mode '$hydrationModeName' does not exist. It should be either: object. array, scalar or single-scalar." + ); + } + + $query = $em->createQuery($dql); + + if (($firstResult = $input->getOption('first-result')) !== null) { + if ( ! is_numeric($firstResult)) { + throw new \LogicException("Option 'first-result' must contains an integer value"); + } + + $query->setFirstResult((int) $firstResult); + } + + if (($maxResult = $input->getOption('max-result')) !== null) { + if ( ! is_numeric($maxResult)) { + throw new \LogicException("Option 'max-result' must contains an integer value"); + } + + $query->setMaxResult((int) $maxResult); + } + + $resultSet = $query->execute(array(), $hydrationMode); + + \Doctrine\Common\Util\Debug::dump($resultSet, $input->getOption('depth')); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php new file mode 100644 index 000000000..4ca0b3090 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php @@ -0,0 +1,120 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to create the database schema for a set of classes based on their mappings. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class CreateCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:schema-tool:create') + ->setDescription( + 'Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.' + ) + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ), + new InputOption( + 'dump-sql', null, InputOption::PARAMETER_NONE, + 'Instead of try to apply generated SQLs into EntityManager Storage Connection, output them.' + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + $reader = new ClassMetadataReader(); + $reader->setEntityManager($em); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as $dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $reader->addMappingSource($dirName); + } + + // Retrieving ClassMetadatas + $metadatas = $reader->getMetadatas(); + + if ( ! empty($metadatas)) { + // Create SchemaTool + $tool = new \Doctrine\ORM\Tools\SchemaTool($em); + + if ($input->getOption('dump-sql') === null) { + $sqls = $tool->getCreateSchemaSql($metadatas); + $output->write(implode(';' . PHP_EOL, $sqls)); + } else { + $output->write('Creating database schema...' . PHP_EOL); + $tool->createSchema($metadatas); + $output->write('Database schema created successfully!' . PHP_EOL); + } + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php new file mode 100644 index 000000000..b41c616a8 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php @@ -0,0 +1,121 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to drop the database schema for a set of classes based on their mappings. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class DropCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:schema-tool:drop') + ->setDescription( + 'Processes the schema and either drop the database schema of EntityManager Storage Connection or generate the SQL output.' + ) + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ), + new InputOption( + 'dump-sql', null, InputOption::PARAMETER_NONE, + 'Instead of try to apply generated SQLs into EntityManager Storage Connection, output them.' + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + $reader = new ClassMetadataReader(); + $reader->setEntityManager($em); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as $dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $reader->addMappingSource($dirName); + } + + // Retrieving ClassMetadatas + $metadatas = $reader->getMetadatas(); + + if ( ! empty($metadatas)) { + // Create SchemaTool + $tool = new \Doctrine\ORM\Tools\SchemaTool($em); + + if ($input->getOption('dump-sql') === null) { + $sqls = $tool->getDropSchemaSql($metadatas); + $output->write(implode(';' . PHP_EOL, $sqls)); + } else { + $output->write('Dropping database schema...' . PHP_EOL); + $tool->dropSchema($metadatas); + $output->write('Database schema dropped successfully!' . PHP_EOL); + } + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php new file mode 100644 index 000000000..9aba1e9cd --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php @@ -0,0 +1,129 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console; + +/** + * Command to update the database schema for a set of classes based on their mappings. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class UpdateCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('orm:schema-tool:update') + ->setDescription( + 'Processes the schema and either update the database schema of EntityManager Storage Connection or generate the SQL output.' + ) + ->setDefinition(array( + new InputArgument( + 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + ), + new InputOption( + 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'Optional paths of mapping information.', + array() + ), + new InputOption( + 'complete', null, InputOption::PARAMETER_NONE, + 'If defined, all assets of the database which are not relevant to the current metadata will be dropped.' + ), + new InputOption( + 'dump-sql', null, InputOption::PARAMETER_NONE, + 'Instead of try to apply generated SQLs into EntityManager Storage Connection, output them.' + ) + )) + ->setHelp(<<getHelper('em')->getEntityManager(); + + $reader = new ClassMetadataReader(); + $reader->setEntityManager($em); + + // Process source directories + $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); + + foreach ($fromPaths as $dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not exist.", $dirName) + ); + } else if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Mapping directory '%s' does not have read permissions.", $dirName) + ); + } + + $reader->addMappingSource($dirName); + } + + // Defining if update is complete or not (--complete not defined means $saveMode = true) + $saveMode = ($input->getOption('complete') === null); + + // Retrieving ClassMetadatas + $metadatas = $reader->getMetadatas(); + + if ( ! empty($metadatas)) { + // Create SchemaTool + $tool = new \Doctrine\ORM\Tools\SchemaTool($em); + + if ($input->getOption('dump-sql') === null) { + $sqls = $tool->getUpdateSchemaSql($metadatas, $saveMode); + $output->write(implode(';' . PHP_EOL, $sqls)); + } else { + $output->write('Updating database schema...' . PHP_EOL); + $tool->updateSchema($metadatas, $saveMode); + $output->write('Database schema updated successfully!' . PHP_EOL); + } + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php b/lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php new file mode 100644 index 000000000..2636006e3 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php @@ -0,0 +1,74 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Helper; + +use Symfony\Components\Console\Helper\Helper, + Doctrine\ORM\EntityManager; + +/** + * Doctrine CLI Connection Helper. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EntityManagerHelper extends Helper +{ + /** + * Doctrine ORM EntityManager + * @var EntityManager + */ + protected $_em; + + /** + * Constructor + * + * @param Connection $connection Doctrine Database Connection + */ + public function __construct(EntityManager $em) + { + $this->_em = $em; + } + + /** + * Retrieves Doctrine ORM EntityManager + * + * @return EntityManager + */ + public function getEntityManager() + { + return $this->_em; + } + + /** + * @see Helper + */ + public function getName() + { + return 'entityManager'; + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php b/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php index 89744c0f1..b559913a4 100644 --- a/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php +++ b/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php @@ -48,7 +48,7 @@ class ConvertDoctrine1Schema * Constructor passes the directory or array of directories * to convert the Doctrine 1 schema files from * - * @param string $from + * @param array $from * @author Jonathan Wage */ public function __construct($from) diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index 129c9aa02..5897e0a72 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -43,15 +43,6 @@ use Doctrine\ORM\ORMException, */ class SchemaTool { - /** - * @var string - */ - const DROP_METADATA = "metadata"; - /** - * @var string - */ - const DROP_DATABASE = "database"; - /** * @var \Doctrine\ORM\EntityManager */ @@ -473,12 +464,11 @@ class SchemaTool * issued for all classes of the schema and some probably just don't exist. * * @param array $classes - * @param string $mode * @return void */ - public function dropSchema(array $classes, $mode=self::DROP_METADATA) + public function dropSchema(array $classes) { - $dropSchemaSql = $this->getDropSchemaSql($classes, $mode); + $dropSchemaSql = $this->getDropSchemaSql($classes); $conn = $this->_em->getConnection(); foreach ($dropSchemaSql as $sql) { @@ -490,7 +480,6 @@ class SchemaTool * Gets the SQL needed to drop the database schema for the given classes. * * @param array $classes - * @param string $mode * @return array */ public function getDropSchemaSql(array $classes) diff --git a/tools/sandbox/cli-config.php b/tools/sandbox/cli-config.php index 06cb51f07..887780dd9 100644 --- a/tools/sandbox/cli-config.php +++ b/tools/sandbox/cli-config.php @@ -22,9 +22,6 @@ $classLoader->register(); $classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__); $classLoader->register(); -$classLoader = new \Doctrine\Common\ClassLoader('Symfony', __DIR__ . '/../../lib/vendor'); -$classLoader->register(); - $config = new \Doctrine\ORM\Configuration(); $config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache); $config->setProxyDir(__DIR__ . '/Proxies'); @@ -37,5 +34,7 @@ $connectionOptions = array( $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config); -$configuration = new \Doctrine\Common\CLI\Configuration(); -$configuration->setAttribute('em', $em); \ No newline at end of file +$helperSet = new \Symfony\Components\Console\Helper\HelperSet(array( + 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) +)); \ No newline at end of file diff --git a/tools/sandbox/doctrine.php b/tools/sandbox/doctrine.php index 9b29b5e49..152a9932e 100644 --- a/tools/sandbox/doctrine.php +++ b/tools/sandbox/doctrine.php @@ -5,8 +5,34 @@ require __DIR__ . '/../../lib/Doctrine/Common/ClassLoader.php'; $classLoader = new \Doctrine\Common\ClassLoader('Doctrine', __DIR__ . '/../../lib'); $classLoader->register(); -// Variable $configuration is defined inside cli-config.php +$classLoader = new \Doctrine\Common\ClassLoader('Symfony', __DIR__ . '/../../lib/vendor'); +$classLoader->register(); + +// Variable $helperSet is defined inside cli-config.php require __DIR__ . '/cli-config.php'; -$cli = new \Doctrine\Common\CLI\CLIController($configuration); -$cli->run($_SERVER['argv']); \ No newline at end of file +$cli = new \Symfony\Components\Console\Application('Doctrine Command Line Interface', Doctrine\Common\Version::VERSION); +$cli->setCatchExceptions(true); +$cli->setHelperSet($helperSet); +$cli->addCommands(array( + // DBAL Commands + new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(), + new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(), + + // ORM Commands + new \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand(), + new \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand(), + new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand(), + new \Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand(), + new \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand(), + new \Doctrine\ORM\Tools\Console\Command\SchemaTool\DropCommand(), + new \Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand(), + new \Doctrine\ORM\Tools\Console\Command\ConvertDoctrine1SchemaCommand(), + new \Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand(), + new \Doctrine\ORM\Tools\Console\Command\GenerateEntitiesCommand(), + new \Doctrine\ORM\Tools\Console\Command\GenerateProxiesCommand(), + new \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand(), + new \Doctrine\ORM\Tools\Console\Command\RunDqlCommand(), + +)); +$cli->run(); \ No newline at end of file From b0e26fa17da2376a1d896aee292491ba5908f1f3 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Thu, 8 Apr 2010 01:03:04 -0300 Subject: [PATCH 3/4] [2.0] Added Symfony Components dependencies --- .../Components/Console/Application.php | 804 ++++++++++++++++++ .../Components/Console/Command/Command.php | 508 +++++++++++ .../Console/Command/HelpCommand.php | 83 ++ .../Console/Command/ListCommand.php | 72 ++ .../Console/Helper/DialogHelper.php | 119 +++ .../Console/Helper/FormatterHelper.php | 89 ++ .../Components/Console/Helper/Helper.php | 45 + .../Console/Helper/HelperInterface.php | 43 + .../Components/Console/Helper/HelperSet.php | 104 +++ .../Components/Console/Input/ArgvInput.php | 284 +++++++ .../Components/Console/Input/ArrayInput.php | 174 ++++ .../Components/Console/Input/Input.php | 198 +++++ .../Console/Input/InputArgument.php | 134 +++ .../Console/Input/InputDefinition.php | 507 +++++++++++ .../Console/Input/InputInterface.php | 58 ++ .../Components/Console/Input/InputOption.php | 191 +++++ .../Components/Console/Input/StringInput.php | 80 ++ .../Console/Output/ConsoleOutput.php | 41 + .../Components/Console/Output/NullOutput.php | 34 + .../Components/Console/Output/Output.php | 230 +++++ .../Console/Output/OutputInterface.php | 44 + .../Console/Output/StreamOutput.php | 109 +++ .../Symfony/Components/Console/Shell.php | 146 ++++ .../Console/Tester/ApplicationTester.php | 92 ++ .../Console/Tester/CommandTester.php | 92 ++ lib/vendor/Symfony/Components/Yaml/Dumper.php | 59 ++ .../Symfony/Components/Yaml/Exception.php | 23 + lib/vendor/Symfony/Components/Yaml/Inline.php | 410 +++++++++ lib/vendor/Symfony/Components/Yaml/Parser.php | 587 +++++++++++++ .../Components/Yaml/ParserException.php | 23 + lib/vendor/Symfony/Components/Yaml/Yaml.php | 121 +++ 31 files changed, 5504 insertions(+) create mode 100644 lib/vendor/Symfony/Components/Console/Application.php create mode 100644 lib/vendor/Symfony/Components/Console/Command/Command.php create mode 100644 lib/vendor/Symfony/Components/Console/Command/HelpCommand.php create mode 100644 lib/vendor/Symfony/Components/Console/Command/ListCommand.php create mode 100644 lib/vendor/Symfony/Components/Console/Helper/DialogHelper.php create mode 100644 lib/vendor/Symfony/Components/Console/Helper/FormatterHelper.php create mode 100644 lib/vendor/Symfony/Components/Console/Helper/Helper.php create mode 100644 lib/vendor/Symfony/Components/Console/Helper/HelperInterface.php create mode 100644 lib/vendor/Symfony/Components/Console/Helper/HelperSet.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/ArgvInput.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/ArrayInput.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/Input.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/InputArgument.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/InputDefinition.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/InputInterface.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/InputOption.php create mode 100644 lib/vendor/Symfony/Components/Console/Input/StringInput.php create mode 100644 lib/vendor/Symfony/Components/Console/Output/ConsoleOutput.php create mode 100644 lib/vendor/Symfony/Components/Console/Output/NullOutput.php create mode 100644 lib/vendor/Symfony/Components/Console/Output/Output.php create mode 100644 lib/vendor/Symfony/Components/Console/Output/OutputInterface.php create mode 100644 lib/vendor/Symfony/Components/Console/Output/StreamOutput.php create mode 100644 lib/vendor/Symfony/Components/Console/Shell.php create mode 100644 lib/vendor/Symfony/Components/Console/Tester/ApplicationTester.php create mode 100644 lib/vendor/Symfony/Components/Console/Tester/CommandTester.php create mode 100644 lib/vendor/Symfony/Components/Yaml/Dumper.php create mode 100644 lib/vendor/Symfony/Components/Yaml/Exception.php create mode 100644 lib/vendor/Symfony/Components/Yaml/Inline.php create mode 100644 lib/vendor/Symfony/Components/Yaml/Parser.php create mode 100644 lib/vendor/Symfony/Components/Yaml/ParserException.php create mode 100644 lib/vendor/Symfony/Components/Yaml/Yaml.php diff --git a/lib/vendor/Symfony/Components/Console/Application.php b/lib/vendor/Symfony/Components/Console/Application.php new file mode 100644 index 000000000..e26319be7 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Application.php @@ -0,0 +1,804 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * An Application is the container for a collection of commands. + * + * It is the main entry point of a Console application. + * + * This class is optimized for a standard CLI environment. + * + * Usage: + * + * $app = new Application('myapp', '1.0 (stable)'); + * $app->addCommand(new SimpleCommand()); + * $app->run(); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class Application +{ + protected $commands; + protected $aliases; + protected $application; + protected $wantHelps = false; + protected $runningCommand; + protected $name; + protected $version; + protected $catchExceptions; + protected $autoExit; + protected $definition; + protected $helperSet; + + /** + * Constructor. + * + * @param string $name The name of the application + * @param string $version The version of the application + */ + public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') + { + $this->name = $name; + $this->version = $version; + $this->catchExceptions = true; + $this->autoExit = true; + $this->commands = array(); + $this->aliases = array(); + $this->helperSet = new HelperSet(array( + new FormatterHelper(), + new DialogHelper(), + )); + + $this->addCommand(new HelpCommand()); + $this->addCommand(new ListCommand()); + + $this->definition = new InputDefinition(array( + new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), + + new InputOption('--help', '-h', InputOption::PARAMETER_NONE, 'Display this help message.'), + new InputOption('--quiet', '-q', InputOption::PARAMETER_NONE, 'Do not output any message.'), + new InputOption('--verbose', '-v', InputOption::PARAMETER_NONE, 'Increase verbosity of messages.'), + new InputOption('--version', '-V', InputOption::PARAMETER_NONE, 'Display this program version.'), + new InputOption('--color', '-c', InputOption::PARAMETER_NONE, 'Force ANSI color output.'), + new InputOption('--no-interaction', '-n', InputOption::PARAMETER_NONE, 'Do not ask any interactive question.'), + )); + } + + /** + * Runs the current application. + * + * @param InputInterface $input An Input instance + * @param OutputInterface $output An Output instance + * + * @return integer 0 if everything went fine, or an error code + */ + public function run(InputInterface $input = null, OutputInterface $output = null) + { + if (null === $input) + { + $input = new ArgvInput(); + } + + if (null === $output) + { + $output = new ConsoleOutput(); + } + + try + { + $statusCode = $this->doRun($input, $output); + } + catch (\Exception $e) + { + if (!$this->catchExceptions) + { + throw $e; + } + + $this->renderException($e, $output); + $statusCode = $e->getCode(); + + $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1; + } + + if ($this->autoExit) + { + // @codeCoverageIgnoreStart + exit($statusCode); + // @codeCoverageIgnoreEnd + } + else + { + return $statusCode; + } + } + + /** + * Runs the current application. + * + * @param InputInterface $input An Input instance + * @param OutputInterface $output An Output instance + * + * @return integer 0 if everything went fine, or an error code + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + $name = $input->getFirstArgument('command'); + + if (true === $input->hasParameterOption(array('--color', '-c'))) + { + $output->setDecorated(true); + } + + if (true === $input->hasParameterOption(array('--help', '-H'))) + { + if (!$name) + { + $name = 'help'; + $input = new ArrayInput(array('command' => 'help')); + } + else + { + $this->wantHelps = true; + } + } + + if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) + { + $input->setInteractive(false); + } + + if (true === $input->hasParameterOption(array('--quiet', '-q'))) + { + $output->setVerbosity(Output::VERBOSITY_QUIET); + } + elseif (true === $input->hasParameterOption(array('--verbose', '-v'))) + { + $output->setVerbosity(Output::VERBOSITY_VERBOSE); + } + + if (true === $input->hasParameterOption(array('--version', '-V'))) + { + $output->writeln($this->getLongVersion()); + + return 0; + } + + if (!$name) + { + $name = 'list'; + $input = new ArrayInput(array('command' => 'list')); + } + + // the command name MUST be the first element of the input + $command = $this->findCommand($name); + + $this->runningCommand = $command; + $statusCode = $command->run($input, $output); + $this->runningCommand = null; + + return is_numeric($statusCode) ? $statusCode : 0; + } + + /** + * Set a helper set to be used with the command. + * + * @param HelperSet $helperSet The helper set + */ + public function setHelperSet(HelperSet $helperSet) + { + $this->helperSet = $helperSet; + } + + /** + * Get the helper set associated with the command + * + * @return HelperSet The HelperSet isntance associated with this command + */ + public function getHelperSet() + { + return $this->helperSet; + } + + /** + * Gets the InputDefinition related to this Application. + * + * @return InputDefinition The InputDefinition instance + */ + public function getDefinition() + { + return $this->definition; + } + + /** + * Gets the help message. + * + * @return string A help message. + */ + public function getHelp() + { + $messages = array( + $this->getLongVersion(), + '', + 'Usage:', + sprintf(" [options] command [arguments]\n"), + 'Options:', + ); + + foreach ($this->definition->getOptions() as $option) + { + $messages[] = sprintf(' %-29s %s %s', + '--'.$option->getName().'', + $option->getShortcut() ? '-'.$option->getShortcut().'' : ' ', + $option->getDescription() + ); + } + + return implode("\n", $messages); + } + + /** + * Sets whether to catch exceptions or not during commands execution. + * + * @param Boolean $boolean Whether to catch exceptions or not during commands execution + */ + public function setCatchExceptions($boolean) + { + $this->catchExceptions = (Boolean) $boolean; + } + + /** + * Sets whether to automatically exit after a command execution or not. + * + * @param Boolean $boolean Whether to automatically exit after a command execution or not + */ + public function setAutoExit($boolean) + { + $this->autoExit = (Boolean) $boolean; + } + + /** + * Gets the name of the application. + * + * @return string The application name + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the application name. + * + * @param string $name The application name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Gets the application version. + * + * @return string The application version + */ + public function getVersion() + { + return $this->version; + } + + /** + * Sets the application version. + * + * @param string $version The application version + */ + public function setVersion($version) + { + $this->version = $version; + } + + /** + * Returns the long version of the application. + * + * @return string The long application version + */ + public function getLongVersion() + { + if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) + { + return sprintf('%s version %s', $this->getName(), $this->getVersion()); + } + else + { + return 'Console Tool'; + } + } + + /** + * Registers a new command. + * + * @param string $name The command name + * + * @return Command The newly created command + */ + public function register($name) + { + return $this->addCommand(new Command($name)); + } + + /** + * Adds an array of command objects. + * + * @param array $commands An array of commands + */ + public function addCommands(array $commands) + { + foreach ($commands as $command) + { + $this->addCommand($command); + } + } + + /** + * Adds a command object. + * + * If a command with the same name already exists, it will be overridden. + * + * @param Command $command A Command object + * + * @return Command The registered command + */ + public function addCommand(Command $command) + { + $command->setApplication($this); + + $this->commands[$command->getFullName()] = $command; + + foreach ($command->getAliases() as $alias) + { + $this->aliases[$alias] = $command; + } + + return $command; + } + + /** + * Returns a registered command by name or alias. + * + * @param string $name The command name or alias + * + * @return Command A Command object + */ + public function getCommand($name) + { + if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) + { + throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); + } + + $command = isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; + + if ($this->wantHelps) + { + $this->wantHelps = false; + + $helpCommand = $this->getCommand('help'); + $helpCommand->setCommand($command); + + return $helpCommand; + } + + return $command; + } + + /** + * Returns true if the command exists, false otherwise + * + * @param string $name The command name or alias + * + * @return Boolean true if the command exists, false otherwise + */ + public function hasCommand($name) + { + return isset($this->commands[$name]) || isset($this->aliases[$name]); + } + + /** + * Returns an array of all unique namespaces used by currently registered commands. + * + * It does not returns the global namespace which always exists. + * + * @return array An array of namespaces + */ + public function getNamespaces() + { + $namespaces = array(); + foreach ($this->commands as $command) + { + if ($command->getNamespace()) + { + $namespaces[$command->getNamespace()] = true; + } + } + + return array_keys($namespaces); + } + + /** + * Finds a registered namespace by a name or an abbreviation. + * + * @return string A registered namespace + */ + public function findNamespace($namespace) + { + $abbrevs = static::getAbbreviations($this->getNamespaces()); + + if (!isset($abbrevs[$namespace])) + { + throw new \InvalidArgumentException(sprintf('There are no commands defined in the "%s" namespace.', $namespace)); + } + + if (count($abbrevs[$namespace]) > 1) + { + throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$namespace]))); + } + + return $abbrevs[$namespace][0]; + } + + /** + * Finds a command by name or alias. + * + * Contrary to getCommand, this command tries to find the best + * match if you give it an abbreviation of a name or alias. + * + * @param string $name A command name or a command alias + * + * @return Command A Command instance + */ + public function findCommand($name) + { + // namespace + $namespace = ''; + if (false !== $pos = strpos($name, ':')) + { + $namespace = $this->findNamespace(substr($name, 0, $pos)); + $name = substr($name, $pos + 1); + } + + $fullName = $namespace ? $namespace.':'.$name : $name; + + // name + $commands = array(); + foreach ($this->commands as $command) + { + if ($command->getNamespace() == $namespace) + { + $commands[] = $command->getName(); + } + } + + $abbrevs = static::getAbbreviations($commands); + if (isset($abbrevs[$name]) && 1 == count($abbrevs[$name])) + { + return $this->getCommand($namespace ? $namespace.':'.$abbrevs[$name][0] : $abbrevs[$name][0]); + } + + if (isset($abbrevs[$name]) && count($abbrevs[$name]) > 1) + { + $suggestions = $this->getAbbreviationSuggestions(array_map(function ($command) use ($namespace) { return $namespace.':'.$command; }, $abbrevs[$name])); + + throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $suggestions)); + } + + // aliases + $abbrevs = static::getAbbreviations(array_keys($this->aliases)); + if (!isset($abbrevs[$fullName])) + { + throw new \InvalidArgumentException(sprintf('Command "%s" is not defined.', $fullName)); + } + + if (count($abbrevs[$fullName]) > 1) + { + throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $this->getAbbreviationSuggestions($abbrevs[$fullName]))); + } + + return $this->getCommand($abbrevs[$fullName][0]); + } + + /** + * Gets the commands (registered in the given namespace if provided). + * + * The array keys are the full names and the values the command instances. + * + * @param string $namespace A namespace name + * + * @return array An array of Command instances + */ + public function getCommands($namespace = null) + { + if (null === $namespace) + { + return $this->commands; + } + + $commands = array(); + foreach ($this->commands as $name => $command) + { + if ($namespace === $command->getNamespace()) + { + $commands[$name] = $command; + } + } + + return $commands; + } + + /** + * Returns an array of possible abbreviations given a set of names. + * + * @param array An array of names + * + * @return array An array of abbreviations + */ + static public function getAbbreviations($names) + { + $abbrevs = array(); + foreach ($names as $name) + { + for ($len = strlen($name) - 1; $len > 0; --$len) + { + $abbrev = substr($name, 0, $len); + if (!isset($abbrevs[$abbrev])) + { + $abbrevs[$abbrev] = array($name); + } + else + { + $abbrevs[$abbrev][] = $name; + } + } + } + + // Non-abbreviations always get entered, even if they aren't unique + foreach ($names as $name) + { + $abbrevs[$name] = array($name); + } + + return $abbrevs; + } + + /** + * Returns a text representation of the Application. + * + * @param string $namespace An optional namespace name + * + * @return string A string representing the Application + */ + public function asText($namespace = null) + { + $commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands; + + $messages = array($this->getHelp(), ''); + if ($namespace) + { + $messages[] = sprintf("Available commands for the \"%s\" namespace:", $namespace); + } + else + { + $messages[] = 'Available commands:'; + } + + $width = 0; + foreach ($commands as $command) + { + $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; + } + $width += 2; + + // add commands by namespace + foreach ($this->sortCommands($commands) as $space => $commands) + { + if (!$namespace && '_global' !== $space) + { + $messages[] = ''.$space.''; + } + + foreach ($commands as $command) + { + $aliases = $command->getAliases() ? ' ('.implode(', ', $command->getAliases()).')' : ''; + + $messages[] = sprintf(" %-${width}s %s%s", ($command->getNamespace() ? ':' : '').$command->getName(), $command->getDescription(), $aliases); + } + } + + return implode("\n", $messages); + } + + /** + * Returns an XML representation of the Application. + * + * @param string $namespace An optional namespace name + * @param Boolean $asDom Whether to return a DOM or an XML string + * + * @return string|DOMDocument An XML string representing the Application + */ + public function asXml($namespace = null, $asDom = false) + { + $commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands; + + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + $dom->appendChild($xml = $dom->createElement('symfony')); + + $xml->appendChild($commandsXML = $dom->createElement('commands')); + + if ($namespace) + { + $commandsXML->setAttribute('namespace', $namespace); + } + else + { + $xml->appendChild($namespacesXML = $dom->createElement('namespaces')); + } + + // add commands by namespace + foreach ($this->sortCommands($commands) as $space => $commands) + { + if (!$namespace) + { + $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); + $namespaceArrayXML->setAttribute('id', $space); + } + + foreach ($commands as $command) + { + if (!$namespace) + { + $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); + $commandXML->appendChild($dom->createTextNode($command->getName())); + } + + $commandXML = new \DOMDocument('1.0', 'UTF-8'); + $commandXML->formatOutput = true; + $commandXML->loadXML($command->asXml()); + $node = $commandXML->getElementsByTagName('command')->item(0); + $node = $dom->importNode($node, true); + + $commandsXML->appendChild($node); + } + } + + return $asDom ? $dom : $dom->saveXml(); + } + + /** + * Renders a catched exception. + * + * @param Exception $e An exception instance + * @param OutputInterface $output An OutputInterface instance + */ + public function renderException($e, $output) + { + $strlen = function ($string) + { + return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string); + }; + + $title = sprintf(' [%s] ', get_class($e)); + $len = $strlen($title); + $lines = array(); + foreach (explode("\n", $e->getMessage()) as $line) + { + $lines[] = sprintf(' %s ', $line); + $len = max($strlen($line) + 4, $len); + } + + $messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title))); + + foreach ($lines as $line) + { + $messages[] = $line.str_repeat(' ', $len - $strlen($line)); + } + + $messages[] = str_repeat(' ', $len); + + $output->writeln("\n"); + foreach ($messages as $message) + { + $output->writeln("$message"); + } + $output->writeln("\n"); + + if (null !== $this->runningCommand) + { + $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); + $output->writeln("\n"); + } + + if (Output::VERBOSITY_VERBOSE === $output->getVerbosity()) + { + $output->writeln('Exception trace:'); + + // exception related properties + $trace = $e->getTrace(); + array_unshift($trace, array( + 'function' => '', + 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', + 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', + 'args' => array(), + )); + + for ($i = 0, $count = count($trace); $i < $count; $i++) + { + $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; + $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; + $function = $trace[$i]['function']; + $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; + $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; + + $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); + } + + $output->writeln("\n"); + } + } + + private function sortCommands($commands) + { + $namespacedCommands = array(); + foreach ($commands as $name => $command) + { + $key = $command->getNamespace() ? $command->getNamespace() : '_global'; + + if (!isset($namespacedCommands[$key])) + { + $namespacedCommands[$key] = array(); + } + + $namespacedCommands[$key][$name] = $command; + } + ksort($namespacedCommands); + + foreach ($namespacedCommands as $name => &$commands) + { + ksort($commands); + } + + return $namespacedCommands; + } + + private function getAbbreviationSuggestions($abbrevs) + { + return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); + } +} diff --git a/lib/vendor/Symfony/Components/Console/Command/Command.php b/lib/vendor/Symfony/Components/Console/Command/Command.php new file mode 100644 index 000000000..bbde5f94e --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Command/Command.php @@ -0,0 +1,508 @@ + + * + * 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. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class Command +{ + protected $name; + protected $namespace; + protected $aliases; + protected $definition; + protected $help; + protected $application; + protected $description; + protected $ignoreValidationErrors; + protected $formatter; + protected $applicationDefinitionMerged; + protected $code; + + /** + * Constructor. + * + * @param string $name The name of the command + */ + public function __construct($name = null) + { + $this->definition = new InputDefinition(); + $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.'); + } + } + + /** + * Sets the application instance for this command. + * + * @param Application $application An Application instance + */ + public function setApplication(Application $application = null) + { + $this->application = $application; + } + + /** + * Configures the current command. + */ + protected function configure() + { + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return integer 0 if everything went fine, or an error code + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + throw new \LogicException('You must override the execute() method in the concrete command class.'); + } + + /** + * 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 + */ + public function run(InputInterface $input, OutputInterface $output) + { + // add the application arguments and options + $this->mergeApplicationDefinition(); + + // bind the input against the command specific arguments/options + try + { + $input->bind($this->definition); + } + catch (\Exception $e) + { + if (!$this->ignoreValidationErrors) + { + throw $e; + } + } + + $this->initialize($input, $output); + + 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. + * + * @param \Closure $code A \Closure + * + * @return Command The current instance + */ + public function setCode(\Closure $code) + { + $this->code = $code; + + return $this; + } + + /** + * Merges the application definition with the command definition. + */ + 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 + */ + public function setDefinition($definition) + { + if ($definition instanceof InputDefinition) + { + $this->definition = $definition; + } + else + { + $this->definition->setDefinition($definition); + } + + $this->applicationDefinitionMerged = false; + + return $this; + } + + /** + * Gets the InputDefinition attached to this Command. + * + * @return InputDefinition $definition An InputDefinition instance + */ + public function getDefinition() + { + return $this->definition; + } + + /** + * Adds an argument. + * + * @param string $name The argument name + * @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param string $description A description text + * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) + * + * @return Command The current instance + */ + public function addArgument($name, $mode = null, $description = '', $default = null) + { + $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); + + 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 + */ + public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) + { + $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); + + return $this; + } + + /** + * Sets the name of the command. + * + * This method can set both the namespace and the name if + * you separate them by a colon (:) + * + * $command->setName('foo:bar'); + * + * @param string $name The command name + * + * @return Command The current instance + */ + 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'); + } + + $this->namespace = $namespace; + $this->name = $name; + + return $this; + } + + /** + * Returns the command namespace. + * + * @return string The command namespace + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * Returns the command name + * + * @return string The command name + */ + public function getName() + { + return $this->name; + } + + /** + * Returns the fully qualified command name. + * + * @return string The fully qualified command name + */ + public function getFullName() + { + return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName(); + } + + /** + * Sets the description for the command. + * + * @param string $description The description for the command + * + * @return Command The current instance + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * Returns the description for the command. + * + * @return string The description for the command + */ + public function getDescription() + { + return $this->description; + } + + /** + * Sets the help for the command. + * + * @param string $help The help for the command + * + * @return Command The current instance + */ + public function setHelp($help) + { + $this->help = $help; + + return $this; + } + + /** + * Returns the help for the command. + * + * @return string The help for the command + */ + public function getHelp() + { + return $this->help; + } + + /** + * Sets the aliases for the command. + * + * @param array $aliases An array of aliases for the command + * + * @return Command The current instance + */ + public function setAliases($aliases) + { + $this->aliases = $aliases; + + return $this; + } + + /** + * Returns the aliases for the command. + * + * @return array An array of aliases for the command + */ + public function getAliases() + { + return $this->aliases; + } + + /** + * Returns the synopsis for the command. + * + * @return string The synopsis + */ + public function getSynopsis() + { + return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis()); + } + + /** + * 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 + */ + protected function getHelper($name) + { + return $this->application->getHelperSet()->get($name); + } + + /** + * 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); + } + + /** + * Returns a text representation of the command. + * + * @return string A string representing the command + */ + public function asText() + { + $messages = array( + 'Usage:', + ' '.$this->getSynopsis(), + '', + ); + + if ($this->getAliases()) + { + $messages[] = 'Aliases: '.implode(', ', $this->getAliases()).''; + } + + $messages[] = $this->definition->asText(); + + if ($help = $this->getHelp()) + { + $messages[] = 'Help:'; + $messages[] = ' '.implode("\n ", explode("\n", $help))."\n"; + } + + return implode("\n", $messages); + } + + /** + * Returns an XML representation of the command. + * + * @param Boolean $asDom Whether to return a DOM or an XML string + * + * @return string|DOMDocument An XML string representing the command + */ + 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()); + + $commandXML->appendChild($usageXML = $dom->createElement('usage')); + $usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), ''))); + + $commandXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription())))); + + $commandXML->appendChild($helpXML = $dom->createElement('help')); + $help = $this->help; + $helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help)))); + + $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); + 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)); + + return $asDom ? $dom : $dom->saveXml(); + } +} diff --git a/lib/vendor/Symfony/Components/Console/Command/HelpCommand.php b/lib/vendor/Symfony/Components/Console/Command/HelpCommand.php new file mode 100644 index 000000000..8258c5c18 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Command/HelpCommand.php @@ -0,0 +1,83 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * HelpCommand displays the help for a given command. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class HelpCommand extends Command +{ + protected $command; + + /** + * @see Command + */ + protected function configure() + { + $this->ignoreValidationErrors = true; + + $this + ->setDefinition(array( + new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), + new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'), + )) + ->setName('help') + ->setAliases(array('?')) + ->setDescription('Displays help for a command') + ->setHelp(<<help command displays help for a given command: + + ./symfony help test:all + +You can also output the help as XML by using the --xml option: + + ./symfony help --xml test:all +EOF + ); + } + + public function setCommand(Command $command) + { + $this->command = $command; + } + + /** + * @see Command + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (null === $this->command) + { + $this->command = $this->application->getCommand($input->getArgument('command_name')); + } + + if ($input->getOption('xml')) + { + $output->writeln($this->command->asXml(), Output::OUTPUT_RAW); + } + else + { + $output->writeln($this->command->asText()); + } + } +} diff --git a/lib/vendor/Symfony/Components/Console/Command/ListCommand.php b/lib/vendor/Symfony/Components/Console/Command/ListCommand.php new file mode 100644 index 000000000..3fddbc224 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Command/ListCommand.php @@ -0,0 +1,72 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * ListCommand displays the list of all available commands for the application. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class ListCommand extends Command +{ + /** + * @see Command + */ + protected function configure() + { + $this + ->setDefinition(array( + new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), + new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'), + )) + ->setName('list') + ->setDescription('Lists commands') + ->setHelp(<<list command lists all commands: + + ./symfony list + +You can also display the commands for a specific namespace: + + ./symfony list test + +You can also output the information as XML by using the --xml option: + + ./symfony list --xml +EOF + ); + } + + /** + * @see Command + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if ($input->getOption('xml')) + { + $output->writeln($this->application->asXml($input->getArgument('namespace')), Output::OUTPUT_RAW); + } + else + { + $output->writeln($this->application->asText($input->getArgument('namespace'))); + } + } +} diff --git a/lib/vendor/Symfony/Components/Console/Helper/DialogHelper.php b/lib/vendor/Symfony/Components/Console/Helper/DialogHelper.php new file mode 100644 index 000000000..a19c3d949 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Helper/DialogHelper.php @@ -0,0 +1,119 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * The Dialog class provides helpers to interact with the user. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class DialogHelper extends Helper +{ + /** + * Asks a question to the user. + * + * @param OutputInterface $output + * @param string|array $question The question to ask + * @param string $default The default answer if none is given by the user + * + * @param string The user answer + */ + public function ask(OutputInterface $output, $question, $default = null) + { + // @codeCoverageIgnoreStart + $output->writeln($question); + + $ret = trim(fgets(STDIN)); + + return $ret ? $ret : $default; + // @codeCoverageIgnoreEnd + } + + /** + * Asks a confirmation to the user. + * + * The question will be asked until the user answer by nothing, yes, or no. + * + * @param OutputInterface $output + * @param string|array $question The question to ask + * @param Boolean $default The default answer if the user enters nothing + * + * @param Boolean true if the user has confirmed, false otherwise + */ + public function askConfirmation(OutputInterface $output, $question, $default = true) + { + // @codeCoverageIgnoreStart + $answer = 'z'; + while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) + { + $answer = $this->ask($output, $question); + } + + if (false === $default) + { + return $answer && 'y' == strtolower($answer[0]); + } + else + { + return !$answer || 'y' == strtolower($answer[0]); + } + // @codeCoverageIgnoreEnd + } + + /** + * Asks for a value and validates the response. + * + * @param OutputInterface $output + * @param string|array $question + * @param Closure $validator + * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) + * + * @return mixed + */ + public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false) + { + // @codeCoverageIgnoreStart + $error = null; + while (false === $attempts || $attempts--) + { + if (null !== $error) + { + $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); + } + + $value = $this->ask($output, $question, null); + + try + { + return $validator($value); + } + catch (\Exception $error) + { + } + } + + throw $error; + // @codeCoverageIgnoreEnd + } + + /** + * Returns the helper's canonical name + */ + public function getName() + { + return 'dialog'; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Helper/FormatterHelper.php b/lib/vendor/Symfony/Components/Console/Helper/FormatterHelper.php new file mode 100644 index 000000000..6eedca733 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Helper/FormatterHelper.php @@ -0,0 +1,89 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * The Formatter class provides helpers to format messages. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class FormatterHelper extends Helper +{ + /** + * Formats a message within a section. + * + * @param string $section The section name + * @param string $message The message + * @param string $style The style to apply to the section + */ + public function formatSection($section, $message, $style = 'info') + { + return sprintf("<%s>[%s] %s", $style, $section, $style, $message); + } + + /** + * Formats a message as a block of text. + * + * @param string|array $messages The message to write in the block + * @param string $style The style to apply to the whole block + * @param Boolean $large Whether to return a large block + * + * @return string The formatter message + */ + public function formatBlock($messages, $style, $large = false) + { + if (!is_array($messages)) + { + $messages = array($messages); + } + + $len = 0; + $lines = array(); + foreach ($messages as $message) + { + $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); + $len = max($this->strlen($message) + ($large ? 4 : 2), $len); + } + + $messages = $large ? array(str_repeat(' ', $len)) : array(); + foreach ($lines as $line) + { + $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); + } + if ($large) + { + $messages[] = str_repeat(' ', $len); + } + + foreach ($messages as &$message) + { + $message = sprintf('<%s>%s', $style, $message, $style); + } + + return implode("\n", $messages); + } + + protected function strlen($string) + { + return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string); + } + + /** + * Returns the helper's canonical name + */ + public function getName() + { + return 'formatter'; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Helper/Helper.php b/lib/vendor/Symfony/Components/Console/Helper/Helper.php new file mode 100644 index 000000000..f083b47ab --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Helper/Helper.php @@ -0,0 +1,45 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Helper is the base class for all helper classes. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +abstract class Helper implements HelperInterface +{ + protected + $helperSet = null; + + /** + * Sets the helper set associated with this helper. + * + * @param HelperSet $helperSet A HelperSet instance + */ + public function setHelperSet(HelperSet $helperSet = null) + { + $this->helperSet = $helperSet; + } + + /** + * Gets the helper set associated with this helper. + * + * @return HelperSet A HelperSet instance + */ + public function getHelperSet() + { + return $this->helperSet; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Helper/HelperInterface.php b/lib/vendor/Symfony/Components/Console/Helper/HelperInterface.php new file mode 100644 index 000000000..f3de9aa65 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Helper/HelperInterface.php @@ -0,0 +1,43 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * HelperInterface is the interface all helpers must implement. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +interface HelperInterface +{ + /** + * Sets the helper set associated with this helper. + * + * @param HelperSet $helperSet A HelperSet instance + */ + function setHelperSet(HelperSet $helperSet = null); + + /** + * Gets the helper set associated with this helper. + * + * @return HelperSet A HelperSet instance + */ + function getHelperSet(); + + /** + * Returns the canonical name of this helper. + * + * @return string The canonical name + */ + function getName(); +} diff --git a/lib/vendor/Symfony/Components/Console/Helper/HelperSet.php b/lib/vendor/Symfony/Components/Console/Helper/HelperSet.php new file mode 100644 index 000000000..67d764f52 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Helper/HelperSet.php @@ -0,0 +1,104 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * HelperSet represents a set of helpers to be used with a command. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class HelperSet +{ + protected + $helpers = array(), + $command = null; + + public function __construct(array $helpers = array()) + { + foreach ($helpers as $alias => $helper) + { + $this->set($helper, is_int($alias) ? null : $alias); + } + } + + /** + * Sets a helper. + * + * @param HelperInterface $value The helper instance + * @param string $alias An alias + */ + public function set(HelperInterface $helper, $alias = null) + { + $this->helpers[$helper->getName()] = $helper; + if (null !== $alias) + { + $this->helpers[$alias] = $helper; + } + + $helper->setHelperSet($this); + } + + /** + * Returns true if the helper if defined. + * + * @param string $name The helper name + * + * @return Boolean true if the helper is defined, false otherwise + */ + public function has($name) + { + return isset($this->helpers[$name]); + } + + /** + * Gets a helper value. + * + * @param string $name The helper name + * + * @return HelperInterface The helper instance + * + * @throws \InvalidArgumentException if the helper is not defined + */ + public function get($name) + { + if (!$this->has($name)) + { + throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); + } + + return $this->helpers[$name]; + } + + /** + * Sets the command associated with this helper set. + * + * @param Command $command A Command instance + */ + public function setCommand(Command $command = null) + { + $this->command = $command; + } + + /** + * Gets the command associated with this helper set. + * + * @return Command A Command instance + */ + public function getCommand() + { + return $this->command; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/ArgvInput.php b/lib/vendor/Symfony/Components/Console/Input/ArgvInput.php new file mode 100644 index 000000000..a140219bf --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/ArgvInput.php @@ -0,0 +1,284 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * ArgvInput represents an input coming from the CLI arguments. + * + * Usage: + * + * $input = new ArgvInput(); + * + * By default, the `$_SERVER['argv']` array is used for the input values. + * + * This can be overriden by explicitly passing the input values in the constructor: + * + * $input = new ArgvInput($_SERVER['argv']); + * + * If you pass it yourself, don't forget that the first element of the array + * is the name of the running program. + * + * When passing an argument to the constructor, be sure that it respects + * the same rules as the argv one. It's almost always better to use the + * `StringInput` when you want to provide your own input. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + * + * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 + */ +class ArgvInput extends Input +{ + protected $tokens; + protected $parsed; + + /** + * Constructor. + * + * @param array $argv An array of parameters from the CLI (in the argv format) + * @param InputDefinition $definition A InputDefinition instance + */ + public function __construct(array $argv = null, InputDefinition $definition = null) + { + if (null === $argv) + { + $argv = $_SERVER['argv']; + } + + // strip the program name + array_shift($argv); + + $this->tokens = $argv; + + parent::__construct($definition); + } + + /** + * Processes command line arguments. + */ + protected function parse() + { + $this->parsed = $this->tokens; + while ($token = array_shift($this->parsed)) + { + if ('--' === substr($token, 0, 2)) + { + $this->parseLongOption($token); + } + elseif ('-' === $token[0]) + { + $this->parseShortOption($token); + } + else + { + $this->parseArgument($token); + } + } + } + + /** + * Parses a short option. + * + * @param string $token The current token. + */ + protected function parseShortOption($token) + { + $name = substr($token, 1); + + if (strlen($name) > 1) + { + if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptParameter()) + { + // an option with a value (with no space) + $this->addShortOption($name[0], substr($name, 1)); + } + else + { + $this->parseShortOptionSet($name); + } + } + else + { + $this->addShortOption($name, null); + } + } + + /** + * Parses a short option set. + * + * @param string $token The current token + */ + protected function parseShortOptionSet($name) + { + $len = strlen($name); + for ($i = 0; $i < $len; $i++) + { + if (!$this->definition->hasShortcut($name[$i])) + { + throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); + } + + $option = $this->definition->getOptionForShortcut($name[$i]); + if ($option->acceptParameter()) + { + $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); + + break; + } + else + { + $this->addLongOption($option->getName(), true); + } + } + } + + /** + * Parses a long option. + * + * @param string $token The current token + */ + protected function parseLongOption($token) + { + $name = substr($token, 2); + + if (false !== $pos = strpos($name, '=')) + { + $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); + } + else + { + $this->addLongOption($name, null); + } + } + + /** + * Parses an argument. + * + * @param string $token The current token + */ + protected function parseArgument($token) + { + if (!$this->definition->hasArgument(count($this->arguments))) + { + throw new \RuntimeException('Too many arguments.'); + } + + $this->arguments[$this->definition->getArgument(count($this->arguments))->getName()] = $token; + } + + /** + * Adds a short option value. + * + * @param string $shortcut The short option key + * @param mixed $value The value for the option + */ + protected function addShortOption($shortcut, $value) + { + if (!$this->definition->hasShortcut($shortcut)) + { + throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @param string $name The long option key + * @param mixed $value The value for the option + */ + protected function addLongOption($name, $value) + { + if (!$this->definition->hasOption($name)) + { + throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + } + + $option = $this->definition->getOption($name); + + if (null === $value && $option->acceptParameter()) + { + // if option accepts an optional or mandatory argument + // let's see if there is one provided + $next = array_shift($this->parsed); + if ('-' !== $next[0]) + { + $value = $next; + } + else + { + array_unshift($this->parsed, $next); + } + } + + if (null === $value) + { + if ($option->isParameterRequired()) + { + throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + } + + $value = $option->isParameterOptional() ? $option->getDefault() : true; + } + + $this->options[$name] = $value; + } + + /** + * Returns the first argument from the raw parameters (not parsed). + * + * @return string The value of the first argument or null otherwise + */ + public function getFirstArgument() + { + foreach ($this->tokens as $token) + { + if ($token && '-' === $token[0]) + { + continue; + } + + return $token; + } + } + + /** + * Returns true if the raw parameters (not parsed) contains a value. + * + * This method is to be used to introspect the input parameters + * before it has been validated. It must be used carefully. + * + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * + * @return Boolean true if the value is contained in the raw parameters + */ + public function hasParameterOption($values) + { + if (!is_array($values)) + { + $values = array($values); + } + + foreach ($this->tokens as $v) + { + if (in_array($v, $values)) + { + return true; + } + } + + return false; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/ArrayInput.php b/lib/vendor/Symfony/Components/Console/Input/ArrayInput.php new file mode 100644 index 000000000..3ae6154d3 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/ArrayInput.php @@ -0,0 +1,174 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * ArrayInput represents an input provided as an array. + * + * Usage: + * + * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class ArrayInput extends Input +{ + protected $parameters; + + /** + * Constructor. + * + * @param array $param An array of parameters + * @param InputDefinition $definition A InputDefinition instance + */ + public function __construct(array $parameters, InputDefinition $definition = null) + { + $this->parameters = $parameters; + + parent::__construct($definition); + } + + /** + * Returns the first argument from the raw parameters (not parsed). + * + * @return string The value of the first argument or null otherwise + */ + public function getFirstArgument() + { + foreach ($this->parameters as $key => $value) + { + if ($key && '-' === $key[0]) + { + continue; + } + + return $value; + } + } + + /** + * Returns true if the raw parameters (not parsed) contains a value. + * + * This method is to be used to introspect the input parameters + * before it has been validated. It must be used carefully. + * + * @param string|array $value The values to look for in the raw parameters (can be an array) + * + * @return Boolean true if the value is contained in the raw parameters + */ + public function hasParameterOption($values) + { + if (!is_array($values)) + { + $values = array($values); + } + + foreach ($this->parameters as $k => $v) + { + if (!is_int($k)) + { + $v = $k; + } + + if (in_array($v, $values)) + { + return true; + } + } + + return false; + } + + /** + * Processes command line arguments. + */ + protected function parse() + { + foreach ($this->parameters as $key => $value) + { + if ('--' === substr($key, 0, 2)) + { + $this->addLongOption(substr($key, 2), $value); + } + elseif ('-' === $key[0]) + { + $this->addShortOption(substr($key, 1), $value); + } + else + { + $this->addArgument($key, $value); + } + } + } + + /** + * Adds a short option value. + * + * @param string $shortcut The short option key + * @param mixed $value The value for the option + */ + protected function addShortOption($shortcut, $value) + { + if (!$this->definition->hasShortcut($shortcut)) + { + throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @param string $name The long option key + * @param mixed $value The value for the option + */ + protected function addLongOption($name, $value) + { + if (!$this->definition->hasOption($name)) + { + throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + } + + $option = $this->definition->getOption($name); + + if (null === $value) + { + if ($option->isParameterRequired()) + { + throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + } + + $value = $option->isParameterOptional() ? $option->getDefault() : true; + } + + $this->options[$name] = $value; + } + + /** + * Adds an argument value. + * + * @param string $name The argument name + * @param mixed $value The value for the argument + */ + protected function addArgument($name, $value) + { + if (!$this->definition->hasArgument($name)) + { + throw new \RuntimeException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/Input.php b/lib/vendor/Symfony/Components/Console/Input/Input.php new file mode 100644 index 000000000..9e9e5f482 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/Input.php @@ -0,0 +1,198 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Input is the base class for all concrete Input classes. + * + * Three concrete classes are provided by default: + * + * * `ArgvInput`: The input comes from the CLI arguments (argv) + * * `StringInput`: The input is provided as a string + * * `ArrayInput`: The input is provided as an array + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +abstract class Input implements InputInterface +{ + protected $definition; + protected $options; + protected $arguments; + protected $interactive = true; + + /** + * Constructor. + * + * @param InputDefinition $definition A InputDefinition instance + */ + public function __construct(InputDefinition $definition = null) + { + if (null === $definition) + { + $this->definition = new InputDefinition(); + } + else + { + $this->bind($definition); + $this->validate(); + } + } + + /** + * Binds the current Input instance with the given arguments and options. + * + * @param InputDefinition $definition A InputDefinition instance + */ + public function bind(InputDefinition $definition) + { + $this->arguments = array(); + $this->options = array(); + $this->definition = $definition; + + $this->parse(); + } + + /** + * Processes command line arguments. + */ + abstract protected function parse(); + + public function validate() + { + if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) + { + throw new \RuntimeException('Not enough arguments.'); + } + } + + public function isInteractive() + { + return $this->interactive; + } + + public function setInteractive($interactive) + { + $this->interactive = (Boolean) $interactive; + } + + /** + * Returns the argument values. + * + * @return array An array of argument values + */ + public function getArguments() + { + return array_merge($this->definition->getArgumentDefaults(), $this->arguments); + } + + /** + * Returns the argument value for a given argument name. + * + * @param string $name The argument name + * + * @return mixed The argument value + */ + public function getArgument($name) + { + if (!$this->definition->hasArgument($name)) + { + throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); + } + + /** + * Sets an argument value by name. + * + * @param string $name The argument name + * @param string $value The argument value + */ + public function setArgument($name, $value) + { + if (!$this->definition->hasArgument($name)) + { + throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } + + /** + * Returns true if an InputArgument object exists by name or position. + * + * @param string|integer $name The InputArgument name or position + * + * @return Boolean true if the InputArgument object exists, false otherwise + */ + public function hasArgument($name) + { + return $this->definition->hasArgument($name); + } + + /** + * Returns the options values. + * + * @return array An array of option values + */ + public function getOptions() + { + return array_merge($this->definition->getOptionDefaults(), $this->options); + } + + /** + * Returns the option value for a given option name. + * + * @param string $name The option name + * + * @return mixed The option value + */ + public function getOption($name) + { + if (!$this->definition->hasOption($name)) + { + throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + } + + /** + * Sets an option value by name. + * + * @param string $name The option name + * @param string $value The option value + */ + public function setOption($name, $value) + { + if (!$this->definition->hasOption($name)) + { + throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + $this->options[$name] = $value; + } + + /** + * Returns true if an InputOption object exists by name. + * + * @param string $name The InputOption name + * + * @return Boolean true if the InputOption object exists, false otherwise + */ + public function hasOption($name) + { + return $this->definition->hasOption($name); + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/InputArgument.php b/lib/vendor/Symfony/Components/Console/Input/InputArgument.php new file mode 100644 index 000000000..9b5925b4b --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/InputArgument.php @@ -0,0 +1,134 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Represents a command line argument. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class InputArgument +{ + const REQUIRED = 1; + const OPTIONAL = 2; + const IS_ARRAY = 4; + + protected $name; + protected $mode; + protected $default; + protected $description; + + /** + * Constructor. + * + * @param string $name The argument name + * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL + * @param string $description A description text + * @param mixed $default The default value (for self::OPTIONAL mode only) + */ + public function __construct($name, $mode = null, $description = '', $default = null) + { + if (null === $mode) + { + $mode = self::OPTIONAL; + } + else if (is_string($mode) || $mode > 7) + { + throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->mode = $mode; + $this->description = $description; + + $this->setDefault($default); + } + + /** + * Returns the argument name. + * + * @return string The argument name + */ + public function getName() + { + return $this->name; + } + + /** + * Returns true if the argument is required. + * + * @return Boolean true if parameter mode is self::REQUIRED, false otherwise + */ + public function isRequired() + { + return self::REQUIRED === (self::REQUIRED & $this->mode); + } + + /** + * Returns true if the argument can take multiple values. + * + * @return Boolean true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray() + { + return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); + } + + /** + * Sets the default value. + * + * @param mixed $default The default value + */ + public function setDefault($default = null) + { + if (self::REQUIRED === $this->mode && null !== $default) + { + throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.'); + } + + if ($this->isArray()) + { + if (null === $default) + { + $default = array(); + } + else if (!is_array($default)) + { + throw new \LogicException('A default value for an array argument must be an array.'); + } + } + + $this->default = $default; + } + + /** + * Returns the default value. + * + * @return mixed The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the description text. + * + * @return string The description text + */ + public function getDescription() + { + return $this->description; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/InputDefinition.php b/lib/vendor/Symfony/Components/Console/Input/InputDefinition.php new file mode 100644 index 000000000..2977e7fd6 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/InputDefinition.php @@ -0,0 +1,507 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * A InputDefinition represents a set of valid command line arguments and options. + * + * Usage: + * + * $definition = new InputDefinition(array( + * new InputArgument('name', InputArgument::REQUIRED), + * new InputOption('foo', 'f', InputOption::PARAMETER_REQUIRED), + * )); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class InputDefinition +{ + protected $arguments; + protected $requiredCount; + protected $hasAnArrayArgument = false; + protected $hasOptional; + protected $options; + protected $shortcuts; + + /** + * Constructor. + * + * @param array $definition An array of InputArgument and InputOption instance + */ + public function __construct(array $definition = array()) + { + $this->setDefinition($definition); + } + + public function setDefinition(array $definition) + { + $arguments = array(); + $options = array(); + foreach ($definition as $item) + { + if ($item instanceof InputOption) + { + $options[] = $item; + } + else + { + $arguments[] = $item; + } + } + + $this->setArguments($arguments); + $this->setOptions($options); + } + + /** + * Sets the InputArgument objects. + * + * @param array $arguments An array of InputArgument objects + */ + public function setArguments($arguments = array()) + { + $this->arguments = array(); + $this->requiredCount = 0; + $this->hasOptional = false; + $this->addArguments($arguments); + } + + /** + * Add an array of InputArgument objects. + * + * @param array $arguments An array of InputArgument objects + */ + public function addArguments($arguments = array()) + { + if (null !== $arguments) + { + foreach ($arguments as $argument) + { + $this->addArgument($argument); + } + } + } + + /** + * Add an InputArgument object. + * + * @param InputArgument $argument An InputArgument object + */ + public function addArgument(InputArgument $argument) + { + if (isset($this->arguments[$argument->getName()])) + { + throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName())); + } + + if ($this->hasAnArrayArgument) + { + throw new \LogicException('Cannot add an argument after an array argument.'); + } + + if ($argument->isRequired() && $this->hasOptional) + { + throw new \LogicException('Cannot add a required argument after an optional one.'); + } + + if ($argument->isArray()) + { + $this->hasAnArrayArgument = true; + } + + if ($argument->isRequired()) + { + ++$this->requiredCount; + } + else + { + $this->hasOptional = true; + } + + $this->arguments[$argument->getName()] = $argument; + } + + /** + * Returns an InputArgument by name or by position. + * + * @param string|integer $name The InputArgument name or position + * + * @return InputArgument An InputArgument object + */ + public function getArgument($name) + { + $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; + + if (!$this->hasArgument($name)) + { + throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + return $arguments[$name]; + } + + /** + * Returns true if an InputArgument object exists by name or position. + * + * @param string|integer $name The InputArgument name or position + * + * @return Boolean true if the InputArgument object exists, false otherwise + */ + public function hasArgument($name) + { + $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; + + return isset($arguments[$name]); + } + + /** + * Gets the array of InputArgument objects. + * + * @return array An array of InputArgument objects + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Returns the number of InputArguments. + * + * @return integer The number of InputArguments + */ + public function getArgumentCount() + { + return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); + } + + /** + * Returns the number of required InputArguments. + * + * @return integer The number of required InputArguments + */ + public function getArgumentRequiredCount() + { + return $this->requiredCount; + } + + /** + * Gets the default values. + * + * @return array An array of default values + */ + public function getArgumentDefaults() + { + $values = array(); + foreach ($this->arguments as $argument) + { + $values[$argument->getName()] = $argument->getDefault(); + } + + return $values; + } + + /** + * Sets the InputOption objects. + * + * @param array $options An array of InputOption objects + */ + public function setOptions($options = array()) + { + $this->options = array(); + $this->shortcuts = array(); + $this->addOptions($options); + } + + /** + * Add an array of InputOption objects. + * + * @param array $options An array of InputOption objects + */ + public function addOptions($options = array()) + { + foreach ($options as $option) + { + $this->addOption($option); + } + } + + /** + * Add an InputOption object. + * + * @param InputOption $option An InputOption object + */ + public function addOption(InputOption $option) + { + if (isset($this->options[$option->getName()])) + { + throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName())); + } + else if (isset($this->shortcuts[$option->getShortcut()])) + { + throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut())); + } + + $this->options[$option->getName()] = $option; + if ($option->getShortcut()) + { + $this->shortcuts[$option->getShortcut()] = $option->getName(); + } + } + + /** + * Returns an InputOption by name. + * + * @param string $name The InputOption name + * + * @return InputOption A InputOption object + */ + public function getOption($name) + { + if (!$this->hasOption($name)) + { + throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); + } + + return $this->options[$name]; + } + + /** + * Returns true if an InputOption object exists by name. + * + * @param string $name The InputOption name + * + * @return Boolean true if the InputOption object exists, false otherwise + */ + public function hasOption($name) + { + return isset($this->options[$name]); + } + + /** + * Gets the array of InputOption objects. + * + * @return array An array of InputOption objects + */ + public function getOptions() + { + return $this->options; + } + + /** + * Returns true if an InputOption object exists by shortcut. + * + * @param string $name The InputOption shortcut + * + * @return Boolean true if the InputOption object exists, false otherwise + */ + public function hasShortcut($name) + { + return isset($this->shortcuts[$name]); + } + + /** + * Gets an InputOption by shortcut. + * + * @return InputOption An InputOption object + */ + public function getOptionForShortcut($shortcut) + { + return $this->getOption($this->shortcutToName($shortcut)); + } + + /** + * Gets an array of default values. + * + * @return array An array of all default values + */ + public function getOptionDefaults() + { + $values = array(); + foreach ($this->options as $option) + { + $values[$option->getName()] = $option->getDefault(); + } + + return $values; + } + + /** + * Returns the InputOption name given a shortcut. + * + * @param string $shortcut The shortcut + * + * @return string The InputOption name + */ + protected function shortcutToName($shortcut) + { + if (!isset($this->shortcuts[$shortcut])) + { + throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + return $this->shortcuts[$shortcut]; + } + + /** + * Gets the synopsis. + * + * @return string The synopsis + */ + public function getSynopsis() + { + $elements = array(); + foreach ($this->getOptions() as $option) + { + $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; + $elements[] = sprintf('['.($option->isParameterRequired() ? '%s--%s="..."' : ($option->isParameterOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); + } + + foreach ($this->getArguments() as $argument) + { + $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); + + if ($argument->isArray()) + { + $elements[] = sprintf('... [%sN]', $argument->getName()); + } + } + + return implode(' ', $elements); + } + + /** + * Returns a textual representation of the InputDefinition. + * + * @return string A string representing the InputDefinition + */ + public function asText() + { + // find the largest option or argument name + $max = 0; + foreach ($this->getOptions() as $option) + { + $max = strlen($option->getName()) + 2 > $max ? strlen($option->getName()) + 2 : $max; + } + foreach ($this->getArguments() as $argument) + { + $max = strlen($argument->getName()) > $max ? strlen($argument->getName()) : $max; + } + ++$max; + + $text = array(); + + if ($this->getArguments()) + { + $text[] = 'Arguments:'; + foreach ($this->getArguments() as $argument) + { + if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) + { + $default = sprintf(' (default: %s)', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault()); + } + else + { + $default = ''; + } + + $text[] = sprintf(" %-${max}s %s%s", $argument->getName(), $argument->getDescription(), $default); + } + + $text[] = ''; + } + + if ($this->getOptions()) + { + $text[] = 'Options:'; + + foreach ($this->getOptions() as $option) + { + if ($option->acceptParameter() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) + { + $default = sprintf(' (default: %s)', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault()); + } + else + { + $default = ''; + } + + $multiple = $option->isArray() ? ' (multiple values allowed)' : ''; + $text[] = sprintf(' %-'.$max.'s %s%s%s%s', '--'.$option->getName().'', $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', $option->getDescription(), $default, $multiple); + } + + $text[] = ''; + } + + return implode("\n", $text); + } + + /** + * Returns an XML representation of the InputDefinition. + * + * @param Boolean $asDom Whether to return a DOM or an XML string + * + * @return string|DOMDocument An XML string representing the InputDefinition + */ + public function asXml($asDom = false) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + $dom->appendChild($definitionXML = $dom->createElement('definition')); + + $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); + foreach ($this->getArguments() as $argument) + { + $argumentsXML->appendChild($argumentXML = $dom->createElement('argument')); + $argumentXML->setAttribute('name', $argument->getName()); + $argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); + $argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); + $argumentXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); + + $argumentXML->appendChild($defaultsXML = $dom->createElement('defaults')); + $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array()); + foreach ($defaults as $default) + { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + } + + $definitionXML->appendChild($optionsXML = $dom->createElement('options')); + foreach ($this->getOptions() as $option) + { + $optionsXML->appendChild($optionXML = $dom->createElement('option')); + $optionXML->setAttribute('name', '--'.$option->getName()); + $optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); + $optionXML->setAttribute('accept_parameter', $option->acceptParameter() ? 1 : 0); + $optionXML->setAttribute('is_parameter_required', $option->isParameterRequired() ? 1 : 0); + $optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); + $optionXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); + + if ($option->acceptParameter()) + { + $optionXML->appendChild($defaultsXML = $dom->createElement('defaults')); + $defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array()); + foreach ($defaults as $default) + { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + } + } + + return $asDom ? $dom : $dom->saveXml(); + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/InputInterface.php b/lib/vendor/Symfony/Components/Console/Input/InputInterface.php new file mode 100644 index 000000000..953553e78 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/InputInterface.php @@ -0,0 +1,58 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * InputInterface is the interface implemented by all input classes. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +interface InputInterface +{ + /** + * Returns the first argument from the raw parameters (not parsed). + * + * @return string The value of the first argument or null otherwise + */ + function getFirstArgument(); + + /** + * Returns true if the raw parameters (not parsed) contains a value. + * + * This method is to be used to introspect the input parameters + * before it has been validated. It must be used carefully. + * + * @param string $value The value to look for in the raw parameters + * + * @return Boolean true if the value is contained in the raw parameters + */ + function hasParameterOption($value); + + /** + * Binds the current Input instance with the given arguments and options. + * + * @param InputDefinition $definition A InputDefinition instance + */ + function bind(InputDefinition $definition); + + function validate(); + + function getArguments(); + + function getArgument($name); + + function getOptions(); + + function getOption($name); +} diff --git a/lib/vendor/Symfony/Components/Console/Input/InputOption.php b/lib/vendor/Symfony/Components/Console/Input/InputOption.php new file mode 100644 index 000000000..46a47d0d5 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/InputOption.php @@ -0,0 +1,191 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Represents a command line option. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class InputOption +{ + const PARAMETER_NONE = 1; + const PARAMETER_REQUIRED = 2; + const PARAMETER_OPTIONAL = 4; + const PARAMETER_IS_ARRAY = 8; + + protected $name; + protected $shortcut; + protected $mode; + protected $default; + protected $description; + + /** + * Constructor. + * + * @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) + */ + public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) + { + if ('--' === substr($name, 0, 2)) + { + $name = substr($name, 2); + } + + if (empty($shortcut)) + { + $shortcut = null; + } + + if (null !== $shortcut) + { + if ('-' === $shortcut[0]) + { + $shortcut = substr($shortcut, 1); + } + } + + if (null === $mode) + { + $mode = self::PARAMETER_NONE; + } + else if (!is_int($mode) || $mode > 15) + { + throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->shortcut = $shortcut; + $this->mode = $mode; + $this->description = $description; + + if ($this->isArray() && !$this->acceptParameter()) + { + throw new \InvalidArgumentException('Impossible to have an option mode PARAMETER_IS_ARRAY if the option does not accept a parameter.'); + } + + $this->setDefault($default); + } + + /** + * Returns the shortcut. + * + * @return string The shortcut + */ + public function getShortcut() + { + return $this->shortcut; + } + + /** + * Returns the name. + * + * @return string The name + */ + public function getName() + { + return $this->name; + } + + /** + * Returns true if the option accept a parameter. + * + * @return Boolean true if parameter mode is not self::PARAMETER_NONE, false otherwise + */ + public function acceptParameter() + { + return $this->isParameterRequired() || $this->isParameterOptional(); + } + + /** + * Returns true if the option requires a parameter. + * + * @return Boolean true if parameter mode is self::PARAMETER_REQUIRED, false otherwise + */ + public function isParameterRequired() + { + return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode); + } + + /** + * Returns true if the option takes an optional parameter. + * + * @return Boolean true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise + */ + public function isParameterOptional() + { + return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode); + } + + /** + * Returns true if the option can take multiple values. + * + * @return Boolean true if mode is self::PARAMETER_IS_ARRAY, false otherwise + */ + public function isArray() + { + return self::PARAMETER_IS_ARRAY === (self::PARAMETER_IS_ARRAY & $this->mode); + } + + /** + * Sets the default value. + * + * @param mixed $default The default value + */ + public function setDefault($default = null) + { + if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default) + { + throw new \LogicException('Cannot set a default value when using Option::PARAMETER_NONE mode.'); + } + + if ($this->isArray()) + { + if (null === $default) + { + $default = array(); + } + elseif (!is_array($default)) + { + throw new \LogicException('A default value for an array option must be an array.'); + } + } + + $this->default = $this->acceptParameter() ? $default : false; + } + + /** + * Returns the default value. + * + * @return mixed The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the description text. + * + * @return string The description text + */ + public function getDescription() + { + return $this->description; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Input/StringInput.php b/lib/vendor/Symfony/Components/Console/Input/StringInput.php new file mode 100644 index 000000000..c66f7b9dc --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Input/StringInput.php @@ -0,0 +1,80 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * StringInput represents an input provided as a string. + * + * Usage: + * + * $input = new StringInput('foo --bar="foobar"'); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class StringInput extends ArgvInput +{ + const REGEX_STRING = '([^ ]+?)(?: |(?tokens = $this->tokenize($input); + } + + protected function tokenize($input) + { + $input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input); + + $tokens = array(); + $length = strlen($input); + $cursor = 0; + while ($cursor < $length) + { + if (preg_match('/\s+/A', $input, $match, null, $cursor)) + { + } + elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) + { + $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); + } + elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) + { + $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); + } + elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) + { + $tokens[] = stripcslashes($match[1]); + } + else + { + // should never happen + // @codeCoverageIgnoreStart + throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); + // @codeCoverageIgnoreEnd + } + + $cursor += strlen($match[0]); + } + + return $tokens; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Output/ConsoleOutput.php b/lib/vendor/Symfony/Components/Console/Output/ConsoleOutput.php new file mode 100644 index 000000000..7950c25ec --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Output/ConsoleOutput.php @@ -0,0 +1,41 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * ConsoleOutput is the default class for all CLI output. It uses STDOUT. + * + * This class is a convenient wrapper around `StreamOutput`. + * + * $output = new ConsoleOutput(); + * + * This is equivalent to: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class ConsoleOutput extends StreamOutput +{ + /** + * Constructor. + * + * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) + * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) + */ + public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null) + { + parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated); + } +} diff --git a/lib/vendor/Symfony/Components/Console/Output/NullOutput.php b/lib/vendor/Symfony/Components/Console/Output/NullOutput.php new file mode 100644 index 000000000..86e2c326f --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Output/NullOutput.php @@ -0,0 +1,34 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * NullOutput suppresses all output. + * + * $output = new NullOutput(); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class NullOutput extends Output +{ + /** + * Writes a message to the output. + * + * @param string $message A message to write to the output + * @param Boolean $newline Whether to add a newline or not + */ + public function doWrite($message, $newline) + { + } +} diff --git a/lib/vendor/Symfony/Components/Console/Output/Output.php b/lib/vendor/Symfony/Components/Console/Output/Output.php new file mode 100644 index 000000000..7bfa8bf01 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Output/Output.php @@ -0,0 +1,230 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Base class for output classes. + * + * There is three level of verbosity: + * + * * normal: no option passed (normal output - information) + * * verbose: -v (more output - debug) + * * quiet: -q (no output) + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +abstract class Output implements OutputInterface +{ + const VERBOSITY_QUIET = 0; + const VERBOSITY_NORMAL = 1; + const VERBOSITY_VERBOSE = 2; + + const OUTPUT_NORMAL = 0; + const OUTPUT_RAW = 1; + const OUTPUT_PLAIN = 2; + + protected $verbosity; + protected $decorated; + + static protected $styles = array( + 'error' => array('bg' => 'red', 'fg' => 'white'), + 'info' => array('fg' => 'green'), + 'comment' => array('fg' => 'yellow'), + 'question' => array('bg' => 'cyan', 'fg' => 'black'), + ); + static protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8); + static protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37); + static protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47); + + /** + * Constructor. + * + * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) + * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) + */ + public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null) + { + $this->decorated = (Boolean) $decorated; + $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; + } + + /** + * Sets a new style. + * + * @param string $name The style name + * @param array $options An array of options + */ + static public function setStyle($name, $options = array()) + { + static::$styles[strtolower($name)] = $options; + } + + /** + * Sets the decorated flag. + * + * @param Boolean $decorated Whether to decorated the messages or not + */ + public function setDecorated($decorated) + { + $this->decorated = (Boolean) $decorated; + } + + /** + * Gets the decorated flag. + * + * @return Boolean true if the output will decorate messages, false otherwise + */ + public function isDecorated() + { + return $this->decorated; + } + + /** + * Sets the verbosity of the output. + * + * @param integer $level The level of verbosity + */ + public function setVerbosity($level) + { + $this->verbosity = (int) $level; + } + + /** + * Gets the current verbosity of the output. + * + * @return integer The current level of verbosity + */ + public function getVerbosity() + { + return $this->verbosity; + } + + /** + * Writes a message to the output and adds a newline at the end. + * + * @param string|array $messages The message as an array of lines of a single string + * @param integer $type The type of output + */ + public function writeln($messages, $type = 0) + { + $this->write($messages, true, $type); + } + + /** + * Writes a message to the output. + * + * @param string|array $messages The message as an array of lines of a single string + * @param Boolean $newline Whether to add a newline or not + * @param integer $type The type of output + */ + public function write($messages, $newline = false, $type = 0) + { + if (self::VERBOSITY_QUIET === $this->verbosity) + { + return; + } + + if (!is_array($messages)) + { + $messages = array($messages); + } + + foreach ($messages as $message) + { + switch ($type) + { + case Output::OUTPUT_NORMAL: + $message = $this->format($message); + break; + case Output::OUTPUT_RAW: + break; + case Output::OUTPUT_PLAIN: + $message = strip_tags($this->format($message)); + break; + default: + throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); + } + + $this->doWrite($message, $newline); + } + } + + /** + * Writes a message to the output. + * + * @param string $message A message to write to the output + * @param Boolean $newline Whether to add a newline or not + */ + abstract public function doWrite($message, $newline); + + /** + * Formats a message according to the given styles. + * + * @param string $message The message to style + * + * @return string The styled message + */ + protected function format($message) + { + $message = preg_replace_callback('#<([a-z][a-z0-9\-_]+)>#i', array($this, 'replaceStartStyle'), $message); + + return preg_replace_callback('##i', array($this, 'replaceEndStyle'), $message); + } + + protected function replaceStartStyle($match) + { + if (!$this->decorated) + { + return ''; + } + + if (!isset(static::$styles[strtolower($match[1])])) + { + throw new \InvalidArgumentException(sprintf('Unknown style "%s".', $match[1])); + } + + $parameters = static::$styles[strtolower($match[1])]; + $codes = array(); + + if (isset($parameters['fg'])) + { + $codes[] = static::$foreground[$parameters['fg']]; + } + + if (isset($parameters['bg'])) + { + $codes[] = static::$background[$parameters['bg']]; + } + + foreach (static::$options as $option => $value) + { + if (isset($parameters[$option]) && $parameters[$option]) + { + $codes[] = $value; + } + } + + return "\033[".implode(';', $codes)."m"; + } + + protected function replaceEndStyle($match) + { + if (!$this->decorated) + { + return ''; + } + + return "\033[0m"; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Output/OutputInterface.php b/lib/vendor/Symfony/Components/Console/Output/OutputInterface.php new file mode 100644 index 000000000..26bc6b76e --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Output/OutputInterface.php @@ -0,0 +1,44 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * OutputInterface is the interface implemented by all Output classes. + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +interface OutputInterface +{ + /** + * Writes a message to the output. + * + * @param string|array $messages The message as an array of lines of a single string + * @param integer $type The type of output + */ + public function write($messages, $type = 0); + + /** + * Sets the verbosity of the output. + * + * @param integer $level The level of verbosity + */ + public function setVerbosity($level); + + /** + * Sets the decorated flag. + * + * @param Boolean $decorated Whether to decorated the messages or not + */ + public function setDecorated($decorated); +} diff --git a/lib/vendor/Symfony/Components/Console/Output/StreamOutput.php b/lib/vendor/Symfony/Components/Console/Output/StreamOutput.php new file mode 100644 index 000000000..fdb74debe --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Output/StreamOutput.php @@ -0,0 +1,109 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * StreamOutput writes the output to a given stream. + * + * Usage: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * + * As `StreamOutput` can use any stream, you can also use a file: + * + * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); + * + * @package symfony + * @subpackage console + * @author Fabien Potencier + */ +class StreamOutput extends Output +{ + protected $stream; + + /** + * Constructor. + * + * @param mixed $stream A stream resource + * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) + * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) + */ + public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null) + { + if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) + { + throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); + } + + $this->stream = $stream; + + if (null === $decorated) + { + $decorated = $this->hasColorSupport($decorated); + } + + parent::__construct($verbosity, $decorated); + } + + /** + * Gets the stream attached to this StreamOutput instance. + * + * @return resource A stream resource + */ + public function getStream() + { + return $this->stream; + } + + /** + * Writes a message to the output. + * + * @param string $message A message to write to the output + * @param Boolean $newline Whether to add a newline or not + */ + public function doWrite($message, $newline) + { + if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) + { + // @codeCoverageIgnoreStart + // should never happen + throw new \RuntimeException('Unable to write output.'); + // @codeCoverageIgnoreEnd + } + + flush(); + } + + /** + * Returns true if the stream supports colorization. + * + * Colorization is disabled if not supported by the stream: + * + * - windows without ansicon + * - non tty consoles + * + * @return Boolean true if the stream supports colorization, false otherwise + */ + protected function hasColorSupport() + { + // @codeCoverageIgnoreStart + if (DIRECTORY_SEPARATOR == '\\') + { + return false !== getenv('ANSICON'); + } + else + { + return function_exists('posix_isatty') && @posix_isatty($this->stream); + } + // @codeCoverageIgnoreEnd + } +} diff --git a/lib/vendor/Symfony/Components/Console/Shell.php b/lib/vendor/Symfony/Components/Console/Shell.php new file mode 100644 index 000000000..f91965c0b --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Shell.php @@ -0,0 +1,146 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * A Shell wraps an Application to add shell capabilities to it. + * + * This class only works with a PHP compiled with readline support + * (either --with-readline or --with-libedit) + * + * @package symfony + * @subpackage cli + * @author Fabien Potencier + */ +class Shell +{ + protected $application; + protected $history; + protected $output; + + /** + * Constructor. + * + * If there is no readline support for the current PHP executable + * a \RuntimeException exception is thrown. + * + * @param Application $application An application instance + */ + public function __construct(Application $application) + { + if (!function_exists('readline')) + { + throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.'); + } + + $this->application = $application; + $this->history = getenv('HOME').'/.history_'.$application->getName(); + $this->output = new ConsoleOutput(); + } + + /** + * Runs the shell. + */ + public function run() + { + $this->application->setAutoExit(false); + $this->application->setCatchExceptions(true); + + readline_read_history($this->history); + readline_completion_function(array($this, 'autocompleter')); + + $this->output->writeln($this->getHeader()); + while (true) + { + $command = readline($this->application->getName().' > '); + + if (false === $command) + { + $this->output->writeln("\n"); + + break; + } + + readline_add_history($command); + readline_write_history($this->history); + + if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) + { + $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); + } + } + } + + /** + * Tries to return autocompletion for the current entered text. + * + * @param string $text The last segment of the entered text + * @param integer $position The current position + */ + protected function autocompleter($text, $position) + { + $info = readline_info(); + $text = substr($info['line_buffer'], 0, $info['end']); + + if ($info['point'] !== $info['end']) + { + return true; + } + + // task name? + if (false === strpos($text, ' ') || !$text) + { + return array_keys($this->application->getCommands()); + } + + // options and arguments? + try + { + $command = $this->application->findCommand(substr($text, 0, strpos($text, ' '))); + } + catch (\Exception $e) + { + return true; + } + + $list = array('--help'); + foreach ($command->getDefinition()->getOptions() as $option) + { + $list[] = '--'.$option->getName(); + } + + return $list; + } + + /** + * Returns the shell header. + * + * @return string The header string + */ + protected function getHeader() + { + return <<{$this->application->getName()} shell ({$this->application->getVersion()}). + +At the prompt, type help for some help, +or list to get a list available commands. + +To exit the shell, type ^D. + +EOF; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Tester/ApplicationTester.php b/lib/vendor/Symfony/Components/Console/Tester/ApplicationTester.php new file mode 100644 index 000000000..aa31f71cb --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Tester/ApplicationTester.php @@ -0,0 +1,92 @@ +application = $application; + } + + /** + * Executes the application. + * + * Available options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * + * @param array $input An array of arguments and options + * @param array $options An array of options + */ + public function run(array $input, $options = array()) + { + $this->input = new ArrayInput($input); + if (isset($options['interactive'])) + { + $this->input->setInteractive($options['interactive']); + } + + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + if (isset($options['decorated'])) + { + $this->output->setDecorated($options['decorated']); + } + if (isset($options['verbosity'])) + { + $this->output->setVerbosity($options['verbosity']); + } + + $ret = $this->application->run($this->input, $this->output); + + rewind($this->output->getStream()); + + return $this->display = stream_get_contents($this->output->getStream()); + } + + /** + * Gets the display returned by the last execution of the application. + * + * @return string The display + */ + public function getDisplay() + { + return $this->display; + } + + /** + * Gets the input instance used by the last execution of the application. + * + * @return InputInterface The current input instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the application. + * + * @return OutputInterface The current output instance + */ + public function getOutput() + { + return $this->output; + } +} diff --git a/lib/vendor/Symfony/Components/Console/Tester/CommandTester.php b/lib/vendor/Symfony/Components/Console/Tester/CommandTester.php new file mode 100644 index 000000000..bc0ee8879 --- /dev/null +++ b/lib/vendor/Symfony/Components/Console/Tester/CommandTester.php @@ -0,0 +1,92 @@ +command = $command; + } + + /** + * Executes the command. + * + * Available options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * + * @param array $input An array of arguments and options + * @param array $options An array of options + */ + public function execute(array $input, array $options = array()) + { + $this->input = new ArrayInput(array_merge($input, array('command' => $this->command->getFullName()))); + if (isset($options['interactive'])) + { + $this->input->setInteractive($options['interactive']); + } + + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + if (isset($options['decorated'])) + { + $this->output->setDecorated($options['decorated']); + } + if (isset($options['verbosity'])) + { + $this->output->setVerbosity($options['verbosity']); + } + + $ret = $this->command->run($this->input, $this->output); + + rewind($this->output->getStream()); + + return $this->display = stream_get_contents($this->output->getStream()); + } + + /** + * Gets the display returned by the last execution of the command. + * + * @return string The display + */ + public function getDisplay() + { + return $this->display; + } + + /** + * Gets the input instance used by the last execution of the command. + * + * @return InputInterface The current input instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the command. + * + * @return OutputInterface The current output instance + */ + public function getOutput() + { + return $this->output; + } +} diff --git a/lib/vendor/Symfony/Components/Yaml/Dumper.php b/lib/vendor/Symfony/Components/Yaml/Dumper.php new file mode 100644 index 000000000..2db3f6cf1 --- /dev/null +++ b/lib/vendor/Symfony/Components/Yaml/Dumper.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Dumper dumps PHP variables to YAML strings. + * + * @package symfony + * @subpackage yaml + * @author Fabien Potencier + */ +class Dumper +{ + /** + * Dumps a PHP value to YAML. + * + * @param mixed $input The PHP value + * @param integer $inline The level where you switch to inline YAML + * @param integer $indent The level o indentation indentation (used internally) + * + * @return string The YAML representation of the PHP value + */ + public function dump($input, $inline = 0, $indent = 0) + { + $output = ''; + $prefix = $indent ? str_repeat(' ', $indent) : ''; + + if ($inline <= 0 || !is_array($input) || empty($input)) + { + $output .= $prefix.Inline::dump($input); + } + else + { + $isAHash = array_keys($input) !== range(0, count($input) - 1); + + foreach ($input as $key => $value) + { + $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value); + + $output .= sprintf('%s%s%s%s', + $prefix, + $isAHash ? Inline::dump($key).':' : '-', + $willBeInlined ? ' ' : "\n", + $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + 2) + ).($willBeInlined ? "\n" : ''); + } + } + + return $output; + } +} diff --git a/lib/vendor/Symfony/Components/Yaml/Exception.php b/lib/vendor/Symfony/Components/Yaml/Exception.php new file mode 100644 index 000000000..49cb7949e --- /dev/null +++ b/lib/vendor/Symfony/Components/Yaml/Exception.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Exception class used by all exceptions thrown by the component. + * + * @package symfony + * @subpackage yaml + * @author Fabien Potencier + */ +class Exception extends \Exception +{ +} diff --git a/lib/vendor/Symfony/Components/Yaml/Inline.php b/lib/vendor/Symfony/Components/Yaml/Inline.php new file mode 100644 index 000000000..854f4bba5 --- /dev/null +++ b/lib/vendor/Symfony/Components/Yaml/Inline.php @@ -0,0 +1,410 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Inline implements a YAML parser/dumper for the YAML inline syntax. + * + * @package symfony + * @subpackage yaml + * @author Fabien Potencier + */ +class Inline +{ + const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; + + /** + * Convert a YAML string to a PHP array. + * + * @param string $value A YAML string + * + * @return array A PHP array representing the YAML string + */ + static public function load($value) + { + $value = trim($value); + + if (0 == strlen($value)) + { + return ''; + } + + switch ($value[0]) + { + case '[': + return self::parseSequence($value); + case '{': + return self::parseMapping($value); + default: + return self::parseScalar($value); + } + } + + /** + * Dumps a given PHP variable to a YAML string. + * + * @param mixed $value The PHP variable to convert + * + * @return string The YAML string representing the PHP array + */ + static public function dump($value) + { + $trueValues = '1.1' == Yaml::getSpecVersion() ? array('true', 'on', '+', 'yes', 'y') : array('true'); + $falseValues = '1.1' == Yaml::getSpecVersion() ? array('false', 'off', '-', 'no', 'n') : array('false'); + + switch (true) + { + case is_resource($value): + throw new Exception('Unable to dump PHP resources in a YAML file.'); + case is_object($value): + return '!!php/object:'.serialize($value); + case is_array($value): + return self::dumpArray($value); + case null === $value: + return 'null'; + case true === $value: + return 'true'; + case false === $value: + return 'false'; + case ctype_digit($value): + return is_string($value) ? "'$value'" : (int) $value; + case is_numeric($value): + return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value); + case false !== strpos($value, "\n") || false !== strpos($value, "\r"): + return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value)); + case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ - ? | < > = ! % @ ` ]/x', $value): + return sprintf("'%s'", str_replace('\'', '\'\'', $value)); + case '' == $value: + return "''"; + case preg_match(self::getTimestampRegex(), $value): + return "'$value'"; + case in_array(strtolower($value), $trueValues): + return "'$value'"; + case in_array(strtolower($value), $falseValues): + return "'$value'"; + case in_array(strtolower($value), array('null', '~')): + return "'$value'"; + default: + return $value; + } + } + + /** + * Dumps a PHP array to a YAML string. + * + * @param array $value The PHP array to dump + * + * @return string The YAML string representing the PHP array + */ + static protected function dumpArray($value) + { + // array + $keys = array_keys($value); + if ( + (1 == count($keys) && '0' == $keys[0]) + || + (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2)) + { + $output = array(); + foreach ($value as $val) + { + $output[] = self::dump($val); + } + + return sprintf('[%s]', implode(', ', $output)); + } + + // mapping + $output = array(); + foreach ($value as $key => $val) + { + $output[] = sprintf('%s: %s', self::dump($key), self::dump($val)); + } + + return sprintf('{ %s }', implode(', ', $output)); + } + + /** + * Parses a scalar to a YAML string. + * + * @param scalar $scalar + * @param string $delimiters + * @param array $stringDelimiter + * @param integer $i + * @param boolean $evaluate + * + * @return string A YAML string + */ + static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true) + { + if (in_array($scalar[$i], $stringDelimiters)) + { + // quoted scalar + $output = self::parseQuotedScalar($scalar, $i); + } + else + { + // "normal" string + if (!$delimiters) + { + $output = substr($scalar, $i); + $i += strlen($output); + + // remove comments + if (false !== $strpos = strpos($output, ' #')) + { + $output = rtrim(substr($output, 0, $strpos)); + } + } + else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) + { + $output = $match[1]; + $i += strlen($output); + } + else + { + throw new ParserException(sprintf('Malformed inline YAML string (%s).', $scalar)); + } + + $output = $evaluate ? self::evaluateScalar($output) : $output; + } + + return $output; + } + + /** + * Parses a quoted scalar to YAML. + * + * @param string $scalar + * @param integer $i + * + * @return string A YAML string + */ + static protected function parseQuotedScalar($scalar, &$i) + { + if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/A', substr($scalar, $i), $match)) + { + throw new ParserException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i))); + } + + $output = substr($match[0], 1, strlen($match[0]) - 2); + + if ('"' == $scalar[$i]) + { + // evaluate the string + $output = str_replace(array('\\"', '\\n', '\\r'), array('"', "\n", "\r"), $output); + } + else + { + // unescape ' + $output = str_replace('\'\'', '\'', $output); + } + + $i += strlen($match[0]); + + return $output; + } + + /** + * Parses a sequence to a YAML string. + * + * @param string $sequence + * @param integer $i + * + * @return string A YAML string + */ + static protected function parseSequence($sequence, &$i = 0) + { + $output = array(); + $len = strlen($sequence); + $i += 1; + + // [foo, bar, ...] + while ($i < $len) + { + switch ($sequence[$i]) + { + case '[': + // nested sequence + $output[] = self::parseSequence($sequence, $i); + break; + case '{': + // nested mapping + $output[] = self::parseMapping($sequence, $i); + break; + case ']': + return $output; + case ',': + case ' ': + break; + default: + $isQuoted = in_array($sequence[$i], array('"', "'")); + $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i); + + if (!$isQuoted && false !== strpos($value, ': ')) + { + // embedded mapping? + try + { + $value = self::parseMapping('{'.$value.'}'); + } + catch (\InvalidArgumentException $e) + { + // no, it's not + } + } + + $output[] = $value; + + --$i; + } + + ++$i; + } + + throw new ParserException(sprintf('Malformed inline YAML string %s', $sequence)); + } + + /** + * Parses a mapping to a YAML string. + * + * @param string $mapping + * @param integer $i + * + * @return string A YAML string + */ + static protected function parseMapping($mapping, &$i = 0) + { + $output = array(); + $len = strlen($mapping); + $i += 1; + + // {foo: bar, bar:foo, ...} + while ($i < $len) + { + switch ($mapping[$i]) + { + case ' ': + case ',': + ++$i; + continue 2; + case '}': + return $output; + } + + // key + $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false); + + // value + $done = false; + while ($i < $len) + { + switch ($mapping[$i]) + { + case '[': + // nested sequence + $output[$key] = self::parseSequence($mapping, $i); + $done = true; + break; + case '{': + // nested mapping + $output[$key] = self::parseMapping($mapping, $i); + $done = true; + break; + case ':': + case ' ': + break; + default: + $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i); + $done = true; + --$i; + } + + ++$i; + + if ($done) + { + continue 2; + } + } + } + + throw new ParserException(sprintf('Malformed inline YAML string %s', $mapping)); + } + + /** + * Evaluates scalars and replaces magic values. + * + * @param string $scalar + * + * @return string A YAML string + */ + static protected function evaluateScalar($scalar) + { + $scalar = trim($scalar); + + $trueValues = '1.1' == Yaml::getSpecVersion() ? array('true', 'on', '+', 'yes', 'y') : array('true'); + $falseValues = '1.1' == Yaml::getSpecVersion() ? array('false', 'off', '-', 'no', 'n') : array('false'); + + switch (true) + { + case 'null' == strtolower($scalar): + case '' == $scalar: + case '~' == $scalar: + return null; + case 0 === strpos($scalar, '!str'): + return (string) substr($scalar, 5); + case 0 === strpos($scalar, '! '): + return intval(self::parseScalar(substr($scalar, 2))); + case 0 === strpos($scalar, '!!php/object:'): + return unserialize(substr($scalar, 13)); + case ctype_digit($scalar): + $raw = $scalar; + $cast = intval($scalar); + return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); + case in_array(strtolower($scalar), $trueValues): + return true; + case in_array(strtolower($scalar), $falseValues): + return false; + case is_numeric($scalar): + return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar); + case 0 == strcasecmp($scalar, '.inf'): + case 0 == strcasecmp($scalar, '.NaN'): + return -log(0); + case 0 == strcasecmp($scalar, '-.inf'): + return log(0); + case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): + return floatval(str_replace(',', '', $scalar)); + case preg_match(self::getTimestampRegex(), $scalar): + return strtotime($scalar); + default: + return (string) $scalar; + } + } + + static protected function getTimestampRegex() + { + return <<[0-9][0-9][0-9][0-9]) + -(?P[0-9][0-9]?) + -(?P[0-9][0-9]?) + (?:(?:[Tt]|[ \t]+) + (?P[0-9][0-9]?) + :(?P[0-9][0-9]) + :(?P[0-9][0-9]) + (?:\.(?P[0-9]*))? + (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) + (?::(?P[0-9][0-9]))?))?)? + $~x +EOF; + } +} diff --git a/lib/vendor/Symfony/Components/Yaml/Parser.php b/lib/vendor/Symfony/Components/Yaml/Parser.php new file mode 100644 index 000000000..330f9a1ef --- /dev/null +++ b/lib/vendor/Symfony/Components/Yaml/Parser.php @@ -0,0 +1,587 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Parser parses YAML strings to convert them to PHP arrays. + * + * @package symfony + * @subpackage yaml + * @author Fabien Potencier + */ +class Parser +{ + protected $offset = 0; + protected $lines = array(); + protected $currentLineNb = -1; + protected $currentLine = ''; + protected $refs = array(); + + /** + * Constructor + * + * @param integer $offset The offset of YAML document (used for line numbers in error messages) + */ + public function __construct($offset = 0) + { + $this->offset = $offset; + } + + /** + * Parses a YAML string to a PHP value. + * + * @param string $value A YAML string + * + * @return mixed A PHP value + * + * @throws \InvalidArgumentException If the YAML is not valid + */ + public function parse($value) + { + $this->currentLineNb = -1; + $this->currentLine = ''; + $this->lines = explode("\n", $this->cleanup($value)); + + $data = array(); + while ($this->moveToNextLine()) + { + if ($this->isCurrentLineEmpty()) + { + continue; + } + + // tab? + if (preg_match('#^\t+#', $this->currentLine)) + { + throw new ParserException(sprintf('A YAML file cannot contain tabs as indentation at line %d (%s).', $this->getRealCurrentLineNb() + 1, $this->currentLine)); + } + + $isRef = $isInPlace = $isProcessed = false; + if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#', $this->currentLine, $values)) + { + if (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#', $values['value'], $matches)) + { + $isRef = $matches['ref']; + $values['value'] = $matches['value']; + } + + // array + if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) + { + $c = $this->getRealCurrentLineNb() + 1; + $parser = new Parser($c); + $parser->refs =& $this->refs; + $data[] = $parser->parse($this->getNextEmbedBlock()); + } + else + { + if (isset($values['leadspaces']) + && ' ' == $values['leadspaces'] + && preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{].*?) *\:(\s+(?P.+?))?\s*$#', $values['value'], $matches)) + { + // this is a compact notation element, add to next block and parse + $c = $this->getRealCurrentLineNb(); + $parser = new Parser($c); + $parser->refs =& $this->refs; + + $block = $values['value']; + if (!$this->isNextLineIndented()) + { + $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2); + } + + $data[] = $parser->parse($block); + } + else + { + $data[] = $this->parseValue($values['value']); + } + } + } + else if (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"].*?) *\:(\s+(?P.+?))?\s*$#', $this->currentLine, $values)) + { + $key = Inline::parseScalar($values['key']); + + if ('<<' === $key) + { + if (isset($values['value']) && '*' === substr($values['value'], 0, 1)) + { + $isInPlace = substr($values['value'], 1); + if (!array_key_exists($isInPlace, $this->refs)) + { + throw new ParserException(sprintf('Reference "%s" does not exist at line %s (%s).', $isInPlace, $this->getRealCurrentLineNb() + 1, $this->currentLine)); + } + } + else + { + if (isset($values['value']) && $values['value'] !== '') + { + $value = $values['value']; + } + else + { + $value = $this->getNextEmbedBlock(); + } + $c = $this->getRealCurrentLineNb() + 1; + $parser = new Parser($c); + $parser->refs =& $this->refs; + $parsed = $parser->parse($value); + + $merged = array(); + if (!is_array($parsed)) + { + throw new ParserException(sprintf("YAML merge keys used with a scalar value instead of an array at line %s (%s)", $this->getRealCurrentLineNb() + 1, $this->currentLine)); + } + else if (isset($parsed[0])) + { + // Numeric array, merge individual elements + foreach (array_reverse($parsed) as $parsedItem) + { + if (!is_array($parsedItem)) + { + throw new ParserException(sprintf("Merge items must be arrays at line %s (%s).", $this->getRealCurrentLineNb() + 1, $parsedItem)); + } + $merged = array_merge($parsedItem, $merged); + } + } + else + { + // Associative array, merge + $merged = array_merge($merge, $parsed); + } + + $isProcessed = $merged; + } + } + else if (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#', $values['value'], $matches)) + { + $isRef = $matches['ref']; + $values['value'] = $matches['value']; + } + + if ($isProcessed) + { + // Merge keys + $data = $isProcessed; + } + // hash + else if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) + { + // if next line is less indented or equal, then it means that the current value is null + if ($this->isNextLineIndented()) + { + $data[$key] = null; + } + else + { + $c = $this->getRealCurrentLineNb() + 1; + $parser = new Parser($c); + $parser->refs =& $this->refs; + $data[$key] = $parser->parse($this->getNextEmbedBlock()); + } + } + else + { + if ($isInPlace) + { + $data = $this->refs[$isInPlace]; + } + else + { + $data[$key] = $this->parseValue($values['value']); + } + } + } + else + { + // 1-liner followed by newline + if (2 == count($this->lines) && empty($this->lines[1])) + { + $value = Inline::load($this->lines[0]); + if (is_array($value)) + { + $first = reset($value); + if ('*' === substr($first, 0, 1)) + { + $data = array(); + foreach ($value as $alias) + { + $data[] = $this->refs[substr($alias, 1)]; + } + $value = $data; + } + } + + return $value; + } + + switch (preg_last_error()) + { + case PREG_INTERNAL_ERROR: + $error = 'Internal PCRE error on line'; + break; + case PREG_BACKTRACK_LIMIT_ERROR: + $error = 'pcre.backtrack_limit reached on line'; + break; + case PREG_RECURSION_LIMIT_ERROR: + $error = 'pcre.recursion_limit reached on line'; + break; + case PREG_BAD_UTF8_ERROR: + $error = 'Malformed UTF-8 data on line'; + break; + case PREG_BAD_UTF8_OFFSET_ERROR: + $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point on line'; + break; + default: + $error = 'Unable to parse line'; + } + + throw new ParserException(sprintf('%s %d (%s).', $error, $this->getRealCurrentLineNb() + 1, $this->currentLine)); + } + + if ($isRef) + { + $this->refs[$isRef] = end($data); + } + } + + return empty($data) ? null : $data; + } + + /** + * Returns the current line number (takes the offset into account). + * + * @return integer The current line number + */ + protected function getRealCurrentLineNb() + { + return $this->currentLineNb + $this->offset; + } + + /** + * Returns the current line indentation. + * + * @return integer The current line indentation + */ + protected function getCurrentLineIndentation() + { + return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' ')); + } + + /** + * Returns the next embed block of YAML. + * + * @param integer $indentation The indent level at which the block is to be read, or null for default + * + * @return string A YAML string + */ + protected function getNextEmbedBlock($indentation = null) + { + $this->moveToNextLine(); + + if (null === $indentation) + { + $newIndent = $this->getCurrentLineIndentation(); + + if (!$this->isCurrentLineEmpty() && 0 == $newIndent) + { + throw new ParserException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine)); + } + } + else + { + $newIndent = $indentation; + } + + $data = array(substr($this->currentLine, $newIndent)); + + while ($this->moveToNextLine()) + { + if ($this->isCurrentLineEmpty()) + { + if ($this->isCurrentLineBlank()) + { + $data[] = substr($this->currentLine, $newIndent); + } + + continue; + } + + $indent = $this->getCurrentLineIndentation(); + + if (preg_match('#^(?P *)$#', $this->currentLine, $match)) + { + // empty line + $data[] = $match['text']; + } + else if ($indent >= $newIndent) + { + $data[] = substr($this->currentLine, $newIndent); + } + else if (0 == $indent) + { + $this->moveToPreviousLine(); + + break; + } + else + { + throw new ParserException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine)); + } + } + + return implode("\n", $data); + } + + /** + * Moves the parser to the next line. + */ + protected function moveToNextLine() + { + if ($this->currentLineNb >= count($this->lines) - 1) + { + return false; + } + + $this->currentLine = $this->lines[++$this->currentLineNb]; + + return true; + } + + /** + * Moves the parser to the previous line. + */ + protected function moveToPreviousLine() + { + $this->currentLine = $this->lines[--$this->currentLineNb]; + } + + /** + * Parses a YAML value. + * + * @param string $value A YAML value + * + * @return mixed A PHP value + */ + protected function parseValue($value) + { + if ('*' === substr($value, 0, 1)) + { + if (false !== $pos = strpos($value, '#')) + { + $value = substr($value, 1, $pos - 2); + } + else + { + $value = substr($value, 1); + } + + if (!array_key_exists($value, $this->refs)) + { + throw new ParserException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine)); + } + return $this->refs[$value]; + } + + if (preg_match('/^(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?$/', $value, $matches)) + { + $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; + + return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers))); + } + else + { + return Inline::load($value); + } + } + + /** + * Parses a folded scalar. + * + * @param string $separator The separator that was used to begin this folded scalar (| or >) + * @param string $indicator The indicator that was used to begin this folded scalar (+ or -) + * @param integer $indentation The indentation that was used to begin this folded scalar + * + * @return string The text value + */ + protected function parseFoldedScalar($separator, $indicator = '', $indentation = 0) + { + $separator = '|' == $separator ? "\n" : ' '; + $text = ''; + + $notEOF = $this->moveToNextLine(); + + while ($notEOF && $this->isCurrentLineBlank()) + { + $text .= "\n"; + + $notEOF = $this->moveToNextLine(); + } + + if (!$notEOF) + { + return ''; + } + + if (!preg_match('#^(?P'.($indentation ? str_repeat(' ', $indentation) : ' +').')(?P.*)$#', $this->currentLine, $matches)) + { + $this->moveToPreviousLine(); + + return ''; + } + + $textIndent = $matches['indent']; + $previousIndent = 0; + + $text .= $matches['text'].$separator; + while ($this->currentLineNb + 1 < count($this->lines)) + { + $this->moveToNextLine(); + + if (preg_match('#^(?P {'.strlen($textIndent).',})(?P.+)$#', $this->currentLine, $matches)) + { + if (' ' == $separator && $previousIndent != $matches['indent']) + { + $text = substr($text, 0, -1)."\n"; + } + $previousIndent = $matches['indent']; + + $text .= str_repeat(' ', $diff = strlen($matches['indent']) - strlen($textIndent)).$matches['text'].($diff ? "\n" : $separator); + } + else if (preg_match('#^(?P *)$#', $this->currentLine, $matches)) + { + $text .= preg_replace('#^ {1,'.strlen($textIndent).'}#', '', $matches['text'])."\n"; + } + else + { + $this->moveToPreviousLine(); + + break; + } + } + + if (' ' == $separator) + { + // replace last separator by a newline + $text = preg_replace('/ (\n*)$/', "\n$1", $text); + } + + switch ($indicator) + { + case '': + $text = preg_replace('#\n+$#s', "\n", $text); + break; + case '+': + break; + case '-': + $text = preg_replace('#\n+$#s', '', $text); + break; + } + + return $text; + } + + /** + * Returns true if the next line is indented. + * + * @return Boolean Returns true if the next line is indented, false otherwise + */ + protected function isNextLineIndented() + { + $currentIndentation = $this->getCurrentLineIndentation(); + $notEOF = $this->moveToNextLine(); + + while ($notEOF && $this->isCurrentLineEmpty()) + { + $notEOF = $this->moveToNextLine(); + } + + if (false === $notEOF) + { + return false; + } + + $ret = false; + if ($this->getCurrentLineIndentation() <= $currentIndentation) + { + $ret = true; + } + + $this->moveToPreviousLine(); + + return $ret; + } + + /** + * Returns true if the current line is blank or if it is a comment line. + * + * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise + */ + protected function isCurrentLineEmpty() + { + return $this->isCurrentLineBlank() || $this->isCurrentLineComment(); + } + + /** + * Returns true if the current line is blank. + * + * @return Boolean Returns true if the current line is blank, false otherwise + */ + protected function isCurrentLineBlank() + { + return '' == trim($this->currentLine, ' '); + } + + /** + * Returns true if the current line is a comment line. + * + * @return Boolean Returns true if the current line is a comment line, false otherwise + */ + protected function isCurrentLineComment() + { + //checking explicitly the first char of the trim is faster than loops or strpos + $ltrimmedLine = ltrim($this->currentLine, ' '); + return $ltrimmedLine[0] === '#'; + } + + /** + * Cleanups a YAML string to be parsed. + * + * @param string $value The input YAML string + * + * @return string A cleaned up YAML string + */ + protected function cleanup($value) + { + $value = str_replace(array("\r\n", "\r"), "\n", $value); + + if (!preg_match("#\n$#", $value)) + { + $value .= "\n"; + } + + // strip YAML header + $count = 0; + $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#s', '', $value, -1, $count); + $this->offset += $count; + + // remove leading comments and/or --- + $trimmedValue = preg_replace('#^((\#.*?\n)|(\-\-\-.*?\n))*#s', '', $value, -1, $count); + if ($count == 1) + { + // items have been removed, update the offset + $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); + $value = $trimmedValue; + } + + return $value; + } +} diff --git a/lib/vendor/Symfony/Components/Yaml/ParserException.php b/lib/vendor/Symfony/Components/Yaml/ParserException.php new file mode 100644 index 000000000..5ba22291d --- /dev/null +++ b/lib/vendor/Symfony/Components/Yaml/ParserException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Exception class used by all exceptions thrown by the component. + * + * @package symfony + * @subpackage yaml + * @author Fabien Potencier + */ +class ParserException extends Exception +{ +} diff --git a/lib/vendor/Symfony/Components/Yaml/Yaml.php b/lib/vendor/Symfony/Components/Yaml/Yaml.php new file mode 100644 index 000000000..ff8671d5f --- /dev/null +++ b/lib/vendor/Symfony/Components/Yaml/Yaml.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Yaml offers convenience methods to load and dump YAML. + * + * @package symfony + * @subpackage yaml + * @author Fabien Potencier + */ +class Yaml +{ + static protected $spec = '1.2'; + + /** + * Sets the YAML specification version to use. + * + * @param string $version The YAML specification version + */ + static public function setSpecVersion($version) + { + if (!in_array($version, array('1.1', '1.2'))) + { + throw new \InvalidArgumentException(sprintf('Version %s of the YAML specifications is not supported', $version)); + } + + self::$spec = $version; + } + + /** + * Gets the YAML specification version to use. + * + * @return string The YAML specification version + */ + static public function getSpecVersion() + { + return self::$spec; + } + + /** + * Loads YAML into a PHP array. + * + * The load method, when supplied with a YAML stream (string or file), + * will do its best to convert YAML in a file into a PHP array. + * + * Usage: + * + * $array = Yaml::load('config.yml'); + * print_r($array); + * + * + * @param string $input Path of YAML file or string containing YAML + * + * @return array The YAML converted to a PHP array + * + * @throws \InvalidArgumentException If the YAML is not valid + */ + public static function load($input) + { + $file = ''; + + // if input is a file, process it + if (strpos($input, "\n") === false && is_file($input)) + { + $file = $input; + + ob_start(); + $retval = include($input); + $content = ob_get_clean(); + + // if an array is returned by the config file assume it's in plain php form else in YAML + $input = is_array($retval) ? $retval : $content; + } + + // if an array is returned by the config file assume it's in plain php form else in YAML + if (is_array($input)) + { + return $input; + } + + $yaml = new Parser(); + + try + { + $ret = $yaml->parse($input); + } + catch (\Exception $e) + { + throw new \InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage())); + } + + return $ret; + } + + /** + * Dumps a PHP array to a YAML string. + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. + * + * @param array $array PHP array + * @param integer $inline The level where you switch to inline YAML + * + * @return string A YAML string representing the original PHP array + */ + public static function dump($array, $inline = 2) + { + $yaml = new Dumper(); + + return $yaml->dump($array, $inline); + } +} From e4d8efa39466620dad6b86d812b083e0400dd44f Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Fri, 9 Apr 2010 00:53:29 -0300 Subject: [PATCH 4/4] [2.0] Couple of fixes to new Console implementation --- lib/Doctrine/Common/Version.php | 2 +- .../DBAL/Tools/Console/Command/RunSqlCommand.php | 3 +-- .../ORM/Tools/Console/Command/RunDqlCommand.php | 2 +- .../Console/Command/SchemaTool/CreateCommand.php | 2 +- .../Console/Command/SchemaTool/DropCommand.php | 2 +- .../Console/Command/SchemaTool/UpdateCommand.php | 2 +- tools/sandbox/cli-config.php | 14 -------------- 7 files changed, 6 insertions(+), 21 deletions(-) diff --git a/lib/Doctrine/Common/Version.php b/lib/Doctrine/Common/Version.php index 2e1847dc6..fd1b499f0 100644 --- a/lib/Doctrine/Common/Version.php +++ b/lib/Doctrine/Common/Version.php @@ -38,7 +38,7 @@ class Version /** * Current Doctrine Version */ - const VERSION = '2.0 ALPHA 4'; + const VERSION = '2.0-DEV'; /** * Compares a Doctrine version with the current one. diff --git a/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php b/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php index 6c5ee824e..0e6c05c82 100644 --- a/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php +++ b/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php @@ -76,8 +76,7 @@ EOT } if (preg_match('/^select/i', $sql)) { - $stmt = $conn->execute($sql); - $resultSet = $stmt->fetchAll(\Doctrine\DBAL\Connection::FETCH_ASSOC); + $resultSet = $conn->fetchAll($sql); } else { $resultSet = $em->getConnection()->executeUpdate($sql); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php index c995fba7b..fc375812b 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php @@ -117,7 +117,7 @@ EOT $query->setMaxResult((int) $maxResult); } - $resultSet = $query->execute(array(), $hydrationMode); + $resultSet = $query->execute(array(), constant($hydrationMode)); \Doctrine\Common\Util\Debug::dump($resultSet, $input->getOption('depth')); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php index 4ca0b3090..fd724c2df 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php @@ -76,7 +76,7 @@ EOT { $em = $this->getHelper('em')->getEntityManager(); - $reader = new ClassMetadataReader(); + $reader = new \Doctrine\ORM\Tools\ClassMetadataReader(); $reader->setEntityManager($em); // Process source directories diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php index b41c616a8..9bcf280e7 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php @@ -77,7 +77,7 @@ EOT { $em = $this->getHelper('em')->getEntityManager(); - $reader = new ClassMetadataReader(); + $reader = new \Doctrine\ORM\Tools\ClassMetadataReader(); $reader->setEntityManager($em); // Process source directories diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php index 9aba1e9cd..7d85bb6a9 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php @@ -82,7 +82,7 @@ EOT { $em = $this->getHelper('em')->getEntityManager(); - $reader = new ClassMetadataReader(); + $reader = new \Doctrine\ORM\Tools\ClassMetadataReader(); $reader->setEntityManager($em); // Process source directories diff --git a/tools/sandbox/cli-config.php b/tools/sandbox/cli-config.php index 887780dd9..dc2c9875e 100644 --- a/tools/sandbox/cli-config.php +++ b/tools/sandbox/cli-config.php @@ -1,18 +1,4 @@ option where you can specify the configuration -# file to use for a particular task. If this option is not given, the CLI looks for a file -# named "cli-config.php" (this one) in the same directory and uses that by default. -# require_once __DIR__ . '/../../lib/Doctrine/Common/ClassLoader.php';