邹景立 34104dad22 Update plugin headers and add rewrite-model script
Replace header text "Payment Plugin for ThinkAdmin" with "ThinkAdmin Plugin for ThinkAdmin" across project files (configs, controllers, plugins, php-cs-fixer, etc.) to unify branding. Add a new composer script "rewrite-model" to regenerate models and run php-cs-fixer. Also apply a minor newline fix in .copilot-commit-message-instructions.md.
2026-02-01 14:24:36 +08:00

234 lines
6.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
/**
* +----------------------------------------------------------------------
* | ThinkAdmin Plugin for ThinkAdmin
* +----------------------------------------------------------------------
* | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
* +----------------------------------------------------------------------
* | 官方网站: https://thinkadmin.top
* +----------------------------------------------------------------------
* | 开源协议 ( https://mit-license.org )
* | 免责声明 ( https://thinkadmin.top/disclaimer )
* | 会员特权 ( https://thinkadmin.top/vip-introduce )
* +----------------------------------------------------------------------
* | gitee 代码仓库https://gitee.com/zoujingli/ThinkAdmin
* | github 代码仓库https://github.com/zoujingli/ThinkAdmin
* +----------------------------------------------------------------------
*/
namespace think\admin;
use think\admin\service\ModuleService;
use think\admin\service\NodeService;
use think\App;
use think\Service;
/**
* 插件注册服务
*
* @class Plugin
*
* @method string getAppCode() static 获取插件编号
* @method string getAppName() static 获取插件名称
* @method string getAppPath() static 获取插件路径
* @method string getAppSpace() static 获取插件空间名
* @method string getAppPackage() static 获取插件安装包
*/
abstract class Plugin extends Service
{
/**
* 必填,插件包名.
* @var string
*/
protected $package = '';
/**
* 必填,插件编码
* @var string
*/
protected $appCode = '';
/**
* 必填,插件名称.
* @var string
*/
protected $appName = '';
/**
* 可选,插件目录.
* @var string
*/
protected $appPath = '';
/**
* 可选,插件别名.
* @var string
*/
protected $appAlias = '';
/**
* 可选,命名空间.
* @var string
*/
protected $appSpace = '';
/**
* 可选,注册服务
* @var string
*/
protected $appService = '';
/**
* 插件配置.
* @var array
*/
private static $addons = [];
/**
* 自动注册插件.
*/
public function __construct(App $app)
{
parent::__construct($app);
// 获取基础服务类
$ref = new \ReflectionClass(static::class);
// 应用服务注册类
if (empty($this->appService)) {
$this->appService = static::class;
}
// 应用命名空间名
if (empty($this->appSpace)) {
$this->appSpace = $ref->getNamespaceName();
}
// 应用插件路径计算
if (empty($this->appPath) || !is_dir($this->appPath)) {
$this->appPath = dirname($ref->getFileName());
}
// 应用插件包名计算
if (empty($this->package) && ($path = $ref->getFileName())) {
for ($level = 1; $level <= 3; ++$level) {
if (is_file($file = dirname($path, $level) . '/composer.json')) {
$this->package = json_decode(file_get_contents($file), true)['name'] ?? '';
break;
}
}
}
// 应用插件计算名称及别名
$attr = explode('\\', $ref->getNamespaceName());
if ($attr[0] === NodeService::space()) {
array_shift($attr);
}
$this->appCode = $this->appCode ?: join('-', $attr);
if ($this->appCode === $this->appAlias) {
$this->appAlias = '';
}
if (is_dir($this->appPath)) {
// 写入插件参数信息
self::$addons[$this->appCode] = [
'name' => $this->appName,
'path' => realpath($this->appPath) . DIRECTORY_SEPARATOR,
'alias' => $this->appAlias,
'space' => $this->appSpace ?: NodeService::space($this->appCode),
'package' => $this->package,
'service' => $this->appService,
];
// 插件别名动态设置
if (!empty($this->appAlias) && $this->appCode !== $this->appAlias) {
Library::$sapp->config->set([
'app_map' => array_merge(Library::$sapp->config->get('app.app_map', []), [
$this->appAlias => $this->appCode,
]),
], 'app');
}
}
}
/**
* 获取对象内部属性.
*/
public function __get(string $name)
{
return $this->{$name} ?? '';
}
/**
* 静态调用方法兼容.
* @return null|array|string
* @throws Exception
*/
public static function __callStatic(string $method, array $arguments)
{
switch (strtolower($method)) {
case 'all':
return self::get(...$arguments);
case 'getappcode':
return app(static::class)->appCode;
case 'getappname':
return app(static::class)->appName;
case 'getapppath':
return app(static::class)->appPath;
case 'getappspace':
return app(static::class)->appSpace;
case 'getapppackage':
return app(static::class)->package;
default:
$class = basename(str_replace('\\', '/', static::class));
throw new Exception("method not exists: {$class}::{$method}()");
}
}
/**
* 魔术方法调用兼容处理.
* @return null|array
* @throws Exception
*/
public function __call(string $method, array $arguments)
{
return self::__callStatic($method, $arguments);
}
/**
* 注册应用启动.
*/
public function boot(): void {}
/**
* 获取插件及安装信息.
* @param ?string $code 指定插件编号
* @param bool $append 关联安装数据
*/
public static function get(?string $code = null, bool $append = false): ?array
{
// 读取插件原始信息
$data = empty($code) ? self::$addons : (self::$addons[$code] ?? null);
if (empty($data) || empty($append)) {
return $data;
}
// 关联插件安装信息
$versions = ModuleService::getLibrarys();
return empty($code) ? array_map(static function ($item) use ($versions) {
$item['install'] = $versions[$item['package']] ?? [];
if (empty($item['name'])) {
$item['name'] = $item['install']['name'] ?? '';
}
return $item;
}, $data) : $data + ['install' => $versions[$data['package']] ?? []];
}
/**
* 定义插件菜单.
* @return array 一级或二级菜单
*/
abstract public static function menu(): array;
}