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:----keab64LDwnQUnxGWQoRxz/T7T8sV0DGrAouq7um9UHi65xlIzH2Mkc2W9j37JjRW0B6UKIDAklCQTwcyWCax24YXZFL6oSFb+ZZgSbVs/GJeApLa3RJDhgahqR/Z+PjKk3mlKn5PTPd8JETuMqPuScUVVdStpznikNaKblSBV68Tbi5vCU++9x6ERjt/hesFAVVwABjG3w7Gub4lpklATrnK1A1DSNihZRWgV26e0RCxrEccgwS8IqGqiK/rxFjxAa2Zl5oBktpUVFQggWinqYQA6BrSrHaIZ+YtAjJWrzSdCbSzmZUH1bjIIecvOz09tBmd46byy/sCtWim7Gagzig0hMUX7A7fAXvJNr1YPo4dz+ht0boNV8JyBJ165kvuuhmQxU4GvQXwZusWXftsvME4RdmkemDsujm2u8/xnu0w3wA2NR9gd+5GmVn7J5fo/tEYDbwOlt2QeEnkENFtFE3RZFdDNa3lh43MAM+cZuVes2q380hPQy73d2Rk575yMEAnxYT2j6AMwWOTtXYS/1usOmA+CeK3CRmPizmPW6Aq01+O+wqvq9QHfSsQwMjHg84Z1S42YrVfhfl/RqDpC7LrH6pCkGReH94fvp3Y8USUNJN/4ocdqI2ALXTI3+N15WF2EkwknGmFlIq5gGxUj1V7YZQ0MdbLxoTKR+GLrHM=----ATTACHMENT:----MzM5MzExOTk3MjkzNzMxIDI1Nzg1ODY0NzE0MjI5MjIgOTU5Njc0MDEwNjQwNTI1NQ==