Initial commit

master
Julien Rosset 6 years ago
commit b89af5c6da

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State />
<State>
<id>PHP</id>
</State>
<State>
<id>SQL</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>SqlResolveInspection</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
</project>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="masterDetails">
<states>
<state key="ScopeChooserConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,115 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="AUTODETECT_INDENTS" value="false" />
<option name="RIGHT_MARGIN" value="190" />
<HTMLCodeStyleSettings>
<option name="HTML_ATTRIBUTE_WRAP" value="4" />
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
<option name="HTML_ELEMENTS_TO_INSERT_NEW_LINE_BEFORE" value="body,div,p,form,h1,h2,h3,br" />
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="html" />
<option name="HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT" value="title,h1,h2,h3,h4,h5,h6" />
<option name="HTML_NEWLINE_BEFORE_FIRST_ATTRIBUTE" value="When multiline" />
<option name="HTML_NEWLINE_AFTER_LAST_ATTRIBUTE" value="When multiline" />
</HTMLCodeStyleSettings>
<JSCodeStyleSettings version="0">
<option name="SPACE_BEFORE_ASYNC_ARROW_LPAREN" value="false" />
</JSCodeStyleSettings>
<JSON>
<option name="PROPERTY_ALIGNMENT" value="1" />
<option name="ARRAY_WRAPPING" value="5" />
</JSON>
<PHPCodeStyleSettings>
<option name="ALIGN_KEY_VALUE_PAIRS" value="true" />
<option name="ALIGN_PHPDOC_PARAM_NAMES" value="true" />
<option name="ALIGN_PHPDOC_COMMENTS" value="true" />
<option name="CONCAT_SPACES" value="false" />
<option name="COMMA_AFTER_LAST_ARRAY_ELEMENT" value="true" />
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
<option name="PHPDOC_BLANK_LINES_AROUND_PARAMETERS" value="true" />
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
<option name="LOWER_CASE_NULL_CONST" value="true" />
<option name="ELSE_IF_STYLE" value="COMBINE" />
<option name="VARIABLE_NAMING_STYLE" value="CAMEL_CASE" />
<option name="KEEP_RPAREN_AND_LBRACE_ON_ONE_LINE" value="true" />
<option name="ALIGN_CLASS_CONSTANTS" value="true" />
<option name="BLANK_LINES_AROUND_CONSTANTS" value="1" />
<option name="BLANK_LINES_AFTER_FUNCTION" value="0" />
<option name="KEEP_BLANK_LINES_AFTER_LBRACE" value="0" />
<option name="SPACE_BETWEEN_TERNARY_QUEST_AND_COLON" value="true" />
</PHPCodeStyleSettings>
<codeStyleSettings language="HTML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<option name="SPACE_WITHIN_BRACKETS" value="true" />
<option name="SPACE_WITHIN_BRACES" value="true" />
<indentOptions>
<option name="INDENT_SIZE" value="4" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
</codeStyleSettings>
<codeStyleSettings language="PHP">
<option name="RIGHT_MARGIN" value="160" />
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="0" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="3" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="BLANK_LINES_BEFORE_PACKAGE" value="0" />
<option name="BLANK_LINES_AROUND_FIELD" value="1" />
<option name="BLANK_LINES_AROUND_METHOD" value="0" />
<option name="CLASS_BRACE_STYLE" value="1" />
<option name="METHOD_BRACE_STYLE" value="1" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="INDENT_BREAK_FROM_CASE" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="5" />
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="2" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE" value="true" />
<arrangement>
<groups>
<group>
<type>GETTERS_AND_SETTERS</type>
<order>KEEP</order>
</group>
<group>
<type>DEPENDENT_METHODS</type>
<order>BREADTH_FIRST</order>
</group>
</groups>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="On explicit save action" autoUploadExternalChanges="true">
<option name="myAutoUpload" value="ON_EXPLICIT_SAVE" />
</component>
</project>

@ -0,0 +1,9 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PhpComposerExtensionStubsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNamedArgumentsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="ERROR" enabled_by_default="false" />
</profile>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/CommandLine.iml" filepath="$PROJECT_DIR$/.idea/CommandLine.iml" />
</modules>
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpIncludePathManager">
<include_path>
<path value="C:/php/includes/fidit" />
</include_path>
</component>
</project>

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="24e3f692-8ba3-4d0b-8b1d-a659bb49096c" name="Default Changelist" comment="" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ComposerSettings">
<execution>
<executable />
</execution>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="PhpWorkspaceProjectConfiguration">
<include_path>
<path value="C:/php/includes/fidit" />
</include_path>
</component>
<component name="ProjectId" id="1QkOgOmQabXBt6Ca0XPelUAw9zz" />
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="true" />
<property name="last_opened_file_path" value="C:/php/includes/fidit" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="settings.editor.selected.configurable" value="terminal" />
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SshConsoleOptionsProvider">
<option name="myEncoding" value="UTF-8" />
<option name="myConnectionType" value="NONE" />
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="24e3f692-8ba3-4d0b-8b1d-a659bb49096c" name="Default Changelist" comment="" />
<created>1568311237973</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1568311237973</updated>
<workItem from="1568311245294" duration="835000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
</project>

