From 55e24a3874b17a2e7ac15dad4e35e083748cd4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E4=B9=89=E5=85=B5?= Date: Thu, 25 Oct 2018 14:46:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20@ignore=20&=20@sdk=20?= =?UTF-8?q?=E7=89=B9=E6=80=A7,=20=E5=90=8C=E6=97=B6=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=8F=B0=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Parsers/Abstracts/Base.php | 7 +++- src/Parsers/Abstracts/Console.php | 40 ++++++++++++++++++ src/Parsers/Annotation.php | 53 +++++++++++++++++++++++ src/Parsers/Collection.php | 19 ++++++--- src/Parsers/Controller.php | 30 +++++++++---- src/Parsers/Method.php | 70 ++++++++++++++++++++++--------- 6 files changed, 184 insertions(+), 35 deletions(-) create mode 100644 src/Parsers/Abstracts/Console.php diff --git a/src/Parsers/Abstracts/Base.php b/src/Parsers/Abstracts/Base.php index 5a88df4..c14f68a 100644 --- a/src/Parsers/Abstracts/Base.php +++ b/src/Parsers/Abstracts/Base.php @@ -26,9 +26,11 @@ abstract class Base public $schema = '{{protocol}}'; public $domain = '{{domain}}'; public $token = '{{token}}'; + public $console; public function __construct() { + $this->console = new Console(); } /** @@ -39,13 +41,14 @@ public function saveMarkdown($path, $name, $contents) $file = $path.'/'.$name; try { if (!is_dir($path)) { - mkdir($path, 0777,true); + mkdir($path, 0777, true); } $fp = fopen($file, 'wb+'); fwrite($fp, $contents); fclose($fp); + $this->console->debug("导出到%s文件", $file); } catch(\Exception $e) { - echo $e->getMessage(); + $this->console->error($e->getMessage()); exit; } } diff --git a/src/Parsers/Abstracts/Console.php b/src/Parsers/Abstracts/Console.php new file mode 100644 index 0000000..35e4bdc --- /dev/null +++ b/src/Parsers/Abstracts/Console.php @@ -0,0 +1,40 @@ + + * @date 2018-05-09 + */ +namespace Uniondrug\Postman\Parsers\Abstracts; + +/** + * 控制台消息 + * @package Uniondrug\Postman\Parsers\Abstracts + */ +class Console +{ + public function debug($format, ... $args) + { + $this->printer("DEBUG", 30, 47, $format, ... $args); + } + + public function error($format, ... $args) + { + $this->printer("ERROR", 33, 41, $format, ... $args); + } + + public function info($format, ... $args) + { + $this->printer("INFO", 0, 0, $format, ... $args); + } + + public function warning($format, ... $args) + { + $this->printer("WARNING", 31, 43, $format, ... $args); + } + + private function printer($level, $bc, $fc, $format, ... $args) + { + $args = is_array($args) ? $args : []; + $message = call_user_func_array('sprintf', array_merge([$format], $args)); + echo sprintf("\033[%d;%dm[%s] %s\033[0m\n", $bc, $fc, sprintf("%5s", $level), $message); + } +} diff --git a/src/Parsers/Annotation.php b/src/Parsers/Annotation.php index b08b1a6..2cfacb1 100644 --- a/src/Parsers/Annotation.php +++ b/src/Parsers/Annotation.php @@ -62,12 +62,15 @@ class Annotation extends Base */ public $validator = null; public $mock = ''; + public $ver = ''; /** * 是否为数组类型 * @var bool */ public $isArrayType = false; public $isStructType = false; + public $isIgnored = false; + public $isSdk = false; /** * @var bool|string */ @@ -86,8 +89,11 @@ class Annotation extends Base private static $regexpMock = "/@Mock[ ]+([^\n]+)\n/i"; private static $regexpPrefix = "/@RoutePrefix[ ]*\(([^\)]*)\)/i"; private static $regexpRequest = "/@(Route|Get|Post|Put|Patch|Delete|Options|head)[ ]*\(([^\)]*)\)/i"; + private static $regexpSdk = "/@(sdk)[^a-z]*/i"; + private static $regexpIgnore = "/@(ignore)[^a-z]*/i"; private static $regexpType = "/@var[ ]+([_a-z0-9\\\]+)[ ]*([\[|\]| ]*)([^\n]*)\n/i"; private static $regexpValidator = "/@validator[ ]*\(([^\)]*)\)/i"; + private static $regexpVersion = "/@version[ ]+([^\n]+)\n/i"; /** * Annotation constructor. @@ -124,6 +130,21 @@ public function alias() } } + public function ignored() + { + // 1. no comment + if ($this->comment === false) { + return; + } + // 2. not defined + preg_match(self::$regexpIgnore, $this->comment, $m); + if (count($m) === 0) { + return; + } + // 3. export + $this->isIgnored = true; + } + /** * 解析name/description */ @@ -231,6 +252,23 @@ public function requeset() ]); } + /** + * 测试单元 + */ + public function sdk() + { + if ($this->comment === false) { + return; + } + // 2. not defined + preg_match(self::$regexpSdk, $this->comment, $m); + if (count($m) === 0) { + return; + } + // 3. export + $this->isSdk = true; + } + /** * 测试单元 */ @@ -305,6 +343,21 @@ public function mock() $this->mock = trim($m[1]); } + public function version() + { + // 1. not comment + if ($this->comment === false) { + return; + } + // 2. not defined + preg_match(self::$regexpVersion, $this->comment, $m); + if (count($m) === 0) { + return; + } + // 3. parse + $this->ver = trim($m[1]); + } + /** * @param string $s * @return array diff --git a/src/Parsers/Collection.php b/src/Parsers/Collection.php index fd6728e..518853a 100644 --- a/src/Parsers/Collection.php +++ b/src/Parsers/Collection.php @@ -26,6 +26,7 @@ class Collection extends Base * @var string */ public $name = ''; + public $prefix = ''; /** * 描述 * @var string @@ -55,14 +56,12 @@ class Collection extends Base /** * Controller constructor. - * * @param string $path 项目路径 */ public function __construct(string $path) { parent::__construct(); $this->basePath = $path; - $this->name = $path; // 1. load config $file = $path.'/postman.json'; if (file_exists($file)) { @@ -72,10 +71,15 @@ public function __construct(string $path) isset($json->name) && $this->name = $json->name; isset($json->description) && $this->description = $json->description; isset($json->host) && $this->host = $json->host; - isset($json->name) && $this->auth = strtoupper($json->auth) === 'YES'; + isset($json->auth) && $this->auth = strtoupper($json->auth) === 'YES'; } } - // 2. 遍历目录 + // 2. console + $this->console->info("{$json->name}, {$json->description}"); + $this->console->info("需要鉴权: {$json->auth}"); + $this->console->info("域名前缀: {$json->host}"); + $this->console->info("扫描目录: %s", $this->controllerPath); + // 3. 遍历目录 $this->scanner($path.'/'.$this->controllerPath); } @@ -91,6 +95,7 @@ public function parser() $controller->parser(); $this->controllers[$class] = $controller; } catch(\Exception $e) { + $this->console->error($e->getMessage()); } } } @@ -125,7 +130,10 @@ public function toMarkdown() $text .= $this->eol; $text .= '### 接口目录'.$this->eol; foreach ($this->controllers as $controller) { - $name = $controller->annotation->name; + if (count($controller->methods) === 0) { + continue; + } + $name = trim($controller->annotation->name); $desc = preg_replace("/\n/", "", trim($controller->annotation->description)); $url = str_replace('\\', '/', substr($controller->reflect->getName(), 16)); $text .= '* ['.$name.'](./'.$url.'/README.md) : '.$desc.$this->crlf; @@ -169,7 +177,6 @@ public function toPostman() /** * 扫描Controller目录 - * * @param string $path */ private function scanner($path) diff --git a/src/Parsers/Controller.php b/src/Parsers/Controller.php index aac8ba0..adee9ab 100644 --- a/src/Parsers/Controller.php +++ b/src/Parsers/Controller.php @@ -38,6 +38,7 @@ public function __construct(Collection $collection, string $class) $this->collection = $collection; $this->reflect = new \ReflectionClass($class); $this->filename = substr($this->reflect->getFileName(), strlen($collection->basePath) + 1); + $this->console->info("发现%s控制器", $this->reflect->name); } /** @@ -68,9 +69,13 @@ public function parser() continue; } // 2.3 execute - $method = new Method($this->collection, $this, $reflect); - $method->parser(); - $this->methods[] = $method; + try { + $method = new Method($this->collection, $this, $reflect); + $method->parser(); + $this->methods[] = $method; + } catch(\Exception $e) { + $this->console->error($e->getMessage()); + } } } @@ -86,9 +91,15 @@ public function getIndex($curr = false) $url = str_replace('\\', '/', substr($this->reflect->getName(), 16)); $prefix = './'.($curr ? '' : $url.'/'); foreach ($this->methods as $method) { - $name = $method->annotation->name; - $desc = preg_replace("/\n/", " ", trim($method->annotation->description)); - $text .= $comma.$space.'* ['.$name.']('.$prefix.$method->reflect->getShortName().'.md) : '.$desc; + $name = trim($method->annotation->name); + $desc = trim(preg_replace("/\n/", " ", trim($method->annotation->description))); + $text .= $comma.$space.'* ['.$name.']('.$prefix.$method->reflect->getShortName().'.md)'; + if ($method->annotation->ver !== '') { + $text .= " `{$method->annotation->ver}` "; + } + if ($desc !== '') { + $text .= ' : '.$desc; + } $comma = $this->crlf; } return $text; @@ -102,6 +113,11 @@ public function toMarkdown() { $name = str_replace('\\', '/', substr($this->reflect->getName(), 16)); $path = $this->collection->basePath.'/'.$this->collection->publishTo.'/'.$name; + $count = count($this->methods); + if ($count === 0) { + $this->console->warning("控制器{$this->reflect->getName()}无可导出动作, 忽略导出"); + return; + } // 1. title $text = '# '.$this->annotation->name; // 2. description @@ -111,7 +127,7 @@ public function toMarkdown() } // 3. information $text .= $this->eol; - $text .= "* **接口** : `".count($this->methods)."` 个".$this->crlf; + $text .= "* **接口** : `".$count."` 个".$this->crlf; $text .= "* **前缀** : `{$this->annotation->prefix}`".$this->crlf; $text .= "* **类名** : `{$this->reflect->name}`".$this->crlf; $text .= "* **文件** : `{$this->filename}`"; diff --git a/src/Parsers/Method.php b/src/Parsers/Method.php index 5dae4c7..a947c19 100644 --- a/src/Parsers/Method.php +++ b/src/Parsers/Method.php @@ -36,7 +36,6 @@ class Method extends Base /** * Method constructor. - * * @param Collection $collection * @param Controller $controller * @param \ReflectionMethod $reflect @@ -47,6 +46,7 @@ public function __construct(Collection $collection, Controller $controller, \Ref $this->collection = $collection; $this->controller = $controller; $this->reflect = $reflect; + $this->console->debug("发现%s动作", $this->reflect->name); } /** @@ -58,9 +58,18 @@ public function parser() $this->annotation = new Annotation($this->reflect); $this->annotation->info(); $this->annotation->requeset(); + $this->annotation->version(); + $this->annotation->sdk(); + $this->annotation->ignored(); $this->annotation->input(); $this->annotation->output(); $this->annotation->test(); + if ($this->annotation->isIgnored) { + throw new \Exception("动作{$this->reflect->class}::{$this->reflect->name}由@ignore约定, 忽略导出"); + } + if ($this->annotation->isSdk) { + $this->console->debug("动作%s::%s导出到SDK", $this->reflect->class, $this->reflect->name); + } // 1. 补齐 if ($this->annotation->name === '') { $this->annotation->name = $this->reflect->name.'()'; @@ -70,6 +79,7 @@ public function parser() try { $this->inputParameter = new Parameters($this, $this->annotation->input, $this->controller->reflect->getNamespaceName()); } catch(\Exception $e) { + $this->console->error($e->getMessage()); } } // 3. 出参 @@ -77,6 +87,7 @@ public function parser() try { $this->outputParameter = new Parameters($this, $this->annotation->output, $this->controller->reflect->getNamespaceName()); } catch(\Exception $e) { + $this->console->error($e->getMessage()); } } } @@ -88,6 +99,7 @@ public function toMarkdown() { $text = '# '.$this->annotation->name.$this->eol; $text .= $this->headerText(); + $text .= $this->eol.$this->sdkText(); $text .= $this->eol.$this->inputText(); $text .= $this->eol.$this->inputCode(); $text .= $this->eol.$this->outputText(); @@ -183,23 +195,6 @@ public function toPostmanResponse() return []; } - private function afterParser() - { - $text = $this->headerText(); - $text .= $this->eol.$this->inputText(); - $text .= $this->eol.$this->inputCode(); - $text .= $this->eol.$this->outputText(); - $text .= $this->eol.$this->outputCode(); - if (false !== ($fp = @fopen($this->collection->basePath.'/vendor/e.md', 'wb+'))) { - fwrite($fp, $text); - fclose($fp); - } - echo "---------\n"; - echo $text; - echo "\n---------------\n"; - exit; - } - /** * 文档头信息 * @return string @@ -217,10 +212,10 @@ private function headerText() $text .= $this->eol; $text .= '* **接口** : `'.$this->annotation->method.' '.$this->controller->annotation->prefix.$this->annotation->path.'`'.$this->crlf; if ($this->annotation->input !== '') { - $text .= '* **入参** : `'.$this->annotation->input.'`'.$this->crlf; + $text .= '* **入参** : `'.preg_replace("/^[^A-Z]/", "", $this->annotation->input).'`'.$this->crlf; } if ($this->annotation->output !== '') { - $text .= '* **出参** : `'.$this->annotation->output.'`'.$this->crlf; + $text .= '* **出参** : `'.preg_replace("/^[^A-Z]/", "", $this->annotation->output).'`'.$this->crlf; } $text .= '* **文件** : `'.$this->controller->filename.'`'.$this->crlf; $text .= '* **执行** : `'.$this->controller->reflect->name.'::'.$this->reflect->name.'()'.'`'.$this->crlf; @@ -229,6 +224,41 @@ private function headerText() return $text; } + private function sdkText() + { + // 1. 不导出SDK + if (!$this->annotation->isSdk) { + return ''; + } + // 2. SDK用法 + $text = '### SDK'.$this->eol; + $text .= '```'.$this->crlf; + $host = "{$this->controller->collection->host}://".preg_replace("/^\/+/", '', $this->controller->annotation->prefix.$this->annotation->path); + // 3. p1 + $text .= '// 调用SDK'.$this->crlf; + $text .= '$sdk = $this->serviceSdk->'.strtolower($this->annotation->method).'('; + if ($this->annotation->method === 'GET') { + $text .= '"'.$host.'");'.$this->crlf; + } else { + $text .= $this->crlf; + $text .= ' "'.$host.'",'.$this->crlf; + $text .= ' ['.$this->crlf; + $text .= ' // 省略...'.$this->crlf; + $text .= ' ]'.$this->crlf; + $text .= ');'.$this->crlf; + } + // 4. p2 + $text .= '// 是否有错'.$this->crlf; + $text .= 'if ($sdk->hasError()){'.$this->crlf; + $text .= ' throw new \Exception("SDK请求出错 - {$sdk->getError()}");'.$this->crlf; + $text .= '}'.$this->crlf; + // 5. p3 + $text .= '// 继承逻辑'.$this->crlf; + $text .= '// ...'.$this->crlf; + $text .= '```'.$this->crlf; + return $text; + } + /** * 入参Text文档 */