mirror of
https://github.com/Sysbot-org/tgscraper.git
synced 2024-12-24 18:55:48 +01:00
First release
This commit is contained in:
parent
e533722af2
commit
c8de8ba74f
22
composer.json
Normal file
22
composer.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "sys-001/tgbotapi-gen",
|
||||
"description": "Utility to extract scheme from Telegram Bot API webpage.",
|
||||
"type": "project",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"TGBotApi\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"ext-json": "*",
|
||||
"nette/php-generator": "^3.3",
|
||||
"paquettg/php-html-parser": "^2.0"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "sys-001",
|
||||
"email": "honfu7891@etlgr.com"
|
||||
}
|
||||
]
|
||||
}
|
259
composer.lock
generated
Normal file
259
composer.lock
generated
Normal file
@ -0,0 +1,259 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e0c67734f3ab978c6aebf8a35453ba15",
|
||||
"packages": [
|
||||
{
|
||||
"name": "nette/php-generator",
|
||||
"version": "v3.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/php-generator.git",
|
||||
"reference": "a4ff22c91681fefaa774cf952a2b69c2ec9477c1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/php-generator/zipball/a4ff22c91681fefaa774cf952a2b69c2ec9477c1",
|
||||
"reference": "a4ff22c91681fefaa774cf952a2b69c2ec9477c1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/utils": "^2.4.2 || ^3.0",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.4 features.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"code",
|
||||
"nette",
|
||||
"php",
|
||||
"scaffolding"
|
||||
],
|
||||
"time": "2020-01-20T11:40:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "d6cd63d77dd9a85c3a2fae707e1255e44c2bc182"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/d6cd63d77dd9a85c3a2fae707e1255e44c2bc182",
|
||||
"reference": "d6cd63d77dd9a85c3a2fae707e1255e44c2bc182",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "~2.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use Image",
|
||||
"ext-iconv": "to use Strings::webalize() and toAscii()",
|
||||
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
|
||||
"ext-json": "to use Nette\\Utils\\Json",
|
||||
"ext-mbstring": "to use Strings::lower() etc...",
|
||||
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()",
|
||||
"ext-xml": "to use Strings::length() etc. when mbstring is not available"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0",
|
||||
"GPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"core",
|
||||
"datetime",
|
||||
"images",
|
||||
"json",
|
||||
"nette",
|
||||
"paginator",
|
||||
"password",
|
||||
"slugify",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utility",
|
||||
"validation"
|
||||
],
|
||||
"time": "2020-01-03T18:13:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paquettg/php-html-parser",
|
||||
"version": "2.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paquettg/php-html-parser.git",
|
||||
"reference": "668c770fc5724ea3f15b8791435f054835be8d5e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paquettg/php-html-parser/zipball/668c770fc5724ea3f15b8791435f054835be8d5e",
|
||||
"reference": "668c770fc5724ea3f15b8791435f054835be8d5e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-zlib": "*",
|
||||
"paquettg/string-encode": "~1.0.0",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.13.4",
|
||||
"mockery/mockery": "^1.2",
|
||||
"phan/phan": "^2.4",
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpunit": "^7.5.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PHPHtmlParser\\": "src/PHPHtmlParser"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gilles Paquette",
|
||||
"email": "paquettg@gmail.com",
|
||||
"homepage": "http://gillespaquette.ca"
|
||||
}
|
||||
],
|
||||
"description": "An HTML DOM parser. It allows you to manipulate HTML. Find tags on an HTML page with selectors just like jQuery.",
|
||||
"homepage": "https://github.com/paquettg/php-html-parser",
|
||||
"keywords": [
|
||||
"dom",
|
||||
"html",
|
||||
"parser"
|
||||
],
|
||||
"time": "2020-01-20T12:59:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paquettg/string-encode",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paquettg/string-encoder.git",
|
||||
"reference": "a8708e9fac9d5ddfc8fc2aac6004e2cd05d80fee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paquettg/string-encoder/zipball/a8708e9fac9d5ddfc8fc2aac6004e2cd05d80fee",
|
||||
"reference": "a8708e9fac9d5ddfc8fc2aac6004e2cd05d80fee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"stringEncode": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gilles Paquette",
|
||||
"email": "paquettg@gmail.com",
|
||||
"homepage": "http://gillespaquette.ca"
|
||||
}
|
||||
],
|
||||
"description": "Facilitating the process of altering string encoding in PHP.",
|
||||
"homepage": "https://github.com/paquettg/string-encoder",
|
||||
"keywords": [
|
||||
"charset",
|
||||
"encoding",
|
||||
"string"
|
||||
],
|
||||
"time": "2018-12-21T02:25:09+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^7.2",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
7
main.php
Normal file
7
main.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
|
||||
$json_scheme = TGBotApi\Generator::toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
echo $json_scheme;
|
265
src/Generator.php
Normal file
265
src/Generator.php
Normal file
@ -0,0 +1,265 @@
|
||||
<?php
|
||||
|
||||
namespace TGBotApi;
|
||||
|
||||
use PHPHtmlParser\Dom;
|
||||
|
||||
class Generator
|
||||
{
|
||||
|
||||
private const EMPTY_FIELDS = [
|
||||
'deleteWebhook',
|
||||
'getWebhookInfo',
|
||||
'getMe',
|
||||
'InputFile',
|
||||
'InputMedia',
|
||||
'InlineQueryResult',
|
||||
'InputMessageContent',
|
||||
'PassportElementError',
|
||||
'CallbackGame'
|
||||
];
|
||||
|
||||
private const BOOL_RETURNS = [
|
||||
'answerShippingQuery',
|
||||
'answerPreCheckoutQuery'
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string $target_directory
|
||||
* @param string $namespace_prefix
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function toClasses(string $target_directory = '', string $namespace_prefix = ''): bool
|
||||
{
|
||||
$target_directory = self::getTargetDirectory($target_directory);
|
||||
mkdir($target_directory . '/Methods', 0755);
|
||||
mkdir($target_directory . '/Types', 0755);
|
||||
try {
|
||||
$stub_provider = new StubProvider($namespace_prefix);
|
||||
$code = $stub_provider->generateCode(self::extractScheme());
|
||||
foreach ($code['methods'] as $class_name => $method) {
|
||||
file_put_contents($target_directory . '/Methods/' . $class_name . '.php', $method);
|
||||
}
|
||||
foreach ($code['types'] as $class_name => $type) {
|
||||
file_put_contents($target_directory . '/Types/' . $class_name . '.php', $type);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function getTargetDirectory(string $target_directory): string
|
||||
{
|
||||
mkdir($target_directory, 0755);
|
||||
$target_directory = realpath($target_directory);
|
||||
if (false == $target_directory) {
|
||||
$target_directory = __DIR__ . '/generated';
|
||||
if (!file_exists($target_directory)) {
|
||||
mkdir($target_directory, 0755);
|
||||
}
|
||||
}
|
||||
return $target_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \PHPHtmlParser\Exceptions\ChildNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\CircularException
|
||||
* @throws \PHPHtmlParser\Exceptions\CurlException
|
||||
* @throws \PHPHtmlParser\Exceptions\NotLoadedException
|
||||
* @throws \PHPHtmlParser\Exceptions\ParentNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\StrictException
|
||||
*/
|
||||
private static function extractScheme(): array
|
||||
{
|
||||
$dom = new Dom;
|
||||
$dom->loadFromURL('https://core.telegram.org/bots/api');
|
||||
$elements = $dom->find('h4');
|
||||
$i = 0;
|
||||
$data = [];
|
||||
foreach ($elements as $element) {
|
||||
if (false === strpos($name = $element->text, ' ')) {
|
||||
$is_method = self::isMethod($name);
|
||||
$path = $is_method ? 'methods' : 'types';
|
||||
$empty = in_array($name, self::EMPTY_FIELDS);
|
||||
/* @var Dom $fields_table */
|
||||
$fields_table = $dom->find('table')[$i];
|
||||
$unparsed_fields = $fields_table->find('tbody')->find('tr');
|
||||
/* @var Dom\AbstractNode $element */
|
||||
/** @noinspection PhpUndefinedFieldInspection */
|
||||
$data[$path][] = self::generateElement($name, $element->nextSibling()->nextSibling()->innerHtml,
|
||||
($empty ? null : $unparsed_fields), $is_method);
|
||||
if (!$empty) {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function isMethod(string $name): bool
|
||||
{
|
||||
$first_letter = substr($name, 0, 1);
|
||||
return (strtolower($first_letter) == $first_letter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $description
|
||||
* @param Dom\Collection|null $unparsed_fields
|
||||
* @param bool $is_method
|
||||
* @return array
|
||||
* @throws \PHPHtmlParser\Exceptions\ChildNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\CircularException
|
||||
* @throws \PHPHtmlParser\Exceptions\CurlException
|
||||
* @throws \PHPHtmlParser\Exceptions\NotLoadedException
|
||||
* @throws \PHPHtmlParser\Exceptions\StrictException
|
||||
*/
|
||||
private static function generateElement(
|
||||
string $name,
|
||||
string $description,
|
||||
?Dom\Collection $unparsed_fields,
|
||||
bool $is_method
|
||||
): array {
|
||||
$fields = self::parseFields($unparsed_fields, $is_method);
|
||||
if (!$is_method) {
|
||||
return [
|
||||
'name' => $name,
|
||||
'description' => htmlspecialchars_decode(strip_tags($description), ENT_QUOTES),
|
||||
'fields' => $fields
|
||||
];
|
||||
}
|
||||
$return_types = self::parseReturnTypes($description);
|
||||
if (empty($return_types) and in_array($name, self::BOOL_RETURNS)) {
|
||||
$return_types[] = 'bool';
|
||||
}
|
||||
return [
|
||||
'name' => $name,
|
||||
'description' => htmlspecialchars_decode(strip_tags($description), ENT_QUOTES),
|
||||
'fields' => $fields,
|
||||
'return_types' => $return_types
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Dom\Collection|null $fields
|
||||
* @param bool $is_method
|
||||
* @return array
|
||||
* @throws \PHPHtmlParser\Exceptions\ChildNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\NotLoadedException
|
||||
*/
|
||||
private static function parseFields(?Dom\Collection $fields, bool $is_method): array
|
||||
{
|
||||
$parsed_fields = [];
|
||||
$fields = $fields ?? [];
|
||||
foreach ($fields as $field) {
|
||||
/* @var Dom $field */
|
||||
$field_data = $field->find('td');
|
||||
$parsed_data = [
|
||||
'name' => $field_data[0]->text,
|
||||
'type' => strip_tags($field_data[1]->innerHtml)
|
||||
];
|
||||
if ($is_method) {
|
||||
$parsed_data['required'] = ($field_data[2]->text == 'Yes');
|
||||
$parsed_data['types'] = self::parseMethodFieldTypes($parsed_data['type']);
|
||||
unset($parsed_data['type']);
|
||||
$parsed_data['description'] = htmlspecialchars_decode(strip_tags($field_data[3]->innerHtml ?? $field_data[3]->text ?? ''),
|
||||
ENT_QUOTES);
|
||||
} else {
|
||||
$parsed_data['type'] = self::parseObjectFieldType($parsed_data['type']);
|
||||
$parsed_data['description'] = htmlspecialchars_decode(strip_tags($field_data[2]->innerHtml),
|
||||
ENT_QUOTES);
|
||||
}
|
||||
$parsed_fields[] = $parsed_data;
|
||||
}
|
||||
return $parsed_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $raw_type
|
||||
* @return array
|
||||
*/
|
||||
private static function parseMethodFieldTypes(string $raw_type): array
|
||||
{
|
||||
$types = explode(' or ', $raw_type);
|
||||
$parsed_types = [];
|
||||
foreach ($types as $type) {
|
||||
$type = trim(str_replace(['number', 'of'], '', $type));
|
||||
$multiples_count = substr_count(strtolower($type), 'array');
|
||||
$parsed_types[] = trim(str_replace(['Array', 'Integer', 'String', 'Boolean', 'Float'],
|
||||
['', 'int', 'string', 'bool', 'float'], $type)) . str_repeat('[]', $multiples_count);
|
||||
}
|
||||
return $parsed_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $raw_type
|
||||
* @return string
|
||||
*/
|
||||
private static function parseObjectFieldType(string $raw_type): string
|
||||
{
|
||||
$type = trim(str_replace(['number', 'of'], '', $raw_type));
|
||||
$multiples_count = substr_count(strtolower($type), 'array');
|
||||
return trim(str_replace(['Array', 'Integer', 'String', 'Boolean', 'Float'],
|
||||
['', 'int', 'string', 'bool', 'float'], $type)) . str_repeat('[]', $multiples_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
* @return array
|
||||
* @throws \PHPHtmlParser\Exceptions\ChildNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\CircularException
|
||||
* @throws \PHPHtmlParser\Exceptions\CurlException
|
||||
* @throws \PHPHtmlParser\Exceptions\NotLoadedException
|
||||
* @throws \PHPHtmlParser\Exceptions\StrictException
|
||||
*/
|
||||
private static function parseReturnTypes(string $description): array
|
||||
{
|
||||
$return_types = [];
|
||||
$phrases = explode('.', $description);
|
||||
$phrases = array_filter($phrases, function ($phrase) {
|
||||
return (false !== stripos($phrase, 'returns') or false !== stripos($phrase, 'is returned'));
|
||||
});
|
||||
foreach ($phrases as $phrase) {
|
||||
$dom = new Dom;
|
||||
$dom->load($phrase);
|
||||
$a = $dom->find('a');
|
||||
$em = $dom->find('em');
|
||||
foreach ($a as $element) {
|
||||
if ($element->text == 'Messages') {
|
||||
$return_types[] = 'Message[]';
|
||||
continue;
|
||||
}
|
||||
$multiples_count = substr_count(strtolower($phrase), 'array');
|
||||
$return_types[] = $element->text . str_repeat('[]', $multiples_count);
|
||||
}
|
||||
foreach ($em as $element) {
|
||||
if (in_array($element->text, ['False', 'force', 'Array'])) {
|
||||
continue;
|
||||
}
|
||||
$type = str_replace(['True', 'Int', 'String'], ['bool', 'int', 'string'], $element->text);
|
||||
$return_types[] = $type;
|
||||
}
|
||||
}
|
||||
return $return_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $options
|
||||
* @return string
|
||||
* @throws \PHPHtmlParser\Exceptions\ChildNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\CircularException
|
||||
* @throws \PHPHtmlParser\Exceptions\CurlException
|
||||
* @throws \PHPHtmlParser\Exceptions\NotLoadedException
|
||||
* @throws \PHPHtmlParser\Exceptions\ParentNotFoundException
|
||||
* @throws \PHPHtmlParser\Exceptions\StrictException
|
||||
*/
|
||||
public static function toJson(int $options = 0): string
|
||||
{
|
||||
$scheme = self::extractScheme();
|
||||
return json_encode($scheme, $options);
|
||||
}
|
||||
|
||||
}
|
238
src/StubProvider.php
Normal file
238
src/StubProvider.php
Normal file
@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace TGBotApi;
|
||||
|
||||
use Nette\{PhpGenerator, PhpGenerator\Type};
|
||||
|
||||
class StubProvider
|
||||
{
|
||||
|
||||
private $namespace_prefix = '';
|
||||
private $methods = [];
|
||||
private $types = [];
|
||||
|
||||
/**
|
||||
* StubProvider constructor.
|
||||
* @param string $namespace_prefix
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(string $namespace_prefix = '')
|
||||
{
|
||||
if (substr($namespace_prefix, -1) == '\\') {
|
||||
$namespace_prefix = substr($namespace_prefix, 0, -1);
|
||||
}
|
||||
if (!empty($namespace_prefix)) {
|
||||
if (!PhpGenerator\Helpers::isNamespaceIdentifier($namespace_prefix)) {
|
||||
throw new \Exception('Invalid namespace prefix provided');
|
||||
}
|
||||
$namespace_prefix .= '\\';
|
||||
}
|
||||
$types_namespace = $namespace_prefix . 'Types';
|
||||
$this->namespace_prefix = $namespace_prefix;
|
||||
$this->methods = $this->createDefaultMethods();
|
||||
$this->types = $this->createDefaultTypes($types_namespace);
|
||||
}
|
||||
|
||||
private function createDefaultMethods(): array
|
||||
{
|
||||
$method_inteface = (new PhpGenerator\ClassType('MethodInterface'))
|
||||
->setInterface();
|
||||
$method_inteface->addMethod('getParams')
|
||||
->setPublic()
|
||||
->setReturnType(Type::ARRAY);
|
||||
$method_inteface->addMethod('getMethodName')
|
||||
->setPublic()
|
||||
->setStatic()
|
||||
->setReturnType(Type::STRING);
|
||||
$method_inteface->addMethod('isMultipart')
|
||||
->setPublic()
|
||||
->setReturnType(Type::BOOL);
|
||||
$method_inteface->addMethod('getResultParams')
|
||||
->setPublic()
|
||||
->setStatic()
|
||||
->setReturnType(Type::ARRAY);
|
||||
$method_abstract = (new PhpGenerator\ClassType('DefaultMethod'))
|
||||
->setClass()
|
||||
->setAbstract()
|
||||
->addImplement('MethodInterface');
|
||||
$method_abstract->addConstant('METHOD_NAME', '')
|
||||
->setPrivate();
|
||||
$method_abstract->addConstant('RESULT_TYPE', '')
|
||||
->setPrivate();
|
||||
$method_abstract->addConstant('MULTIPLE_RESULTS', false)
|
||||
->setPrivate();
|
||||
$method_abstract->addProperty('multipart', false)
|
||||
->setPrivate();
|
||||
$method_abstract->addMethod('getMethodName')
|
||||
->setPublic()
|
||||
->setStatic()
|
||||
->setReturnType(Type::STRING)
|
||||
->setBody('return static::METHOD_NAME;');
|
||||
$method_abstract->addMethod('isMultipart')
|
||||
->setPublic()
|
||||
->setReturnType(Type::BOOL)
|
||||
->setBody('return $this->multipart;');
|
||||
$method_abstract->addMethod('getResultParams')
|
||||
->setPublic()
|
||||
->setStatic()
|
||||
->setReturnType(Type::ARRAY)
|
||||
->addBody('return [')
|
||||
->addBody(' \'type\' => static::RESULT_TYPE,')
|
||||
->addBody(' \'multiple\' => static::MULTIPLE_RESULTS')
|
||||
->addBody('];');
|
||||
return [
|
||||
'MethodInterface' => $this->addNamespace($method_inteface, 'Methods'),
|
||||
'DefaultMethod' => $this->addNamespace($method_abstract, 'Methods')
|
||||
];
|
||||
}
|
||||
|
||||
private function addNamespace(string $code, string $sub_namespace): string
|
||||
{
|
||||
return '<?php' . str_repeat(PHP_EOL,
|
||||
2) . 'namespace ' . $this->namespace_prefix . $sub_namespace . ';' . str_repeat(PHP_EOL, 2) . $code;
|
||||
}
|
||||
|
||||
private function createDefaultTypes(string $namespace): array
|
||||
{
|
||||
$response = (new PhpGenerator\ClassType('Response'))
|
||||
->setType('class');
|
||||
$response->addProperty('ok')
|
||||
->setPublic();
|
||||
$response->addProperty('result')
|
||||
->setPublic();
|
||||
$response->addProperty('error_code')
|
||||
->setPublic();
|
||||
$response->addProperty('description')
|
||||
->setPublic();
|
||||
$response->addMethod('parseResponse')
|
||||
->setReturnType(Type::SELF)
|
||||
->setReturnNullable(true)
|
||||
->setPublic()
|
||||
->setStatic()
|
||||
->setBody('if (null == $response) {
|
||||
return null;
|
||||
}
|
||||
$parsed_response = (new self())
|
||||
->setOk($response->ok ?? null)
|
||||
->setErrorCode($response->error_code ?? null)
|
||||
->setDescription($response->description ?? null);
|
||||
if (empty($response->result)) {
|
||||
$parsed_response->setResult(null);
|
||||
} elseif (!empty($response->result->migrate_to_chat_id) or !empty($response->result->retry_after)) {
|
||||
$parsed_response->setResult(ResponseParameters::parseResponseParameters($response->result ?? null));
|
||||
} elseif (!empty($response->result_type)) {
|
||||
$result_class = sprintf(\'' . $namespace . '\\%s\', $response->result_type->class);
|
||||
$parsed_response->setResult(call_user_func([$result_class, $response->result_type->method],
|
||||
$response->result ?? null));
|
||||
} else {
|
||||
$parsed_response->setResult($response->result ?? null);
|
||||
}
|
||||
return $parsed_response;')
|
||||
->addParameter('response')
|
||||
->setType('\stdClass')
|
||||
->setNullable(true);
|
||||
$this->createSetters($response, [
|
||||
['name' => 'ok', 'type' => 'bool', 'nullable' => true],
|
||||
['name' => 'result', 'type' => null, 'nullable' => false],
|
||||
['name' => 'error_code', 'type' => 'int', 'nullable' => true],
|
||||
['name' => 'description', 'type' => 'string', 'nullable' => true]
|
||||
]);
|
||||
return ['Response' => $this->addNamespace($response, 'Types')];
|
||||
}
|
||||
|
||||
private function createSetters(PhpGenerator\ClassType $class, array $properties): void
|
||||
{
|
||||
foreach ($properties as $property) {
|
||||
$class->addMethod('set' . $this->getCamelCaseName($property['name']))
|
||||
->setPublic()
|
||||
->setReturnType(Type::SELF)
|
||||
->setBody('$this->' . $property['name'] . ' = $' . $property['name'] . ';' . PHP_EOL . 'return $this;')
|
||||
->addParameter($property['name'])
|
||||
->setType($property['type'])
|
||||
->setNullable($property['nullable']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private function getCamelCaseName(string $snake_case): string
|
||||
{
|
||||
return str_replace(' ', '', ucwords(str_replace('_', ' ', $snake_case)));
|
||||
}
|
||||
|
||||
public function generateCode(array $scheme): array
|
||||
{
|
||||
foreach ($scheme['types'] as $type) {
|
||||
$type_class = (new PhpGenerator\ClassType($type['name']))
|
||||
->setType('class');
|
||||
$fields = [];
|
||||
foreach ($type['fields'] as $field) {
|
||||
$type_class->addProperty($field['name'])
|
||||
->setPublic()
|
||||
->setType($field['type']);
|
||||
$fields[] = [
|
||||
'name' => $field['name'],
|
||||
'type' => $field['type'],
|
||||
'nullable' => true
|
||||
];
|
||||
}
|
||||
$this->createSetters($type_class, $fields);
|
||||
$this->types[$type['name']] = $this->addNamespace($type_class, 'Types');
|
||||
}
|
||||
foreach ($scheme['methods'] as $method) {
|
||||
$method_class = (new PhpGenerator\ClassType(ucfirst($method['name'])))
|
||||
->setType('class')
|
||||
->addExtend('DefaultMethod');
|
||||
$method_class->addConstant('METHOD_NAME', $method['name'])
|
||||
->setPrivate();
|
||||
$return_type = $method['return_types'][0];
|
||||
$multiple_results = false;
|
||||
if (substr($return_type, -2) == '[]') {
|
||||
$return_type = substr($return_type, 0, -2);
|
||||
$multiple_results = true;
|
||||
}
|
||||
$method_class->addConstant('RESULT_TYPE', $return_type)
|
||||
->setPrivate();
|
||||
$method_class->addConstant('MULTIPLE_RESULTS', $multiple_results)
|
||||
->setPrivate();
|
||||
$fields = [];
|
||||
$get_params = $method_class->addMethod('getParams')
|
||||
->setPublic()
|
||||
->setReturnType(Type::ARRAY)
|
||||
->addBody('return [');
|
||||
$last_index = array_key_last($method['fields']);
|
||||
foreach ($method['fields'] as $index => $field) {
|
||||
$field_type = count($field['types']) == 0 ? $field['types'][0] : null; //maybe there will be a better implementation
|
||||
$method_class->addProperty($field['name'])
|
||||
->setPublic()
|
||||
->setType($field_type);
|
||||
$comma = $index != $last_index ? ',' : '';
|
||||
$get_params->addBody(' \'' . $field['name'] . '\' => $this->' . $field['name'] . $comma);
|
||||
$fields[] = [
|
||||
'name' => $field['name'],
|
||||
'type' => $field_type,
|
||||
'nullable' => true
|
||||
];
|
||||
}
|
||||
$get_params->addBody('];');
|
||||
$this->createConstructor($method_class, $fields);
|
||||
$this->methods[ucfirst($method['name'])] = $this->addNamespace($method_class, 'Methods');
|
||||
}
|
||||
return [
|
||||
'methods' => $this->methods,
|
||||
'types' => $this->types
|
||||
];
|
||||
}
|
||||
|
||||
private function createConstructor(PhpGenerator\ClassType $class, array $properties): void
|
||||
{
|
||||
$method = $class->addMethod('__construct');
|
||||
foreach ($properties as $property) {
|
||||
$method->addBody('$this->' . $property['name'] . ' = $' . $property['name'] . ';')
|
||||
->addParameter($property['name'])
|
||||
->setType($property['type'])
|
||||
->setNullable($property['nullable']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user