2022-12-30 21:54:44 +01:00
< ? php
declare ( strict_types = 1 );
2018-02-24 17:54:13 +01:00
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
/**
* AnnotationsBuilder module .
*
* This file is part of MadelineProto .
* MadelineProto is free software : you can redistribute it and / or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation , either version 3 of the License , or ( at your option ) any later version .
* MadelineProto is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU Affero General Public License for more details .
* You should have received a copy of the GNU General Public License along with MadelineProto .
* If not , see < http :// www . gnu . org / licenses />.
*
* @ author Daniil Gentili < daniil @ daniil . it >
2023-01-04 12:43:01 +01:00
* @ copyright 2016 - 2023 Daniil Gentili < daniil @ daniil . it >
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
* @ license https :// opensource . org / licenses / AGPL - 3.0 AGPLv3
2019-10-31 15:07:35 +01:00
* @ link https :// docs . madelineproto . xyz MadelineProto documentation
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
*/
2018-02-24 17:54:39 +01:00
2017-01-22 17:40:56 +01:00
namespace danog\MadelineProto ;
2023-01-27 19:10:52 +01:00
use AssertionError ;
2023-08-05 19:13:26 +02:00
use danog\ClassFinder\ClassFinder ;
2019-10-31 20:48:06 +01:00
use danog\MadelineProto\TL\TL ;
2022-12-30 19:21:36 +01:00
use ReflectionClass ;
use ReflectionMethod ;
2022-07-16 18:10:33 +02:00
use ReflectionNamedType ;
2023-01-08 20:33:54 +01:00
use ReflectionType ;
2022-07-16 18:10:33 +02:00
use ReflectionUnionType ;
2018-02-24 17:54:39 +01:00
2023-01-27 18:12:33 +01:00
/**
* @ internal
*/
2023-01-15 12:05:38 +01:00
final class AnnotationsBuilder
2017-01-22 17:40:56 +01:00
{
2020-10-03 12:36:08 +02:00
/**
2020-10-03 15:04:35 +02:00
* Reflection classes .
2020-10-03 12:36:08 +02:00
*/
private array $reflectionClasses = [];
/**
2020-10-03 15:04:35 +02:00
* Namespace .
2020-10-03 12:36:08 +02:00
*/
private string $namespace ;
/**
2020-10-03 15:04:35 +02:00
* TL instance .
2020-10-03 12:36:08 +02:00
*/
private TL $TL ;
2023-01-27 14:20:47 +01:00
private array $blacklist ;
private array $blacklistHard ;
2023-01-27 18:25:02 +01:00
private array $special ;
2023-01-27 14:20:47 +01:00
public function __construct ( Logger $logger , array $settings , array $reflectionClasses , string $namespace )
2017-01-22 17:40:56 +01:00
{
2019-12-14 16:47:04 +01:00
$this -> reflectionClasses = $reflectionClasses ;
$this -> namespace = $namespace ;
2020-10-03 15:36:03 +02:00
/** @psalm-suppress InvalidArgument */
2023-01-08 20:33:54 +01:00
$this -> TL = new TL ();
2023-08-13 16:21:59 +02:00
$this -> TL -> init ( $settings [ 'TL' ]);
2023-10-01 20:05:04 +02:00
$this -> blacklist = json_decode ( file_get_contents ( __DIR__ . '/../docs/template/disallow.json' ), true );
2023-09-06 18:19:45 +02:00
$this -> blacklist [ 'updates.getDifference' ] = 'You cannot use this method directly, please use the [event handler](https://docs.madelineproto.xyz/docs/UPDATES.html), instead.' ;
$this -> blacklist [ 'updates.getChannelDifference' ] = 'You cannot use this method directly, please use the [event handler](https://docs.madelineproto.xyz/docs/UPDATES.html), instead.' ;
$this -> blacklist [ 'updates.getState' ] = 'You cannot use this method directly, please use the [event handler](https://docs.madelineproto.xyz/docs/UPDATES.html), instead.' ;
2023-01-27 14:20:47 +01:00
$this -> blacklistHard = $this -> blacklist ;
2023-09-06 18:19:45 +02:00
unset ( $this -> blacklistHard [ 'messages.getHistory' ], $this -> blacklistHard [ 'channels.getMessages' ], $this -> blacklistHard [ 'messages.getMessages' ], $this -> blacklistHard [ 'updates.getDifference' ], $this -> blacklistHard [ 'updates.getChannelDifference' ], $this -> blacklistHard [ 'updates.getState' ]);
2023-10-01 20:05:04 +02:00
file_put_contents ( __DIR__ . '/Namespace/Blacklist.php' , ' < ? php
2023-01-27 14:36:54 +01:00
namespace danog\MadelineProto\Namespace ;
final class Blacklist {
2023-10-01 20:05:04 +02:00
public const BLACKLIST = '.var_export($this->blacklistHard, true).' ;
2023-01-27 14:36:54 +01:00
}
' );
2023-01-27 18:25:02 +01:00
$special = [];
2023-01-27 19:00:11 +01:00
foreach ( DocsBuilder :: DEFAULT_TEMPLATES as $key => $types ) {
$replace = match ( $key ) {
'User' => 'array|int|string' ,
'InputFile' => 'mixed' ,
'PhoneCall' => '\\danog\\MadelineProto\\VoIP|array' ,
default => 'array'
};
2023-01-27 18:25:02 +01:00
foreach ( $types as $type ) {
2023-01-27 19:00:11 +01:00
$special [ $type ] = $replace ;
2023-01-27 18:25:02 +01:00
}
}
$this -> special = $special ;
2017-01-22 17:40:56 +01:00
}
2020-10-01 21:03:25 +02:00
public function mkAnnotations () : void
2017-01-22 17:40:56 +01:00
{
2022-12-30 19:21:36 +01:00
Logger :: log ( 'Generating annotations...' , Logger :: NOTICE );
2017-01-22 17:40:56 +01:00
$this -> createInternalClasses ();
}
2023-01-27 18:12:33 +01:00
private static function isVector ( string $type ) : array
{
2023-10-01 20:05:04 +02:00
if ( str_contains ( $type , '<' )) {
return [ true , str_replace ([ 'Vector<' , '>' ], '' , $type )];
2023-01-27 18:12:33 +01:00
}
return [ false , $type ];
}
2023-09-06 18:39:48 +02:00
private function prepareTLType ( string $type , bool $optional ) : string
2017-01-22 17:40:56 +01:00
{
2023-01-27 18:12:33 +01:00
[ $isVector , $type ] = self :: isVector ( $type );
if ( $isVector ) {
2023-09-06 18:39:48 +02:00
return $optional ? 'array' : 'array|null' ;
2023-01-27 18:12:33 +01:00
}
2023-09-06 18:39:48 +02:00
$type = match ( $type ) {
2023-01-27 14:20:47 +01:00
'string' => 'string' ,
'bytes' => 'string' ,
2023-07-08 17:11:21 +02:00
'waveform' => 'array' ,
2023-01-27 14:20:47 +01:00
'int' => 'int' ,
'long' => 'int' ,
2023-07-01 14:17:11 +02:00
'strlong' => 'int' ,
2023-01-27 14:20:47 +01:00
'double' => 'float' ,
'float' => 'float' ,
'Bool' => 'bool' ,
2023-01-27 18:12:33 +01:00
'true' => 'bool' ,
2023-01-27 18:25:02 +01:00
'InputMessage' => 'array|int' ,
2023-07-21 19:21:34 +02:00
'InputMedia' => '\\danog\\MadelineProto\\EventHandler\\Media|array|string' ,
2023-04-29 14:26:32 +02:00
'InputCheckPasswordSRP' => 'string|array' ,
2023-01-27 19:10:52 +01:00
'DataJSON' => 'mixed' ,
'JSONValue' => 'mixed' ,
2023-01-27 19:00:11 +01:00
default => $this -> special [ $type ] ? ? 'array'
2023-01-27 14:20:47 +01:00
};
2023-09-06 18:39:48 +02:00
if ( $type === 'mixed' || ! $optional ) {
return $type ;
}
return $type . '|null' ;
2023-01-27 14:20:47 +01:00
}
2023-01-27 19:00:11 +01:00
private function prepareTLPsalmType ( string $type , bool $input , int $depth = - 2 , array $stack = []) : string
2023-01-27 18:12:33 +01:00
{
[ $isVector , $type ] = self :: isVector ( $type );
$base = match ( $type ) {
'string' => 'string' ,
'bytes' => 'string' ,
2023-07-08 17:11:21 +02:00
'waveform' => 'non-empty-list<int<0, 31>>' ,
2023-01-27 18:12:33 +01:00
'int' => 'int' ,
'long' => 'int' ,
2023-07-01 14:17:11 +02:00
'strlong' => 'int' ,
2023-01-27 18:12:33 +01:00
'double' => 'float' ,
'float' => 'float' ,
'Bool' => 'bool' ,
'true' => 'bool' ,
2023-01-27 19:00:11 +01:00
'Updates' => 'array' ,
2023-04-29 14:26:32 +02:00
'InputCheckPasswordSRP' => 'string|array' ,
2023-01-27 19:10:52 +01:00
'DataJSON' => 'mixed' ,
'JSONValue' => 'mixed' ,
2023-01-27 19:00:11 +01:00
default => $this -> special [ $type ] ? ? ''
2023-01-27 18:12:33 +01:00
};
2023-01-27 18:25:02 +01:00
if ( $type === 'channels.AdminLogResults' ) {
2023-04-29 14:26:32 +02:00
$depth = 3 ;
2023-01-27 18:25:02 +01:00
}
2023-04-03 12:07:27 +02:00
if ( $type === 'messages.Messages' ) {
2023-04-29 14:26:32 +02:00
$depth = 3 ;
2023-04-03 12:07:27 +02:00
}
if ( $type === 'messages.Dialogs' ) {
2023-04-29 14:26:32 +02:00
$depth = 3 ;
2023-04-03 12:07:27 +02:00
}
if ( $type === 'MessageMedia' ) {
$depth = 2 ;
}
2023-04-29 14:26:32 +02:00
if ( $type === 'DecryptedMessage' || $type === 'messages.BotResults' || $type === 'InputBotInlineResult' ) {
$depth = 2 ;
}
if ( $type === 'WebPage' ) {
$depth = 3 ;
}
if ( $type === 'Document' || $type === 'Photo' ) {
$depth = 3 ;
}
2023-01-27 18:25:02 +01:00
if ( $depth > 3 ) {
$base = 'array' ;
}
2023-01-27 18:12:33 +01:00
if ( ! $base ) {
$constructors = [];
foreach ( $this -> TL -> getConstructors () -> by_id as $constructor ) {
if ( $constructor [ 'type' ] === $type ) {
$params = [ " _: ' { $constructor [ 'predicate' ] } ' " ];
foreach ( $this -> filterParams ( $constructor [ 'params' ], $constructor [ 'type' ]) as $name => $param ) {
if ( isset ( $stack [ $param [ 'type' ]])) {
continue 2 ;
}
$stack [ $param [ 'type' ]] = true ;
if ( $input ) {
$optional = isset ( $param [ 'pow' ]) ? '?' : '' ;
} else {
$optional = isset ( $param [ 'pow' ]) && \is_int ( $param [ 'pow' ]) && $param [ 'type' ] !== 'true'
? '?'
: '' ;
}
2023-01-27 18:25:02 +01:00
$params [] = " $name $optional : " . $this -> prepareTLPsalmType ( $param [ 'type' ], $input , $depth + 1 , $stack );
2023-01-27 18:12:33 +01:00
unset ( $stack [ $param [ 'type' ]]);
}
2023-10-01 20:05:04 +02:00
$params = implode ( ', ' , $params );
2023-01-27 18:12:33 +01:00
$constructors [] = 'array{' . $params . '}' ;
}
}
2023-01-27 19:10:52 +01:00
if ( $constructors === []) {
throw new AssertionError ( " No constructors for $type ! " );
}
2023-10-01 20:05:04 +02:00
$base = implode ( '|' , $constructors );
2023-01-27 18:12:33 +01:00
}
2023-01-27 18:25:02 +01:00
if ( $type === 'InputMessage' ) {
2023-01-27 19:00:11 +01:00
$base = " int| $base " ;
2023-01-27 18:25:02 +01:00
}
2023-05-06 20:35:03 +02:00
if ( $type === 'InputMedia' ) {
2023-07-21 19:21:34 +02:00
$base = " \\ danog \\ MadelineProto \\ EventHandler \\ Media|string| $base " ;
2023-05-06 20:35:03 +02:00
}
2023-01-27 18:12:33 +01:00
if ( $isVector ) {
$base = " list< $base > " ;
}
return $base ;
}
2023-01-27 14:20:47 +01:00
private function prepareTLDefault ( string $type ) : string
{
2023-01-27 18:12:33 +01:00
[ $isVector , $type ] = self :: isVector ( $type );
if ( $isVector ) {
return '[]' ;
}
2023-01-27 14:20:47 +01:00
return match ( $type ) {
'string' => " '' " ,
'bytes' => " '' " ,
'int' => '0' ,
'long' => '0' ,
2023-07-01 14:17:11 +02:00
'strlong' => '0' ,
2023-01-27 14:20:47 +01:00
'double' => '0.0' ,
'float' => '0.0' ,
'Bool' => 'false' ,
2023-01-27 18:12:33 +01:00
'true' => 'false' ,
'DataJSON' => 'null' ,
2023-01-27 19:10:52 +01:00
'JSONValue' => 'null' ,
2023-09-06 18:39:48 +02:00
default => 'null'
2023-01-27 14:20:47 +01:00
};
}
2023-08-05 19:13:26 +02:00
private function preparePsalmDefault ( string $type ) : string
{
[ $isVector , $type ] = self :: isVector ( $type );
if ( $isVector ) {
return 'array<never, never>' ;
}
return match ( $type ) {
'string' => " '' " ,
'bytes' => " '' " ,
'int' => '0' ,
'long' => '0' ,
'strlong' => '0' ,
'double' => '0.0' ,
'float' => '0.0' ,
'Bool' => 'false' ,
'true' => 'false' ,
'DataJSON' => 'null' ,
'JSONValue' => 'null' ,
2023-09-06 18:39:48 +02:00
default => 'null'
2023-08-05 19:13:26 +02:00
};
}
2023-01-27 18:12:33 +01:00
private function prepareTLTypeDescription ( string $type , string $description ) : string
2023-01-27 14:20:47 +01:00
{
2023-01-27 18:12:33 +01:00
[ $isList , $type ] = self :: isVector ( $type );
if ( $isList ) {
$descriptionEnhanced = " Array of $description " ;
} else {
$descriptionEnhanced = $description ;
}
2023-01-27 14:20:47 +01:00
return match ( $type ) {
2023-01-27 18:12:33 +01:00
'string' => $description ,
'bytes' => $description ,
2023-07-08 17:11:21 +02:00
'waveform' => $description ,
2023-01-27 18:12:33 +01:00
'int' => $description ,
'long' => $description ,
2023-07-01 14:17:11 +02:00
'strlong' => $description ,
2023-01-27 18:12:33 +01:00
'double' => $description ,
'float' => $description ,
'Bool' => $description ,
'true' => $description ,
'DataJSON' => 'Any JSON-encodable data' ,
2023-01-27 19:10:52 +01:00
'JSONValue' => 'Any JSON-encodable data' ,
2023-01-27 18:12:33 +01:00
'InputFile' => 'A file name or a file URL. You can also use amphp async streams, amphp HTTP response objects, and [much more](https://docs.madelineproto.xyz/docs/FILES.html#downloading-files)!' ,
default => $descriptionEnhanced
? " $descriptionEnhanced @see https://docs.madelineproto.xyz/API_docs/types/ $type .html "
: " @see https://docs.madelineproto.xyz/API_docs/types/ $type .html "
2023-01-27 14:20:47 +01:00
};
2017-01-22 17:40:56 +01:00
}
2023-01-27 18:12:33 +01:00
private function filterParams ( array $params , string $type , ? string $method = null ) : array
{
$newParams = [];
foreach ( $params as $param ) {
2023-06-28 15:50:38 +02:00
if ( \in_array ( $param [ 'name' ], [ 'flags' , 'flags2' , 'random_id' , 'random_bytes' ], true )) {
2023-01-27 18:12:33 +01:00
continue ;
}
if ( $method ) {
2023-10-01 20:05:04 +02:00
$param [ 'description' ] = str_replace ([ '](../' , '.md' ], [ '](https://docs.madelineproto.xyz/API_docs/' , '.html' ], Lang :: $lang [ 'en' ][ " method_ { $method } _param_ { $param [ 'name' ] } _type_ { $param [ 'type' ] } " ] ? ? '' );
2023-01-27 18:12:33 +01:00
}
2023-10-01 20:05:04 +02:00
$param [ 'type' ] = ltrim ( $param [ 'type' ], '%' );
2023-01-27 18:12:33 +01:00
if ( $param [ 'name' ] === 'data' && $type === 'messages.SentEncryptedMessage' ) {
$param [ 'name' ] = 'message' ;
$param [ 'type' ] = 'DecryptedMessage' ;
}
2023-01-27 19:00:11 +01:00
if ( $param [ 'name' ] === 'bytes' && $type === 'EncryptedMessage' ) {
$param [ 'name' ] = 'decrypted_message' ;
$param [ 'type' ] = 'DecryptedMessage' ;
}
2023-06-28 15:50:38 +02:00
if ( $type === 'DecryptedMessageMedia' && \in_array ( $param [ 'name' ], [ 'key' , 'iv' ], true )) {
2023-01-27 19:00:11 +01:00
continue ;
}
2023-01-27 18:12:33 +01:00
if ( $param [ 'name' ] === 'chat_id' && $method !== 'messages.discardEncryption' ) {
$param [ 'type' ] = 'InputPeer' ;
}
if ( $param [ 'name' ] === 'hash' && $param [ 'type' ] === 'long' ) {
$param [ 'pow' ] = 'optional' ;
$param [ 'type' ] = 'Vector t' ;
$param [ 'subtype' ] = 'int' ;
}
2023-07-01 14:17:11 +02:00
if ( \in_array ( $param [ 'type' ], [ 'int' , 'long' , 'strlong' , 'string' , 'bytes' ], true )) {
2023-01-27 18:12:33 +01:00
$param [ 'pow' ] = 'optional' ;
}
$param [ 'array' ] = isset ( $param [ 'subtype' ]);
if ( $param [ 'array' ]) {
2023-10-01 20:05:04 +02:00
$param [ 'subtype' ] = ltrim ( $param [ 'subtype' ], '%' );
2023-01-27 18:12:33 +01:00
$param [ 'type' ] = 'Vector<' . $param [ 'subtype' ] . '>' ;
$param [ 'pow' ] = 'optional' ;
}
2023-10-01 20:05:04 +02:00
if ( $this -> TL -> getConstructors () -> findByPredicate ( lcfirst ( $param [ 'type' ]) . 'Empty' )) {
2023-09-06 18:39:48 +02:00
$param [ 'pow' ] = 'optional' ;
}
2023-01-27 18:12:33 +01:00
$newParams [ $param [ 'name' ]] = $param ;
}
2023-10-01 20:05:04 +02:00
uasort ( $newParams , fn ( array $arr1 , array $arr2 ) => isset ( $arr1 [ 'pow' ]) <=> isset ( $arr2 [ 'pow' ]));
2023-01-27 18:12:33 +01:00
return $newParams ;
}
private function prepareTLParams ( array $data ) : array
{
[
'params' => $params ,
'type' => $type ,
'method' => $method
] = $data ;
$params = $this -> filterParams ( $params , $type , $method );
$contents = '' ;
$signature = [];
foreach ( $params as $name => $param ) {
2023-10-26 20:26:25 +02:00
if ( $name === 'reply_to' ) {
$param [ 'pow' ] = true ;
$contents .= " * @param int \$ reply_to_msg_id ID Of message to reply to \n " ;
$signature [] = " int \$ reply_to_msg_id = 0 " ;
$contents .= " * @param int \$ top_msg_id This field must contain the topic ID only when replying to messages in forum topics different from the \" General \" topic (i.e. reply_to_msg_id is set and reply_to_msg_id != topicID and topicID != 1). \n " ;
$signature [] = " int \$ top_msg_id = 0 " ;
}
2023-01-27 18:12:33 +01:00
$description = $this -> prepareTLTypeDescription ( $param [ 'type' ], $param [ 'description' ]);
$psalmType = $this -> prepareTLPsalmType ( $param [ 'type' ], true );
2023-09-06 18:39:48 +02:00
$type = $this -> prepareTLType ( $param [ 'type' ], isset ( $param [ 'pow' ]));
2023-01-27 18:12:33 +01:00
$param_var = $type . ' $' . $name ;
if ( isset ( $param [ 'pow' ])) {
$param_var .= ' = ' . $this -> prepareTLDefault ( $param [ 'type' ]);
2023-08-05 19:13:26 +02:00
$psalmDef = $this -> preparePsalmDefault ( $param [ 'type' ]);
if ( $psalmDef === 'array<never, never>' ) {
$psalmType .= '|' . $psalmDef ;
}
2023-01-27 18:12:33 +01:00
}
$signature [] = $param_var ;
$contents .= " * @param { $psalmType } \$ { $name } { $description } \n " ;
2023-01-27 19:00:11 +01:00
if ( $name === 'entities' ) {
2023-07-15 16:34:38 +02:00
$contents .= " * @param \\ danog \\ MadelineProto \\ ParseMode \$ parse_mode Whether to parse HTML or Markdown markup in the message \n " ;
$signature [] = " \\ danog \\ MadelineProto \\ ParseMode \$ parse_mode = \\ danog \\ MadelineProto \\ ParseMode::TEXT " ;
2023-01-27 19:00:11 +01:00
}
2023-01-27 18:12:33 +01:00
}
2023-10-04 21:57:17 +02:00
$contents .= " * @param ?int \$ floodWaitLimit Can be used to specify a custom flood wait limit: if a FLOOD_WAIT_ rate limiting error is received with a waiting period bigger than this integer, an RPCErrorException will be thrown; otherwise, MadelineProto will simply wait for the specified amount of time. Defaults to the value specified in the settings: https://docs.madelineproto.xyz/PHP/danog/MadelineProto/Settings/RPC.html#setfloodtimeout-int-floodtimeout-self \n " ;
$signature [] = " ?int \$ floodWaitLimit = null " ;
2023-10-05 18:25:18 +02:00
$contents .= " * @param bool \$ postpone If true, will postpone execution of this method until the first method call with \$ postpone = false to the same DC or a call to flush() is made, bundling all queued in a single container for higher efficiency. Will not return until the method is queued and a response is received, so this should be used in combination with \\ Amp \\ async. \n " ;
2023-10-04 21:57:17 +02:00
$signature [] = " bool \$ postpone = false " ;
$contents .= " * @param ? \\ Amp \\ Cancellation \$ cancellation Cancellation \n " ;
$signature [] = " ? \\ Amp \\ Cancellation \$ cancellation = null " ;
2023-01-27 18:12:33 +01:00
return [ $contents , $signature ];
}
2017-01-22 17:40:56 +01:00
/**
2019-12-28 16:07:09 +01:00
* Create internalDoc .
2017-01-22 17:40:56 +01:00
*/
2019-12-28 16:07:09 +01:00
private function createInternalClasses () : void
2017-01-22 17:40:56 +01:00
{
2022-12-30 19:21:36 +01:00
Logger :: log ( 'Creating internal classes...' , Logger :: NOTICE );
2019-09-18 20:46:20 +02:00
$internalDoc = [];
2023-01-27 18:12:33 +01:00
foreach ( $this -> TL -> getMethods () -> by_id as $data ) {
2023-10-01 20:05:04 +02:00
if ( ! strpos ( $data [ 'method' ], '.' )) {
2017-01-22 17:40:56 +01:00
continue ;
}
2023-09-28 15:55:32 +02:00
if ( $data [ 'type' ] === 'Vector t' ) {
$data [ 'type' ] = " Vector< { $data [ 'subtype' ] } > " ;
}
2023-10-01 20:05:04 +02:00
[ $namespace , $method ] = explode ( '.' , $data [ 'method' ]);
2023-06-28 15:50:38 +02:00
if ( ! \in_array ( $namespace , $this -> TL -> getMethodNamespaces (), true )) {
2017-01-22 17:40:56 +01:00
continue ;
}
2023-01-27 14:20:47 +01:00
if ( isset ( $this -> blacklist [ $data [ 'method' ]])) {
continue ;
}
2023-01-27 18:12:33 +01:00
2023-10-01 20:05:04 +02:00
$title = str_replace ([ '](../' , '.md' ], [ '](https://docs.madelineproto.xyz/API_docs/' , '.html' ], Lang :: $lang [ 'en' ][ " method_ { $data [ 'method' ] } " ] ? ? '' );
$title = implode ( " \n * " , explode ( " \n " , $title ));
2023-01-27 18:12:33 +01:00
$contents = " \n /** \n " ;
$contents .= " * { $title } \n " ;
$contents .= " * \n " ;
[ $params , $signature ] = $this -> prepareTLParams ( $data );
$contents .= $params ;
2023-09-06 18:39:48 +02:00
$returnType = $this -> prepareTLType ( $data [ 'type' ], isset ( $data [ 'pow' ]));
2023-01-27 18:12:33 +01:00
$psalmType = $this -> prepareTLPsalmType ( $data [ 'type' ], false );
$description = $this -> prepareTLTypeDescription ( $data [ 'type' ], '' );
$contents .= " * @return { $psalmType } { $description } \n " ;
$contents .= " */ \n " ;
$contents .= " public function { $method } ( " ;
2023-10-01 20:05:04 +02:00
$contents .= implode ( ', ' , $signature );
2023-01-27 18:12:33 +01:00
$contents .= " ): { $returnType } ; \n " ;
$internalDoc [ $namespace ][ $method ] = $contents ;
2017-01-22 17:40:56 +01:00
}
2022-12-30 19:21:36 +01:00
$class = new ReflectionClass ( $this -> reflectionClasses [ 'MTProto' ]);
$methods = $class -> getMethods (( ReflectionMethod :: IS_STATIC & ReflectionMethod :: IS_PUBLIC ) | ReflectionMethod :: IS_PUBLIC );
$class = new ReflectionClass ( Tools :: class );
2023-10-01 20:05:04 +02:00
$methods = array_merge ( $methods , $class -> getMethods (( ReflectionMethod :: IS_STATIC & ReflectionMethod :: IS_PUBLIC ) | ReflectionMethod :: IS_PUBLIC ));
2019-09-18 21:21:34 +02:00
foreach ( $methods as $key => $method ) {
2019-09-18 20:46:20 +02:00
$name = $method -> getName ();
2023-01-08 20:33:54 +01:00
if ( $name == 'methodCallAsyncRead' ) {
2023-10-01 20:05:04 +02:00
unset ( $methods [ array_search ( 'methodCall' , $methods )]);
} elseif ( strpos ( $name , '__' ) === 0 ) {
2019-09-18 21:21:34 +02:00
unset ( $methods [ $key ]);
2023-10-01 20:05:04 +02:00
} elseif ( stripos ( $name , 'async' ) !== false ) {
if ( strpos ( $name , '_async' ) !== false ) {
unset ( $methods [ array_search ( str_ireplace ( '_async' , '' , $name ), $methods )]);
2019-09-18 20:46:20 +02:00
} else {
2023-10-01 20:05:04 +02:00
unset ( $methods [ array_search ( str_ireplace ( 'async' , '' , $name ), $methods )]);
2019-09-18 20:46:20 +02:00
}
}
}
2020-04-05 15:33:01 +02:00
$sortedMethods = [];
foreach ( $methods as $method ) {
$sortedMethods [ $method -> getName ()] = $method ;
}
2023-10-01 20:05:04 +02:00
ksort ( $sortedMethods );
$methods = array_values ( $sortedMethods );
2020-04-05 15:33:01 +02:00
2019-09-18 20:46:20 +02:00
foreach ( $methods as $method ) {
$name = $method -> getName ();
2023-10-01 20:05:04 +02:00
if ( strpos ( $method -> getDocComment () ? : '' , '@internal' ) !== false ) {
2019-12-28 16:07:09 +01:00
continue ;
}
2019-12-28 16:45:00 +01:00
$static = $method -> isStatic ();
if ( ! $static ) {
2023-10-01 20:05:04 +02:00
$code = file_get_contents ( $method -> getFileName ());
$code = implode ( " \n " , \array_slice ( explode ( " \n " , $code ), $method -> getStartLine (), $method -> getEndLine () - $method -> getStartLine ()));
if ( strpos ( $code , '$this' ) === false ) {
2020-01-31 19:29:43 +01:00
Logger :: log ( " { $name } should be STATIC! " , Logger :: FATAL_ERROR );
2019-12-28 16:45:00 +01:00
}
}
2019-10-29 22:41:31 +01:00
if ( $name == 'methodCallAsyncRead' ) {
$name = 'methodCall' ;
2023-10-01 20:05:04 +02:00
} elseif ( stripos ( $name , 'async' ) !== false ) {
if ( strpos ( $name , '_async' ) !== false ) {
$name = str_ireplace ( '_async' , '' , $name );
2019-09-18 20:46:20 +02:00
} else {
2023-10-01 20:05:04 +02:00
$name = str_ireplace ( 'async' , '' , $name );
2019-09-18 20:46:20 +02:00
}
}
2020-06-16 17:52:55 +02:00
$name = StrTools :: toCamelCase ( $name );
2023-10-01 20:05:04 +02:00
$name = str_ireplace ([ 'mtproto' , 'api' ], [ 'MTProto' , 'API' ], $name );
2022-07-26 18:41:15 +02:00
$doc = 'public ' ;
if ( $static ) {
$doc .= 'static ' ;
}
$doc .= 'function ' ;
2019-09-18 20:46:20 +02:00
$doc .= $name ;
$doc .= '(' ;
$paramList = '' ;
foreach ( $method -> getParameters () as $param ) {
if ( $type = $param -> getType ()) {
2023-01-08 20:33:54 +01:00
$doc .= $this -> typeToStr ( $type ) . ' ' ;
2019-12-28 17:11:08 +01:00
} else {
2023-01-04 15:13:55 +01:00
Logger :: log ( $name . '.' . $param -> getName () . ' has no type!' , Logger :: WARNING );
2019-09-18 20:46:20 +02:00
}
if ( $param -> isVariadic ()) {
$doc .= '...' ;
}
if ( $param -> isPassedByReference ()) {
$doc .= '&' ;
}
$doc .= '$' ;
$doc .= $param -> getName ();
if ( $param -> isOptional () && ! $param -> isVariadic ()) {
$doc .= ' = ' ;
if ( $param -> isDefaultValueConstant ()) {
2023-10-01 20:05:04 +02:00
$doc .= '\\' . str_replace ([ 'NULL' , 'self' ], [ 'null' , 'danog\\MadelineProto\\MTProto' ], $param -> getDefaultValueConstantName ());
2019-09-18 20:46:20 +02:00
} else {
2023-10-01 20:05:04 +02:00
$doc .= str_replace ( 'NULL' , 'null' , var_export ( $param -> getDefaultValue (), true ));
2019-09-18 20:46:20 +02:00
}
}
$doc .= ', ' ;
2019-09-18 21:21:34 +02:00
if ( $param -> isVariadic ()) {
$paramList .= '...' ;
}
2020-04-05 15:33:01 +02:00
$paramList .= '$' . $param -> getName () . ', ' ;
2019-09-18 20:46:20 +02:00
}
2022-07-16 18:10:33 +02:00
$type = $method -> getReturnType ();
$hasReturnValue = $type !== null ;
2023-10-01 20:05:04 +02:00
$doc = rtrim ( $doc , ', ' );
$paramList = rtrim ( $paramList , ', ' );
2023-01-04 15:13:55 +01:00
$doc .= ')' ;
2019-12-28 16:45:00 +01:00
$async = true ;
2023-01-31 14:11:31 +01:00
if ( $hasReturnValue ) {
2019-09-18 20:46:20 +02:00
$doc .= ': ' ;
2023-01-08 20:33:54 +01:00
$doc .= $this -> typeToStr ( $type );
2019-12-28 16:45:00 +01:00
$async = false ;
2019-09-18 20:46:20 +02:00
}
2020-04-05 15:33:01 +02:00
if ( $method -> getDeclaringClass () -> getName () == Tools :: class ) {
$async = false ;
}
2022-06-04 16:51:23 +02:00
if ( $method -> getDeclaringClass () -> getName () == StrTools :: class ) {
$async = false ;
}
2023-01-27 14:20:47 +01:00
if ( $method -> getDeclaringClass () -> getName () == AsyncTools :: class ) {
$async = false ;
}
$ret = $type && $type instanceof ReflectionNamedType && $type -> getName () === 'void' ? '' : 'return' ;
2020-01-03 13:09:42 +01:00
$doc .= " \n { \n " ;
2020-01-19 13:46:49 +01:00
if ( $async ) {
2023-01-31 14:11:31 +01:00
$doc .= " { $ret } \$ this->wrapper->getAPI()-> { $name } ( { $paramList } ); \n " ;
2020-01-19 13:46:49 +01:00
} elseif ( ! $static ) {
2023-01-26 14:33:30 +01:00
$doc .= " { $ret } \$ this->wrapper->getAPI()-> { $name } ( { $paramList } ); \n " ;
2019-12-28 16:45:00 +01:00
} else {
2023-01-04 15:13:55 +01:00
$doc .= " { $ret } \\ " . $method -> getDeclaringClass () -> getName () . '::' . $name . " ( { $paramList } ); \n " ;
2019-12-28 16:45:00 +01:00
}
2020-01-03 13:09:42 +01:00
$doc .= " } \n " ;
2019-12-28 16:07:09 +01:00
if ( ! $method -> getDocComment ()) {
2020-01-31 19:29:43 +01:00
Logger :: log ( " { $name } has no PHPDOC! " , Logger :: FATAL_ERROR );
2019-12-28 16:07:09 +01:00
}
if ( ! $type ) {
2020-01-31 19:29:43 +01:00
Logger :: log ( " { $name } has no return type! " , Logger :: FATAL_ERROR );
2019-12-28 16:07:09 +01:00
}
2023-01-15 11:21:57 +01:00
$phpdoc = $method -> getDocComment () ? : '' ;
2023-01-27 18:12:33 +01:00
$internalDoc [ 'InternalDoc' ][ $name ] = $phpdoc ;
2023-10-01 20:05:04 +02:00
$internalDoc [ 'InternalDoc' ][ $name ] .= " \n " . implode ( " \n " , explode ( " \n " , $doc ));
2019-09-18 20:46:20 +02:00
}
2017-01-22 17:40:56 +01:00
foreach ( $internalDoc as $namespace => $methods ) {
2019-09-18 20:46:20 +02:00
if ( $namespace === 'InternalDoc' ) {
2023-10-01 20:05:04 +02:00
$handle = fopen ( __DIR__ . '/InternalDoc.php' , 'w' );
fwrite ( $handle , " <?php \n " );
fwrite ( $handle , " /** \n " );
fwrite ( $handle , " * This file is automatically generated by the build_docs.php file \n " );
fwrite ( $handle , " * and is used only for autocompletion in multiple IDEs \n " );
fwrite ( $handle , " * don't modify it manually. \n " );
fwrite ( $handle , " */ \n \n " );
fwrite ( $handle , " namespace { $this -> namespace } ; \n " );
fwrite ( $handle , " use Generator; \n " );
fwrite ( $handle , " use Amp \\ Future; \n " );
fwrite ( $handle , " use Closure; \n " );
fwrite ( $handle , " use __PHP_Incomplete_Class; \n " );
fwrite ( $handle , " use Amp \\ ByteStream \\ WritableStream; \n " );
fwrite ( $handle , " use Amp \\ ByteStream \\ ReadableStream; \n " );
fwrite ( $handle , " use Amp \\ ByteStream \\ Pipe; \n " );
fwrite ( $handle , " use Amp \\ Cancellation; \n " );
fwrite ( $handle , " use Amp \\ Http \\ Server \\ Request as ServerRequest; \n " );
fwrite ( $handle , " use danog \\ MadelineProto \\ Broadcast \\ Action; \n " );
fwrite ( $handle , " use danog \\ MadelineProto \\ MTProtoTools \\ DialogId; \n " );
2023-08-31 18:50:48 +02:00
$had = [];
2023-08-05 19:13:26 +02:00
foreach ( ClassFinder :: getClassesInNamespace ( \danog\MadelineProto\EventHandler :: class , ClassFinder :: RECURSIVE_MODE ) as $class ) {
2023-10-01 20:05:04 +02:00
$name = basename ( str_replace ( '\\' , '//' , $class ));
2023-09-06 19:33:52 +02:00
if ( isset ( $had [ $name ]) || $name === 'Status' || $name === 'Action' ) {
2023-08-31 18:50:48 +02:00
continue ;
}
$had [ $name ] = true ;
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " use $class ; \n " );
2023-08-05 19:13:26 +02:00
}
2023-08-05 20:15:50 +02:00
/** @psalm-suppress UndefinedClass */
2023-08-05 19:13:26 +02:00
foreach ( ClassFinder :: getClassesInNamespace ( \danog\MadelineProto\Ipc :: class , ClassFinder :: RECURSIVE_MODE ) as $class ) {
2023-10-01 20:05:04 +02:00
if ( str_contains ( $class , 'Wrapper' )) {
2023-08-05 19:13:26 +02:00
continue ;
}
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " use $class ; \n " );
2023-08-05 19:13:26 +02:00
}
2023-08-05 20:15:50 +02:00
/** @psalm-suppress UndefinedClass */
2023-08-05 19:13:26 +02:00
foreach ( ClassFinder :: getClassesInNamespace ( \danog\MadelineProto\Broadcast :: class , ClassFinder :: RECURSIVE_MODE ) as $class ) {
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " use $class ; \n " );
2023-08-05 19:13:26 +02:00
}
2023-01-27 14:20:47 +01:00
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " \n /** @psalm-suppress PossiblyNullReference */ \n abstract class { $namespace } \n { \n protected APIWrapper \$ wrapper; \n " );
2023-01-27 14:20:47 +01:00
foreach ( $this -> TL -> getMethodNamespaces () as $namespace ) {
2023-10-01 20:05:04 +02:00
$namespaceInterface = '\\danog\\MadelineProto\\Namespace\\' . ucfirst ( $namespace );
fwrite ( $handle , '/** @var ' . $namespaceInterface . ' $' . $namespace . " */ \n " );
fwrite ( $handle , 'public $' . $namespace . " ; \n " );
2023-01-27 14:20:47 +01:00
}
2023-10-01 20:05:04 +02:00
fwrite ( $handle , '
2023-01-27 14:20:47 +01:00
/**
* Export APIFactory instance with the specified namespace .
2023-01-27 14:42:41 +01:00
* @ psalm - suppress InaccessibleProperty
2023-01-27 14:20:47 +01:00
*/
protected function exportNamespaces () : void
{
' );
foreach ( $this -> TL -> getMethodNamespaces () as $namespace ) {
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " \$ this-> $namespace ??= new \\ danog \\ MadelineProto \\ Namespace \\ AbstractAPI(' $namespace '); \n " );
fwrite ( $handle , " \$ this-> { $namespace } ->setWrapper( \$ this->wrapper); \n " );
2023-01-27 14:20:47 +01:00
}
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " } \n " );
2019-09-18 20:46:20 +02:00
} else {
2023-10-01 20:05:04 +02:00
$namespace = ucfirst ( $namespace );
$handle = fopen ( __DIR__ . " /Namespace/ $namespace .php " , 'w' );
fwrite ( $handle , " <?php \n " );
fwrite ( $handle , " /** \n " );
fwrite ( $handle , " * This file is automatic generated by build_docs.php file \n " );
fwrite ( $handle , " * and is used only for autocomplete in multiple IDE \n " );
fwrite ( $handle , " * don't modify manually. \n " );
fwrite ( $handle , " */ \n \n " );
fwrite ( $handle , " namespace { $this -> namespace } \\ Namespace; \n " );
2023-01-27 14:20:47 +01:00
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " \n interface { $namespace } \n { " );
2019-09-18 20:46:20 +02:00
}
2023-01-27 18:12:33 +01:00
foreach ( $methods as $contents ) {
2023-10-01 20:05:04 +02:00
fwrite ( $handle , $contents );
2017-01-22 17:40:56 +01:00
}
2023-10-01 20:05:04 +02:00
fwrite ( $handle , " } \n " );
2017-01-22 17:40:56 +01:00
}
2023-10-01 20:05:04 +02:00
fclose ( $handle );
2023-09-16 19:49:34 +02:00
2023-10-01 20:05:04 +02:00
$handle = fopen ( __DIR__ . '/EventHandler/SimpleFilters.php' , 'w' );
fwrite ( $handle , " <?php \n " );
fwrite ( $handle , " /** \n " );
fwrite ( $handle , " * This file is automatically generated by the build_docs.php file \n " );
fwrite ( $handle , " * and is used only for autocompletion in multiple IDEs \n " );
fwrite ( $handle , " * don't modify it manually. \n " );
fwrite ( $handle , " */ \n \n " );
fwrite ( $handle , " namespace { $this -> namespace } \\ EventHandler; \n " );
fwrite ( $handle , " /** @internal An internal interface used to avoid type errors when using simple filters. */ \n " );
fwrite ( $handle , " interface SimpleFilters extends " );
2023-09-16 19:49:34 +02:00
/** @psalm-suppress UndefinedClass */
2023-10-01 20:05:04 +02:00
fwrite ( $handle , implode ( " , " , array_map ( fn ( $s ) => " \\ $s " , ClassFinder :: getClassesInNamespace ( \danog\MadelineProto\EventHandler\SimpleFilter :: class , ClassFinder :: RECURSIVE_MODE | ClassFinder :: ALLOW_INTERFACES ))));
fwrite ( $handle , " { } \n " );
2017-01-22 17:40:56 +01:00
}
2023-01-08 20:33:54 +01:00
private function typeToStr ( ReflectionType $type ) : string
{
$new = '' ;
if ( $type instanceof ReflectionNamedType ) {
2023-01-31 14:11:31 +01:00
if ( $type -> allowsNull () && $type -> getName () !== 'mixed' && $type -> getName () !== 'null' ) {
2023-01-08 20:33:54 +01:00
$new .= '?' ;
}
if ( ! $type -> isBuiltin ()) {
$new .= '\\' ;
2023-01-27 19:10:52 +01:00
};
2023-01-08 20:33:54 +01:00
$new .= $type -> getName () === 'self' ? $this -> reflectionClasses [ 'API' ] : $type -> getName ();
} elseif ( $type instanceof ReflectionUnionType ) {
2023-10-01 20:05:04 +02:00
return implode ( '|' , array_map ( $this -> typeToStr ( ... ), $type -> getTypes ()));
2023-01-08 20:33:54 +01:00
}
return $new ;
}
2018-02-24 17:54:39 +01:00
}