@ -0,0 +1,121 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\AbstractArgument.
*/
namespace CommandLine\Argument;
use Fidit\v3\AutoProperty;
use Fidit\v3\Exception\InvalidArgument;
/**
* Classe abstraite pour n'importe quel type de paramètre
*
* @property string $varName {@see $_varName $_varName }
* @property string $name {@see $_name $_name }
* @property string|null $description {@see $_description $_description}
* @property mixed|null $default {@see $_default $_default }
*
* @package CommandLine\Argument
*/
abstract class ArgumentAbstract extends AutoProperty implements IArgument {
/**
* @var string Le nom de la variable de retour de l'argument.
*/
protected $_varName;
/**
* @var string Le nom de l'argument.
*/
protected $_name;
/**
* @var string|null La description de l'argument.
*/
protected $_description;
/**
* @var mixed|null La valeur par défaut. Null si aucune.
*/
protected $_default = null;
/**
* Crée un nouvel argument.
*
* @param string $name Le nom de l'argument
* @param string|null $description La description de l'argument
*/
protected function __construct ($name, $description) {
$this->setName($name, true);
$this->setDescription($description);
}
public function getVarName() {
return $this->_varName;
}
/**
* Définit le nom de la variable de retour de l'argument.
*
* @param string $varName Le nom
*
* @return $this
*
* @see $_name
*/
public function setVarName($varName) {
$this->_varName = $varName;
return $this;
}
public function getName() {
return $this->_name;
}
/**
* Définit le nom de l'argument.
*
* @param string $name Le nom
* @param boolean $replaceVarName Remplacer également le nom de la variable de retour ?
*
* @return $this
*
* @see $_name
*/
public function setName($name, $replaceVarName = true) {
$this->_name = $name;
if($replaceVarName)
$this->setVarName($name);
return $this;
}
public function getDescription() {
return $this->_description;
}
/**
* Définit la description de l'argument.
*
* @param string|null $description La description
*
* @return $this
*
* @see $_description
*/
public function setDescription($description) {
$this->_description = $description;
return $this;
}
public function getDefault() {
return $this->_default;
}
/**
* Définit le valeur par défaut
*
* @param mixed|null $default La valeur par défaut.
*
* @return $this
*
* @see $_default
*/
public function setDefault($default = null) {
$this->_default = $default;
return $this;
}
}

@ -0,0 +1,51 @@
<?php
/**
* Déclaration de l'interface CommandLine\Argument\IArgument
*/
namespace CommandLine\Argument;
use CommandLine\Exception\IncorrectParse;
/**
* Interface que tout argument doit implémenter
*
* @package CommandLine\Argument
*/
interface IArgument {
/**
* Le nom de la variable de sortie l'argument
*
* @return string Le nom
*/
public function getVarName();
/**
* Le nom de l'argument
*
* @return string Le nom
*/
public function getName();
/**
* La valeur par défaut de l'argument. Null si pas de valeur par défaut
*
* @return mixed|null La valeur par défaut
*/
public function getDefault();
/**
* La description de l'argument
*
* @return string|null La description
*/
public function getDescription();
/**
* Parse les arguments.
*
* @param $args array La liste des arguments encore à traiter (par ordre de réception)
*
* @return ParseResult|null Le résultat du parsage. Null si rien parsé
*
* @throws IncorrectParse Echec du parsage de l'argument
*/
public function parse($args);
}

@ -0,0 +1,19 @@
<?php
/**
* Déclaration de l'interface CommandLine\Argument\IArgumentValueDescription
*/
namespace CommandLine\Argument;
/**
* Interface à implementer par les arguments qui souhaitent détailler la valeur attendue
*
* @package CommandLine\Argument
*/
interface IArgumentValueDescription {
/**
* La description de la valeur de d'argument.
*
* @return string La description.
*/
public function getValueDescription();
}

@ -0,0 +1,60 @@
<?php
/**
* Déclare la classe CommandLine\Argument\Option\Flag.
*/
namespace CommandLine\Argument\Option;
use Fidit\v3\Exception\InvalidArgument;
use CommandLine\Argument\ArgumentAbstract;
use CommandLine\Argument\ParseResult;
/**
* Option de type "flag" contenant True ou False.
*
* Si fourni, retournera la valeur inverse de {@see getDefault() getDefault}
*
* @see FlagReverse
*
* @package CommandLine\Argument\Option
*/
class Flag extends OptionAbstract {
/**
* Crée un nouvel argument de type option.
*
* @param string $name Le nom.
* @param boolean $default La valeur par défaut.
* @param string|null $description La description.
* @param string|null $tagLong Le tag long.
* @param string|null $tagShort Le tag court.
*
* @throws InvalidArgument Si l'un des paramètres n'est pas correct
*/
public function __construct ($name, $default, $description, $tagLong = null, $tagShort = null) {
parent::__construct($name, $description, $tagLong, $tagShort);
$this->setDefault($default);
}
public function parse ($args) {
if($this->_parseTag($args[0]))
return new ParseResult(true, 1);
return null;
}
/**
* Définit le valeur par défaut
*
* @param boolean $default La valeur par défaut.
*
* @return $this
*
* @throws InvalidArgument Si la valeur n'est pas un booléen.
*/
public function setDefault ($default = null) {
if(is_null($default) || !is_bool($default))
throw new InvalidArgument($default, 'La valeur par défaut DOIT être un booléen');
parent::setDefault($default);
return $this;
}
}

@ -0,0 +1,48 @@
<?php
/**
* Déclare la classe CommandLine\Argument\Option\OptionFlagWithReverse.
*/
namespace CommandLine\Argument\Option;
/**
* Option de type "flag" : vaut True ou False avec son tag inversé.
*
* Le tag long inversé est automatiquement généré en préfixant avec "no-" sauf si l'initial commence déjà par "no-".
* Le tag court inversé est fait de la même manière, mais avec le préfixe "n".
*
* Exemples :
* - "--force" donne "--no-force"
* - "-f" donne "-nf"
* - "--no-stop" devient "--stop"
*
* @package CommandLine\Argument\Option
*/
class FlagWithReverse extends Flag implements IArgumentOptionSecondary {
public function getOthersOptions () {
$tagShort = null;
if($this->hasTagShort()) {
if(substr($this->getTagShort(), 0, 1) == 'n')
$tagShort = substr($this->getTagShort(), 1);
else
$tagShort = 'n'.$this->getTagShort();
}
if(substr($this->getTagLong(), 0, 3) == 'no-')
$tagLong = substr($this->getTagLong(), 3);
else
$tagLong = 'no-'.$this->getTagLong();
$name = $this->getName();
if(substr($name, 0, 3) == 'no')
$name = strtolower(substr($name, 2, 1)).substr($name, 3);
else
$name = 'no'.strtoupper(substr($name, 0, 1)).substr($name, 1);
$description = '[INVERSE] '.$this->getDescription();
$reverse = new Flag($name, !$this->getDefault(), $description, $tagLong, $tagShort);
$reverse->setVarName($this->getVarName());
return array($reverse);
}
}

