Finish merging Solution into CommandeLine
parent
183b738c50
commit
3d869f684f
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
File diff suppressed because it is too large
Load Diff
@ -1,279 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Déclaration de la classe CommandLine\Solution
|
|
||||||
*/
|
|
||||||
namespace CommandLine;
|
|
||||||
|
|
||||||
use Fidit\v3\Exception\InvalidArgument;
|
|
||||||
use CommandLine\Exception\IncorrectParse;
|
|
||||||
use CommandLine\Exception\MissingArgument;
|
|
||||||
use CommandLine\Exception\TooMuchValues;
|
|
||||||
use CommandLine\Argument\IArgument;
|
|
||||||
use CommandLine\Argument\Option\IArgumentOption;
|
|
||||||
use CommandLine\Argument\Option\IArgumentOptionSecondary;
|
|
||||||
use CommandLine\Argument\ParseResult;
|
|
||||||
use CommandLine\Argument\Value\IArgumentValue;
|
|
||||||
use stdClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Représente *une* solution d'une ligne de commande.
|
|
||||||
*
|
|
||||||
* @package CommandLine
|
|
||||||
*/
|
|
||||||
class Solution {
|
|
||||||
/**
|
|
||||||
* @var IArgumentValue[] Liste des arguments de la ligne de commande
|
|
||||||
*/
|
|
||||||
protected $_arguments = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var IArgumentOption[] Liste des options de la ligne de commande
|
|
||||||
*/
|
|
||||||
protected $_options = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crée un nouvelle solution.
|
|
||||||
*/
|
|
||||||
public function __construct () {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ajoute un argument
|
|
||||||
*
|
|
||||||
* @param int $order Ordre de l'argument.
|
|
||||||
* @param IArgumentValue $argument L'argument
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*
|
|
||||||
* @throws InvalidArgument Si les arguments secondaires (le cas échéant) sont invalides.
|
|
||||||
*
|
|
||||||
* @see $_arguments
|
|
||||||
*/
|
|
||||||
public function addArgument ($order, IArgumentValue $argument) {
|
|
||||||
if(is_null($order) || !is_numeric($order))
|
|
||||||
throw new InvalidArgument($order, 'L\'ordre n\'est pas un nombre');
|
|
||||||
if(array_key_exists($order, $this->_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;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue