- <?php
- /**
- * Defines list and formats of command line arguments
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- */
-
- namespace Clapp;
-
- /**
- * Defines list and formats of command line arguments
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- */
- class CommandLineArgumentDefinition
- {
-
- /**
- * @var array
- */
- private $definitions = array();
-
- /**
- * long names as keys and array of properties as values
- *
- * properties are as follows
- * * string "shortName" one letter char to the corresponding short name
- * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed
- * * mixed "parameterType" false if paramters are not alloweda value,
- * otherwise a string with the value "integer" or "string"
- * * string "description" description of the parameter
- * @var array
- */
- private $longNames = array();
-
- /**
- * list of short names as keys and their long name equivalent as values
- * @var array
- */
- private $shortNames = array();
-
- /**
- * Flag if arguments have been parsed in to params
- * @var boolean
- */
- private $isParsed = false;
-
- /**
- * class constructor
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param array $definitions contains list of allowed parameters
- * the key is the long name of the parameter followed by a pipe (|)
- * then a single character specifying the short name.
- *
- * If the parameter allows for arguments then an equal sign (=)
- * follows and then the type of paramter.
- *
- * Allowed types are either i, int or integer for integer types
- * and s, str or string for string types.
- *
- * If a parameter can appear more than once the last character of
- * the key should be a plus character (+).
- *
- * The value of the entry is the definition of what the paramter
- * does.
- */
- public function __construct($definitions)
- {
- if (is_array($definitions)) {
- $this->definitions = $definitions;
- } //if
- } // __construct()
-
- /**
- * checks if parameter is allowed
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param string $name either short or long name of the parameter to check
- *
- * @return boolean true if definition exisits, false otherwise
- */
- public function paramExists($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- if (strlen($name) == 1) {
- return isset($this->shortNames[$name]);
- } else {
- return isset($this->longNames[$name]);
- } //if
- } // paramExists($name)
-
-
- /**
- * checks if parameter allows a value if so what type
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param string $name either short or long name of the parameter to check
- *
- * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows
- */
- public function allowsValue($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
-
- if (isset($this->longNames[$longName])) {
- return $this->longNames[$longName]['parameterType'] !== false ? true : false;
- } else {
- return false;
- } //if
- } // allowsValue()
-
- /**
- * returns the type of value allowed
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- */
- public function getValueType($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
-
- if (isset($this->longNames[$longName]['parameterType'])
- && $this->longNames[$longName]['parameterType'] !== false) {
- return $this->longNames[$longName]['parameterType'];
- } else {
- return '';
- } //if
- } // getValueType()
-
-
- /**
- * checks if pamultiple instance of parameter are allowed
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param string $name either short or long name of the parameter to check
- *
- * @return boolean false if parameter doesn't allow multiple values, true if it does
- */
- public function allowsMultiple($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
-
- if (isset($this->longNames[$longName])) {
- return $this->longNames[$longName]['isMultipleAllowed'];
- } else {
- return false;
- } //if
- } // allowsMultiple()
-
- /**
- * retreive short name of a parameter using its long name
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param string $name long name of the parameter to check
- *
- * @return string character of the short name or null if it doesn't exist
- */
- public function getShortName($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- if (isset($this->longNames[$name])) {
- return $this->longNames[$name]['shortName'];
- } else {
- return null;
- } //if
- } // getShortName($name)
-
- /**
- * retreive long name of a parameter using its short name
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param string $name short name of the parameter to check
- *
- * @return string long name or null if it doesn't exist
- */
- public function getLongName($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- if (isset($this->shortNames[$name])) {
- return $this->shortNames[$name];
- } else {
- return null;
- } //if
- } // getLongName($name)
-
- /**
- * retreive description of a paramter
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- *
- * @param string $name either short or long name of the parameter to check
- *
- * @return string description or null if it doesn't exist
- */
- public function getDescription($name)
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
-
- if (isset($this->longNames[$longName])) {
- return $this->longNames[$longName]['description'];
- } else {
- return null;
- } //if
- } // getDescription()
-
- /**
- * builds a usage definition based on definition of params
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- */
- public function getUsage()
- {
- if (!$this->isParsed) {
- $this->parseDefinitions();
- } //if
-
- /* build list of argument names and calculate
- the first column width so we can pad to
- align definitions */
- $firstCol = array();
- $longestDef = 0;
- foreach (array_keys($this->longNames) as $longName) {
- ob_start();
- echo "--{$longName}|-{$this->getShortName($longName)}";
-
- if ($this->allowsValue($longName)) {
- echo "={$this->getValueType($longName)}";
- } //if
-
- if ($this->allowsMultiple($longName)) {
- echo "+";
- } //if
-
- $defLength = ob_get_length();
-
- $longestDef = max($longestDef, $defLength);
-
- $firstCol[$longName] = ob_get_contents();
- ob_end_clean();
-
- } //foreach
-
- $firstColMaxWidth = $longestDef + 4;
-
- ob_start();
-
- foreach ($firstCol as $longName => $def) {
- $currentDefLength = strlen($def);
-
- $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength);
-
- echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL;
- } //foreach
-
- echo PHP_EOL;
-
- $usage = ob_get_contents();
- ob_end_clean();
-
- return $usage;
-
- } // getUsage()
-
-
- /**
- * parses the definitions
- *
- * @author Patrick Forget <patforg at webtrendi.com>
- */
- protected function parseDefinitions()
- {
- foreach ($this->definitions as $nameDef => $description) {
- $nameParts = explode("|", $nameDef);
-
- if (sizeof($nameParts) !== 2) {
- throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\"");
- } //if
-
- $longName = $nameParts[0];
- $isMulti = false;
- $parameterType = false;
-
- $shortNameLength = strlen($nameParts[1]);
-
- if ($shortNameLength == 1) {
- $shortName = $nameParts[1];
- } else {
- $secondChar = substr($nameParts[1], 1, 1);
-
- switch ($secondChar) {
- case '=':
- $shortNameParts = explode("=", $nameParts[1]);
-
- $shortName = $shortNameParts[0];
- $parameterTypeString = $shortNameParts[1];
-
- if (substr($parameterTypeString, -1) === '+') {
- $isMulti = true;
- $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing +
- } //if
-
- switch ($parameterTypeString) {
- case 'i':
- case 'int':
- case 'integer':
- $parameterType = 'integer';
- break;
- case 's':
- case 'str':
- case 'string':
- $parameterType = 'string';
- break;
- default:
- throw new \UnexpectedValueException("Expecting parameter type".
- " to be either integer or string");
- break;
- } //switch
-
- break;
- case '+':
- if ($shortNameLength > 2) {
- throw new \UnexpectedValueException("Multiple flag charachter (+)".
- " should be last character in definition");
- } //if
-
- $shortName = substr($nameParts[1], 0, 1);
- $isMulti = true;
-
- break;
- default:
- throw new \UnexpectedValueException("Expecting short name definition to be a single char");
- break;
- } // switch
-
- } //if
-
- if (isset($this->longNames[$longName])) {
- throw new \UnexpectedValueException("Cannot redefine long name {$longName}");
- } //if
-
- if (isset($this->shortNames[$shortName])) {
- throw new \UnexpectedValueException("Cannot redefine short name {$shortName}");
- } //if
-
- $this->longNames[$longName] = array(
- 'shortName' => $shortName,
- 'isMultipleAllowed' => $isMulti,
- 'parameterType' => $parameterType,
- 'description' => $description
- );
-
- $this->shortNames[$shortName] = $longName;
-
- } //foreach
-
- $this->isParsed = true;
- } // parseDefinitions()
- }