diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CommandLine.class.php b/CommandLine.class.php
index 715100c..cbf3be6 100644
--- a/CommandLine.class.php
+++ b/CommandLine.class.php
@@ -1,871 +1,1019 @@
-setProgramName($programName);
- $this->setDescription($mainDescription);
- $this->setCommand($command);
- $this->setVersion($version);
- }
-
- /**
- * Ajoute les options communes à la plupart des programmes
- *
- * Voici la liste des options générées :
- * - Aide : --help ou -h
- * - Version : --version ou -v (voir $shortForVersion)
- *
- * @param bool $shortForVersion L'option pour la version existe également au format "court" (-v)
- *
- * @return $this
- */
- public function addDefaultArguments ($shortForVersion = true) {
- if(!$this->existsOption(self::ARGUMENT_OPTION_HELP)) {
- $this->addOption(
- (new Argument\Option\Flag(self::ARGUMENT_OPTION_HELP, false, 'Affiche cette aide', 'help', 'h'))
- ->setStoppingParse(true)
- );
- }
-
- if (!$this->existsOption(self::ARGUMENT_OPTION_HELP) && !is_null($this->getVersion())) {
- $this->addOption(
- (new Argument\Option\Flag(self::ARGUMENT_OPTION_VERSION,false,'Affiche la version','version',$shortForVersion ? 'v' : null))
- ->setStoppingParse(true)
- );
- }
-
- return $this;
- }
- /**
- * Auto-lance les fonctions correspondantes aux options communes.
- *
- * @param stdClass $values Les valeurs du parsage
- * @param boolean $exitAtEnd Terminer le script à la fin de la fonction correspondante ?
- */
- public function treatDefaultArguments ($values, $exitAtEnd = true) {
- if ($values->{self::ARGUMENT_OPTION_HELP} === true) {
- $this->showHelp($exitAtEnd);
- }
-
- if ($values->{self::ARGUMENT_OPTION_VERSION} === true) {
- $this->showVersion($exitAtEnd);
- }
- }
-
- /**
- * Traite la ligne de commande du script actuel pour en sortir les valeurs.
- *
- * @return stdClass Les valeurs extraites.
- * @throws IException Quand toutes les solutions ne correspond pas
- * @throws Exception Autre erreur
- */
- public function parse () {
- $argv = $_SERVER['argv'];
- array_shift($argv); // Supprime le 1er paramètre : le nom du script PHP
-
- return $this->parseExplicit($argv);
- }
- /**
- * Traite une ligne de commande pour en sortir les valeurs.
- *
- * @param string[] $argv La liste des arguments.
- *
- * @return stdClass Les valeurs extraites.
- * @throws IException Quand toutes les solutions ne correspond pas
- * @throws Exception Autre erreur
- */
- public function parseExplicit ($argv) {
- ksort($this->_solutions, SORT_NUMERIC);
- foreach ($this->_solutions as $ordre => $solution) {
- $argv_loop = $argv;
- try {
- $values = $solution->parseExplicit($argv_loop, $this->_optionsCommon);
- }
- catch (IException $e) {
- if ($ordre >= ($this->getNextSolutionOrder() - 1)) {
- throw $e;
- }
-
- continue;
- }
- catch (Exception $e) {
- throw $e;
- }
-
- return $values;
- }
-
- if (count($argv) > 0) {
- throw new TooMuchValues($argv, 'Trop de valeurs');
- }
-
- return null;
- }
-
- /**
- * Affiche la version du programme
- *
- * @param boolean $exitAtEnd Terminer le script à la fin de la fonction ?
- */
- public function showVersion ($exitAtEnd = true) {
- echo $this->getVersion() . "\n";
-
- if ($exitAtEnd) {
- exit(0);
- }
- }
- /**
- * Affiche l'aide du programme.
- *
- * @param boolean $exitAtEnd Terminer le script à la fin de la fonction ?
- */
- public function showHelp ($exitAtEnd = true) {
- echo $this->generateHelp() . "\n";
-
- if ($exitAtEnd) {
- exit(0);
- }
- }
- /**
- * Génère l'aide du programme.
- *
- * @return string Le texte de l'aide.
- */
- public function generateHelp () {
- ksort($this->_solutions);
-
- $help = array();
-
- $help[] = $this->getProgramName() . (is_null($this->getVersion()) ? '' : ', version ' . $this->getVersion());
- $help[] = $this->getDescription();
- $help[] = '';
-
- foreach ($this->_solutions as $solution) {
- $syntax = array(
- $this->getCommand(),
- count($this->_optionsCommon) > 0 || count($solution->getOptions()) > 0 ? '[OPTIONS]' : '',
- );
- $syntax = array_merge($syntax, array_map(array(__CLASS__, '_getSyntaxOfArgument'), $solution->getArguments()));
-
- $help[] = implode(' ', $syntax);
-
- $help[] = self::TAB . 'Arguments :';
- $help = array_merge($help, self::_getArgumentsListing($solution->getArguments()));
- $help[] = '';
-
- $help[] = self::TAB . 'Options :';
- $help = array_merge($help, self::_getOptionsListing(array_merge($this->_optionsCommon, $solution->getOptions())));
- $help[] = '';
- }
- $help[] = '';
-
- return implode("\n", $help);
- }
-
- /**
- * La syntax d'un argument
- *
- * @param IArgumentValue $argument L'argument
- *
- * @return string La syntax de l'argument
- * @see generateHelp()
- */
- protected static function _getSyntaxOfArgument (IArgumentValue $argument) {
- $syntax = '';
-
- $min = $argument->getOccurMin();
- $max = $argument->getOccurMax();
- if (is_null($max)) {
- $max = -1;
- }
-
- if ($min == 0) {
- $syntax .= '[';
- }
-
- $syntax .= $argument->getName();
- for ($curr = 2; $curr <= $min; $curr++) {
- $syntax .= ' ' . $argument->getName() . $curr;
- }
-
- if ($max === -1 || $max > 1) {
- if ($min < 2) {
- $syntax .= ' [' . $argument->getName() . '2]';
- }
-
- $syntax .= ' ... [' . $argument->getName() . ($max === -1 ? 'N' : $max) . ']';
- }
-
- if ($min == 0) {
- $syntax .= ']';
- }
-
- return $syntax;
- }
- /**
- * Transforme une liste d'argument en un liste de leur descriptif complet (pour l'aide).
- *
- * @param IArgumentValue[] $arguments La liste des arguments
- *
- * @return string[] Les descriptifs complet des arguments
- */
- protected static function _getArgumentsListing ($arguments) {
- /*
- * Calcul des différents padding
- */
- // Initialisation
- $pads = new stdClass;
- $pads->name = 0;
- $pads->occurMin = 0;
- $pads->occurMax = 0;
- $pads->valueDescription = 0;
-
- // Lecture des arguments
- foreach ($arguments as $argument) {
- $pads->name = max($pads->name, strlen($argument->getName()));
-
- $max = $argument->getOccurMax();
- $pads->occurMin = max($pads->occurMin, strlen($argument->getOccurMin()));
- $pads->occurMax = max($pads->occurMax, strlen(is_null($max) ? 'N' : $max));
-
- if ($argument instanceof IArgumentValueDescription) {
- $pads->valueDescription = max($pads->valueDescription, strlen($argument->getValueDescription()));
- }
- }
-
- /*
- * Génération des descriptifs
- */
- $entries = array();
- foreach ($arguments as $argument) {
- $label = str_pad($argument->getName(), $pads->name, ' ', STR_PAD_RIGHT);
-
- $max = $argument->getOccurMax();
-
- $occur = '';
- $occur .= str_pad($argument->getOccurMin(), $pads->occurMin, ' ', STR_PAD_LEFT);
- $occur .= ' => ';
- $occur .= str_pad(is_null($max) ? 'N' : $max, $pads->occurMax, ' ', STR_PAD_RIGHT);
-
- $valueDescription = str_pad(
- $argument instanceof IArgumentValueDescription ? $argument->getValueDescription() : '',
- $pads->valueDescription,
- ' ',
- STR_PAD_RIGHT
- );
-
- $entries[] = self::TAB . self::TAB . implode(self::TAB, array(
- $label,
- $occur,
- $valueDescription,
- preg_replace(
- /** @lang RegExp */ '@\r?\n@',
- '$0' . self::TAB . self::TAB . implode(self::TAB, array(
- str_pad('', $pads->name, ' '),
- str_pad('',
- $pads->occurMin + 4 + $pads->occurMax,
- ' '
- ),
- str_pad('', $pads->valueDescription, ' '),
- '',
- )
- ),
- $argument->getDescription()
- ),
- )
- );
- }
-
- return $entries;
- }
- /**
- * Transforme une liste d'options en un liste de leur descriptif complet (pour l'aide).
- *
- * @param IArgumentOption[] $options La liste des options
- *
- * @return string[] Les descriptifs complet des options
- */
- protected static function _getOptionsListing ($options) {
- /*
- * Calcul des différents padding
- */
- // Initialisation
- $pads = new stdClass;
- $pads->tagShort = 0;
- $pads->tagLong = 0;
- $pads->valueDescription = 0;
-
- // Lecture des arguments
- foreach ($options as $option) {
- $short = $option->getTagShort();
- if (!is_null($short)) {
- $pads->tagShort = max($pads->tagShort, strlen($short));
- }
- $pads->tagLong = max($pads->tagLong, strlen($option->getTagLong()));
-
- if ($option instanceof IArgumentValueDescription) {
- $pads->valueDescription = max($pads->valueDescription, strlen($option->getValueDescription()));
- }
- }
-
- // Les tags ont une taille suplémentaire incompressible
- $pads->tagShort += 1;
- $pads->tagLong += 2;
-
- /*
- * Génération des descriptifs
- */
- $entries = array();
- foreach ($options as $option) {
- $short = $option->getTagShort();
-
- $label = '';
- $label .= str_pad(is_null($short) ? '' : '-' . $short, $pads->tagShort, ' ', STR_PAD_RIGHT);
- $label .= ' ';
- $label .= str_pad('--' . $option->getTagLong(), $pads->tagLong, ' ', STR_PAD_RIGHT);
- $label .= $option->allowMultiple() ? ' *' : ($option->isStoppingParse() ? ' X' : ' ');
-
- $valueDescription = str_pad(
- $option instanceof IArgumentValueDescription ? $option->getValueDescription() : '',
- $pads->valueDescription,
- ' ',
- STR_PAD_RIGHT
- );
-
- $entries[] = self::TAB . self::TAB . implode(self::TAB, array(
- $label,
- $valueDescription,
- preg_replace(
- /** @lang RegExp */ '@\r?\n@',
- '$0' . self::TAB . self::TAB . implode(self::TAB, array(
- str_pad('', $pads->tagShort + 1 + $pads->tagLong
- + 2, ' '
- ),
- str_pad('', $pads->valueDescription, ' '),
- '',
- )
- ),
- $option->getDescription()
- ),
- )
- );
- }
-
- return $entries;
- }
-
- /**
- * Le nom du programme.
- *
- * @return string Le nom.
- * @see CommandLine::$_programName
- */
- public function getProgramName () {
- return $this->_programName;
- }
- /**
- * Modifie le nom du programme.
- *
- * @param string $programName Le nouveau nom
- *
- * @return $this
- * @see CommandLine::$_programName
- */
- public function setProgramName ($programName) {
- $this->_programName = $programName;
- return $this;
- }
-
- /**
- * La commande de lancement du programme
- *
- * NULL = {@see CommandLine::$_programName Nom du programme}
- *
- * @return string|null La commande
- * @see CommandLine::$_command
- */
- public function getCommand () {
- return $this->_command;
- }
- /**
- * Modifie la commande de lancement du programme
- *
- * @param string|null $command La nouvelle commande
- *
- * @return $this
- * @see CommandLine::$_command
- */
- public function setCommand ($command) {
- $this->_command = $command;
- return $this;
- }
-
- /**
- * La description du programme
- *
- * @return string La description
- * @see CommandLine::$_description
- */
- public function getDescription () {
- return $this->_description;
- }
- /**
- * Modifie la description du programme.
- *
- * @param string $description La nouvelle description.
- *
- * @return $this
- * @see CommandLine::$_description
- */
- public function setDescription ($description) {
- $this->_description = $description;
- return $this;
- }
-
- /**
- * La version du programme
- *
- * @return string|null La version
- * @see CommandLine::$_version
- */
- public function getVersion () {
- return $this->_version;
- }
- /**
- * Modifie la version du programme.
- *
- * @param string|null $version La nouvelle version.
- *
- * @return $this
- * @see CommandLine::$_version
- */
- public function setVersion ($version) {
- $this->_version = $version;
- return $this;
- }
-
- /**
- * La liste des arguments "option"
- *
- * @return IArgumentOption[] La liste des options
- * @see CommandLine::$_arguments_options
- */
- public function getOptions () {
- return $this->_arguments_options;
- }
- /**
- * Modifie la liste des arguments "option"
- *
- * *Attention* : cette fonction _remplace_ la liste des options.
- * Pour seulement en ajouter, utiliser {@see CommandLine::addOptions()}
- *
- * @param IArgumentOption[] $options La nouvelle liste d'options
- *
- * @return $this
- * @see CommandLine::$_arguments_options
- */
- public function setOptions ($options) {
- self::_checkOptionList($options);
-
- $this->_arguments_options = $options;
- return $this;
- }
- /**
- * Ajoute des arguments "option" à ceux existants
- *
- * Pour ajouter une seule option, il est conseillé d'utiliser {@see CommandLine::addOption()}
- *
- * @param IArgumentOption[]|IArgumentOption $options La liste d'options à ajouter
- *
- * @return $this
- * @see CommandLine::$_arguments_options
- */
- public function addOptions ($options) {
- if (!is_array($options) && $options instanceof IArgumentOption) {
- $options = array($options);
- }
- self::_checkOptionList($options);
-
- $this->_arguments_options = array_merge($this->_arguments_options, $options);
- return $this;
- }
- /**
- * Ajoute un seul argument "option" à ceux existants
- *
- * Pour ajouter plusieurs options à la fois, il est conseillé d'utiliser {@see CommandLine::addOptions()}
- *
- * @param IArgumentOption $option L'options à ajouter
- *
- * @return $this
- * @see CommandLine::$_arguments_options
- */
- public function addOption ($option) {
- return $this->addOptions(array($option));
- }
- /**
- * Est-ce que l'argument "option" existe déjà ?
- *
- * @param string $optionName Le nom de l'option
- *
- * @return bool True si l'option existe déjà, sinon False
- */
- public function existsOption ($optionName) {
- foreach ($this->_arguments_options as $option) {
- if ($option->getName() == $optionName) {
- return true;
- }
- }
-
- return false;
- }
- /**
- * Est-ce que c'est un argument "option" ?
- *
- * @param mixed $argument L'argument à tester
- *
- * @return bool True si c'est bien un argument "option", sinon False
- */
- public static function isOption ($argument) {
- return $argument instanceof IArgumentOption;
- }
- /**
- * Vérifie que la liste d'arguments "option" est valide
- *
- * Doit être un tableau et chaque élément doit implémenter {@see IArgumentOption}
- *
- * @param IArgumentOption[] $options Les options à vérifier
- */
- protected static function _checkOptionList ($options) {
- if (!is_array($options)) {
- throw new InvalidArgumentException('La liste des options n\'est pas un tableau');
- }
- foreach ($options as $key => $option) {
- if (!self::isOption($option)) {
- throw new InvalidArgumentException('L\'option ' . $key . ' n\'est pas valide (n\'implémente pas IArgumentOption)');
- }
- }
- }
-
- /**
- * La liste des arguments "value"
- *
- * @return IArgumentValue[] La liste des valeurs
- * @see CommandLine::$_arguments_values
- */
- public function getValues () {
- return $this->_arguments_values;
- }
- /**
- * Modifie la liste des arguments "value"
- *
- * *Attention* : cette fonction _remplace_ la liste des valeurs.
- * Pour seulement en ajouter, utiliser {@see CommandLine::addValues()}
- *
- * @param IArgumentValue[] $values La nouvelle liste de valeurs
- *
- * @return $this
- * @see CommandLine::$_arguments_values
- */
- public function setValues ($values) {
- self::_checkValueList($values);
-
- $this->_arguments_values = $values;
- return $this;
- }
- /**
- * Ajoute des arguments "value" à celles existantes
- *
- * Pour ajouter une seule valeur, il est conseillé d'utiliser {@see CommandLine::addValue()}
- *
- * @param IArgumentValue[]|IArgumentValue $values La liste des valeurs à ajouter
- *
- * @return $this
- * @see CommandLine::$_arguments_values
- */
- public function addValues ($values) {
- if (!is_array($values) && $values instanceof IArgumentValue) {
- $values = array($values);
- }
- self::_checkValueList($values);
-
- $this->_arguments_values = array_merge($this->_arguments_values, $values);
- return $this;
- }
- /**
- * Ajoute un seul argument "value" à celles existantes
- *
- * Pour ajouter plusieurs valeurs à la fois, il est conseillé d'utiliser {@see CommandLine::addValues()}
- *
- * @param IArgumentValue $value La valeur à ajouter
- *
- * @return $this
- * @see CommandLine::$_arguments_values
- */
- public function addValue ($value) {
- return $this->addValues(array($value));
- }
- /**
- * Est-ce que l'argument "value" existe déjà ?
- *
- * @param string $valueName Le nom de la valeur
- *
- * @return bool True si la valeur existe déjà, sinon False
- */
- public function existsValue ($valueName) {
- foreach ($this->_arguments_values as $option) {
- if ($option->getName() == $valueName) {
- return true;
- }
- }
-
- return false;
- }
- /**
- * Est-ce que c'est un argument "value" ?
- *
- * @param mixed $argument L'argument à tester
- *
- * @return bool True si c'est bien un argument "value", sinon False
- */
- public static function isValue ($argument) {
- return $argument instanceof IArgumentValue;
- }
- /**
- * Vérifie que la liste d'arguments "value" est valide
- *
- * Doit être un tableau et chaque élément doit implémenter {@see IArgumentValue}
- *
- * @param IArgumentValue[] $values Les valeurs à vérifier
- */
- protected static function _checkValueList ($values) {
- if (!is_array($values)) {
- throw new InvalidArgumentException('La liste des valeurs n\'est pas un tableau');
- }
- foreach ($values as $key => $value) {
- if (!self::isValue($value)) {
- throw new InvalidArgumentException('La valeur ' . $key . ' n\'est pas valide (n\'implémente pas IArgumentValue)');
- }
- }
- }
-
- /**
- * La liste de tous les arguments ("value" et "option")
- *
- * @return IArgument[] La liste des arguments
- */
- public function getArguments () {
- return array_merge($this->getValues(), $this->getOptions());
- }
- /**
- * Modifie la liste de tous les arguments ("value" et "option")
- *
- * *Attention* : cette fonction _remplace_ la liste des arguments.
- * Pour seulement en ajouter, utiliser {@see CommandLine::addArguments()}
- *
- * @param IArgumentValue[] $arguments La nouvelle liste d'arguments
- *
- * @return $this
- */
- public function setArguments ($arguments) {
- $this->setOptions(array());
- $this->setValues(array());
-
- return $this->addArguments($arguments);
- }
- /**
- * Ajoute des arguments "value" à celles existantes
- *
- * Pour ajouter un seul argument, il est conseillé d'utiliser {@see CommandLine::addArgument()}
- *
- * @param IArgument[]|IArgument $arguments La liste des arguments à ajouter
- *
- * @return $this
- */
- public function addArguments ($arguments) {
- if (!is_array($arguments) && $arguments instanceof IArgumentValue) {
- $arguments = array($arguments);
- }
- self::_checkValueList($arguments);
-
- foreach ($arguments as $argument) {
- $this->addArgument($argument);
- }
-
- return $this;
- }
- /**
- * Ajoute un seul argument ("value" ou "option") à ceux existants
- *
- * Pour ajouter plusieurs arguments à la fois, il est conseillé d'utiliser {@see CommandLine::addArguments()}
- *
- * @param IArgument $argument L'argument à ajouter
- *
- * @return $this
- */
- public function addArgument ($argument) {
- if (!self::isArgument($argument)) {
- throw new InvalidArgumentException('L\'argument n\'est pas valide (n\'implémente pas IArgument)');
- }
-
- if (self::isOption($argument)) {
- $this->addOption($argument);
- }
- elseif (self::isValue($argument)) {
- $this->addValue($argument);
- }
- else {
- $type = '';
- try {
- $reflex = new ReflectionClass($argument);
- foreach ($reflex->getInterfaces() as $interface) {
- if ($interface->implementsInterface(IArgument::class)) {
- $type = $interface->getName();
- break;
- }
- }
- }
- catch (ReflectionException $e) {
- $type = '';
- }
-
- throw new InvalidArgumentException('L\'argument n\'est pas d\'un type géré : ' . $type);
- }
-
- return $this;
- }
- /**
- * Est-ce que l'argument ("value" ou "option") existe déjà ?
- *
- * @param string $argumentName Le nom de l'argument
- *
- * @return bool True si l'argument existe déjà, sinon False
- */
- public function existsArgument ($argumentName) {
- $arguments = $this->getArguments();
- foreach ($arguments as $argument) {
- if ($argument->getName() == $argumentName) {
- return true;
- }
- }
-
- return false;
- }
- /**
- * Est-ce que c'est un argument ("value" ou "option") ?
- *
- * @param mixed $argument L'argument à tester
- *
- * @return bool True si c'est bien un argument, sinon False
- */
- public static function isArgument ($argument) {
- return $argument instanceof IArgument;
- }
- /**
- * Vérifie que la liste d'arguments ("value" et "option") est valide
- *
- * Doit être un tableau et chaque élément doit implémenter {@see IArgument}
- *
- * @param IArgument[] $arguments Les arguments à vérifier
- */
- protected static function _checkArgumentList ($arguments) {
- if (!is_array($arguments)) {
- throw new InvalidArgumentException('La liste des arguments n\'est pas un tableau');
- }
- foreach ($arguments as $key => $argument) {
- if (!self::isArgument($argument)) {
- throw new InvalidArgumentException('L\'argument ' . $key . ' n\'est pas valide (n\'implémente pas IArgument)');
- }
- }
- }
+setProgramName($programName);
+ $this->setDescription($mainDescription);
+ $this->setCommand($command);
+ $this->setVersion($version);
+ }
+
+ /**
+ * La commande de lancement du programme
+ *
+ * NULL = {@see CommandLine::$_programName Nom du programme}
+ *
+ * @return string|null La commande
+ * @see CommandLine::$_command
+ */
+ public function getCommand () {
+ return $this->_command;
+ }
+ /**
+ * Modifie la commande de lancement du programme
+ *
+ * @param string|null $command La nouvelle commande
+ *
+ * @return $this
+ * @see CommandLine::$_command
+ */
+ public function setCommand ($command) {
+ $this->_command = $command;
+ return $this;
+ }
+
+ /**
+ * Le nom du programme.
+ *
+ * @return string Le nom.
+ * @see CommandLine::$_programName
+ */
+ public function getProgramName () {
+ return $this->_programName;
+ }
+ /**
+ * Modifie le nom du programme.
+ *
+ * @param string $programName Le nouveau nom
+ *
+ * @return $this
+ * @see CommandLine::$_programName
+ */
+ public function setProgramName ($programName) {
+ $this->_programName = $programName;
+ return $this;
+ }
+
+ /**
+ * La description du programme
+ *
+ * @return string La description
+ * @see CommandLine::$_description
+ */
+ public function getDescription () {
+ return $this->_description;
+ }
+ /**
+ * Modifie la description du programme.
+ *
+ * @param string $description La nouvelle description.
+ *
+ * @return $this
+ * @see CommandLine::$_description
+ */
+ public function setDescription ($description) {
+ $this->_description = $description;
+ return $this;
+ }
+
+ /**
+ * La version du programme
+ *
+ * @return string|null La version
+ * @see CommandLine::$_version
+ */
+ public function getVersion () {
+ return $this->_version;
+ }
+ /**
+ * Modifie la version du programme.
+ *
+ * @param string|null $version La nouvelle version.
+ *
+ * @return $this
+ * @see CommandLine::$_version
+ */
+ public function setVersion ($version) {
+ $this->_version = $version;
+ return $this;
+ }
+
+ /**
+ * La liste des arguments "value"
+ *
+ * @return IArgumentValue[] La liste des valeurs
+ * @see CommandLine::$_arguments_values
+ */
+ public function getValues () {
+ return $this->_arguments_values;
+ }
+ /**
+ * Modifie la liste des arguments "value"
+ *
+ * *Attention* : cette fonction _remplace_ la liste des valeurs.
+ * Pour seulement en ajouter, utiliser {@see CommandLine::addValues()}
+ *
+ * @param IArgumentValue[] $values La nouvelle liste de valeurs
+ *
+ * @return $this
+ * @see CommandLine::$_arguments_values
+ */
+ public function setValues ($values) {
+ self::_checkValueList($values);
+
+ $this->_arguments_values = $values;
+ return $this;
+ }
+ /**
+ * Ajoute des arguments "value" à celles existantes
+ *
+ * Pour ajouter une seule valeur, il est conseillé d'utiliser {@see CommandLine::addValue()}
+ *
+ * @param IArgumentValue[]|IArgumentValue $values La liste des valeurs à ajouter
+ *
+ * @return $this
+ * @see CommandLine::$_arguments_values
+ */
+ public function addValues ($values) {
+ if (!is_array($values) && $values instanceof IArgumentValue) {
+ $values = array($values);
+ }
+ self::_checkValueList($values);
+
+ $this->_arguments_values = array_merge($this->_arguments_values, $values);
+ return $this;
+ }
+ /**
+ * Ajoute un seul argument "value" à celles existantes
+ *
+ * Pour ajouter plusieurs valeurs à la fois, il est conseillé d'utiliser {@see CommandLine::addValues()}
+ *
+ * @param IArgumentValue $value La valeur à ajouter
+ *
+ * @return $this
+ * @see CommandLine::$_arguments_values
+ */
+ public function addValue ($value) {
+ return $this->addValues(array($value));
+ }
+ /**
+ * Est-ce que l'argument "value" existe déjà ?
+ *
+ * @param string $valueName Le nom de la valeur
+ *
+ * @return bool True si la valeur existe déjà, sinon False
+ */
+ public function existsValue ($valueName) {
+ foreach ($this->_arguments_values as $option) {
+ if ($option->getName() == $valueName) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ /**
+ * Est-ce que c'est un argument "value" ?
+ *
+ * @param mixed $argument L'argument à tester
+ *
+ * @return bool True si c'est bien un argument "value", sinon False
+ */
+ public static function isValue ($argument) {
+ return $argument instanceof IArgumentValue;
+ }
+ /**
+ * Vérifie que la liste d'arguments "value" est valide
+ *
+ * Doit être un tableau et chaque élément doit implémenter {@see IArgumentValue}
+ *
+ * @param IArgumentValue[] $values Les valeurs à vérifier
+ */
+ protected static function _checkValueList ($values) {
+ if (!is_array($values)) {
+ throw new InvalidArgumentException('La liste des valeurs n\'est pas un tableau');
+ }
+ foreach ($values as $key => $value) {
+ if (!self::isValue($value)) {
+ throw new InvalidArgumentException('La valeur ' . $key . ' n\'est pas valide (n\'implémente pas IArgumentValue)');
+ }
+ }
+ }
+
+ /**
+ * La liste des arguments "option"
+ *
+ * @return IArgumentOption[] La liste des options
+ * @see CommandLine::$_arguments_options
+ */
+ public function getOptions () {
+ return $this->_arguments_options;
+ }
+ /**
+ * Modifie la liste des arguments "option"
+ *
+ * *Attention* : cette fonction _remplace_ la liste des options.
+ * Pour seulement en ajouter, utiliser {@see CommandLine::addOptions()}
+ *
+ * @param IArgumentOption[] $options La nouvelle liste d'options
+ *
+ * @return $this
+ * @see CommandLine::$_arguments_options
+ */
+ public function setOptions ($options) {
+ self::_checkOptionList($options);
+
+ $this->_arguments_options = $options;
+ return $this;
+ }
+ /**
+ * Ajoute des arguments "option" à ceux existants
+ *
+ * Pour ajouter une seule option, il est conseillé d'utiliser {@see CommandLine::addOption()}
+ *
+ * @param IArgumentOption[]|IArgumentOption $options La liste d'options à ajouter
+ *
+ * @return $this
+ * @see CommandLine::$_arguments_options
+ */
+ public function addOptions ($options) {
+ if (!is_array($options) && $options instanceof IArgumentOption) {
+ $options = array($options);
+ }
+ self::_checkOptionList($options);
+
+ $this->_arguments_options = array_merge($this->_arguments_options, $options);
+ return $this;
+ }
+ /**
+ * Ajoute un seul argument "option" à ceux existants
+ *
+ * Pour ajouter plusieurs options à la fois, il est conseillé d'utiliser {@see CommandLine::addOptions()}
+ *
+ * @param IArgumentOption $option L'options à ajouter
+ *
+ * @return $this
+ * @see CommandLine::$_arguments_options
+ */
+ public function addOption ($option) {
+ return $this->addOptions(array($option));
+ }
+ /**
+ * Est-ce que l'argument "option" existe déjà ?
+ *
+ * @param string $optionName Le nom de l'option
+ *
+ * @return bool True si l'option existe déjà, sinon False
+ */
+ public function existsOption ($optionName) {
+ foreach ($this->_arguments_options as $option) {
+ if ($option->getName() == $optionName) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ /**
+ * Est-ce que c'est un argument "option" ?
+ *
+ * @param mixed $argument L'argument à tester
+ *
+ * @return bool True si c'est bien un argument "option", sinon False
+ */
+ public static function isOption ($argument) {
+ return $argument instanceof IArgumentOption;
+ }
+ /**
+ * Vérifie que la liste d'arguments "option" est valide
+ *
+ * Doit être un tableau et chaque élément doit implémenter {@see IArgumentOption}
+ *
+ * @param IArgumentOption[] $options Les options à vérifier
+ */
+ protected static function _checkOptionList ($options) {
+ if (!is_array($options)) {
+ throw new InvalidArgumentException('La liste des options n\'est pas un tableau');
+ }
+ foreach ($options as $key => $option) {
+ if (!self::isOption($option)) {
+ throw new InvalidArgumentException('L\'option ' . $key . ' n\'est pas valide (n\'implémente pas IArgumentOption)');
+ }
+ }
+ }
+
+ /**
+ * La liste de tous les arguments ("value" et "option")
+ *
+ * @return IArgument[] La liste des arguments
+ */
+ public function getArguments () {
+ return array_merge($this->getValues(), $this->getOptions());
+ }
+ /**
+ * Modifie la liste de tous les arguments ("value" et "option")
+ *
+ * *Attention* : cette fonction _remplace_ la liste des arguments.
+ * Pour seulement en ajouter, utiliser {@see CommandLine::addArguments()}
+ *
+ * @param IArgumentValue[] $arguments La nouvelle liste d'arguments
+ *
+ * @return $this
+ */
+ public function setArguments ($arguments) {
+ $this->setOptions(array());
+ $this->setValues(array());
+
+ return $this->addArguments($arguments);
+ }
+ /**
+ * Ajoute des arguments "value" à celles existantes
+ *
+ * Pour ajouter un seul argument, il est conseillé d'utiliser {@see CommandLine::addArgument()}
+ *
+ * @param IArgument[]|IArgument $arguments La liste des arguments à ajouter
+ *
+ * @return $this
+ */
+ public function addArguments ($arguments) {
+ if (!is_array($arguments) && $arguments instanceof IArgumentValue) {
+ $arguments = array($arguments);
+ }
+ self::_checkValueList($arguments);
+
+ foreach ($arguments as $argument) {
+ $this->addArgument($argument);
+ }
+
+ return $this;
+ }
+ /**
+ * Ajoute un seul argument ("value" ou "option") à ceux existants
+ *
+ * Pour ajouter plusieurs arguments à la fois, il est conseillé d'utiliser {@see CommandLine::addArguments()}
+ *
+ * @param IArgument $argument L'argument à ajouter
+ *
+ * @return $this
+ */
+ public function addArgument ($argument) {
+ if (!self::isArgument($argument)) {
+ throw new InvalidArgumentException('L\'argument n\'est pas valide (n\'implémente pas IArgument)');
+ }
+
+ if (self::isOption($argument)) {
+ /** @var IArgumentOption $argument */
+ $this->addOption($argument);
+ }
+ elseif (self::isValue($argument)) {
+ /** @var IArgumentValue $argument */
+ $this->addValue($argument);
+ }
+ else {
+ $type = '';
+ try {
+ $reflex = new ReflectionClass($argument);
+ foreach ($reflex->getInterfaces() as $interface) {
+ if ($interface->implementsInterface(IArgument::class)) {
+ $type = $interface->getName();
+ break;
+ }
+ }
+ }
+ catch (ReflectionException $e) {
+ $type = '';
+ }
+
+ throw new InvalidArgumentException('L\'argument n\'est pas d\'un type géré : ' . $type);
+ }
+
+ return $this;
+ }
+ /**
+ * Est-ce que l'argument ("value" ou "option") existe déjà ?
+ *
+ * @param string $argumentName Le nom de l'argument
+ *
+ * @return bool True si l'argument existe déjà, sinon False
+ */
+ public function existsArgument ($argumentName) {
+ $arguments = $this->getArguments();
+ foreach ($arguments as $argument) {
+ if ($argument->getName() == $argumentName) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ /**
+ * Est-ce que c'est un argument ("value" ou "option") ?
+ *
+ * @param mixed $argument L'argument à tester
+ *
+ * @return bool True si c'est bien un argument, sinon False
+ */
+ public static function isArgument ($argument) {
+ return $argument instanceof IArgument;
+ }
+ /**
+ * Vérifie que la liste d'arguments ("value" et "option") est valide
+ *
+ * Doit être un tableau et chaque élément doit implémenter {@see IArgument}
+ *
+ * @param IArgument[] $arguments Les arguments à vérifier
+ */
+ protected static function _checkArgumentList ($arguments) {
+ if (!is_array($arguments)) {
+ throw new InvalidArgumentException('La liste des arguments n\'est pas un tableau');
+ }
+ foreach ($arguments as $key => $argument) {
+ if (!self::isArgument($argument)) {
+ throw new InvalidArgumentException('L\'argument ' . $key . ' n\'est pas valide (n\'implémente pas IArgument)');
+ }
+ }
+ }
+
+ /**
+ * Ajoute les options communes à la plupart des programmes
+ *
+ * Voici la liste des options générées :
+ * - Aide : --help ou -h
+ * - Version : --version ou -v (voir $shortForVersion)
+ *
+ * @param bool $shortForVersion L'option pour la version existe également au format "court" (-v)
+ *
+ * @return $this
+ */
+ public function addDefaultArguments ($shortForVersion = true) {
+ if (!$this->existsOption(self::ARGUMENT_OPTION_HELP)) {
+ $this->addOption(
+ (new Argument\Option\Flag(self::ARGUMENT_OPTION_HELP, false, 'Affiche cette aide', 'help', 'h'))
+ ->setStoppingParse(true)
+ );
+ }
+
+ if (!$this->existsOption(self::ARGUMENT_OPTION_HELP) && !is_null($this->getVersion())) {
+ $this->addOption(
+ (new Argument\Option\Flag(self::ARGUMENT_OPTION_VERSION, false, 'Affiche la version', 'version', $shortForVersion ? 'v' : null))
+ ->setStoppingParse(true)
+ );
+ }
+
+ return $this;
+ }
+ /**
+ * Auto-lance les fonctions correspondantes aux options communes.
+ *
+ * @param stdClass $values Les valeurs du parsage
+ * @param boolean $exitAtEnd Terminer le script à la fin de la fonction correspondante ?
+ */
+ public function treatDefaultArguments ($values, $exitAtEnd = true) {
+ if ($values->{self::ARGUMENT_OPTION_HELP} === true) {
+ $this->showHelp($exitAtEnd);
+ }
+
+ if ($values->{self::ARGUMENT_OPTION_VERSION} === true) {
+ $this->showVersion($exitAtEnd);
+ }
+ }
+
+ /**
+ * Affiche la version du programme
+ *
+ * @param boolean $exitAtEnd Terminer le script à la fin de la fonction ?
+ *
+ * @see CommandLine::getVersion()
+ */
+ public function showVersion ($exitAtEnd = true) {
+ echo $this->getVersion() . "\n";
+
+ if ($exitAtEnd) {
+ exit(0);
+ }
+ }
+ /**
+ * Affiche l'aide du programme.
+ *
+ * @param boolean $exitAtEnd Terminer le script à la fin de la fonction ?
+ *
+ * @see CommandLine::generateHelp()
+ */
+ public function showHelp ($exitAtEnd = true) {
+ echo $this->generateHelp() . "\n";
+
+ if ($exitAtEnd) {
+ exit(0);
+ }
+ }
+ /**
+ * Génère l'aide du programme.
+ *
+ * @return string Le texte de l'aide.
+ *
+ * @see CommandLine::showHelp()
+ */
+ public function generateHelp () {
+ $help = array();
+
+ $help[] = $this->getProgramName() . (is_null($this->getVersion()) ? '' : ', version ' . $this->getVersion());
+ $help[] = $this->getDescription();
+ $help[] = '';
+
+ $syntax = array(
+ $this->getCommand(),
+ count($this->getOptions()) > 0 ? '[OPTIONS]' : '',
+ );
+ $syntax = array_merge($syntax, array_map(array(__CLASS__, '_getSyntaxOfValue'), $this->getValues()));
+
+ $help[] = implode(' ', $syntax);
+
+ $help[] = 'Arguments :';
+ $help = array_merge($help, self::_getValuesListing($this->getValues()));
+ $help[] = '';
+
+ $help[] = 'Options :';
+ $help = array_merge($help, self::_getOptionsListing($this->getOptions()));
+ $help[] = '';
+
+ return implode("\n", $help);
+ }
+
+ /**
+ * La syntax d'un argument "value"
+ *
+ * @param IArgumentValue $value L'argument
+ *
+ * @return string La syntax de l'argument
+ * @see generateHelp()
+ */
+ protected static function _getSyntaxOfValue (IArgumentValue $value) {
+ $syntax = '';
+
+ $min = $value->getOccurMin();
+ $max = $value->getOccurMax();
+ if (is_null($max)) {
+ $max = -1;
+ }
+
+ if ($min == 0) {
+ $syntax .= '[';
+ }
+
+ $syntax .= $value->getName();
+ for ($curr = 2; $curr <= $min; $curr++) {
+ $syntax .= ' ' . $value->getName() . $curr;
+ }
+
+ if ($max === -1 || $max > 1) {
+ if ($min < 2) {
+ $syntax .= ' [' . $value->getName() . '2]';
+ }
+
+ $syntax .= ' ... [' . $value->getName() . ($max === -1 ? 'N' : $max) . ']';
+ }
+
+ if ($min == 0) {
+ $syntax .= ']';
+ }
+
+ return $syntax;
+ }
+ /**
+ * Genère l'aide d'une liste d'arguments "value"
+ *
+ * @param IArgumentValue[] $values La liste des valeurs
+ *
+ * @return string[] L'aide de chaque valeur
+ */
+ protected static function _getValuesListing ($values) {
+ /*
+ * Calcul des différents padding
+ */
+ // Initialisation
+ $pads = new stdClass;
+ $pads->name = 0;
+ $pads->occurMin = 0;
+ $pads->occurMax = 0;
+ $pads->valueDescription = 0;
+
+ // Lecture des arguments
+ foreach ($values as $value) {
+ $pads->name = max($pads->name, strlen($value->getName()));
+
+ $max = $value->getOccurMax();
+ $pads->occurMin = max($pads->occurMin, strlen($value->getOccurMin()));
+ $pads->occurMax = max($pads->occurMax, strlen(is_null($max) ? 'N' : $max));
+
+ if ($value instanceof IArgumentValueDescription) {
+ $pads->valueDescription = max($pads->valueDescription, strlen($value->getValueDescription()));
+ }
+ }
+
+ /*
+ * Génération des descriptifs
+ */
+ $entries = array();
+ foreach ($values as $value) {
+ $label = str_pad($value->getName(), $pads->name, ' ', STR_PAD_RIGHT);
+
+ $max = $value->getOccurMax();
+
+ $occur = '';
+ $occur .= str_pad($value->getOccurMin(), $pads->occurMin, ' ', STR_PAD_LEFT);
+ $occur .= ' => ';
+ $occur .= str_pad(is_null($max) ? 'N' : $max, $pads->occurMax, ' ', STR_PAD_RIGHT);
+
+ $valueDescription = str_pad(
+ $value instanceof IArgumentValueDescription ? $value->getValueDescription() : '',
+ $pads->valueDescription,
+ ' ',
+ STR_PAD_RIGHT
+ );
+
+ $entries[] = self::TAB . implode(self::TAB, array(
+ $label,
+ $occur,
+ $valueDescription,
+ preg_replace(
+ /** @lang RegExp */ '@\r?\n@',
+ '$0' . self::TAB . implode(self::TAB, array(
+ str_pad('', $pads->name, ' '),
+ str_pad('', $pads->occurMin + 4 + $pads->occurMax, ' '),
+ str_pad('', $pads->valueDescription, ' '),
+ '',
+ )
+ ),
+ $value->getDescription()
+ ),
+ )
+ );
+ }
+
+ return $entries;
+ }
+ /**
+ * Genère l'aide d'une liste d'arguments "option"
+ *
+ * @param IArgumentOption[] $options La liste des options
+ *
+ * @return string[] L'aide de chaque option
+ */
+ protected static function _getOptionsListing ($options) {
+ /*
+ * Calcul des différents padding
+ */
+ // Initialisation
+ $pads = new stdClass;
+ $pads->tagShort = 0;
+ $pads->tagLong = 0;
+ $pads->valueDescription = 0;
+
+ // Lecture des arguments
+ foreach ($options as $option) {
+ $short = $option->getTagShort();
+ if (!is_null($short)) {
+ $pads->tagShort = max($pads->tagShort, strlen($short));
+ }
+ $pads->tagLong = max($pads->tagLong, strlen($option->getTagLong()));
+
+ if ($option instanceof IArgumentValueDescription) {
+ $pads->valueDescription = max($pads->valueDescription, strlen($option->getValueDescription()));
+ }
+ }
+
+ // Les tags ont une taille suplémentaire incompressible
+ $pads->tagShort += 1;
+ $pads->tagLong += 2;
+
+ /*
+ * Génération des descriptifs
+ */
+ $entries = array();
+ foreach ($options as $option) {
+ $short = $option->getTagShort();
+
+ $label = '';
+ $label .= str_pad(is_null($short) ? '' : '-' . $short, $pads->tagShort, ' ', STR_PAD_RIGHT);
+ $label .= ' ';
+ $label .= str_pad('--' . $option->getTagLong(), $pads->tagLong, ' ', STR_PAD_RIGHT);
+ $label .= $option->allowMultiple() ? ' *' : ($option->isStoppingParse() ? ' X' : ' ');
+
+ $valueDescription = str_pad(
+ $option instanceof IArgumentValueDescription ? $option->getValueDescription() : '',
+ $pads->valueDescription,
+ ' ',
+ STR_PAD_RIGHT
+ );
+
+ $entries[] = self::TAB . self::TAB . implode(self::TAB, array(
+ $label,
+ $valueDescription,
+ preg_replace(
+ /** @lang RegExp */ '@\r?\n@',
+ '$0' . self::TAB . self::TAB . implode(self::TAB, array(
+ str_pad('', $pads->tagShort + 1 + $pads->tagLong + 2, ' '),
+ str_pad('', $pads->valueDescription, ' '),
+ '',
+ )
+ ),
+ $option->getDescription()
+ ),
+ )
+ );
+ }
+
+ return $entries;
+ }
+
+ /**
+ * Traite les arguments du script
+ *
+ * Revient à appeler {@see CommandLine::parseExplicit()} avec les arguments du script {@link https://www.php.net/manual/en/reserved.variables.argv.php $_SERVER['argv']}
+ *
+ * @return stdClass Les valeurs extraites
+ * @throws MissingArgument Quand un argument de la liste est manquant ou en quantité insuffisante
+ * @throws TooMuchValues Quand il reste des valeurs supplémentaires après le traitement de la liste d'arguments
+ */
+ public function parse () {
+ $argv = $_SERVER['argv'];
+ array_shift($argv); // Supprime le 1er paramètre : le nom du script PHP
+
+ return $this->parseExplicit($argv);
+ }
+ /**
+ * Traite une liste d'arguments.
+ *
+ * 1/ Vérifie que la liste d'arguments correspond à la syntaxe de la ligne de commande
+ * 2/ Extrait les valeurs voulues de la liste d'arguments
+ *
+ * @param string[] $argv La liste d'arguments
+ *
+ * @return stdClass Les valeurs extraites
+ * @throws MissingArgument Quand un argument de la liste est manquant ou en quantité insuffisante
+ * @throws TooMuchValues Quand il reste des valeurs supplémentaires après le traitement de la liste d'arguments
+ */
+ public function parseExplicit ($argv) {
+ $stop = false;
+ $nb_args = count($argv);
+
+ $out = $this->_parseOptions($argv, $this->getOptions(), $stop);
+ if ($stop) {
+ return $out;
+ }
+
+ $values = array_values($this->getValues());
+ /**
+ * @var int $ordre
+ * @var IArgumentValue $value
+ */
+ foreach ($values as $ordre => $value) {
+ $min = $value->getOccurMin();
+ self::_parseXTimes($argv, $out, $value, $min);
+
+ $max = $value->getOccurMax();
+ if (is_null($max) || $max > $min) {
+ $nbArgs = $this->_getNbArgumentRestant($ordre);
+ if ($nbArgs >= 0 && count($argv) > $nbArgs) {
+ $nbParse = count($argv) - $nbArgs;
+ if (!is_null($max)) {
+ $nbParse = min($nbParse, $max - $min);
+ }
+
+ self::_parseXTimes($argv, $out, $value, $nbParse, $min);
+ }
+ }
+ }
+
+ if (count($argv)) {
+ throw new TooMuchValues('Trop de paramètres : '.count($argv).' / '.$nb_args);
+ }
+
+ // Valeurs par défaut
+ foreach ($this->getOptions() as $option) {
+ if (!isset($out->{$option->getVarName()})) {
+ $out->{$option->getVarName()} = $option->getDefault();
+ }
+ }
+ foreach ($values as $value) {
+ if (!isset($out->{$value->getVarName()})) {
+ $out->{$value->getVarName()} = $value->getDefault();
+ }
+ }
+
+ return $out;
+ }
+ /**
+ * Calcule le nombre d'argument "value" restant à honorer.
+ *
+ * @param int $ordre_start L'ordre de la valeur en cours
+ *
+ * @return int Le nombre de valeurs restantes à traiter, ou -1 si un nombre "illimité"
+ */
+ protected function _getNbArgumentRestant ($ordre_start) {
+ $nb = 0;
+ /**
+ * @var int $ordre
+ * @var IArgumentValue $argument
+ */
+ foreach (array_values($this->getValues()) as $ordre => $argument) {
+ if ($ordre <= $ordre_start) {
+ continue;
+ }
+
+ $max = $argument->getOccurMax();
+ if (is_null($max)) {
+ return -1;
+ }
+
+ $nb += $max;
+ }
+
+ return $nb;
+ }
+ /**
+ * Parse des arguments "option"
+ *
+ * @param string[] $argv La liste des arguments du script
+ * @param IArgumentOption[] $options La liste des options
+ * @param boolean $stop Arrêt du parsage ?
+ *
+ * @return stdClass Les options extraites
+ * @throws IncorrectParse Si le parsage d'une des options échoue
+ */
+ protected static function _parseOptions (&$argv, $options, &$stop) {
+ $values = new stdClass();
+ $stop = false;
+
+ foreach ($options as $option) {
+ do {
+ $argv_option = $argv;
+
+ $find = false;
+ while (count($argv_option) > 0) {
+ $result = $option->parse($argv_option);
+
+ if (!is_null($result)) {
+ if ($option->isStoppingParse()) {
+ $values = new stdClass();
+ }
+
+ self::_setValue($values, $option, $result, $option->allowMultiple() ? 2 : 1);
+
+ if ($option->isStoppingParse()) {
+ $stop = true;
+ return $values;
+ }
+
+ array_splice($argv, count($argv) - count($argv_option), $result->getConsume());
+ $find = true;
+ break;
+ }
+
+ array_shift($argv_option);
+ }
+ } while (count($argv_option) > 1 && (!$find || $option->allowMultiple()));
+ }
+
+ return $values;
+ }
+ /**
+ * Parse un argument "value" X fois
+ *
+ * @param string[] $argv Liste des arguments du script
+ * @param stdClass $out Les valeurs de sortie
+ * @param IArgumentValue $value L'argument "value" à parser
+ * @param int $xTimes Le nombre de fois à parser
+ * @param int $offset L'offset pour le n° d'occurence
+ *
+ * @throws MissingArgument Si l'argument n'est pas en quantité suffisante
+ * @throws IncorrectParse Si l'argument échoue à se parser
+ */
+ protected static function _parseXTimes (&$argv, &$out, $value, $xTimes, $offset = 0) {
+ if ($xTimes > count($argv)) {
+ throw new MissingArgument('L\'argument ' . $value->getName() . ' est en quantité insuffisante (' . count($argv) . ' / ' . $xTimes . ')');
+ }
+
+ for ($curr = 1; $curr <= $xTimes; $curr++) {
+ $result = $value->parse($argv);
+ if (is_null($result)) {
+ throw new MissingArgument('L\'occurence n° ' . ($offset + $curr) . ' de l\'argument ' . $value->getName() . ' ne correspond pas');
+ }
+
+ self::_setValue($out, $value, $result, $value->getOccurMax());
+ $argv = array_slice($argv, $result->getConsume());
+ }
+ }
+ /**
+ * Ajoute le résultat d'un argument "value" ou "option") aux valeurs de sortie
+ *
+ * @param stdClass $out Les valeurs de sortie, auxquelles ajouter la résultat
+ * @param IArgument $argument L'argument actuel
+ * @param ParseResult $result Le résultat du parsage de l'argument
+ * @param int|null $max Le nombre maximum de valeur autorisé
+ */
+ protected static function _setValue (&$out, $argument, $result, $max) {
+ if (is_null($max) || $max > 1) {
+ if (!isset($out->{$argument->getVarName()})) {
+ $out->{$argument->getVarName()} = array();
+ }
+
+ $out->{$argument->getVarName()}[] = $result->getValue();
+ }
+ else {
+ $out->{$argument->getVarName()} = $result->getValue();
+ }
+ }
}
\ No newline at end of file
diff --git a/Solution.class.php b/Solution.class.php
deleted file mode 100644
index 06ca8f7..0000000
--- a/Solution.class.php
+++ /dev/null
@@ -1,279 +0,0 @@
-_arguments))
- throw new InvalidArgument($order, 'Cet ordre est déjà utilisé pour un autre argument');
-
- $this->_arguments[$order] = $argument;
- return $this;
- }
- /**
- * Liste des arguments de la solution.
- *
- * @return IArgumentValue[] Les arguments.
- */
- public function getArguments () {
- ksort($this->_arguments);
- return $this->_arguments;
- }
- /**
- * Le prochain ordre disponible pour un argument
- *
- * @return int La prochaine position
- */
- public function getNextOrder () {
- $keys = array_keys($this->_arguments);
- if(count($keys) < 1)
- return 1;
-
- return max($keys) + 1;
- }
-
- /**
- * Ajoute une option
- *
- * @param IArgumentOption $option L'option
- *
- * @return $this
- *
- * @throws InvalidArgument Si les arguments secondaires (le cas échéant) sont invalides.
- *
- * @see $_options
- */
- public function addOption (IArgumentOption $option) {
- if(array_key_exists($option->getName(), $this->_options))
- throw new InvalidArgument($option, 'Il existe déjà une autre option avec le même nom');
-
- $this->_options[$option->getName()] = $option;
-
- if($option instanceof IArgumentOptionSecondary) {
- foreach($option->getOthersOptions() as $option_second)
- $this->addOption($option_second);
- }
-
- return $this;
- }
- /**
- * Liste des options de la solution.
- *
- * @return IArgumentOption[] Les options.
- */
- public function getOptions () {
- return $this->_options;
- }
-
- /**
- * Traite la solution pour en sortir les valeurs.
- *
- * @param string[] $argv La liste des arguments
- * @param IArgumentOption[] $common_options La liste des options communes
- *
- * @return stdClass Les valeurs extraites.
- * @throws MissingArgument Quand un argument est manquant ou en quantité insuffisante
- * @throws InvalidArgument Quand un argument n'arrive pas à parser sa valeur
- * @throws TooMuchValues Quand la solution ne consumme pas la totalité des arguments
- */
- public function parseExplicit ($argv, $common_options) {
- $stop = false;
- /** @var IArgumentOption[] $options */$options = array_merge($common_options, $this->getOptions());
-
- $values = $this->_parseOptions($argv, $options, $stop);
- if($stop)
- return $values;
-
- $arguments = $this->getArguments();
- foreach($arguments as $ordre => $argument) {
- $min = $argument->getOccurMin();
- self::_parseXTimes($argv, $values, $argument, $min);
-
- $max = $argument->getOccurMax();
- if(is_null($max) || $max > $min) {
- $nbArgs = $this->_getNbArgumentRestant($ordre);
- if($nbArgs >= 0 && count($argv) > $nbArgs) {
- $nbParse = count($argv) - $nbArgs;
- if(!is_null($max))
- $nbParse = min($nbParse, $max - $min);
-
- self::_parseXTimes($argv, $values, $argument, $nbParse, $min);
- }
- }
- }
-
- if(count($argv))
- throw new TooMuchValues($argv, 'Trop de paramètres');
-
- // Valeurs par défaut
- foreach($options as $option) {
- if(!isset($values->{$option->getVarName()}))
- $values->{$option->getVarName()} = $option->getDefault();
- }
- foreach($arguments as $argument) {
- if(!isset($values->{$argument->getVarName()}))
- $values->{$argument->getVarName()} = $argument->getDefault();
- }
-
- return $values;
- }
- /**
- * Parse des options.
- *
- * @param string[] $argv La liste des arguments
- * @param IArgumentOption[] $options La liste des options
- * @param boolean $stop Arrêt du parsage ?
- *
- * @return stdClass Les options extraites
- * @throws IncorrectParse Si le parsage d'une des options échoue
- */
- protected static function _parseOptions (&$argv, $options, &$stop) {
- $values = new stdClass();
- $stop = false;
-
- foreach($options as $option) {
- do {
- $argv_option = $argv;
-
- $find = false;
- while(count($argv_option) > 0) {
- $result = $option->parse($argv_option);
-
- if(!is_null($result)) {
- if($option->isStoppingParse())
- $values = new stdClass();
-
- self::_setValue($values, $option, $result, $option->allowMultiple() ? 2 : 1);
-
- if($option->isStoppingParse()) {
- $stop = true;
- return $values;
- }
-
- array_splice($argv, count($argv) - count($argv_option), $result->getConsume());
- $find = true;
- break;
- }
-
- array_shift($argv_option);
- }
- } while(count($argv_option) > 1 && (!$find || $option->allowMultiple()));
- }
-
- return $values;
- }
-
- /**
- * Parse un argument X fois
- *
- * @param string[] $argv Liste des arguments
- * @param stdClass $values Les valeurs de sortie
- * @param IArgumentValue $argument L'argument à parser
- * @param int $xTimes Le nombre de fois à parser
- * @param int $offset L'offset pour le n° d'occurence
- *
- * @throws MissingArgument Si l'argument n'est pas en quantité suffisante
- * @throws IncorrectParse Si l'argument échoue à se parser
- */
- protected static function _parseXTimes (&$argv, &$values, $argument, $xTimes, $offset = 0) {
- if($xTimes > count($argv))
- throw new MissingArgument($argument, 'L\'argument est en quantité insuffisante (' . count($argv) . ' / ' . $xTimes . ')');
-
- for($curr = 1; $curr <= $xTimes; $curr++) {
- $result = $argument->parse($argv);
- if(is_null($result))
- throw new MissingArgument($argument, 'L\'occurence n° ' . ($offset + $curr) . ' de l\'argument ne correspond pas');
-
- self::_setValue($values, $argument, $result, $argument->getOccurMax());
- $argv = array_slice($argv, $result->getConsume());
- }
- }
- /**
- * Ajoute le résultat d'un argument aux valeurs de sortie
- *
- * @param stdClass $values Les valeurs de sortie, auxquelles ajouter la résultat
- * @param IArgument $argument L'argument actuel
- * @param ParseResult $result Le résultat de l'argument
- * @param int|null $max Le nombre max de valeur autorisé
- */
- protected static function _setValue (&$values, $argument, $result, $max) {
- if(is_null($max) || $max > 1) {
- if(!isset($values->{$argument->getVarName()}))
- $values->{$argument->getVarName()} = array();
-
- $values->{$argument->getVarName()}[] = $result->getValue();
- }
- else
- $values->{$argument->getVarName()} = $result->getValue();
- }
- /**
- * Calcule le nombre d'argument restant à honorer.
- *
- * @param int $ordre_start L'ordre de l'argument en cours
- *
- * @return int Le nombre d'argument restant, ou -1 si un argument "illimité"
- */
- protected function _getNbArgumentRestant ($ordre_start) {
- $nb = 0;
- foreach($this->getArguments() as $ordre => $argument) {
- if($ordre <= $ordre_start)
- continue;
-
- $max = $argument->getOccurMax();
- if(is_null($max))
- return -1;
-
- $nb += $max;
- }
-
- return $nb;
- }
-}
\ No newline at end of file