2020-03-02 16:14:20 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace ZM\Annotation;
|
|
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use Doctrine\Common\Annotations\AnnotationReader;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
2021-09-01 14:14:00 +08:00
|
|
|
|
use ZM\Config\ZMConfig;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Console\Console;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
use ReflectionClass;
|
|
|
|
|
|
use ReflectionException;
|
|
|
|
|
|
use ReflectionMethod;
|
2021-04-06 01:19:56 +08:00
|
|
|
|
use ZM\Annotation\Http\HandleAfter;
|
|
|
|
|
|
use ZM\Annotation\Http\HandleBefore;
|
|
|
|
|
|
use ZM\Annotation\Http\HandleException;
|
|
|
|
|
|
use ZM\Annotation\Http\Middleware;
|
|
|
|
|
|
use ZM\Annotation\Http\MiddlewareClass;
|
|
|
|
|
|
use ZM\Annotation\Http\RequestMapping;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
use ZM\Annotation\Interfaces\Level;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Annotation\Module\Closed;
|
2021-09-01 14:14:00 +08:00
|
|
|
|
use ZM\Exception\AnnotationException;
|
2021-06-16 00:17:30 +08:00
|
|
|
|
use ZM\Utils\Manager\RouteManager;
|
|
|
|
|
|
use ZM\Utils\ZMUtil;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
|
|
|
|
|
class AnnotationParser
|
|
|
|
|
|
{
|
2020-08-31 10:11:06 +08:00
|
|
|
|
private $path_list = [];
|
|
|
|
|
|
|
|
|
|
|
|
private $start_time;
|
|
|
|
|
|
|
|
|
|
|
|
private $annotation_map = [];
|
2020-09-29 15:07:43 +08:00
|
|
|
|
private $middleware_map = [];
|
|
|
|
|
|
private $middlewares = [];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
/** @var null|AnnotationReader */
|
|
|
|
|
|
private $reader = null;
|
|
|
|
|
|
private $req_mapping = [];
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* AnnotationParser constructor.
|
|
|
|
|
|
*/
|
2020-08-31 10:11:06 +08:00
|
|
|
|
public function __construct() {
|
|
|
|
|
|
$this->start_time = microtime(true);
|
2021-01-02 13:15:50 +08:00
|
|
|
|
//$this->loadAnnotationClasses();
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$this->req_mapping[0] = [
|
2020-03-05 12:03:14 +08:00
|
|
|
|
'id' => 0,
|
|
|
|
|
|
'pid' => -1,
|
|
|
|
|
|
'name' => '/'
|
|
|
|
|
|
];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 注册各个模块类的注解和模块level的排序
|
|
|
|
|
|
* @throws ReflectionException
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function registerMods() {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
foreach ($this->path_list as $path) {
|
2021-09-01 14:14:00 +08:00
|
|
|
|
Console::debug("parsing annotation in " . $path[0].":".$path[1]);
|
2021-06-16 00:17:30 +08:00
|
|
|
|
$all_class = ZMUtil::getClassesPsr4($path[0], $path[1]);
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$this->reader = new AnnotationReader();
|
2020-08-31 10:11:06 +08:00
|
|
|
|
foreach ($all_class as $v) {
|
|
|
|
|
|
Console::debug("正在检索 " . $v);
|
|
|
|
|
|
$reflection_class = new ReflectionClass($v);
|
|
|
|
|
|
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$class_annotations = $this->reader->getClassAnnotations($reflection_class);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
// 这段为新加的:start
|
2020-08-31 10:11:06 +08:00
|
|
|
|
//这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
|
|
|
|
|
|
/*
|
|
|
|
|
|
$annotation_map: {
|
|
|
|
|
|
Module\Example\Hello: {
|
|
|
|
|
|
class_annotations: [
|
|
|
|
|
|
注解对象1, 注解对象2, ...
|
|
|
|
|
|
],
|
|
|
|
|
|
methods: [
|
|
|
|
|
|
ReflectionMethod, ReflectionMethod, ...
|
|
|
|
|
|
],
|
|
|
|
|
|
methods_annotations: {
|
|
|
|
|
|
foo: [ 注解对象1, 注解对象2, ... ],
|
|
|
|
|
|
bar: [ 注解对象1, 注解对象2, ... ],
|
2020-03-29 16:29:02 +08:00
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
*/
|
2020-09-29 15:07:43 +08:00
|
|
|
|
|
|
|
|
|
|
// 生成主树
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$this->annotation_map[$v]["class_annotations"] = $class_annotations;
|
|
|
|
|
|
$this->annotation_map[$v]["methods"] = $methods;
|
|
|
|
|
|
foreach ($methods as $method) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$this->annotation_map[$v]["methods_annotations"][$method->getName()] = $this->reader->getMethodAnnotations($method);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach ($this->annotation_map[$v]["class_annotations"] as $vs) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$vs->class = $v;
|
|
|
|
|
|
|
|
|
|
|
|
//预处理1:将适用于每一个函数的注解到类注解重新注解到每个函数下面
|
|
|
|
|
|
if ($vs instanceof ErgodicAnnotation) {
|
2021-01-02 16:36:25 +08:00
|
|
|
|
foreach (($this->annotation_map[$v]["methods"] ?? []) as $method) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$copy = clone $vs;
|
2021-01-29 23:34:34 +08:00
|
|
|
|
/** @noinspection PhpUndefinedFieldInspection */
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$copy->method = $method->getName();
|
|
|
|
|
|
$this->annotation_map[$v]["methods_annotations"][$method->getName()][] = $copy;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//预处理2:处理 class 下面的注解
|
2020-08-31 10:11:06 +08:00
|
|
|
|
if ($vs instanceof Closed) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
unset($this->annotation_map[$v]);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
continue 2;
|
|
|
|
|
|
} elseif ($vs instanceof MiddlewareClass) {
|
2021-09-01 14:14:00 +08:00
|
|
|
|
//注册中间件本身的类,标记到 middlewares 属性中
|
2021-01-02 13:15:50 +08:00
|
|
|
|
Console::debug("正在注册中间件 " . $reflection_class->getName());
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$rs = $this->registerMiddleware($vs, $reflection_class);
|
|
|
|
|
|
$this->middlewares[$rs["name"]] = $rs;
|
2020-03-25 18:35:16 +08:00
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
2020-06-20 14:51:24 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
//预处理3:处理每个函数上面的特殊注解,就是需要操作一些东西的
|
2021-01-02 16:36:25 +08:00
|
|
|
|
foreach (($this->annotation_map[$v]["methods_annotations"] ?? []) as $method_name => $methods_annotations) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
foreach ($methods_annotations as $method_anno) {
|
|
|
|
|
|
/** @var AnnotationBase $method_anno */
|
|
|
|
|
|
$method_anno->class = $v;
|
|
|
|
|
|
$method_anno->method = $method_name;
|
|
|
|
|
|
if ($method_anno instanceof RequestMapping) {
|
2021-01-13 15:40:27 +08:00
|
|
|
|
RouteManager::importRouteByAnnotation($method_anno, $method_name, $v, $methods_annotations);
|
2020-09-29 15:07:43 +08:00
|
|
|
|
} elseif ($method_anno instanceof Middleware) {
|
2021-07-04 15:45:30 +08:00
|
|
|
|
$this->middleware_map[$method_anno->class][$method_anno->method][] = $method_anno;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
Console::debug("解析注解完毕!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-04-06 01:19:56 +08:00
|
|
|
|
public function generateAnnotationEvents() {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$o = [];
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach ($this->annotation_map as $obj) {
|
2021-01-02 16:36:25 +08:00
|
|
|
|
foreach (($obj["class_annotations"] ?? []) as $class_annotation) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
if ($class_annotation instanceof ErgodicAnnotation) continue;
|
|
|
|
|
|
else $o[get_class($class_annotation)][] = $class_annotation;
|
|
|
|
|
|
}
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach (($obj["methods_annotations"] ?? []) as $methods_annotations) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
foreach ($methods_annotations as $annotation) {
|
|
|
|
|
|
$o[get_class($annotation)][] = $annotation;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-09-29 15:07:43 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach ($o as $k => $v) {
|
|
|
|
|
|
$this->sortByLevel($o, $k);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
2020-09-29 15:07:43 +08:00
|
|
|
|
return $o;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
2021-03-18 14:56:35 +08:00
|
|
|
|
public function getMiddlewares(): array { return $this->middlewares; }
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
2021-03-18 14:56:35 +08:00
|
|
|
|
public function getMiddlewareMap(): array { return $this->middleware_map; }
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
2021-03-18 14:56:35 +08:00
|
|
|
|
public function getReqMapping(): array { return $this->req_mapping; }
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param $path
|
|
|
|
|
|
* @param $indoor_name
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function addRegisterPath($path, $indoor_name) { $this->path_list[] = [$path, $indoor_name]; }
|
|
|
|
|
|
|
|
|
|
|
|
//private function below
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
2021-03-18 14:56:35 +08:00
|
|
|
|
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class): array {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$result = [
|
|
|
|
|
|
"class" => "\\" . $reflection_class->getName(),
|
|
|
|
|
|
"name" => $vs->name
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
foreach ($reflection_class->getMethods() as $vss) {
|
|
|
|
|
|
$method_annotations = $this->reader->getMethodAnnotations($vss);
|
|
|
|
|
|
foreach ($method_annotations as $vsss) {
|
2020-12-14 01:24:34 +08:00
|
|
|
|
if ($vsss instanceof HandleBefore) $result["before"] = $vss->getName();
|
|
|
|
|
|
if ($vsss instanceof HandleAfter) $result["after"] = $vss->getName();
|
2020-09-29 15:07:43 +08:00
|
|
|
|
if ($vsss instanceof HandleException) {
|
|
|
|
|
|
$result["exceptions"][$vsss->class_name] = $vss->getName();
|
|
|
|
|
|
}
|
2020-05-10 18:25:51 +08:00
|
|
|
|
}
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
return $result;
|
2020-04-29 15:29:56 +08:00
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2021-09-01 14:14:00 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @internal 用于 level 排序
|
|
|
|
|
|
* @param $events
|
|
|
|
|
|
* @param string $class_name
|
|
|
|
|
|
* @param string $prefix
|
|
|
|
|
|
*/
|
2021-01-02 13:15:50 +08:00
|
|
|
|
public function sortByLevel(&$events, string $class_name, $prefix = "") {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
if (is_a($class_name, Level::class, true)) {
|
|
|
|
|
|
$class_name .= $prefix;
|
|
|
|
|
|
usort($events[$class_name], function ($a, $b) {
|
|
|
|
|
|
$left = $a->level;
|
|
|
|
|
|
$right = $b->level;
|
|
|
|
|
|
return $left > $right ? -1 : ($left == $right ? 0 : 1);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2021-09-01 14:14:00 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @throws AnnotationException
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function verifyMiddlewares() {
|
|
|
|
|
|
if ((ZMConfig::get("global", "runtime")["middleware_error_policy"] ?? 1) === 2) {
|
|
|
|
|
|
//我承认套三层foreach很不优雅,但是这个会很快的。
|
|
|
|
|
|
foreach($this->middleware_map as $class => $v) {
|
|
|
|
|
|
foreach ($v as $method => $vs) {
|
|
|
|
|
|
foreach($vs as $mid) {
|
|
|
|
|
|
if (!isset($this->middlewares[$mid->middleware])) {
|
|
|
|
|
|
throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$mid->middleware}\"!");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-03-29 16:29:02 +08:00
|
|
|
|
}
|