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) { /** @var \PhpParser\Node\Stmt\Namespace_ $namespace */ $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:----e3hhXxC54Af30RWw913wnMFIZxQkyK63hp1XKzna5Z/RXI3maWBwempsZFc0bkWk27aOqDTS8qwYD+cNd8PZu0yFapI6Cbot66q+I7cF4ll7uLyvrMnV5Rin6ea8lqpRruldWBd8AZeuvW2IBrH02A68/vFlCnD1/j4/ILqmzgqgoJWiFvPF+STIW/b7vBVxW/8dtMFH4mkFY3Zhid99/7UuSFDgE5oTokXmV/hIB2yY4/7OCs/Gv342b6TTWWOqtnp69mMkc50/ZxzSZxSLFFYzkrhyh0i0lbttoa92WpospEpqeZRxjG1ADRM7yAVuV//7/iRYB3Yjv8AltQJlkuHfy1VbL+7nXe9LbCOz1ayEkSsAGa1Xdg3v/cJzkVoBAncUV2QD3L/i/8P+198xNNsEwROg8/2vpwI9QgXOjqiq5ED88723Q66QSI2h0vXlg3IxJIsskqJvMso/UTri5D9KySc7mjQCINFoRZXZ3gATqhq8MrPWMb8y6AkSOt8oXUnTGq+e4GRrBwG5dPpwxUelD/rw0/NkWvn2hlNRCTEpew6VxSpNYfGP52Vc5+6p35K4QhZ5i4dyK79GhlPddpT/UbP0lKq6RMTpSDUDCBIMJxvCUHFPvgdF4nOLrNEY2upTP8O7t8hyzclnZbUUabvXFK44lBdsGjYIkOGc2ww=----ATTACHMENT:----NDkyMjE1ODc5MTIxNTIzMyAzNTMwMzU5Njk0MjU4MjQzIDcyNTYwMDcxNDQ4NDk0NDQ=