Newer
Older
DirtyScripts / ReportToolz / classes / CommandLineArgumentDefinition.php
root on 12 Nov 2019 11 KB added some stuff
  1. <?php
  2. /**
  3. * Defines list and formats of command line arguments
  4. *
  5. * @author Patrick Forget <patforg at webtrendi.com>
  6. */
  7.  
  8. namespace Clapp;
  9.  
  10. /**
  11. * Defines list and formats of command line arguments
  12. *
  13. * @author Patrick Forget <patforg at webtrendi.com>
  14. */
  15. class CommandLineArgumentDefinition
  16. {
  17.  
  18. /**
  19. * @var array
  20. */
  21. private $definitions = array();
  22.  
  23. /**
  24. * long names as keys and array of properties as values
  25. *
  26. * properties are as follows
  27. * * string "shortName" one letter char to the corresponding short name
  28. * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed
  29. * * mixed "parameterType" false if paramters are not alloweda value,
  30. * otherwise a string with the value "integer" or "string"
  31. * * string "description" description of the parameter
  32. * @var array
  33. */
  34. private $longNames = array();
  35. /**
  36. * list of short names as keys and their long name equivalent as values
  37. * @var array
  38. */
  39. private $shortNames = array();
  40.  
  41. /**
  42. * Flag if arguments have been parsed in to params
  43. * @var boolean
  44. */
  45. private $isParsed = false;
  46.  
  47. /**
  48. * class constructor
  49. *
  50. * @author Patrick Forget <patforg at webtrendi.com>
  51. *
  52. * @param array $definitions contains list of allowed parameters
  53. * the key is the long name of the parameter followed by a pipe (|)
  54. * then a single character specifying the short name.
  55. *
  56. * If the parameter allows for arguments then an equal sign (=)
  57. * follows and then the type of paramter.
  58. *
  59. * Allowed types are either i, int or integer for integer types
  60. * and s, str or string for string types.
  61. *
  62. * If a parameter can appear more than once the last character of
  63. * the key should be a plus character (+).
  64. *
  65. * The value of the entry is the definition of what the paramter
  66. * does.
  67. */
  68. public function __construct($definitions)
  69. {
  70. if (is_array($definitions)) {
  71. $this->definitions = $definitions;
  72. } //if
  73. } // __construct()
  74.  
  75. /**
  76. * checks if parameter is allowed
  77. *
  78. * @author Patrick Forget <patforg at webtrendi.com>
  79. *
  80. * @param string $name either short or long name of the parameter to check
  81. *
  82. * @return boolean true if definition exisits, false otherwise
  83. */
  84. public function paramExists($name)
  85. {
  86. if (!$this->isParsed) {
  87. $this->parseDefinitions();
  88. } //if
  89.  
  90. if (strlen($name) == 1) {
  91. return isset($this->shortNames[$name]);
  92. } else {
  93. return isset($this->longNames[$name]);
  94. } //if
  95. } // paramExists($name)
  96.  
  97. /**
  98. * checks if parameter allows a value if so what type
  99. *
  100. * @author Patrick Forget <patforg at webtrendi.com>
  101. *
  102. * @param string $name either short or long name of the parameter to check
  103. *
  104. * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows
  105. */
  106. public function allowsValue($name)
  107. {
  108. if (!$this->isParsed) {
  109. $this->parseDefinitions();
  110. } //if
  111.  
  112. $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
  113.  
  114. if (isset($this->longNames[$longName])) {
  115. return $this->longNames[$longName]['parameterType'] !== false ? true : false;
  116. } else {
  117. return false;
  118. } //if
  119. } // allowsValue()
  120. /**
  121. * returns the type of value allowed
  122. *
  123. * @author Patrick Forget <patforg at webtrendi.com>
  124. */
  125. public function getValueType($name)
  126. {
  127. if (!$this->isParsed) {
  128. $this->parseDefinitions();
  129. } //if
  130.  
  131. $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
  132.  
  133. if (isset($this->longNames[$longName]['parameterType'])
  134. && $this->longNames[$longName]['parameterType'] !== false) {
  135. return $this->longNames[$longName]['parameterType'];
  136. } else {
  137. return '';
  138. } //if
  139. } // getValueType()
  140.  
  141. /**
  142. * checks if pamultiple instance of parameter are allowed
  143. *
  144. * @author Patrick Forget <patforg at webtrendi.com>
  145. *
  146. * @param string $name either short or long name of the parameter to check
  147. *
  148. * @return boolean false if parameter doesn't allow multiple values, true if it does
  149. */
  150. public function allowsMultiple($name)
  151. {
  152. if (!$this->isParsed) {
  153. $this->parseDefinitions();
  154. } //if
  155.  
  156. $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
  157.  
  158. if (isset($this->longNames[$longName])) {
  159. return $this->longNames[$longName]['isMultipleAllowed'];
  160. } else {
  161. return false;
  162. } //if
  163. } // allowsMultiple()
  164.  
  165. /**
  166. * retreive short name of a parameter using its long name
  167. *
  168. * @author Patrick Forget <patforg at webtrendi.com>
  169. *
  170. * @param string $name long name of the parameter to check
  171. *
  172. * @return string character of the short name or null if it doesn't exist
  173. */
  174. public function getShortName($name)
  175. {
  176. if (!$this->isParsed) {
  177. $this->parseDefinitions();
  178. } //if
  179.  
  180. if (isset($this->longNames[$name])) {
  181. return $this->longNames[$name]['shortName'];
  182. } else {
  183. return null;
  184. } //if
  185. } // getShortName($name)
  186. /**
  187. * retreive long name of a parameter using its short name
  188. *
  189. * @author Patrick Forget <patforg at webtrendi.com>
  190. *
  191. * @param string $name short name of the parameter to check
  192. *
  193. * @return string long name or null if it doesn't exist
  194. */
  195. public function getLongName($name)
  196. {
  197. if (!$this->isParsed) {
  198. $this->parseDefinitions();
  199. } //if
  200.  
  201. if (isset($this->shortNames[$name])) {
  202. return $this->shortNames[$name];
  203. } else {
  204. return null;
  205. } //if
  206. } // getLongName($name)
  207.  
  208. /**
  209. * retreive description of a paramter
  210. *
  211. * @author Patrick Forget <patforg at webtrendi.com>
  212. *
  213. * @param string $name either short or long name of the parameter to check
  214. *
  215. * @return string description or null if it doesn't exist
  216. */
  217. public function getDescription($name)
  218. {
  219. if (!$this->isParsed) {
  220. $this->parseDefinitions();
  221. } //if
  222.  
  223. $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name);
  224.  
  225. if (isset($this->longNames[$longName])) {
  226. return $this->longNames[$longName]['description'];
  227. } else {
  228. return null;
  229. } //if
  230. } // getDescription()
  231. /**
  232. * builds a usage definition based on definition of params
  233. *
  234. * @author Patrick Forget <patforg at webtrendi.com>
  235. */
  236. public function getUsage()
  237. {
  238. if (!$this->isParsed) {
  239. $this->parseDefinitions();
  240. } //if
  241.  
  242. /* build list of argument names and calculate
  243. the first column width so we can pad to
  244. align definitions */
  245. $firstCol = array();
  246. $longestDef = 0;
  247. foreach (array_keys($this->longNames) as $longName) {
  248. ob_start();
  249. echo "--{$longName}|-{$this->getShortName($longName)}";
  250.  
  251. if ($this->allowsValue($longName)) {
  252. echo "={$this->getValueType($longName)}";
  253. } //if
  254.  
  255. if ($this->allowsMultiple($longName)) {
  256. echo "+";
  257. } //if
  258.  
  259. $defLength = ob_get_length();
  260.  
  261. $longestDef = max($longestDef, $defLength);
  262.  
  263. $firstCol[$longName] = ob_get_contents();
  264. ob_end_clean();
  265.  
  266. } //foreach
  267.  
  268. $firstColMaxWidth = $longestDef + 4;
  269.  
  270. ob_start();
  271.  
  272. foreach ($firstCol as $longName => $def) {
  273. $currentDefLength = strlen($def);
  274.  
  275. $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength);
  276.  
  277. echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL;
  278. } //foreach
  279.  
  280. echo PHP_EOL;
  281.  
  282. $usage = ob_get_contents();
  283. ob_end_clean();
  284. return $usage;
  285.  
  286. } // getUsage()
  287.  
  288. /**
  289. * parses the definitions
  290. *
  291. * @author Patrick Forget <patforg at webtrendi.com>
  292. */
  293. protected function parseDefinitions()
  294. {
  295. foreach ($this->definitions as $nameDef => $description) {
  296. $nameParts = explode("|", $nameDef);
  297.  
  298. if (sizeof($nameParts) !== 2) {
  299. throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\"");
  300. } //if
  301.  
  302. $longName = $nameParts[0];
  303. $isMulti = false;
  304. $parameterType = false;
  305.  
  306. $shortNameLength = strlen($nameParts[1]);
  307.  
  308. if ($shortNameLength == 1) {
  309. $shortName = $nameParts[1];
  310. } else {
  311. $secondChar = substr($nameParts[1], 1, 1);
  312.  
  313. switch ($secondChar) {
  314. case '=':
  315. $shortNameParts = explode("=", $nameParts[1]);
  316.  
  317. $shortName = $shortNameParts[0];
  318. $parameterTypeString = $shortNameParts[1];
  319.  
  320. if (substr($parameterTypeString, -1) === '+') {
  321. $isMulti = true;
  322. $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing +
  323. } //if
  324.  
  325. switch ($parameterTypeString) {
  326. case 'i':
  327. case 'int':
  328. case 'integer':
  329. $parameterType = 'integer';
  330. break;
  331. case 's':
  332. case 'str':
  333. case 'string':
  334. $parameterType = 'string';
  335. break;
  336. default:
  337. throw new \UnexpectedValueException("Expecting parameter type".
  338. " to be either integer or string");
  339. break;
  340. } //switch
  341.  
  342. break;
  343. case '+':
  344. if ($shortNameLength > 2) {
  345. throw new \UnexpectedValueException("Multiple flag charachter (+)".
  346. " should be last character in definition");
  347. } //if
  348.  
  349. $shortName = substr($nameParts[1], 0, 1);
  350. $isMulti = true;
  351.  
  352. break;
  353. default:
  354. throw new \UnexpectedValueException("Expecting short name definition to be a single char");
  355. break;
  356. } // switch
  357.  
  358. } //if
  359.  
  360. if (isset($this->longNames[$longName])) {
  361. throw new \UnexpectedValueException("Cannot redefine long name {$longName}");
  362. } //if
  363.  
  364. if (isset($this->shortNames[$shortName])) {
  365. throw new \UnexpectedValueException("Cannot redefine short name {$shortName}");
  366. } //if
  367.  
  368. $this->longNames[$longName] = array(
  369. 'shortName' => $shortName,
  370. 'isMultipleAllowed' => $isMulti,
  371. 'parameterType' => $parameterType,
  372. 'description' => $description
  373. );
  374.  
  375. $this->shortNames[$shortName] = $longName;
  376.  
  377. } //foreach
  378.  
  379. $this->isParsed = true;
  380. } // parseDefinitions()
  381. }
Buy Me A Coffee