@ -0,0 +1,46 @@
<?php
/**
* Déclaration de l'interface CommandLine\Argument\Option\IArgumentOption
*/
namespace CommandLine\Argument\Option;
use CommandLine\Argument\IArgument;
/**
* Interface à implémenter si l'argument est de type "option"
*
* @package CommandLine\Argument\Option
*/
interface IArgumentOption extends IArgument {
/**
* La tag court.
*
* @return string|null Le tag court.
*
* @see $_tagShort
*/
public function getTagShort();
/**
* Le tag long.
*
* @return string Le tag long.
*
* @see $_tagLong
*/
public function getTagLong();
/**
* Est-ce que l'argument est autorisé plusieurs fois ?
*
* @return boolean True si l'argument est autorisé plusieurs fois, sinon False
*/
public function allowMultiple();
/**
* Est-ce que l'argument met fin au parsage ?
*
* Exemple : --help = affiche l'aide et stoppe le programme
*
* @return boolean True si la présence de l'argument mat fin au parsage, sinon False.
*/
public function isStoppingParse();
}

@ -0,0 +1,23 @@
<?php
/**
* Déclaration de l'interface CommandLine\Argument\Option\IArgumentSecondary.
*/
namespace CommandLine\Argument\Option;
use Fidit\v3\Exception\InvalidArgument;
/**
* Interface à implémenter si l'argument "option" auto-déclare d'autres arguments
*
* @package CommandLine\Argument\Option
*/
interface IArgumentOptionSecondary {
/**
* La liste des arguments auto-déclarés.
*
* @return IArgumentOption[] La liste des arguments
*
* @throws InvalidArgument
*/
public function getOthersOptions();
}

@ -0,0 +1,177 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Option\OptionAbstract.
*/
namespace CommandLine\Argument\Option;
use Fidit\v3\Exception\InvalidArgument;
use CommandLine\Argument\ArgumentAbstract;
/**
* Classe abstraite pour les arguments de type "option" : --xxx / -x
*
* NOTE : les arguments de type "option" ne peuvent autoriser plusieurs valeurs ({@see $default $default} = 1).
*
* @property string|null $tagShort {@see $_tagShort $_tagShort }
* @property string|null $tagLong {@see $_tagLong $_tagLong }
* @property boolean $multiple {@see $_multiple $_multiple }
* @property boolean $isStoppingParse {@see $_isStoppingParse $_isStoppingParse}
*
* @package CommandLine\Argument\Option
*/
abstract class OptionAbstract extends ArgumentAbstract implements IArgumentOption {
/**
* @var string|null L'argument court (cas d'un seul "-"). Null si aucun.
*/
protected $_tagShort;
/**
* @var string L'argument long (cas d'un "--").
*/
protected $_tagLong;
/**
* @var boolean Est-ce que l'argument est autorisé plusieurs fois ?
*/
protected $_multiple = false;
/**
* @var boolean Est-ce que l'argument met fin au parsage ?
*/
protected $_isStoppingParse = false;
/**
* Crée un nouvel argument de type option.
*
* @param string $name Le nom.
* @param string|null $description La description.
* @param string|null $tagLong Le tag long.
* @param string|null $tagShort Le tag court.
*/
public function __construct ($name, $description, $tagLong = null, $tagShort = null) {
parent::__construct($name, $description);
$this->setTagLong($tagLong);
$this->setTagShort($tagShort);
}
/**
* Est-ce la valeur correspond au tag court ou long ?
*
* Utilisé par les classes enfants pour savoir si le tag correspond.
*
* @param string $arg La valeur à examiner.
*
* @return boolean True si le tag correspond, sinon False.
*/
protected function _parseTag($arg) {
if($this->hasTagShort()) {
if ($arg == '-'.$this->getTagShort())
return true;
}
return $arg == '--'.$this->getTagLong();
}
public function getTagShort() {
return $this->_tagShort;
}
/**
* Définit le tag court.
*
* @param string|null $tagShort Le tage court.
*
* @return $this
*
* @see $_tagShort
*/
public function setTagShort($tagShort = null) {
$this->_tagShort = $tagShort;
return $this;
}
/**
* Est-ce que l'argument existe en forme courte ?
*
* @return boolean True si existe en forme courte, sinon False.
*/
public function hasTagShort() {
return !is_null($this->_tagShort);
}
public function getTagLong() {
return $this->_tagLong;
}
/**
* Définit le tag long.
*
* Si non fourni, est déduit du {@see $_name nom de l'argument} :
* - Les "_" sont remplacés par "-"
* - Les lettres majuscules sont remplacées par "-" suivit de la lettre en minuscule
*
* @param string|null $tagLong Le tag long.
*
* @return $this
*
* @see $_tagLong
*/
public function setTagLong($tagLong = null) {
$this->_tagLong = $tagLong;
if(is_null($this->_tagLong)) {
$this->_tagLong = preg_replace_callback(
'/[A-Z_]/',
function ($matches) {
if($matches[0] == '_')
return '-';
else
return '-'.strtolower($matches[0]);
},
$this->getName()
);
}
return $this;
}
public function allowMultiple() {
return $this->_multiple;
}
/**
* Définit si l'argument est autorisé plusieurs fois ou non.
*
* @param boolean $multiple Argument autorisé plusieurs fois ?
*
* @return $this
*
* @throws InvalidArgument Si la valeur n'est pas un booléen
*
* @see $_optional
*/
public function setMultiple($multiple) {
if (!is_bool($multiple))
throw new InvalidArgument($multiple, 'La valeur n\'est pas un booléen');
$this->_multiple = $multiple;
return $this;
}
public function isStoppingParse() {
return $this->_isStoppingParse;
}
/**
* Définit si l'argument met fin au parsage ou non.
*
* @param boolean $stoppingParse Met fin au parsage ?
*
* @return $this
*
* @throws InvalidArgument Si la valeur n'est pas un booléen
*
* @see $_optional
*/
public function setStoppingParse($stoppingParse) {
if (!is_bool($stoppingParse))
throw new InvalidArgument($stoppingParse, 'La valeur n\'est pas un booléen');
$this->_isStoppingParse = $stoppingParse;
return $this;
}
}

