<?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() }