PHPDOC
This commit is contained in:
parent
ac47a23639
commit
def6199437
@ -44,12 +44,12 @@
|
|||||||
"amphp/websocket-client": "^1.0"
|
"amphp/websocket-client": "^1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"danog/class-finder": "dev-master",
|
||||||
"phpdocumentor/reflection-docblock": "^5.2",
|
"phpdocumentor/reflection-docblock": "^5.2",
|
||||||
"vlucas/phpdotenv": "^3",
|
"vlucas/phpdotenv": "^3",
|
||||||
"ennexa/amp-update-cache": "dev-master",
|
"ennexa/amp-update-cache": "dev-master",
|
||||||
"phpunit/phpunit": "^8",
|
"phpunit/phpunit": "^9",
|
||||||
"amphp/php-cs-fixer-config": "dev-master",
|
"amphp/php-cs-fixer-config": "dev-master",
|
||||||
"haydenpierce/class-finder": "^0.4.2",
|
|
||||||
"amphp/http-server": "dev-master",
|
"amphp/http-server": "dev-master",
|
||||||
"amphp/http": "^1.6",
|
"amphp/http": "^1.6",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
@ -57,8 +57,7 @@
|
|||||||
"danog/7to5": "^1",
|
"danog/7to5": "^1",
|
||||||
"vimeo/psalm": "dev-master",
|
"vimeo/psalm": "dev-master",
|
||||||
"phpstan/phpstan": "^0.12.14",
|
"phpstan/phpstan": "^0.12.14",
|
||||||
"friendsofphp/php-cs-fixer": "^2.16",
|
"friendsofphp/php-cs-fixer": "^2"
|
||||||
"squizlabs/php_codesniffer": "^3.5"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)"
|
"ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)"
|
||||||
|
@ -122,7 +122,7 @@ final class APIWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property list
|
* Property list.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
@ -132,7 +132,7 @@ final class APIWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleep function
|
* Sleep function.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -55,7 +55,7 @@ class ContextConnector implements Connector
|
|||||||
$this->logger->logger('OK!', \danog\MadelineProto\Logger::WARNING);
|
$this->logger->logger('OK!', \danog\MadelineProto\Logger::WARNING);
|
||||||
return $result->getSocket();
|
return $result->getSocket();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
if (defined('MADELINEPROTO_TEST') && \constant("MADELINEPROTO_TEST") === 'pony') {
|
if (\defined('MADELINEPROTO_TEST') && \constant("MADELINEPROTO_TEST") === 'pony') {
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
$this->logger->logger('Connection failed: '.$e, \danog\MadelineProto\Logger::ERROR);
|
$this->logger->logger('Connection failed: '.$e, \danog\MadelineProto\Logger::ERROR);
|
||||||
|
@ -281,7 +281,7 @@ final class Coroutine implements Promise, \ArrayAccess, JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain
|
* Obtain.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -146,6 +146,7 @@ class DataCenter
|
|||||||
/** @psalm-suppress UndefinedPropertyFetch */
|
/** @psalm-suppress UndefinedPropertyFetch */
|
||||||
$array[$id]['permAuthKey']['authorized'] = $socket->authorized;
|
$array[$id]['permAuthKey']['authorized'] = $socket->authorized;
|
||||||
}
|
}
|
||||||
|
$array[$id] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->setDataCenterConnections($array);
|
$this->setDataCenterConnections($array);
|
||||||
|
@ -208,10 +208,10 @@ class RedisArray extends SqlArray
|
|||||||
return call(function () {
|
return call(function () {
|
||||||
$iterator = $this->getIterator();
|
$iterator = $this->getIterator();
|
||||||
$result = [];
|
$result = [];
|
||||||
$len = strlen($this->rKey(''));
|
$len = \strlen($this->rKey(''));
|
||||||
while (yield $iterator->advance()) {
|
while (yield $iterator->advance()) {
|
||||||
[$key, $value] = $iterator->getCurrent();
|
[$key, $value] = $iterator->getCurrent();
|
||||||
$key = substr($key, $len);
|
$key = \substr($key, $len);
|
||||||
$result[$key] = $value;
|
$result[$key] = $value;
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -53,7 +53,8 @@ class Wrapper extends ClientAbstract
|
|||||||
* @param mixed $data Payload data
|
* @param mixed $data Payload data
|
||||||
* @param SessionPaths $ipc IPC URI
|
* @param SessionPaths $ipc IPC URI
|
||||||
*
|
*
|
||||||
* @return \Generator<int, Promise<ChannelledSocket>|Promise<mixed>, mixed, Wrapper>
|
* @return \Generator
|
||||||
|
* @psalm-return \Generator<int, Promise<ChannelledSocket>|Promise<mixed>, mixed, Wrapper>
|
||||||
*/
|
*/
|
||||||
public static function create(&$data, SessionPaths $session, Logger $logger): \Generator
|
public static function create(&$data, SessionPaths $session, Logger $logger): \Generator
|
||||||
{
|
{
|
||||||
|
@ -862,9 +862,13 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
$this->rpcLoop = new PeriodicLoopInternal($this, [$this, 'rpcReport'], 'config', 60 * 1000);
|
$this->rpcLoop = new PeriodicLoopInternal($this, [$this, 'rpcReport'], 'config', 60 * 1000);
|
||||||
}
|
}
|
||||||
if (!$this->ipcServer) {
|
if (!$this->ipcServer) {
|
||||||
|
try {
|
||||||
$this->ipcServer = new Server($this);
|
$this->ipcServer = new Server($this);
|
||||||
$this->ipcServer->setSettings($this->settings->getIpc());
|
$this->ipcServer->setSettings($this->settings->getIpc());
|
||||||
$this->ipcServer->setIpcPath($this->wrapper->session);
|
$this->ipcServer->setIpcPath($this->wrapper->session);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->logger->logger("Error while starting IPC server: $e", Logger::FATAL_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->callCheckerLoop->start();
|
$this->callCheckerLoop->start();
|
||||||
$this->serializeLoop->start();
|
$this->serializeLoop->start();
|
||||||
@ -872,7 +876,11 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
$this->configLoop->start();
|
$this->configLoop->start();
|
||||||
$this->checkTosLoop->start();
|
$this->checkTosLoop->start();
|
||||||
$this->rpcLoop->start();
|
$this->rpcLoop->start();
|
||||||
|
try {
|
||||||
$this->ipcServer->start();
|
$this->ipcServer->start();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->logger->logger("Error while starting IPC server: $e", Logger::FATAL_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Stop all internal loops.
|
* Stop all internal loops.
|
||||||
@ -1167,6 +1175,9 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
*/
|
*/
|
||||||
public function unreference(): void
|
public function unreference(): void
|
||||||
{
|
{
|
||||||
|
if (!isset($this->logger)) {
|
||||||
|
$this->logger = new Logger(new \danog\MadelineProto\Settings\Logger);
|
||||||
|
}
|
||||||
$this->logger->logger("Will unreference instance");
|
$this->logger->logger("Will unreference instance");
|
||||||
if (isset(self::$references[\spl_object_hash($this)])) {
|
if (isset(self::$references[\spl_object_hash($this)])) {
|
||||||
unset(self::$references[\spl_object_hash($this)]);
|
unset(self::$references[\spl_object_hash($this)]);
|
||||||
@ -1175,6 +1186,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
if (isset($this->seqUpdater)) {
|
if (isset($this->seqUpdater)) {
|
||||||
$this->seqUpdater->signal(true);
|
$this->seqUpdater->signal(true);
|
||||||
}
|
}
|
||||||
|
if (isset($this->channels_state)) {
|
||||||
$channelIds = [];
|
$channelIds = [];
|
||||||
foreach ($this->channels_state->get() as $state) {
|
foreach ($this->channels_state->get() as $state) {
|
||||||
$channelIds[] = $state->getChannel();
|
$channelIds[] = $state->getChannel();
|
||||||
@ -1188,9 +1200,12 @@ class MTProto extends AsyncConstruct implements TLCallback
|
|||||||
$this->updaters[$channelId]->signal(true);
|
$this->updaters[$channelId]->signal(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (isset($this->datacenter)) {
|
||||||
foreach ($this->datacenter->getDataCenterConnections() as $datacenter) {
|
foreach ($this->datacenter->getDataCenterConnections() as $datacenter) {
|
||||||
$datacenter->disconnect();
|
$datacenter->disconnect();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$this->logger->logger("Unreferenced instance");
|
$this->logger->logger("Unreferenced instance");
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -24,22 +24,25 @@ class ClassDoc extends GenericDoc
|
|||||||
* @var array<string, MethodDoc>
|
* @var array<string, MethodDoc>
|
||||||
*/
|
*/
|
||||||
private array $methods = [];
|
private array $methods = [];
|
||||||
public function __construct(ReflectionClass $reflectionClass)
|
public function __construct(PhpDocBuilder $builder, ReflectionClass $reflectionClass)
|
||||||
{
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
$this->name = $reflectionClass->getName();
|
||||||
$doc = $reflectionClass->getDocComment();
|
$doc = $reflectionClass->getDocComment();
|
||||||
if (!$doc) {
|
if (!$doc) {
|
||||||
Logger::log($reflectionClass->getName()." has no PHPDOC");
|
Logger::log($reflectionClass->getName()." has no PHPDOC");
|
||||||
$this->ignore = true;
|
$this->ignore = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$doc = PhpDocBuilder::$factory->create($doc);
|
$doc = $this->builder->getFactory()->create($doc);
|
||||||
|
|
||||||
parent::__construct($doc);
|
parent::__construct($doc, $reflectionClass);
|
||||||
|
|
||||||
$tags = $doc->getTags();
|
$tags = $doc->getTags();
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
if ($tag instanceof Property) {
|
if ($tag instanceof Property) {
|
||||||
$this->properties[$tag->getVariableName()] = new PropertyDoc(
|
$this->properties[$tag->getVariableName()] = new PropertyDoc(
|
||||||
|
$this->builder,
|
||||||
$tag->getName(),
|
$tag->getName(),
|
||||||
$tag->getType(),
|
$tag->getType(),
|
||||||
$tag->getDescription()
|
$tag->getDescription()
|
||||||
@ -52,6 +55,7 @@ class ClassDoc extends GenericDoc
|
|||||||
$type = \str_replace('@property ', '', $type);
|
$type = \str_replace('@property ', '', $type);
|
||||||
$description ??= '';
|
$description ??= '';
|
||||||
$this->properties[$varName] = new PropertyDoc(
|
$this->properties[$varName] = new PropertyDoc(
|
||||||
|
$this->builder,
|
||||||
$varName,
|
$varName,
|
||||||
$type,
|
$type,
|
||||||
$description
|
$description
|
||||||
@ -66,8 +70,8 @@ class ClassDoc extends GenericDoc
|
|||||||
}
|
}
|
||||||
$description = '';
|
$description = '';
|
||||||
if ($refl->getDocComment()) {
|
if ($refl->getDocComment()) {
|
||||||
$docConst = PhpDocBuilder::$factory->create($refl->getDocComment());
|
$docConst = $this->builder->getFactory()->create($refl->getDocComment());
|
||||||
if (\in_array($refl->getDeclaringClass()->getName(), PhpDocBuilder::DISALLOW)) {
|
if ($this->builder->shouldIgnore($refl->getDeclaringClass()->getName())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$description .= $docConst->getSummary();
|
$description .= $docConst->getSummary();
|
||||||
@ -88,12 +92,40 @@ class ClassDoc extends GenericDoc
|
|||||||
|
|
||||||
|
|
||||||
foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
||||||
if (str_starts_with($method->getName(), '__') && $method !== '__construct') continue;
|
if (str_starts_with($method->getName(), '__') && $method !== '__construct') {
|
||||||
$this->methods[$method->getName()] = new MethodDoc($method);
|
continue;
|
||||||
}
|
}
|
||||||
|
$this->methods[$method->getName()] = new MethodDoc($this->builder, $method);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->methods = \array_filter($this->methods, fn (MethodDoc $doc): bool => !$doc->shouldIgnore());
|
||||||
|
//$this->properties = \array_filter($this->properties, fn (PropertyDoc $doc): bool => !$doc->shouldIgnore());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function format(): string
|
public function format(): string
|
||||||
{
|
{
|
||||||
|
$init = parent::format();
|
||||||
|
$methods = '';
|
||||||
|
$properties = '';
|
||||||
|
if ($this->methods) {
|
||||||
|
$init .= "\n";
|
||||||
|
foreach ($this->methods as $method) {
|
||||||
|
$init .= "* ".$method->getSignature()."\n";
|
||||||
|
}
|
||||||
|
$init .= "\n";
|
||||||
|
$init .= "## Methods:\n$methods\n";
|
||||||
|
foreach ($this->methods as $method) {
|
||||||
|
$init .= $method->format();
|
||||||
|
$init .= "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($properties) {
|
||||||
|
$init .= "## Properties:\n$properties\n";
|
||||||
|
/*foreach ($this->properties as $property) {
|
||||||
|
$init .= $property->format();
|
||||||
|
$init .= "\n";
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
return $init;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
src/danog/MadelineProto/PhpDoc/FunctionDoc.php
Normal file
25
src/danog/MadelineProto/PhpDoc/FunctionDoc.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace danog\MadelineProto\PhpDoc;
|
||||||
|
|
||||||
|
use danog\MadelineProto\Logger;
|
||||||
|
use danog\MadelineProto\PhpDocBuilder;
|
||||||
|
use ReflectionFunction;
|
||||||
|
|
||||||
|
class FunctionDoc extends MethodDoc
|
||||||
|
{
|
||||||
|
public function __construct(PhpDocBuilder $builder, ReflectionFunction $reflectionClass)
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
$this->nameGenericDoc = $reflectionClass->getName();
|
||||||
|
$doc = $reflectionClass->getDocComment();
|
||||||
|
if (!$doc) {
|
||||||
|
Logger::log($reflectionClass->getName()." has no PHPDOC");
|
||||||
|
$this->ignore = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$doc = $this->builder->getFactory()->create($doc);
|
||||||
|
|
||||||
|
parent::__construct($builder, $reflectionClass);
|
||||||
|
}
|
||||||
|
}
|
@ -2,39 +2,60 @@
|
|||||||
|
|
||||||
namespace danog\MadelineProto\PhpDoc;
|
namespace danog\MadelineProto\PhpDoc;
|
||||||
|
|
||||||
|
use danog\MadelineProto\PhpDocBuilder;
|
||||||
use phpDocumentor\Reflection\DocBlock;
|
use phpDocumentor\Reflection\DocBlock;
|
||||||
use phpDocumentor\Reflection\DocBlock\Description;
|
use phpDocumentor\Reflection\DocBlock\Description;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Author;
|
use phpDocumentor\Reflection\DocBlock\Tags\Author;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
|
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen;
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\See;
|
use phpDocumentor\Reflection\DocBlock\Tags\See;
|
||||||
|
|
||||||
abstract class GenericDoc
|
abstract class GenericDoc
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Builder instance.
|
||||||
|
*/
|
||||||
|
protected PhpDocBuilder $builder;
|
||||||
|
/**
|
||||||
|
* Name.
|
||||||
|
*/
|
||||||
|
protected string $name;
|
||||||
/**
|
/**
|
||||||
* Title.
|
* Title.
|
||||||
*/
|
*/
|
||||||
private string $title;
|
protected string $title;
|
||||||
/**
|
/**
|
||||||
* Description.
|
* Description.
|
||||||
*/
|
*/
|
||||||
private Description $description;
|
protected Description $description;
|
||||||
/**
|
/**
|
||||||
* See also array.
|
* See also array.
|
||||||
*
|
*
|
||||||
* @var array<string, string>
|
* @var array<string, See>
|
||||||
*/
|
*/
|
||||||
private array $seeAlso = [];
|
protected array $seeAlso = [];
|
||||||
/**
|
/**
|
||||||
* Author.
|
* Author.
|
||||||
*/
|
*/
|
||||||
private Author $author;
|
protected Author $author;
|
||||||
/**
|
/**
|
||||||
* Ignore this class.
|
* Ignore this class.
|
||||||
*/
|
*/
|
||||||
protected bool $ignore = false;
|
protected bool $ignore = false;
|
||||||
public function __construct(DocBlock $doc)
|
/**
|
||||||
|
* Class name.
|
||||||
|
*/
|
||||||
|
protected string $className;
|
||||||
|
/**
|
||||||
|
* Class namespace.
|
||||||
|
*/
|
||||||
|
protected string $namespace;
|
||||||
|
public function __construct(DocBlock $doc, $reflectionClass)
|
||||||
{
|
{
|
||||||
|
$this->className = $reflectionClass->getName();
|
||||||
|
$this->namespace = \str_replace('/', '\\', \dirname(\str_replace('\\', '/', $this->className)));
|
||||||
$this->title = $doc->getSummary();
|
$this->title = $doc->getSummary();
|
||||||
$this->description = $doc->getDescription();
|
$this->description = $doc->getDescription();
|
||||||
$tags = $doc->getTags();
|
$tags = $doc->getTags();
|
||||||
@ -53,14 +74,65 @@ abstract class GenericDoc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ($tag instanceof See) {
|
if ($tag instanceof See) {
|
||||||
$this->seeAlso[$tag->getReference()->__toString()] = $tag->render();
|
$this->seeAlso[$tag->getReference()->__toString()] = $tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function seeAlso(): string
|
||||||
|
{
|
||||||
|
$seeAlso = '';
|
||||||
|
foreach ($this->seeAlso as $see) {
|
||||||
|
$ref = $see->getReference();
|
||||||
|
if ($ref instanceof Fqsen) {
|
||||||
|
$ref = (string) $ref;
|
||||||
|
$ref = $this->builder->resolveTypeAlias($this->className, $ref);
|
||||||
|
$refExpl = \explode("\\", $ref);
|
||||||
|
$name = \array_pop($refExpl);
|
||||||
|
$namespace = \explode('/', $this->namespace);
|
||||||
|
$count = \count($refExpl);
|
||||||
|
foreach ($namespace as $k => $name) {
|
||||||
|
if (isset($refExpl[$k]) && $refExpl[$k] === $name) {
|
||||||
|
$count--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ref = \str_repeat('../', $count)
|
||||||
|
.\implode('/', \array_slice($refExpl, $count))
|
||||||
|
."/$name.md";
|
||||||
|
|
||||||
|
$desc = $see->getDescription() ?: $ref;
|
||||||
|
$seeAlso .= "* [$desc]($ref)\n";
|
||||||
|
}
|
||||||
|
if ($ref instanceof Url) {
|
||||||
|
$desc = $see->getDescription() ?: $ref;
|
||||||
|
$seeAlso .= "* [$desc]($ref)\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($seeAlso) {
|
||||||
|
$seeAlso = "\n#### See also: \n$seeAlso\n\n";
|
||||||
|
}
|
||||||
|
return $seeAlso;
|
||||||
|
}
|
||||||
public function format(): string
|
public function format(): string
|
||||||
{
|
{
|
||||||
return '';
|
$seeAlso = $this->seeAlso();
|
||||||
|
return <<<EOF
|
||||||
|
---
|
||||||
|
title: $this->name: $this->title
|
||||||
|
description: $this->description
|
||||||
|
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||||
|
---
|
||||||
|
# `$this->name`: $this->title
|
||||||
|
[Back to API index](index.md)
|
||||||
|
|
||||||
|
> Author: $this->author
|
||||||
|
|
||||||
|
$this->description
|
||||||
|
$seeAlso
|
||||||
|
EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shouldIgnore(): bool
|
public function shouldIgnore(): bool
|
||||||
|
@ -8,27 +8,37 @@ use phpDocumentor\Reflection\DocBlock\Description;
|
|||||||
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Param;
|
use phpDocumentor\Reflection\DocBlock\Tags\Param;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
|
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
|
||||||
|
use ReflectionFunctionAbstract;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
|
|
||||||
class MethodDoc extends GenericDoc
|
class MethodDoc extends GenericDoc
|
||||||
{
|
{
|
||||||
private $return;
|
private $return;
|
||||||
private array $params = [];
|
private array $params = [];
|
||||||
public function __construct(ReflectionMethod $method)
|
public function __construct(PhpDocBuilder $phpDocBuilder, ReflectionFunctionAbstract $method)
|
||||||
{
|
{
|
||||||
|
$this->builder = $phpDocBuilder;
|
||||||
|
$this->name = $method->getName();
|
||||||
$doc = $method->getDocComment();
|
$doc = $method->getDocComment();
|
||||||
if (!$doc) {
|
if (!$doc) {
|
||||||
$this->ignore = true;
|
$this->ignore = true;
|
||||||
|
if ($method instanceof ReflectionMethod) {
|
||||||
Logger::log($method->getDeclaringClass()->getName().'::'.$method->getName().' has no PHPDOC!');
|
Logger::log($method->getDeclaringClass()->getName().'::'.$method->getName().' has no PHPDOC!');
|
||||||
|
} else {
|
||||||
|
Logger::log($method->getName().' has no PHPDOC!');
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$doc = PhpDocBuilder::$factory->create($doc);
|
$doc = $this->builder->getFactory()->create($doc);
|
||||||
|
|
||||||
parent::__construct($doc);
|
parent::__construct($doc, $method instanceof ReflectionMethod ? $method->getDeclaringClass() : $method);
|
||||||
|
|
||||||
foreach ($doc->getTags() as $tag) {
|
foreach ($doc->getTags() as $tag) {
|
||||||
if ($tag instanceof Param && !isset($this->params[$tag->getVariableName()])) {
|
if ($tag instanceof Param && !isset($this->params[$tag->getVariableName()])) {
|
||||||
$this->params[$tag->getVariableName()] = $tag;
|
$this->params[$tag->getVariableName()] = [
|
||||||
|
$tag->getType(),
|
||||||
|
$tag->getDescription()
|
||||||
|
];
|
||||||
} elseif ($tag instanceof Return_ && !$this->return) {
|
} elseif ($tag instanceof Return_ && !$this->return) {
|
||||||
$this->return = $tag;
|
$this->return = $tag;
|
||||||
} elseif ($tag instanceof Generic && $tag->getName() === 'psalm-return') {
|
} elseif ($tag instanceof Generic && $tag->getName() === 'psalm-return') {
|
||||||
@ -38,7 +48,7 @@ class MethodDoc extends GenericDoc
|
|||||||
$description .= ' ';
|
$description .= ' ';
|
||||||
[$varName, $description] = \explode(" ", $description, 2);
|
[$varName, $description] = \explode(" ", $description, 2);
|
||||||
if (!$description && isset($this->params[$varName])) {
|
if (!$description && isset($this->params[$varName])) {
|
||||||
$description = $this->params[$varName]->getDescription();
|
$description = (string) $this->params[$varName][1];
|
||||||
} else {
|
} else {
|
||||||
$description = new Description($description);
|
$description = new Description($description);
|
||||||
}
|
}
|
||||||
@ -50,8 +60,36 @@ class MethodDoc extends GenericDoc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(): string
|
public function getSignature(): string
|
||||||
{
|
{
|
||||||
return '';
|
$sig = $this->name;
|
||||||
|
$sig .= "(";
|
||||||
|
foreach ($this->params as $var => [$type, $description]) {
|
||||||
|
$sig .= $type.' ';
|
||||||
|
$sig .= "$".$var;
|
||||||
|
$sig .= ', ';
|
||||||
|
}
|
||||||
|
$sig = \trim($sig, ', ');
|
||||||
|
$sig .= ')';
|
||||||
|
if ($this->return) {
|
||||||
|
$sig .= ': ';
|
||||||
|
$sig .= $this->return;
|
||||||
|
}
|
||||||
|
return $sig;
|
||||||
|
}
|
||||||
|
public function format(): string
|
||||||
|
{
|
||||||
|
$sig = '### '.$this->getSignature();
|
||||||
|
$sig .= "\n\n";
|
||||||
|
$sig .= $this->title;
|
||||||
|
$sig .= "\n";
|
||||||
|
$sig .= $this->description;
|
||||||
|
$sig .= "\n";
|
||||||
|
if ($this->return && $this->return->getDescription() && $this->return->getDescription()->render()) {
|
||||||
|
$sig .= "\nReturn value: ".$this->return->getDescription()."\n";
|
||||||
|
}
|
||||||
|
$sig .= $this->seeAlso();
|
||||||
|
$sig .= "\n";
|
||||||
|
return $sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace danog\MadelineProto\PhpDoc;
|
namespace danog\MadelineProto\PhpDoc;
|
||||||
|
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Property;
|
use danog\MadelineProto\PhpDocBuilder;
|
||||||
|
|
||||||
class PropertyDoc
|
class PropertyDoc
|
||||||
{
|
{
|
||||||
public function __construct(string $name, $type, $description)
|
public function __construct(PhpDocBuilder $phpDocBuilder, string $name, $type, $description)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,109 +18,159 @@
|
|||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
use danog\MadelineProto\Async\AsyncConstruct;
|
use danog\ClassFinder\ClassFinder;
|
||||||
use danog\MadelineProto\Db\DbPropertiesTrait;
|
|
||||||
use danog\MadelineProto\Files\Server;
|
|
||||||
use danog\MadelineProto\MTProtoTools\Crypt;
|
|
||||||
use danog\MadelineProto\MTProtoTools\GarbageCollector;
|
|
||||||
use danog\MadelineProto\MTProtoTools\MinDatabase;
|
|
||||||
use danog\MadelineProto\MTProtoTools\PasswordCalculator;
|
|
||||||
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
|
|
||||||
use danog\MadelineProto\MTProtoTools\UpdatesState;
|
|
||||||
use danog\MadelineProto\PhpDoc\ClassDoc;
|
use danog\MadelineProto\PhpDoc\ClassDoc;
|
||||||
use danog\MadelineProto\TL\TL;
|
use danog\MadelineProto\PhpDoc\FunctionDoc;
|
||||||
use danog\MadelineProto\TL\TLCallback;
|
|
||||||
use danog\MadelineProto\TL\TLConstructors;
|
|
||||||
use danog\MadelineProto\TL\TLMethods;
|
|
||||||
use danog\MadelineProto\TON\ADNLConnection;
|
|
||||||
use danog\MadelineProto\TON\APIFactory as TAPIFactory;
|
|
||||||
use danog\MadelineProto\TON\InternalDoc as TInternalDoc;
|
|
||||||
use danog\MadelineProto\TON\Lite;
|
|
||||||
use HaydenPierce\ClassFinder\ClassFinder;
|
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Author;
|
|
||||||
use phpDocumentor\Reflection\DocBlockFactory;
|
use phpDocumentor\Reflection\DocBlockFactory;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionMethod;
|
use ReflectionFunction;
|
||||||
|
|
||||||
class PhpDocBuilder
|
class PhpDocBuilder
|
||||||
{
|
{
|
||||||
const DISALLOW = [
|
/**
|
||||||
AnnotationsBuilder::class,
|
* Namespace.
|
||||||
APIFactory::class,
|
*/
|
||||||
APIWrapper::class,
|
private string $namespace;
|
||||||
AbstractAPIFactory::class,
|
/**
|
||||||
Bug74586Exception::class,
|
* Scan mode.
|
||||||
Connection::class,
|
*/
|
||||||
ContextConnector::class,
|
private int $mode;
|
||||||
DataCenter::class,
|
/**
|
||||||
DataCenterConnection::class,
|
* Docblock factory.
|
||||||
DoHConnector::class,
|
*/
|
||||||
DocsBuilder::class,
|
private DocBlockFactory $factory;
|
||||||
InternalDoc::class,
|
/**
|
||||||
Lang::class,
|
* Classes/interfaces/traits to ignore.
|
||||||
LightState::class,
|
*
|
||||||
Magic::class,
|
* @var ?callable
|
||||||
PhpDocBuilder::class,
|
* @psalm-var null|callable(class-string)
|
||||||
RSA::class,
|
*/
|
||||||
Serialization::class,
|
private $ignore;
|
||||||
SessionPaths::class,
|
/**
|
||||||
SettingsEmpty::class,
|
* Output directory.
|
||||||
SettingsAbstract::class,
|
*/
|
||||||
Snitch::class,
|
|
||||||
AsyncConstruct::class,
|
|
||||||
Server::class, // Remove when done
|
|
||||||
VoIP::class,
|
|
||||||
|
|
||||||
Crypt::class,
|
|
||||||
NothingInTheSocketException::class,
|
|
||||||
|
|
||||||
GarbageCollector::class,
|
|
||||||
MinDatabase::class,
|
|
||||||
PasswordCalculator::class,
|
|
||||||
ReferenceDatabase::class,
|
|
||||||
UpdatesState::class,
|
|
||||||
|
|
||||||
TL::class,
|
|
||||||
TLConstructors::class,
|
|
||||||
TLMethods::class,
|
|
||||||
TLCallback::class,
|
|
||||||
|
|
||||||
ADNLConnection::class,
|
|
||||||
TAPIFactory::class,
|
|
||||||
TInternalDoc::class,
|
|
||||||
Lite::class,
|
|
||||||
|
|
||||||
\ArrayIterator::class,
|
|
||||||
];
|
|
||||||
public static DocBlockFactory $factory;
|
|
||||||
private string $output;
|
private string $output;
|
||||||
public function __construct(string $output)
|
/**
|
||||||
|
* Use map.
|
||||||
|
*
|
||||||
|
* array<class-string, array<class-string, class-string>>
|
||||||
|
*/
|
||||||
|
private array $useMap = [];
|
||||||
|
/**
|
||||||
|
* Create docblock builder.
|
||||||
|
*
|
||||||
|
* @param string $namespace Namespace
|
||||||
|
* @param int $mode Finder mode, an OR-selection of ClassFinder::ALLOW_*
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public static function fromNamespace(string $namespace, int $mode = ClassFinder::ALLOW_ALL): self
|
||||||
|
{
|
||||||
|
return new self($namespace, $mode);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string $namespace
|
||||||
|
* @param int $mode
|
||||||
|
*/
|
||||||
|
private function __construct(string $namespace, int $mode)
|
||||||
|
{
|
||||||
|
$this->factory = DocBlockFactory::createInstance();
|
||||||
|
$this->namespace = $namespace;
|
||||||
|
$this->mode = $mode;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set filter to ignore certain classes.
|
||||||
|
*
|
||||||
|
* @param callable $ignore
|
||||||
|
*
|
||||||
|
* @psalm-param callable(class-string) $ignore
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setFilter(callable $ignore): self
|
||||||
|
{
|
||||||
|
$this->ignore = $ignore;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set output directory.
|
||||||
|
*
|
||||||
|
* @param string $output Output directory
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setOutput(string $output): self
|
||||||
{
|
{
|
||||||
self::$factory = DocBlockFactory::createInstance();
|
|
||||||
$this->output = $output;
|
$this->output = $output;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
public function run()
|
/**
|
||||||
|
* Run documentor.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function run(): self
|
||||||
{
|
{
|
||||||
$classes = ClassFinder::getClassesInNamespace('danog\\MadelineProto', ClassFinder::RECURSIVE_MODE);
|
$classes = ClassFinder::getClassesInNamespace($this->namespace, $this->mode | ClassFinder::RECURSIVE_MODE);
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
if (\in_array($class, self::DISALLOW) || str_starts_with($class, 'danog\\MadelineProto\\Ipc')
|
$this->addTypeAliases($class);
|
||||||
|| str_starts_with($class, 'danog\\MadelineProto\\Loop\\Update')
|
}
|
||||||
|| str_starts_with($class, 'danog\\MadelineProto\\Loop\\Connection')
|
foreach ($classes as $class) {
|
||||||
|| str_starts_with($class, 'danog\\MadelineProto\\MTProto\\')
|
if ($this->ignore && ($this->ignore)($class)) {
|
||||||
|| str_starts_with($class, 'danog\\MadelineProto\\MTProtoSession\\')
|
|
||||||
|| str_starts_with($class, 'danog\\MadelineProto\\PhpDoc\\')
|
|
||||||
|| str_starts_with($class, 'danog\\MadelineProto\\Db\\NullCache')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$class = new ReflectionClass($class);
|
|
||||||
if ($class->isTrait()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$class = \function_exists($class)
|
||||||
|
? new ReflectionFunction($class)
|
||||||
|
: new ReflectionClass($class);
|
||||||
$this->generate($class);
|
$this->generate($class);
|
||||||
}
|
}
|
||||||
$this->generate(new ReflectionClass(DbPropertiesTrait::class));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Resolve type alias.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @param string $fromClass Class from where this function is called
|
||||||
|
* @param string $name Name to resolve
|
||||||
|
*
|
||||||
|
* @psalm-param class-string $fromClass Class from where this function is called
|
||||||
|
* @psalm-param class-string $name Name to resolve
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function resolveTypeAlias(string $fromClass, string $name): string
|
||||||
|
{
|
||||||
|
return $this->useMap[$fromClass][$name] ?? $name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add type alias.
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
*
|
||||||
|
* @psalm-param class-string $class
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function addTypeAliases(string $class)
|
||||||
|
{
|
||||||
|
$reflectionClass = \function_exists($class)
|
||||||
|
? new ReflectionFunction($class)
|
||||||
|
: new ReflectionClass($class);
|
||||||
|
$payload = \file_get_contents($reflectionClass->getFileName());
|
||||||
|
\preg_match_all("/use *(function)? +(.*?)(?: +as +(.+))? *;/", $payload, $matches, PREG_SET_ORDER|PREG_UNMATCHED_AS_NULL);
|
||||||
|
foreach ($matches as [, $function, $import, $alias]) {
|
||||||
|
$import = "\\$import";
|
||||||
|
$alias ??= \basename(\str_replace('\\', '/', $import));
|
||||||
|
$this->useMap[$class][$alias] = $import;
|
||||||
|
$this->useMap[$class]['\\'.$alias] = $import;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Create directory recursively.
|
* Create directory recursively.
|
||||||
*
|
*
|
||||||
@ -137,25 +187,52 @@ class PhpDocBuilder
|
|||||||
return $file;
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generate(ReflectionClass $class): void
|
/**
|
||||||
|
* Generate documentation for class.
|
||||||
|
*
|
||||||
|
* @param ReflectionClass|ReflectionFunction $class Class
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function generate($class): void
|
||||||
{
|
{
|
||||||
$name = $class->getName();
|
$name = $class->getName();
|
||||||
$fName = $this->output;
|
$fName = $this->output;
|
||||||
$fName .= \str_replace(['\\', 'danog\\MadelineProto'], ['/', ''], $name);
|
$fName .= \str_replace('\\', DIRECTORY_SEPARATOR, $name);
|
||||||
$fName .= '.md';
|
$fName .= '.md';
|
||||||
|
|
||||||
|
$class = $class instanceof ReflectionFunction
|
||||||
|
? new FunctionDoc($this, $class)
|
||||||
|
: new ClassDoc($this, $class);
|
||||||
|
if ($class->shouldIgnore()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$class = $class->format();
|
||||||
|
|
||||||
$handle = \fopen(self::createDir($fName), 'w+');
|
$handle = \fopen(self::createDir($fName), 'w+');
|
||||||
|
\fwrite($handle, $class);
|
||||||
|
\fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
$class = new ClassDoc($class);
|
/**
|
||||||
/*
|
* Get docblock factory.
|
||||||
\fwrite($handle, "---\n");
|
*
|
||||||
\fwrite($handle, "title: $name: $title\n");
|
* @internal
|
||||||
\fwrite($handle, "description: $description\n");
|
*
|
||||||
\fwrite($handle, "image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png\n");
|
* @return DocBlockFactory
|
||||||
\fwrite($handle, "---\n");
|
|
||||||
\fwrite($handle, "# $name: $title\n");
|
|
||||||
\fwrite($handle, "[Back to API index](index.md)\n\n");
|
|
||||||
|
|
||||||
\fwrite($handle, "> Author: $author \n");
|
|
||||||
*/
|
*/
|
||||||
|
public function getFactory(): DocBlockFactory
|
||||||
|
{
|
||||||
|
return $this->factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether should ignore trait/class/interface.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shouldIgnore(string $class): bool
|
||||||
|
{
|
||||||
|
return ($this->ignore)($class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<?php
|
|
@ -170,7 +170,9 @@ class Logger extends SettingsAbstract
|
|||||||
public function setExtra($extra): self
|
public function setExtra($extra): self
|
||||||
{
|
{
|
||||||
if ($this->type === MadelineProtoLogger::CALLABLE_LOGGER && !\is_callable($extra)) {
|
if ($this->type === MadelineProtoLogger::CALLABLE_LOGGER && !\is_callable($extra)) {
|
||||||
$this->setType(MadelineProtoLogger::NO_LOGGER);
|
$this->setType((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg')
|
||||||
|
? MadelineProtoLogger::ECHO_LOGGER
|
||||||
|
: MadelineProtoLogger::FILE_LOGGER);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
$this->extra = $extra;
|
$this->extra = $extra;
|
||||||
|
@ -8,7 +8,7 @@ use danog\MadelineProto\MTProto;
|
|||||||
use danog\MadelineProto\Tools;
|
use danog\MadelineProto\Tools;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
\define("MADELINEPROTO_TEST", "pony");
|
\define('MADELINEPROTO_TEST', 'pony');
|
||||||
|
|
||||||
final class DataCenterTest extends TestCase
|
final class DataCenterTest extends TestCase
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user