@ -0,0 +1,84 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Option\Value
*/
namespace CommandLine\Argument\Option;
use Fidit\v3\Exception\InvalidArgument;
use CommandLine\Exception\IncorrectParse;
use CommandLine\Argument\IArgumentValueDescription;
use CommandLine\Argument\Parser\IValueParser;
use CommandLine\Argument\ParseResult;
/**
* Option contenant une valeur.
*
* @property IValueParser $valueParser Le parseur de valeur.
*
* @package CommandLine\Argument\Option
*/
class Value extends OptionAbstract implements IArgumentValueDescription {
/**
* @var IValueParser Parseur pour la valeur
*/
protected $_valueParser;
/**
* Crée un nouvel argument de type option.
*
* @param string $name Le nom.
* @param string|null $description La description.
* @param IValueParser $valueParser Le parseur de valeur.
* @param string|null $tagLong Le tag long.
* @param string|null $tagShort Le tag court.
*
* @throws \Fidit\v3\Exception\InvalidArgument Si l'un des paramètres n'est pas correct
*/
public function __construct ($name, $description, IValueParser $valueParser, $tagLong = null, $tagShort = null) {
parent::__construct($name, $description, $tagLong, $tagShort);
$this->setValueParser($valueParser);
}
public function parse ($args) {
try {
if(!$this->_parseTag($args[0]))
return null;
if(count($args) < 2 || is_null($args[1]))
throw new IncorrectParse($this,null, 'Seconde valeur de l\'argument manquante');
return new ParseResult($this->_valueParser->parseValue($args[1]), 2);
}
catch (InvalidArgument $e) {
throw IncorrectParse::createFromInvalidArgument($this, $e);
}
}
public function getValueDescription () {
return $this->_valueParser->getValueDescription();
}
/**
* Le parseur de valeur.
*
* @return IValueParser Le parseur.
*
* @see $_valueParser
*/
public function getValueParser() {
return $this->_valueParser;
}
/**
* Définit le parseur de valeur
*
* @param IValueParser $valueParser Le parseur
*
* @return $this
*
* @see $_valueParser
*/
public function setValueParser(IValueParser $valueParser) {
$this->_valueParser = $valueParser;
return $this;
}
}

@ -0,0 +1,85 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\ParseResult.
*/
namespace CommandLine\Argument;
use Fidit\v3\AutoProperty;
/**
* Résultat du parsage d'un argument
*
* @property int $consume {@see $_consume $_consume}
* @property mixed $value {@see $_value $_value }
*
* @package CommandLine\Argument
*/
class ParseResult extends AutoProperty {
/**
* @var int Le nombre d'argument consumé.
*/
protected $_consume;
/**
* @var mixed La valeur.
*/
protected $_value;
/**
* ArgumentParseResult constructor.
*
* @param mixed $value La valeur.
* @param int $consume Le nombre d'argument consumé.
*/
public function __construct ($value, $consume = 1) {
$this->setValue($value);
$this->setConsume($consume);
}
/**
* Le nombre d'argument consumé.
*
* @return int Le nombre d'argument consumé.
*
* @see $_consume
*/
public function getConsume() {
return $this->_consume;
}
/**
* Définit le nombre d'argument consumé.
*
* @param $consume int Le nombre d'argument consumé.
*
* @return $this
*
* @see $_consume
*/
public function setConsume($consume) {
$this->_consume = $consume;
return $this;
}
/**
* La valeur.
*
* @return mixed La valeur.
*
* @see $_value
*/
public function getValue() {
return $this->_value;
}
/**
* Définit les valeurs définies.
*
* @param mixed $value La valeur.
*
* @return $this
*
* @see $_value
*/
public function setValue($value) {
$this->_value = $value;
return $this;
}
}

@ -0,0 +1,32 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Parser\BooleanParser
*/
namespace CommandLine\Argument\Parser;
use Fidit\v3\Exception\InvalidArgument;
/**
* Parseur vers un booléen
*
* Les valeurs suivantes sont acceptées :
* - true , 1, oui, vrai
* - false, 0, non, faux
*
* @package CommandLine\Argument\Parser
*/
class BooleanParser implements IValueParser {
public function parseValue ($arg) {
if(!in_array($arg, array(
'true' , '1', 'oui', 'vrai',
'false', '0', 'non', 'faux',
)))
throw new InvalidArgument($arg, 'La valeur n\'est pas un booléen valide');
return in_array($arg, array('true' , '1', 'oui', 'vrai'));
}
public function getValueDescription () {
return 'boolean';
}
}

