add class alias support

This commit is contained in:
sunxyw 2022-12-25 18:15:07 +08:00
parent 05b3446f59
commit a813e80b32
No known key found for this signature in database
GPG Key ID: F391C42B19AFFC98
8 changed files with 50 additions and 189 deletions

View File

@ -2,24 +2,22 @@
declare(strict_types=1);
use ZM\Container\ClassAliasHelper;
ClassAliasHelper::addAlias(\ZM\Annotation\Framework\BindEvent::class, 'BindEvent');
ClassAliasHelper::addAlias(\ZM\Annotation\Framework\Init::class, 'Init');
ClassAliasHelper::addAlias(\ZM\Annotation\Framework\Setup::class, 'Setup');
ClassAliasHelper::addAlias(\ZM\Annotation\Http\Controller::class, 'Controller');
ClassAliasHelper::addAlias(\ZM\Annotation\Http\Route::class, 'Route');
ClassAliasHelper::addAlias(\ZM\Annotation\Middleware\Middleware::class, 'Middleware');
ClassAliasHelper::addAlias(\ZM\Annotation\OneBot\BotCommand::class, 'BotCommand');
ClassAliasHelper::addAlias(\ZM\Annotation\OneBot\BotEvent::class, 'BotEvent');
ClassAliasHelper::addAlias(\ZM\Annotation\OneBot\CommandArgument::class, 'CommandArgument');
ClassAliasHelper::addAlias(\ZM\Annotation\Closed::class, 'Closed');
ClassAliasHelper::addAlias(\ZM\Plugin\ZMPlugin::class, 'ZMPlugin');
ClassAliasHelper::addAlias(\OneBot\V12\Object\OneBotEvent::class, 'OneBotEvent');
ClassAliasHelper::addAlias(\ZM\Context\BotContext::class, 'BotContext');
class_alias(\ZM\Annotation\Framework\BindEvent::class, 'BindEvent');
class_alias(\ZM\Annotation\Framework\Init::class, 'Init');
class_alias(\ZM\Annotation\Framework\Setup::class, 'Setup');
class_alias(\ZM\Annotation\Http\Controller::class, 'Controller');
class_alias(\ZM\Annotation\Http\Route::class, 'Route');
class_alias(\ZM\Annotation\Middleware\Middleware::class, 'Middleware');
class_alias(\ZM\Annotation\OneBot\BotCommand::class, 'BotCommand');
class_alias(\ZM\Annotation\OneBot\BotEvent::class, 'BotEvent');
class_alias(\ZM\Annotation\OneBot\CommandArgument::class, 'CommandArgument');
class_alias(\ZM\Annotation\Closed::class, 'Closed');
class_alias(\ZM\Plugin\ZMPlugin::class, 'ZMPlugin');
class_alias(\OneBot\V12\Object\OneBotEvent::class, 'OneBotEvent');
class_alias(\ZM\Context\BotContext::class, 'BotContext');
// 下面是 OneBot 相关类的全局别称
ClassAliasHelper::addAlias(\OneBot\Driver\Event\WebSocket\WebSocketOpenEvent::class, 'WebSocketOpenEvent');
ClassAliasHelper::addAlias(\OneBot\Driver\Event\WebSocket\WebSocketCloseEvent::class, 'WebSocketCloseEvent');
ClassAliasHelper::addAlias(\OneBot\Driver\Event\WebSocket\WebSocketMessageEvent::class, 'WebSocketMessageEvent');
ClassAliasHelper::addAlias(\OneBot\Driver\Event\Http\HttpRequestEvent::class, 'HttpRequestEvent');
class_alias(\OneBot\Driver\Event\WebSocket\WebSocketOpenEvent::class, 'WebSocketOpenEvent');
class_alias(\OneBot\Driver\Event\WebSocket\WebSocketCloseEvent::class, 'WebSocketCloseEvent');
class_alias(\OneBot\Driver\Event\WebSocket\WebSocketMessageEvent::class, 'WebSocketMessageEvent');
class_alias(\OneBot\Driver\Event\Http\HttpRequestEvent::class, 'HttpRequestEvent');

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
class_alias(ZM\Annotation\Framework\BindEvent::class, 'BindEvent');
class_alias(ZM\Annotation\Framework\Init::class, 'Init');
class_alias(ZM\Annotation\Framework\Setup::class, 'Setup');
class_alias(ZM\Annotation\Http\Controller::class, 'Controller');
class_alias(ZM\Annotation\Http\Route::class, 'Route');
class_alias(ZM\Annotation\Middleware\Middleware::class, 'Middleware');
class_alias(ZM\Annotation\OneBot\BotCommand::class, 'BotCommand');
class_alias(ZM\Annotation\OneBot\BotEvent::class, 'BotEvent');
class_alias(ZM\Annotation\OneBot\CommandArgument::class, 'CommandArgument');
class_alias(ZM\Annotation\Closed::class, 'Closed');
class_alias(ZM\Plugin\ZMPlugin::class, 'ZMPlugin');
class_alias(OneBot\V12\Object\OneBotEvent::class, 'OneBotEvent');
class_alias(ZM\Context\BotContext::class, 'BotContext');
class_alias(OneBot\Driver\Event\WebSocket\WebSocketOpenEvent::class, 'WebSocketOpenEvent');
class_alias(OneBot\Driver\Event\WebSocket\WebSocketCloseEvent::class, 'WebSocketCloseEvent');
class_alias(OneBot\Driver\Event\WebSocket\WebSocketMessageEvent::class, 'WebSocketMessageEvent');
class_alias(OneBot\Driver\Event\Http\HttpRequestEvent::class, 'HttpRequestEvent');

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Module\Example;
use OneBot\Driver\Event\WebSocket\WebSocketMessageEvent;
use OneBot\V12\Object\OneBotEvent;
use ZM\Annotation\Http\Route;
use ZM\Annotation\Middleware\Middleware;
use ZM\Annotation\OneBot\BotEvent;
@ -21,7 +20,7 @@ class Hello123
}
#[BotEvent()]
public function onOBEvent(OneBotEvent $event, WebSocketMessageEvent $messageEvent): void
public function onOBEvent(\OneBotEvent $event, WebSocketMessageEvent $messageEvent): void
{
logger()->info("收到了 {$event->getType()}.{$event->getDetailType()} 事件");
}

