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