@ -0,0 +1,138 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Parser\DecimalParser
*/
namespace CommandLine\Argument\Parser;
use Fidit\v3\Exception\InvalidArgument;
/**
* Parseur vers un réel
*
* @property double|null $valueMin {@see $_valueMin $_valueMin}
* @property double|null $valueMax {@see $_valueMax $_valueMax}
*
* @package CommandLine\Argument\Parser
*/
class DecimalParser implements IValueParser {
/**
* @var double|null La valeur minimum autorisée. Null si pas de limite.
*/
protected $_valueMin = null;
/**
* @var double|null La valeur maximum autorisée. Null si pas de limite
*/
protected $_valueMax = null;
/**
* Crée un nouveau parseur
*
* @param double|null $valueMin La valeur minimum autorisée
* @param double|null $valueMax La valeur maximum autorisée
*
* @throws InvalidArgument Si l'un des paramètre est invalide.
*/
public function __construct ($valueMin = null, $valueMax = null) {
$this->setValueMin($valueMin);
$this->setValueMax($valueMax);
}
public function parseValue ($arg) {
if (!$this->_isDecimal($arg))
throw new InvalidArgument($arg, 'La valeur n\'est pas un réel valide');
$int = (int)$arg;
if ($this->hasValueMin()) {
if ($int < $this->getValueMin())
throw new InvalidArgument($int, 'La valeur est inférieure au minimum : ' . $this->getValueMin());
}
if ($this->hasValueMax()) {
if ($int > $this->getValueMax())
throw new InvalidArgument($int, 'La valeur est supérieur au maximum : ' . $this->getValueMax());
}
return $int;
}
protected function _isDecimal($val) {
if(!is_numeric($val))
return false;
return true;
}
public function getValueDescription () {
return ($this->hasValueMin() ? $this->getValueMin().' <= ' : '').'decimal'.($this->hasValueMax() ? ' <= '.$this->getValueMax() : '');
}
/**
* La valeur minimumm autorisée
*
* @return double|null La valeur minimum.
*
* @see $_valueMin
*/
public function getValueMin() {
return $this->_valueMin;
}
/**
* Définit la valeur minimum autorisée.
*
* @param double|null $valueMin La valeur minimum.
*
* @return $this
*
* @throws InvalidArgument Si la valeur minimum n'est ni null, ni un entier
*/
public function setValueMin($valueMin = null) {
if(!is_null($valueMin) && !$this->_isDecimal($valueMin))
throw new InvalidArgument($valueMin, 'La valeur n\'est pas un entier ou null');
$this->_valueMin = (int)$valueMin;
return $this;
}
/**
* Est-ce qu'il existe une limite minimum ?
*
* @return boolean True s'il existe une limite, sinon False
*/
public function hasValueMin() {
return !is_null($this->getValueMin());
}
/**
* La valeur maximum autorisée
*
* @return double|null La valeur maximum.
*
* @see $_valueMax
*/
public function getValueMax() {
return $this->_valueMax;
}
/**
* Définit la valeur maximum autorisée.
*
* @param double|null $valueMax La valeur maximum.
*
* @return $this
*
* @throws InvalidArgument Si la valeur maximum n'est ni null, ni un entier
*/
public function setValueMax($valueMax = null) {
if(!is_null($valueMax) && !$this->_isDecimal($valueMax))
throw new InvalidArgument($valueMax, 'La valeur n\'est pas un entier ou null');
$this->_valueMax = (int)$valueMax;
return $this;
}
/**
* Est-ce qu'il existe une limite maximum ?
*
* @return boolean True s'il existe une limite, sinon False
*/
public function hasValueMax() {
return !is_null($this->getValueMax());
}
}

@ -0,0 +1,75 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Parser\EnumParser
*/
namespace CommandLine\Argument\Parser;
use Fidit\v3\Exception\InvalidArgument;
/**
* Parseur vers une liste de valeurs possible (chaine de caractère).
*
* @property string[] $values {@see $_values $_values}
*
* @package CommandLine\Argument\Parser
*/
class EnumParser implements IValueParser {
/**
* @var string[] Liste des valeurs autorisées
*/
protected $_values;
/**
* Crée un nouveau parseur.
*
* @param string[] $values La liste des valeurs autorisées.
*
* @throws InvalidArgument Si l'un des paramètres n'est pas correct
*/
public function __construct ($values) {
$this->setValues($values);
}
public function parseValue ($arg) {
if(!in_array($arg, $this->_values))
throw new InvalidArgument($arg, 'La valeur ne fait partie de liste des valeurs autorisées : '.implode(', ', $this->getValues()));
return $arg;
}
public function getValueDescription () {
return 'enum('.implode(',', $this->getValues()).')';
}
/**
* La liste des valeurs autoriséees.
*
* @return string[] La liste des valeurs
*
* @see $_values
*/
public function getValues() {
return $this->_values;
}
/**
* Définit la liste des valeurs autorisées.
*
* @param string[] $values La liste des valeurs
*
* @return $this
*
* @throws InvalidArgument Si la liste n'est pas un tableau ou si celui-ci est vide
*
* @see $_values
*/
public function setValues($values) {
if(!is_array($values))
throw new InvalidArgument($values, 'La liste de valeurs n\'est pas un tableau');
if(count($values) == 0)
throw new InvalidArgument($values, 'La liste de valeurs doit avoir au moins un élément');
$this->_values = $values;
return $this;
}
}

@ -0,0 +1,32 @@
<?php
/**
* Déclare l'interface CommandLine\Argument\Parser\IValueParser
*/
namespace CommandLine\Argument\Parser;
use Fidit\v3\Exception\InvalidArgument;
/**
* Interface pour les parseurs
*
* @package CommandLine\Argument\Parser
*/
interface IValueParser {
/**
* Vérifie et transforme une valeur.
*
* @param string $val La valeur à transformer.
*
* @return mixed La valeur transformée.
*
* @throws InvalidArgument Si la valeur n'est pas valide.
*/
public function parseValue($val);
/**
* La description des contraintes de la valeur.
*
* @return string La description.
*/
public function getValueDescription();
}

