PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Util/Getopt.php

http://github.com/sebastianbergmann/phpunit
PHP | 179 lines | 124 code | 31 blank | 24 comment | 33 complexity | 71ae7f1d1cc27a4b6bcd0bf9169d347e MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of PHPUnit.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace PHPUnit\Util;
  11. /**
  12. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  13. */
  14. final class Getopt
  15. {
  16. /**
  17. * @throws Exception
  18. */
  19. public static function getopt(array $args, string $short_options, array $long_options = null): array
  20. {
  21. if (empty($args)) {
  22. return [[], []];
  23. }
  24. $opts = [];
  25. $non_opts = [];
  26. if ($long_options) {
  27. \sort($long_options);
  28. }
  29. if (isset($args[0][0]) && $args[0][0] !== '-') {
  30. \array_shift($args);
  31. }
  32. \reset($args);
  33. $args = \array_map('trim', $args);
  34. /* @noinspection ComparisonOperandsOrderInspection */
  35. while (false !== $arg = \current($args)) {
  36. $i = \key($args);
  37. \next($args);
  38. if ($arg === '') {
  39. continue;
  40. }
  41. if ($arg === '--') {
  42. $non_opts = \array_merge($non_opts, \array_slice($args, $i + 1));
  43. break;
  44. }
  45. if ($arg[0] !== '-' || (\strlen($arg) > 1 && $arg[1] === '-' && !$long_options)) {
  46. $non_opts[] = $args[$i];
  47. continue;
  48. }
  49. if (\strlen($arg) > 1 && $arg[1] === '-') {
  50. self::parseLongOption(
  51. \substr($arg, 2),
  52. $long_options,
  53. $opts,
  54. $args
  55. );
  56. } else {
  57. self::parseShortOption(
  58. \substr($arg, 1),
  59. $short_options,
  60. $opts,
  61. $args
  62. );
  63. }
  64. }
  65. return [$opts, $non_opts];
  66. }
  67. /**
  68. * @throws Exception
  69. */
  70. private static function parseShortOption(string $arg, string $short_options, array &$opts, array &$args): void
  71. {
  72. $argLen = \strlen($arg);
  73. for ($i = 0; $i < $argLen; $i++) {
  74. $opt = $arg[$i];
  75. $opt_arg = null;
  76. if ($arg[$i] === ':' || ($spec = \strstr($short_options, $opt)) === false) {
  77. throw new Exception(
  78. "unrecognized option -- $opt"
  79. );
  80. }
  81. if (\strlen($spec) > 1 && $spec[1] === ':') {
  82. if ($i + 1 < $argLen) {
  83. $opts[] = [$opt, \substr($arg, $i + 1)];
  84. break;
  85. }
  86. if (!(\strlen($spec) > 2 && $spec[2] === ':')) {
  87. /* @noinspection ComparisonOperandsOrderInspection */
  88. if (false === $opt_arg = \current($args)) {
  89. throw new Exception(
  90. "option requires an argument -- $opt"
  91. );
  92. }
  93. \next($args);
  94. }
  95. }
  96. $opts[] = [$opt, $opt_arg];
  97. }
  98. }
  99. /**
  100. * @throws Exception
  101. */
  102. private static function parseLongOption(string $arg, array $long_options, array &$opts, array &$args): void
  103. {
  104. $count = \count($long_options);
  105. $list = \explode('=', $arg);
  106. $opt = $list[0];
  107. $opt_arg = null;
  108. if (\count($list) > 1) {
  109. $opt_arg = $list[1];
  110. }
  111. $opt_len = \strlen($opt);
  112. foreach ($long_options as $i => $long_opt) {
  113. $opt_start = \substr($long_opt, 0, $opt_len);
  114. if ($opt_start !== $opt) {
  115. continue;
  116. }
  117. $opt_rest = \substr($long_opt, $opt_len);
  118. if ($opt_rest !== '' && $i + 1 < $count && $opt[0] !== '=' && \strpos($long_options[$i + 1], $opt) === 0) {
  119. throw new Exception(
  120. "option --$opt is ambiguous"
  121. );
  122. }
  123. if (\substr($long_opt, -1) === '=') {
  124. /* @noinspection StrlenInEmptyStringCheckContextInspection */
  125. if (\substr($long_opt, -2) !== '==' && !\strlen((string) $opt_arg)) {
  126. /* @noinspection ComparisonOperandsOrderInspection */
  127. if (false === $opt_arg = \current($args)) {
  128. throw new Exception(
  129. "option --$opt requires an argument"
  130. );
  131. }
  132. \next($args);
  133. }
  134. } elseif ($opt_arg) {
  135. throw new Exception(
  136. "option --$opt doesn't allow an argument"
  137. );
  138. }
  139. $full_option = '--' . \preg_replace('/={1,2}$/', '', $long_opt);
  140. $opts[] = [$full_option, $opt_arg];
  141. return;
  142. }
  143. throw new Exception("unrecognized option --$opt");
  144. }
  145. }