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:----iYl5/HnCX/WieHxlotUZ0XQWWZL/L6JVB4DfkFW20lFqlLIFl/9lYxP9L6zJV5ZQL1D9qhxVM/wSK2jRuzlhpjBILJ2DyWiUSs9vGMpP38oJcGjhLrzj23xDsujolD9GPNJCCgxk08IH0xQ9Y6cCZlHjeS1+YIabLR4hGCXKd58VFo0ow1O4xbdXJ8XP4dJL/WXPNutiHwG0PP78GLjwtK3oOry0cBmL2h/aU85AZjGjL/gG8+K1ghQ3n/8VM6HGQQ5sRd/V2KnAvSdXdQ/rZAR0i90CJ72BAEqlO2ttQozhinJHuQgKbfw57mZayHe7zdgNSlWjGVz8HmSRtXIIe9S1v4Gpy7brb36E6tL5/JwYqotOUO3QjT0+Q391dGTxVNjcXDNHuJImbb1VVRLmq1sy4kJtuU2xJrxslT3cVBtBum6oclLQ/dzGhjRRVdFjjPVEypSlIdKnc0rVauhKTYX0DYcdiHMuHcmXYLMUpw141s2GwY2SaEorEyohzaV/bQDZeKtR79tWo6OkqHaQj/2mHAhFvKGUESkos6E21BYdKeKsGEQFWC1V1FqXuM18VPUHFGFRyvRgcf3UtIFnVYso6oiN1JCSWpnW5KM8vmafXVh0V2fTQEkfSk063ztIBDmmsMaHSRVgUWZQli6z7XUXPDWA3eCKbbdEDwOIueI=----ATTACHMENT:----NTUzMjQ0NzcyNzQ2NzkwNSA0OTc2NTQ2MTgwMjY4MTA5IDQyMzg4NzU2NzU2OTU2NzQ=