@ -0,0 +1,141 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Parser\IntegerParser
*/
namespace CommandLine\Argument\Parser;
use Fidit\v3\Exception\InvalidArgument;
/**
* Parseur vers un entier.
*
* @property int|null $valueMin {@see $_valueMin $_valueMin}
* @property int|null $valueMax {@see $_valueMax $_valueMax}
*
* @package CommandLine\Argument\Parser
*/
class IntegerParser implements IValueParser {
/**
* @var int|null La valeur minimum autorisée. Null si pas de limite.
*/
protected $_valueMin = null;
/**
* @var int|null La valeur maximum autorisée. Null si pas de limite
*/
protected $_valueMax = null;
/**
* Crée un nouveau parseur
*
* @param int|null $valueMin La valeur minimum autorisée
* @param int|null $valueMax La valeur maximum autorisée
*
* @throws InvalidArgument Si l'un des paramètre est invalide.
*/
public function __construct ($valueMin = null, $valueMax = null) {
$this->setValueMin($valueMin);
$this->setValueMax($valueMax);
}
public function parseValue ($arg) {
if(!$this->_isInt($arg))
throw new InvalidArgument($arg, 'La valeur n\'est pas un entier valide');
$int = (int)$arg;
if($this->hasValueMin()) {
if($int < $this->getValueMin())
throw new InvalidArgument($int, 'La valeur est inférieure au minimum : '.$this->getValueMin());
}
if($this->hasValueMax()) {
if($int > $this->getValueMax())
throw new InvalidArgument($int, 'La valeur est supérieur au maximum : '.$this->getValueMax());
}
return $int;
}
protected function _isInt($val) {
if(!is_numeric($val))
return false;
if(floor($val) != $val)
return false;
return true;
}
public function getValueDescription () {
return ($this->hasValueMin() ? $this->getValueMin().' <= ' : '').'integer'.($this->hasValueMax() ? ' <= '.$this->getValueMax() : '');
}
/**
* La valeur minimumm autorisée
*
* @return int|null La valeur minimum.
*
* @see $_valueMin
*/
public function getValueMin() {
return $this->_valueMin;
}
/**
* Définit la valeur minimum autorisée.
*
* @param int|null $valueMin La valeur minimum.
*
* @return $this
*
* @throws InvalidArgument Si la valeur minimum n'est ni null, ni un entier
*/
public function setValueMin($valueMin = null) {
if(!is_null($valueMin) && !$this->_isInt($valueMin))
throw new InvalidArgument($valueMin, 'La valeur n\'est pas un entier ou null');
$this->_valueMin = (int)$valueMin;
return $this;
}
/**
* Est-ce qu'il existe une limite minimum ?
*
* @return boolean True s'il existe une limite, sinon False
*/
public function hasValueMin() {
return !is_null($this->getValueMin());
}
/**
* La valeur maximum autorisée
*
* @return int|null La valeur maximum.
*
* @see $_valueMax
*/
public function getValueMax() {
return $this->_valueMax;
}
/**
* Définit la valeur maximum autorisée.
*
* @param int|null $valueMax La valeur maximum.
*
* @return $this
*
* @throws InvalidArgument Si la valeur maximum n'est ni null, ni un entier
*/
public function setValueMax($valueMax = null) {
if(!is_null($valueMax) && !$this->_isInt($valueMax))
throw new InvalidArgument($valueMax, 'La valeur n\'est pas un entier ou null');
$this->_valueMax = (int)$valueMax;
return $this;
}
/**
* Est-ce qu'il existe une limite maximum ?
*
* @return boolean True s'il existe une limite, sinon False
*/
public function hasValueMax() {
return !is_null($this->getValueMax());
}
}

@ -0,0 +1,65 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Parser\RegexParser
*/
namespace CommandLine\Argument\Parser;
use Fidit\v3\Exception\InvalidArgument;
/**
* Parseur vers une chaine de caractère correspondant à un motif
*
* Renvoie la liste des groupes capturants
*
* @property string $regex {@see $_regex $_regex}
*
* @package CommandLine\Argument\Parser
*/
class RegexParser implements IValueParser {
/**
* @var string La regex à respecter
*/
protected $_regex = '';
/**
* Crée un nouveau parseur
*
* @param string $regex Le motif à respecter
*/
public function __construct ($regex) {
$this->setRegex($regex);
}
public function parseValue ($arg) {
if(!preg_match($this->regex, $arg, $matches))
throw new InvalidArgument($arg, 'La valeur ne correspond pas au motif attendu');
return $matches;
}
public function getValueDescription () {
return $this->getRegex();
}
/**
* Le motif à respecter
*
* @return string Le motif
*
* @see $_regex
*/
public function getRegex() {
return $this->_regex;
}
/**
* Modifie le motif à respecter
*
* @param string $regex Le nouveau motif
*
* @return $this
*/
public function setRegex($regex = null) {
$this->_regex = $regex;
return $this;
}
}

@ -0,0 +1,20 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Parser\StringParser
*/
namespace CommandLine\Argument\Parser;
/**
* Parseur vers une chaine de caractères
*
* @package CommandLine\Argument\Parser
*/
class StringParser implements IValueParser {
public function parseValue ($arg) {
return $arg;
}
public function getValueDescription () {
return 'string';
}
}

@ -0,0 +1,74 @@
<?php
/**
* Déclaration de CommandLine\Argument\Value\FixedValue
*/
namespace CommandLine\Argument\Value;
use CommandLine\Argument\IArgumentValueDescription;
use CommandLine\Argument\ParseResult;
/**
* Argument devant correspondre une valeur fixe
*
* @property string $value {@see $_value $_value}.
*
* @package CommandLine\Argument
*/
class FixedValue extends ValueAbstract implements IArgumentValueDescription {
/**
* @var string La valeur que doit avoir l'argument
*/
protected $_value;
/**
* Crée un nouvel argument de type valeur
*
* @param int $position La position
* @param string $varName Le nom de la variable
* @param string $value La valeur
* @param string|null $description La description
* @param boolean $optional Valeur optionnelle ?
*
* @throws \Fidit\v3\Exception\InvalidArgument Si l'un des paramètres n'est pas correct
*/
public function __construct ($varName, $value, $description, $optional = false) {
parent::__construct($value, $description, $optional);
$this->setVarName($varName);
$this->setValue($value);
}
public function parse ($args) {
if($args[0] == $this->getValue())
return new ParseResult($this->getValue(), 1);
return null;
}
public function getValueDescription () {
return '"'.$this->getValue().'"';
}
/**
* La valeur.
*
* @return string La valeur.
*
* @see $_value
*/
public function getValue() {
return $this->_value;
}
/**
* Définit la valeur
*
* @param string $value La valeur
*
* @return $this
*
* @see $_value
*/
public function setValue($value) {
$this->_value = $value;
return $this;
}
}

