swagger 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #!/usr/bin/env php
  2. <?php
  3. error_reporting(E_ALL);
  4. // Possible options and their default values.
  5. $options = array(
  6. 'output' => 'swagger.json',
  7. 'stdout' => false,
  8. 'exclude' => null,
  9. 'bootstrap' => false,
  10. 'help' => false,
  11. 'version' => false,
  12. 'debug' => false,
  13. );
  14. $aliases = array(
  15. 'o' => 'output',
  16. 'e' => 'exclude',
  17. 'b' => 'bootstrap',
  18. 'v' => 'version',
  19. 'h' => 'help',
  20. 'd' => 'debug'
  21. );
  22. $needsArgument = array(
  23. 'output',
  24. 'exclude',
  25. 'bootstrap',
  26. );
  27. $paths = array();
  28. $error = false;
  29. try {
  30. // Parse cli arguments
  31. for ($i = 1; $i < $argc; $i++) {
  32. $arg = $argv[$i];
  33. if (substr($arg, 0, 2) === '--') { // longopt
  34. $option = substr($arg, 2);
  35. } elseif ($arg[0] === '-') { // shortopt
  36. if (array_key_exists(substr($arg, 1), $aliases)) {
  37. $option = $aliases[$arg[1]];
  38. } else {
  39. throw new Exception('Unknown option: "' . $arg . '"');
  40. }
  41. } else {
  42. $paths[] = $arg;
  43. continue;
  44. }
  45. if (array_key_exists($option, $options) === false) {
  46. throw new Exception('Unknown option: "' . $arg . '"');
  47. }
  48. if (in_array($option, $needsArgument)) {
  49. if (empty($argv[$i + 1]) || $argv[$i + 1][0] === '-') {
  50. throw new Exception('Missing argument for "' . $arg . '"');
  51. }
  52. $options[$option] = $argv[$i + 1];
  53. $i++;
  54. } else {
  55. $options[$option] = true;
  56. }
  57. }
  58. } catch (Exception $e) {
  59. $error = $e->getMessage();
  60. }
  61. $version = trim(file_get_contents(__DIR__ . '/../VERSION'));
  62. if ($options['version']) {
  63. echo $version, PHP_EOL;
  64. exit;
  65. }
  66. error_log('');
  67. error_log('Swagger-PHP ' . $version);
  68. error_log('------------'. str_repeat('-', strlen($version)));
  69. if (!$error && $options['bootstrap']) {
  70. if (is_readable($options['bootstrap']) === false) {
  71. $error = 'Invalid `--bootstrap` value: "'.$options['bootstrap'].'"';
  72. } else {
  73. require_once($options['bootstrap']);
  74. }
  75. }
  76. if ($error) {
  77. error_log('[ERROR] '.$error);
  78. $options['help'] = true; // Show help
  79. }
  80. if ($options['help']) {
  81. $help = <<<EOF
  82. Usage: swagger [--option value] [/path/to/project ...]
  83. Options:
  84. --output (-o) Path to store the generated documentation.
  85. --stdout Write to the standard output.
  86. --exclude (-e) Exclude path(s).
  87. ex: --exclude vendor,library/Zend
  88. --bootstrap (-b) Bootstrap a php file for defining constants, etc.
  89. ex: --bootstrap config/constants.php
  90. --version (-v) Display Swagger-PHP version.
  91. --help (-h) Display this help message.
  92. EOF;
  93. error_log($help);
  94. exit;
  95. }
  96. if (count($paths) === 0) {
  97. $paths[] = getcwd();
  98. echo "Scanning files in '".$paths[0]."' ...\n";
  99. }
  100. if (class_exists('Swagger\Logger') === false) {
  101. if (file_exists(__DIR__.'/../vendor/autoload.php')) { // cloned / dev environment?
  102. require_once(__DIR__.'/../vendor/autoload.php');
  103. } else {
  104. require_once(realpath(__DIR__.'/../../../').'/autoload.php');
  105. }
  106. }
  107. $errorTypes = [
  108. E_ERROR => 'ERROR',
  109. E_WARNING => 'WARNING',
  110. E_PARSE => 'PARSE',
  111. E_NOTICE => 'NOTICE',
  112. E_CORE_ERROR => 'CORE_ERROR',
  113. E_CORE_WARNING => 'CORE_WARNING',
  114. E_COMPILE_ERROR => 'COMPILE_ERROR',
  115. E_COMPILE_WARNING => 'COMPILE_WARNING',
  116. E_USER_ERROR => 'ERROR',
  117. E_USER_WARNING => 'WARNING',
  118. E_USER_NOTICE => 'NOTICE',
  119. E_STRICT => 'STRICT',
  120. E_RECOVERABLE_ERROR => 'RECOVERABLE_ERROR',
  121. E_DEPRECATED => 'DEPRECATED',
  122. E_USER_DEPRECATED => 'DEPRECATED'
  123. ];
  124. set_error_handler(function ($errno, $errstr, $file, $line) use ($errorTypes) {
  125. if (!(error_reporting() & $errno)) {
  126. return; // This error code is not included in error_reporting
  127. }
  128. $type = array_key_exists($errno, $errorTypes) ? $errorTypes[$errno] : 'ERROR';
  129. error_log('[' . $type . '] '.$errstr .' in '.$file.' on line '.$line);
  130. if ($type === 'ERROR') {
  131. exit($errno);
  132. }
  133. });
  134. set_exception_handler(function ($exception) use ($options) {
  135. if ($options['debug']) {
  136. error_log($exception);
  137. } else {
  138. error_log('[EXCEPTION] '.$exception->getMessage() .' in '.$exception->getFile().' on line '.$exception->getLine());
  139. }
  140. exit($exception->getCode() ?: 1);
  141. });
  142. \Swagger\Logger::getInstance()->log = function ($entry, $type) {
  143. $type = $type === E_USER_NOTICE ? 'INFO' : 'WARN';
  144. if ($entry instanceof Exception) {
  145. $entry = $entry->getMessage();
  146. }
  147. error_log('[' . $type . '] ' . $entry . PHP_EOL);
  148. };
  149. $exclude = $options['exclude'] ? explode(',', $options['exclude']) : null;
  150. $swagger = Swagger\scan($paths, ['exclude' => $exclude]);
  151. $methods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'];
  152. $counter = 0;
  153. // Output report
  154. foreach ($swagger->paths as $path) {
  155. foreach ($path as $method => $operation) {
  156. if ($operation !== null && in_array($method, $methods)) {
  157. error_log(str_pad($method, 7, ' ', STR_PAD_LEFT) . ' ' . $path->path);
  158. $counter++;
  159. }
  160. }
  161. }
  162. error_log('----------------------'. str_repeat('-', strlen($counter)));
  163. error_log($counter.' operations documented');
  164. error_log('----------------------'. str_repeat('-', strlen($counter)));
  165. if ($options['stdout']) {
  166. echo $swagger;
  167. } else {
  168. if (is_dir($options['output'])) {
  169. $options['output'] .= '/swagger.json';
  170. }
  171. $swagger->saveAs($options['output']);
  172. error_log('Written to '.realpath($options['output']));
  173. }
  174. error_log('');