View File

@ -1,28 +0,0 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Generate;
use Symfony\Component\Console\Attribute\AsCommand;
use ZM\Command\Command;
use ZM\Container\ClassAliasHelper;
#[AsCommand(name: 'generate:alias-helper', description: '类别名的 IDE Helper 文件生成')]
class ClassAliasHelperGenerateCommand extends Command
{
/**
* {@inheritDoc}
*/
protected function handle(): int
{
$str = "<?php\n\ndeclare(strict_types=1);\n\n";
$alias = ClassAliasHelper::getAllAlias();
foreach ($alias as $a => $c) {
$str .= "class_alias({$c['class']}::class, '{$a}');\n";
}
file_put_contents(FRAMEWORK_ROOT_DIR . '/src/Globals/global_class_alias_helper.php', $str);
$this->info('生成成功');
return Command::SUCCESS;
}
}

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace ZM\Container;
use DI\Definition\Definition;
use DI\Definition\Source\DefinitionSource;
class AliasBasedAutowiring implements DefinitionSource
{
private DefinitionSource $source;
public function __construct(DefinitionSource $source)
{
$this->source = $source;
}
public function getDefinition(string $name): ?Definition
{
// 如果是别名,使用类名获取定义
if (ClassAliasHelper::isAlias($name)) {
$class = ClassAliasHelper::getAlias($name);
} else {
$class = $name;
}
return $this->source->getDefinition($class);
}
public function getDefinitions(): array
{
return $this->source->getDefinitions();
}
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace ZM\Container;
use DI\Definition\Definition;
use DI\Definition\Reference;
use DI\Definition\Source\DefinitionSource;
class AliasDefinitionSource implements DefinitionSource
{
public function getDefinition(string $name): ?Definition
{
if (!class_exists($name)) {
return null;
}
$ref = (new \ReflectionClass($name))->getName();
// 如果反射类名和类名不一致,说明是别名,使用类名获取定义
return $ref === $name ? null : new Reference($ref);
}
public function getDefinitions(): array
{
return [];
}
}

View File

@ -1,79 +0,0 @@
<?php
declare(strict_types=1);
namespace ZM\Container;
/**
* 旨在帮助识别 class_alias 定义的类别名
*/
class ClassAliasHelper
{
/**
* @var array<string, class-string>
*/
private static array $aliases = [];
/**
* 添加一个类别名
*
* @param string $class 类名
* @param string $alias 别名
*/
public static function addAlias(string $class, string $alias): void
{
class_alias($class, $alias);
self::$aliases[$alias] = $class;
}
/**
* 判断一个类是否是别名
*
* @param string $alias 别名
*/
public static function isAlias(string $alias): bool
{
return isset(self::$aliases[$alias]);
}
/**
* 获取别名定义信息
*
* @param string $alias 别名
* @return null|class-string 如果没有定义则返回 null
*/
public static function getAlias(string $alias): ?string
{
return self::$aliases[$alias] ?? null;
}
/**
* 根据类名获取别名
*
* @param string $class 类名
* @return null|class-string 如果没有定义则返回 null
*/
public static function getAliasByClass(string $class): ?string
{
return array_search($class, self::$aliases, true) ?: null;
}
/**
* 根据别名获取类名
*
* @param string $alias 别名
* @return string 类名
*/
public static function getClass(string $alias): string
{
return self::$aliases[$alias] ?? $alias;
}
/**
* 获取所有别名定义信息
*/
public static function getAllAlias(): array
{
return self::$aliases;
}
}

View File

@ -28,13 +28,12 @@ class ContainerHolder
private static function buildContainer(): Container
{
$builder = new ContainerBuilder();
$sources = [
new DI\Definition\Source\ReflectionBasedAutowiring(),
new DI\Definition\Source\AttributeBasedAutowiring(),
$builder->addDefinitions(
new AliasDefinitionSource(),
new DI\Definition\Source\DefinitionArray(config('container.definitions', [])),
];
$source = new DI\Definition\Source\SourceChain($sources);
$builder->addDefinitions(new AliasBasedAutowiring($source));
);
$builder->useAutowiring(true);
$builder->useAttributes(true);
return $builder->build();
}
}