@ -0,0 +1,31 @@
<?php
/**
* Déclaration de l'interface CommandLine\Argument\Option\IArgumentValue
*/
namespace CommandLine\Argument\Value;
use CommandLine\Argument\IArgument;
/**
* Interface à implémenter si l'argument est de type "valeur"
*
* @package CommandLine\Argument\value
*/
interface IArgumentValue extends IArgument {
/**
* Le nombre minimum d'occurence.
*
* Généralement 0 (falcultatif) ou 1 (obligatoire).
*
* @return int Le nombre minimum d'occurence
*/
public function getOccurMin();
/**
* Le nombre maximum d'occurence.
*
* Généralement 1 ou Null (illimité).
*
* @return int|null Le nombre maximum d'occurence
*/
public function getOccurMax();
}

@ -0,0 +1,76 @@
<?php
/**
* Déclaration de CommandLine\Argument\Value\Value
*/
namespace CommandLine\Argument\Value;
use Fidit\v3\Exception\InvalidArgument;
use CommandLine\Exception\IncorrectParse;
use CommandLine\Argument\IArgumentValueDescription;
use CommandLine\Argument\Parser\IValueParser;
use CommandLine\Argument\ParseResult;
/**
* Argument de type "valeur"
*
* @property IValueParser $valueParser Le parseur de valeur.
*
* @package CommandLine\Argument\Value
*/
class Value extends ValueAbstract implements IArgumentValueDescription {
/**
* @var IValueParser Parseur pour la valeur
*/
protected $_valueParser;
/**
* Crée un nouvel argument de type valeur
*
* @param string $name Le nom
* @param string|null $description La description
* @param IValueParser $valueParser Le parseur de valeur.
* @param boolean $optional Valeur optionnelle ?
*/
public function __construct ($name, $description, IValueParser $valueParser, $optional = false) {
parent::__construct($name, $description, $optional);
$this->setValueParser($valueParser);
}
public function parse ($args) {
try {
return new ParseResult($this->_valueParser->parseValue($args[0]), 1);
}
catch(InvalidArgument $e) {
throw IncorrectParse::createFromInvalidArgument($this, $e);
}
}
public function getValueDescription () {
return $this->_valueParser->getValueDescription();
}
/**
* Le parseur de valeur.
*
* @return IValueParser Le parseur.
*
* @see $_valueParser
*/
public function getValueParser() {
return $this->_valueParser;
}
/**
* Définit le parseur de valeur
*
* @param IValueParser $valueParser Le parseur
*
* @return $this
*
* @see $_valueParser
*/
public function setValueParser(IValueParser $valueParser) {
$this->_valueParser = $valueParser;
return $this;
}
}

@ -0,0 +1,117 @@
<?php
/**
* Déclaration de la classe CommandLine\Argument\Value\ValueArgument.
*/
namespace CommandLine\Argument\Value;
use Fidit\v3\Exception\InvalidArgument;
use CommandLine\Argument\ArgumentAbstract;
use CommandLine\Argument\Value\IArgumentValue;
/**
* Classe abstraite pour les paramètres de type "valeur"
*
* @property int $occurMin {@see $_occurMin $_occurMin}
* @property int|null $occurMax {@see $_occurMax $_occurMax}
*
* @package CommandLine\Argument\Value
*/
abstract class ValueAbstract extends ArgumentAbstract implements IArgumentValue {
/**
* @var int Le nombre minimum d'occurence.
*/
protected $_occurMin = 1;
/**
* @var int|null Le nombre maximum d'occurence.
*/
protected $_occurMax = 1;
/**
* Crée un nouvel argument.
*
* @param string $name Le nom de l'argument
* @param string|null $description La description de l'argument
* @param boolean $optional Argument optionel ?
*/
protected function __construct ($name, $description, $optional = false) {
parent::__construct($name, $description);
$this->setOptional($optional);
}
public function getOccurMin() {
return $this->_occurMin;
}
/**
* Définit le nombre minimum d'occurence.
*
* @param int $occurMin Le nombre minimum
*
* @return $this
*
* @throws InvalidArgument Si la valeur n'est pas un entier positif.
*
* @see $_occurMin
*/
public function setOccurMin($occurMin) {
if (!is_numeric($occurMin))
throw new InvalidArgument($occurMin, 'La valeur n\'est pas un entier');
if (floor($occurMin) != $occurMin)
throw new InvalidArgument($occurMin, 'La valeur n\'est pas un entier');
$int = (int)$occurMin;
if($int < 0)
throw new InvalidArgument($occurMin, 'La valeur n\'est pas un entier positif');
$this->_occurMin = $int;
return $this;
}
/**
* Définit si l'argument est facultatif ou non.
*
* @param bool $optional Argument facultatif ?
*
* @return $this
*/
public function setOptional($optional = false) {
try {
$this->setOccurMin($optional ? 0 : 1);
}
catch(InvalidArgument $e) {}
return $this;
}
public function getOccurMax() {
return $this->_occurMax;
}
/**
* Définit le nombre mawimum d'occurence.
*
* @param int|null $occurMax Le nombre maximum
*
* @return $this
*
* @throws InvalidArgument Si la valeur n'est pas Null ou un entier strictement positif.
*
* @see $_occurMax
*/
public function setOccurMax($occurMax) {
if (!is_null($occurMax)) {
if (!is_numeric($occurMax))
throw new InvalidArgument($occurMax, 'La valeur n\'est pas un entier');
if (floor($occurMax) != $occurMax)
throw new InvalidArgument($occurMax, 'La valeur n\'est pas un entier');
$occurMax = (int)$occurMax;
if ($occurMax <= 0)
throw new InvalidArgument($occurMax, 'La valeur n\'est pas un entier strictement positif');
}
$this->_occurMax = $occurMax;
return $this;
}
}

