PageRenderTime 45ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/GetOpt.class.php

https://bitbucket.org/nsa/mmp
PHP | 171 lines | 124 code | 13 blank | 34 comment | 9 complexity | 9cd7918efd71e3194933655db44a74cc MD5 | raw file
  1. <?php
  2. class GetOpt {
  3. static protected $default_config = array(
  4. 'optVal'
  5. );
  6. private static $errors = array();
  7. /**
  8. * Parse and extract left-most options up to the first non-option argument
  9. *
  10. * @param array $args List of arguments to search through
  11. * @param array $opts Option templates. Defines rules for the options we need to parse
  12. * @return array Extracted options
  13. */
  14. static function extractLeft(&$args, $opts)
  15. {
  16. $result = array();
  17. self::$errors = array();
  18. $opts = self::normalizeTpl($opts);
  19. $short_opts = self::mapShortOpts($opts);
  20. while(!empty($args))
  21. {
  22. $arg = array_shift($args);
  23. if(preg_match('/^--([a-z][a-z\-]*)/i', $arg, $matches)) //long options start with "--"
  24. {
  25. $matches[1] = strtolower($matches[1]);
  26. if(isset($opts[$matches[1]]))
  27. {
  28. try
  29. {
  30. $result[$matches[1]] = self::parseValue($args, $arg, $opts[$matches[1]]);
  31. }
  32. catch(Exception $e)
  33. {
  34. self::$errors[] = $e->getMessage();
  35. return false;
  36. }
  37. }
  38. else
  39. {
  40. self::$errors[] = 'Invalid option \'' . $matches[1] . '\'';
  41. return false;
  42. }
  43. }
  44. elseif(preg_match('/^-([a-z])/', $arg, $matches)) //short options start with '-', are case-sensitive
  45. {
  46. foreach(str_split($matches[1]) as $o)
  47. {
  48. if(isset($short_opts[$o]))
  49. {
  50. try
  51. {
  52. $result[$short_opts[$o]] = self::parseValue($args, $arg, $opts[$short_opts[$o]]);
  53. }
  54. catch(Exception $e)
  55. {
  56. self::$errors[] = $e->getMessage();
  57. return false;
  58. }
  59. }
  60. else
  61. {
  62. self::$errors[] = 'Invalid option \'' . $matches[1] . '\'';
  63. return false;
  64. }
  65. }
  66. }
  67. else
  68. {
  69. array_unshift($args, $arg);
  70. break;
  71. }
  72. }
  73. return $result;
  74. }
  75. /**
  76. * Return list errors encountered while parsing the arguments
  77. *
  78. * @return array List of errors
  79. */
  80. static function errors()
  81. {
  82. return self::$errors;
  83. }
  84. /**
  85. * Expand array values without custom keys into "'value' => true" pairs
  86. *
  87. * @param array $opts Array to process
  88. * @return array Processed array
  89. */
  90. private static function normalizeTpl($opts)
  91. {
  92. foreach($opts as &$tpl)
  93. {
  94. $ntpl = array();
  95. foreach($tpl as $k => $t)
  96. {
  97. if(is_string($k))
  98. $ntpl[$k] = $t;
  99. elseif(is_int($k) && is_string($t))
  100. $ntpl[$t] = true;
  101. }
  102. $tpl = $ntpl;
  103. }
  104. return $opts;
  105. }
  106. /**
  107. * Get the associations between short and long options, if any exist
  108. *
  109. * @param array $opts Options to parse
  110. * @return array List of mappings between short_options => long_options
  111. */
  112. private static function mapShortOpts($opts)
  113. {
  114. $result = array();
  115. foreach($opts as $k => $o)
  116. {
  117. if(!empty($o['short']))
  118. $result[$o['short']] = $k;
  119. }
  120. return $result;
  121. }
  122. /**
  123. * Get "value" part of the long, if any, from the arguments list.
  124. *
  125. * Note: $args might be modified depending on the given option template
  126. *
  127. * @param array $args List of command-line arguments
  128. * @param string $arg Argument being parsed
  129. * @param array $tpl Template for the argument being parsed
  130. * @return mixed Parsed option value, null if no value required
  131. */
  132. private static function parseValue(&$args, $arg, $tpl)
  133. {
  134. foreach($tpl as $t => $v)
  135. {
  136. switch($t)
  137. {
  138. case 'req_val':
  139. if(strpos($arg, '=') === false)
  140. {
  141. if(!empty($args))
  142. return array_shift($args);
  143. else
  144. throw new Exception('Missing option value');
  145. }
  146. else
  147. return substr(strstr($arg, '='), 1);
  148. break;
  149. case 'opt_val':
  150. if(strpos($arg, '=') !== false)
  151. return substr(strstr($arg, '='), 1);
  152. break;
  153. }
  154. }
  155. return null;
  156. }
  157. }
  158. ?>