Newer
Older
DirtyScripts / ReportToolz / classes / CommandArgumentFilter.php
root on 12 Nov 2019 11 KB added some stuff
  1. <?php
  2. /**
  3. * Filters an array and extracts and validates command line arguments
  4. *
  5. * @author Patrick Forget <patforg at webtrendi.com>
  6. */
  7.  
  8. namespace Clapp;
  9.  
  10. /**
  11. * Filters an array and extracts and validates command line arguments
  12. *
  13. * @author Patrick Forget <patforg at webtrendi.com>
  14. */
  15. class CommandArgumentFilter
  16. {
  17. /**
  18. * Command line arguments
  19. * @var array
  20. */
  21. private $arguments = array();
  22. /**
  23. * Definition of allowed parameters
  24. * @var \Clapp\CommandLineArgumentDefinition
  25. */
  26. private $definitions = null;
  27.  
  28. /**
  29. * Flag if arguments have been parsed in to params
  30. * @var boolean
  31. */
  32. private $parsed = false;
  33.  
  34. /**
  35. * Parsed params
  36. * @var array
  37. */
  38. private $params = array();
  39.  
  40. /**
  41. * Trailing values
  42. * @var string
  43. */
  44. private $trailingValues = "";
  45. /**
  46. * program name
  47. * @var string
  48. */
  49. private $programName = "";
  50.  
  51. /**
  52. * class constructor
  53. *
  54. * @author Patrick Forget <patforg at webtrendi.com>
  55. *
  56. * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters
  57. * @param array $args list of arguments to filter.
  58. */
  59. public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args)
  60. {
  61. if (is_array($args)) {
  62. $this->arguments = $args;
  63. } //if
  64.  
  65. $this->definitions = $definitions;
  66. } // __construct()
  67.  
  68. /**
  69. * returns parameter matching provided name
  70. *
  71. * @author Patrick Forget <patforg at webtrendi.com>
  72. *
  73. * @param string name of the paramter to retreive
  74. *
  75. * @return mixed if param the param appears only once the method will
  76. * return 1 if the parameter doesn't take a value. The specified value
  77. * for that param will returned if it does take value.
  78. *
  79. * If many occurence of the param appear the number of occurences will
  80. * be returned for params that do not take values. An array of values
  81. * will be returned for the parameters that do take values.
  82. *
  83. * If the parameter is not present null if it takes a value and false if
  84. * it's not present and doesn't allow values
  85. */
  86. public function getParam($name)
  87. {
  88. if (!$this->parsed) {
  89. $this->parseParams();
  90. } //if
  91.  
  92. $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name;
  93. if (isset($this->params[$longName])) {
  94. return $this->params[$longName];
  95. } else {
  96. if ($this->definitions->allowsValue($longName)) {
  97. return null;
  98. } else {
  99. return false;
  100. } //if
  101. } //if
  102.  
  103. } // getParam()
  104.  
  105. /**
  106. * retreive the program name
  107. *
  108. * @author Patrick Forget <patforg at webtrendi.com>
  109. */
  110. public function getProgramName()
  111. {
  112. if (!$this->parsed) {
  113. $this->parseParams();
  114. } //if
  115.  
  116. return $this->programName;
  117. } // getProgramName()
  118. /**
  119. * retreive the trailing values
  120. *
  121. * @author Patrick Forget <patforg at webtrendi.com>
  122. */
  123. public function getTrailingValues()
  124. {
  125. if (!$this->parsed) {
  126. $this->parseParams();
  127. } //if
  128.  
  129. return $this->trailingValues;
  130. } // getTrailingValues()
  131.  
  132. /**
  133. * extracts params from arguments
  134. *
  135. * @author Patrick Forget <patforg at webtrendi.com>
  136. */
  137. protected function parseParams()
  138. {
  139.  
  140. $argumentStack = $this->arguments;
  141.  
  142. $expectingValue = false;
  143. $currentLongName = null;
  144. $currentValue = null;
  145. $trailingValues = "";
  146. $endOfDashedArguments = false;
  147. $addParam = false;
  148. $argumentsLeft = sizeof($argumentStack);
  149. $multiShortParams = array();
  150.  
  151. $this->programName = array_shift($argumentStack); // remove first argument which is the program name
  152.  
  153. while ($currentArgument = array_shift($argumentStack)) {
  154. $argumentsLeft--;
  155. $currentArgumentLength = strlen($currentArgument);
  156.  
  157. // arguments that don't start with a dash
  158. if (substr($currentArgument, 0, 1) !== '-') {
  159. if ($expectingValue) {
  160. $currentValue = $currentArgument;
  161. $addParam = true;
  162. } else {
  163. $trailingValues .= " ". $currentArgument;
  164. $endOfDashedArguments = true;
  165. } //if
  166.  
  167. // double dash detected
  168. } elseif (substr($currentArgument, 1, 1) === '-') {
  169. if ($expectingValue) {
  170. throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values");
  171. } //if
  172.  
  173. /* stop parsing arguments if double dash
  174. only param is encountered */
  175. if ($currentArgumentLength == 2) {
  176. if ($trailingValues !== "") {
  177. throw new \UnexpectedValueException("Trailing values must appear after double dash");
  178. } //if
  179.  
  180. $trailingValues = " ". implode(" ", $argumentStack);
  181. $argumentStack = array();
  182. $endOfDashedArguments = true;
  183. break;
  184. } //if
  185.  
  186. $longNameParts = explode("=", substr($currentArgument, 2), 2);
  187.  
  188. $currentLongName = $longNameParts[0];
  189.  
  190. if (sizeof($longNameParts) > 1) {
  191. $currentValue = $longNameParts[1];
  192. $addParam = true;
  193. } elseif ($this->definitions->allowsValue($currentLongName)) {
  194. $expectingValue = true;
  195. } else {
  196. $addParam = true;
  197. } //if
  198.  
  199. // single dash
  200. } else {
  201. if ($expectingValue) {
  202. throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values");
  203. } //if
  204.  
  205. $shortNameParts = explode("=", substr($currentArgument, 1), 2);
  206.  
  207. $shortName = $shortNameParts[0];
  208.  
  209. if (strlen($shortName) <= 1) {
  210. $currentLongName = $this->definitions->getLongName($shortName);
  211.  
  212. if ($currentLongName === null) {
  213. throw new \InvalidArgumentException("Unable to find name with ".
  214. "provided parameter ({$shortName})");
  215. } //if
  216.  
  217. if (sizeof($shortNameParts) > 1) {
  218. $currentValue = $shortNameParts[1];
  219. $addParam = true;
  220. } elseif ($this->definitions->allowsValue($currentLongName)) {
  221. $expectingValue = true;
  222. } else {
  223. $addParam = true;
  224. } //if
  225.  
  226. } else {
  227. $multiShortParams = str_split($shortName);
  228.  
  229. /* process the last one (which is the only one that can have a value) */
  230. $lastParam = array_pop($multiShortParams);
  231. $currentLongName = $this->definitions->getLongName($lastParam);
  232. if (sizeof($shortNameParts) > 1) {
  233. $currentValue = $shortNameParts[1];
  234. $addParam = true;
  235. } elseif ($this->definitions->allowsValue($lastParam)) {
  236. $expectingValue = true;
  237. } else {
  238. $addParam = true;
  239. } //if
  240.  
  241. } //if
  242. } //if
  243.  
  244. if ($addParam) {
  245. if ($endOfDashedArguments) {
  246. throw new \UnexpectedValueException("Unexpected argument after undashed values");
  247. } //if
  248.  
  249. /* Not sure how this could happen */
  250. // @codeCoverageIgnoreStart
  251. if ($currentLongName === false || $currentLongName === null) {
  252. throw new \UnexpectedValueException("Missing argument name");
  253. } //if
  254. // @codeCoverageIgnoreEnd
  255.  
  256. if (!$this->definitions->paramExists($currentLongName)) {
  257. throw new \InvalidArgumentException("Invalid argument name");
  258. } //if
  259.  
  260. $allowsMultiple = $this->definitions->allowsMultiple($currentLongName);
  261. $allowsValue = $this->definitions->allowsValue($currentLongName);
  262.  
  263. if (isset($this->params[$currentLongName]) && !$allowsMultiple) {
  264. throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed");
  265. } //if
  266.  
  267. if ($allowsValue) {
  268. /* Missing values should always be detected before addParam is true */
  269. // @codeCoverageIgnoreStart
  270. if ($currentValue === null) {
  271. throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values");
  272. } //if
  273. // @codeCoverageIgnoreEnd
  274.  
  275. } elseif ($currentValue !== null) {
  276. throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values");
  277.  
  278. } else {
  279. $currentValue = true;
  280. } //if
  281.  
  282. if ($allowsMultiple) {
  283. if ($allowsValue) {
  284. if (!isset($this->params[$currentLongName])) {
  285. $this->params[$currentLongName] = array();
  286. } //if
  287.  
  288. $this->params[$currentLongName][] = $currentValue;
  289.  
  290. } else {
  291. if (!isset($this->params[$currentLongName])) {
  292. $this->params[$currentLongName] = 0;
  293. } //if
  294.  
  295. $this->params[$currentLongName]++;
  296.  
  297. } //if
  298.  
  299. } else {
  300. $this->params[$currentLongName] = $currentValue;
  301. } //if
  302.  
  303. foreach ($multiShortParams as $shortName) {
  304. $argumentStack[] = "-{$shortName}";
  305. $argumentsLeft++;
  306. } //foreach
  307.  
  308. /* reset stuff for next param */
  309. $expectingValue = false;
  310. $currentLongName = null;
  311. $currentValue = null;
  312. $addParam = false;
  313. $multiShortParams = array();
  314.  
  315. } //if
  316.  
  317. } //while
  318.  
  319. if ($expectingValue !== false) {
  320. throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values");
  321. } //if
  322.  
  323. /* Not sure how this could happen */
  324. // @codeCoverageIgnoreStart
  325. if ($currentLongName !== null ||
  326. $addParam !== false ||
  327. $currentValue !== null ||
  328. sizeof($multiShortParams) !== 0) {
  329. throw new \UnexpectedValueException("Unable to process some parameters");
  330. } //if
  331. // @codeCoverageIgnoreEnd
  332.  
  333. if ($trailingValues !== "") {
  334. $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging
  335. } //if
  336.  
  337. $this->parsed = true;
  338. } // parseParams()
  339. }
Buy Me A Coffee