@ -0,0 +1,871 @@
<?php
/**
* Déclaration de la classe CommandLine\CommandLine
*/
namespace CommandLine;
use CommandLine\Argument\IArgument;
use CommandLine\Argument\Option\OptionAbstract;
use CommandLine\Argument\Value\ValueAbstract;
use CommandLine\Exception\IException;
use CommandLine\Exception\TooMuchValues;
use CommandLine\Argument\IArgumentValueDescription;
use CommandLine\Argument\Option\IArgumentOption;
use CommandLine\Argument\Option\IArgumentOptionSecondary;
use CommandLine\Argument\Value\IArgumentValue;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionException;
use stdClass;
/**
* Une ligne de commande (description, arguments, etc.)
*
* A la base, chaque type d'argument doit au minimum implémenter {@see IArgument}.
* Mais il faut implémenter l'un des deux grands types d'arguments :
* - {@see IArgumentOption} (implémentation de base avec {@see OptionAbstract}) Options : commencent par un "-" (version courte) ou "--" (version longue)
* - {@see IArgumentValue} (implémentation de base avec {@see ValueAbstract} ) Valeurs : une valeur directe
*
* Le traitement de la ligne de commande est généralement faite dans cet ordre :
* - Création ligne de commande : définition des propriétés du script lui-même (nom, description, etc.)
* - Définition des arguments
* - Parsage des arguments du script : {@see CommandLine::parse() fonction parse}
* - Traitement des valeurs extraites des arguments du script (résultat de la {@see CommandLine::parse() fonction parse})
*
* @package CommandLine
*/
class CommandLine {
/**
* Chaine de caractère se substituant à la tabulation pour la construction de l'aide (help).
*/
const TAB = ' ';
/**
* Nom de l'argument auto-généré pour l'affichage de l'aide.
*
* @see CommandLine::addDefaultArguments()
* @see CommandLine::generateHelp()
*/
const ARGUMENT_OPTION_HELP = 'help';
/**
* Nom de l'argument auto-généré pour l'affichage de la version.
*
* @see CommandLine::addDefaultArguments()
* @see CommandLine::getVersion()
*/
const ARGUMENT_OPTION_VERSION = 'version';
/**
* @var string|null La commande de lancement du script (si non fourni, égal au {@see CommandeLine::_programName nom du programme})
*/
protected $_command;
/**
* @var string Le nom du programme
*/
protected $_programName;
/**
* @var string Description du programme
*/
protected $_description;
/**
* @var string|null La version du programme.
*/
protected $_version;
/**
* @var IArgumentOption[] Liste des options de la ligne de commande
*/
protected $_arguments_options = array();
/**
* @var IArgumentValue[] Liste _ordonnée_ des arguments "valeur" de la ligne de commande
*/
protected $_arguments_values = array();
/**
* Crée un ligne de commande
*
* @param string $programName Le nom du programme
* @param string $mainDescription La description du programme
* @param string|null $command La commande de lancement du programme
* @param string|null $version La version du programme
*
* @throws InvalidArgumentException
*/
public function __construct ($programName, $mainDescription, $command = null, $version = null) {
$this->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 = '<inconnu>';
}
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)');
}
}
}
}

@ -0,0 +1,12 @@
<?php
/**
* Déclaration de l'interface d'exception CommandLine\Exception\IException.
*/
namespace CommandLine\Exception;
/**
* Interface pour toutes les exceptions du module.
*
* @package CommandLine\Exception
*/
interface IException {}

@ -0,0 +1,21 @@
<?php
/**
* Déclaration de l'exception CommandLine\Exception\IncorrectParse.
*/
namespace CommandLine\Exception;
use CommandLine\Argument\IArgument;
use LogicException;
/**
* Exception levée quand le parsage d'un argument échoue
*
* Exemples :
* - Valeur incorrecte
* - Valeur manquante
*
* @package CommandLine\Exception
*
* @see IArgument::parse()
*/
class IncorrectParse extends LogicException implements IException {}

@ -0,0 +1,17 @@
<?php
/**
* Déclaration de l'exception CommandLine\Exception\MissingArgument
*/
namespace CommandLine\Exception;
use CommandLine\Solution;
use RuntimeException;
/**
* Exception levée quand un argument est manquant lors d'un parsage d'une solution
*
* @package CommandLine\Exception
*
* @see Solution::parseExplicit()
*/
class MissingArgument extends RuntimeException implements IException {}

@ -0,0 +1,14 @@
<?php
/**
* Déclaration de l'exception CommandLine\Exception\TooMushValues
*/
namespace CommandLine\Exception;
use RuntimeException;
/**
* Exception levée quand il y a des valeurs en trop lors d'un parsage d'une solution
*
* @package CommandLine\Exception
*/
class TooMuchValues extends RuntimeException implements IException {}

@ -0,0 +1,96 @@
# [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)
## Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
### Section 1 Definitions.
Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
Licensor means the individual(s) or entity(ies) granting rights under this Public License.
Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
### Section 2 Scope.
License grant.
Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
reproduce and Share the Licensed Material, in whole or in part; and
produce, reproduce, and Share Adapted Material.
Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
Term. The term of this Public License is specified in Section 6(a).
Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
Downstream recipients.
Offer from the Licensor Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
Other rights.
Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
Patent and trademark rights are not licensed under this Public License.
To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
### Section 3 License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
Attribution.
If You Share the Licensed Material (including in modified form), You must:
retain the following if it is supplied by the Licensor with the Licensed Material:
identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
a copyright notice;
a notice that refers to this Public License;
a notice that refers to the disclaimer of warranties;
a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License.
### Section 4 Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
### Section 5 Disclaimer of Warranties and Limitation of Liability.
Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
### Section 6 Term and Termination.
This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
### Section 7 Other Terms and Conditions.
The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
### Section 8 Interpretation.
For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.

@ -0,0 +1,2 @@
# PHPCommandLine
Command line management library in PHP (CLI)

@ -0,0 +1,279 @@
<?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…
Cancel
Save