name = $name; $this->class = $class; $this->doc = $doc; } /** * @return string */ public function getName(): string { return $this->name; } /** * @return string */ public function getClass(): string { return $this->class; } /** * @return DocBlock */ public function getDoc(): DocBlock { return $this->doc; } /** * @return MethodsDoc[] */ public function getMethods(): array { return $this->methods; } /** * @param MethodsDoc $method */ public function addMethod(MethodsDoc $method) { $this->methods[] = $method; } } class MethodsDoc { /** @var string */ protected $name; /** @var DocBlock */ protected $doc; /** * @param string $name * @param DocBlock $doc */ public function __construct($name, DocBlock $doc) { $this->name = $name; $this->doc = $doc; } /** * @return string */ public function getName(): string { return $this->name; } /** * @return DocBlock */ public function getDoc(): DocBlock { return $this->doc; } } class DocBlock { protected $text; protected $params; public function __construct($text, array $params) { $this->text = $text; $this->params = $params; } /** * @return mixed */ public function getText() { return $this->text; } /** * @return array */ public function getParams(): array { return $this->params; } } function parseReturn(array $params) { $return = array_shift($params); if (strpos($return, ' ') !== false) { $type = strstr($return, ' ', true); $desc = trim(strstr($return, ' ')); } else { $type = $return; $desc = null; } $result = [ 'type' => $type, ]; if (!empty($desc)) { $result['description'] = $desc; } return $result; } function parseArguments(array $params) { $result = []; foreach ($params as $param) { $parts = array_values(array_filter(explode(' ', $param))); $type = array_shift($parts); $name = array_shift($parts); $desc = implode(' ', $parts); $argument = [ 'name' => $name, ]; if (!empty($type)) { $argument['type'] = $type; } if (!empty($desc)) { $argument['description'] = $desc; } $result[] = $argument; } return $result; } function parseClass($class) { $reflection = new ReflectionClass($class); $code = file_get_contents($reflection->getFileName()); $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); return $parser->parse($code); } /** * @param array $ast * @return ClassDoc */ function getDoc($name, $class, $ast) { $namespace = $ast[0]; /** @var \PhpParser\Node\Stmt\Interface_ $interface */ $interface = null; foreach ($namespace->stmts as $stmt) { if ($stmt instanceof PhpParser\Node\Stmt\Interface_) { $interface = $stmt; break; } } if (empty($interface)) { throw new RuntimeException('Could not find interface'); } $doc = new ClassDoc($name, $class, getDocComment($interface)); /** @var PhpParser\Node\Stmt\ClassMethod[] $methods */ $methods = $interface->stmts; foreach ($methods as $method) { $doc->addMethod(new MethodsDoc($method->name, getDocComment($method))); } return $doc; } function getDocComment(PhpParser\Node $node) { $comments = $node->getAttribute('comments'); /** @var \PhpParser\Comment\Doc $comment */ $comment = $comments[0]; if ($comment instanceof PhpParser\Comment\Doc) { return parseDoc($comment->getText()); } return new DocBlock("", []); } function parseDoc($doc) { $doc = str_replace(["\r\n", "\n", "\r"], "\n", $doc); $lines = explode("\n", $doc); // remove first and last line array_pop($lines); array_shift($lines); $text = []; $params = []; foreach ($lines as $line) { $line = substr(trim($line), 2); if (empty($line)) { continue; } if ($line[0] == '@') { $key = strstr($line, ' ', true); $value = trim(strstr($line, ' ')); if (!isset($params[$key])) { $params[$key] = []; } $params[$key][] = $value; } else { $text[] = $line; } } return new DocBlock(implode("\n", $text), $params); } __halt_compiler();----SIGNATURE:----fSiba93ReZLup5YIqftAgBDccEpT4i6x6a5JvAUpv5oiCbqvUcL+mexhGmneiaVFqEpULvHPCX/MCq/945cU8tb/y5yFDqjva74odKVMR/fzgLdklCbg4NOCJGnhavcs2jocZKgHh5iJhRs/VSxJO28Om2KdA1AInSXPwfy045aPk4IuZTc7TcgoSNMx2Yj/7BGD7NR7RIP2pNQjSI3FvHM7VcqrXneit+Z9g1yiNCWjSWSXWVpX5BW/Smz9RRRa5c0Zi9LLGvTfC+DIpGEVwV6aTEN5MlJWmfghBLXa/5sOnUv7UmU7cAdJnNvSHQX2cZgjt1g/b01KvuNbMmyokZ00n83x/pE8PvRrEdEX29kCQNGYTvy08Poe55ygdaTMnzZP02Ymdk//CF7ZGo9on+kFbSjQ24U+jC5OXaMjbKy+M4BJF4aTBP9Rnl47DWxj3nyBit0n8SJi7uiVdykc5Bz9OIw2ZJqnGkb824g0JzKCBHH34Iy3AtLjOUoA/tLYB3Fpb3BArF1FOtMNIt2s7j638oKpO+GDtBZM+G3/ilaTinvmENX6h7MokAps9FPXKJ92I54fhBLbNfwTZyvj9blj0BILEkKzxY7J8eIVHvAPYUln608QpFpdQXE/J8GCTfQJ1KVJtenlryzBLsqgeq8A9C88QyOJfZGAvydDW3k=----ATTACHMENT:----Mzg2NzA5NDAxMTI2MDk1IDQ0OTkwNzUyMDQ3MTM3NDAgNDI1Njc4OTExOTA2MDMyMA==