OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
28
app/Core/Plugins/Attributes/RequiresPlugin.php
Normal file
28
app/Core/Plugins/Attributes/RequiresPlugin.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Core\Plugins\Attributes;
|
||||
|
||||
/**
|
||||
* Marks a JSON-RPC service method (or whole class) as requiring a named plugin to be enabled.
|
||||
*
|
||||
* Enforced at the JSON-RPC dispatch boundary. When the named plugin is disabled, calls return
|
||||
* a clean JSON-RPC error (-32004) in the response body with HTTP 200 — mirroring the convention
|
||||
* used by AuthorizationException / NotFoundException.
|
||||
*
|
||||
* Class-level usage gates every method on the class; method-level usage overrides per-method.
|
||||
*
|
||||
* Single-plugin gating only — the attribute is NOT `IS_REPEATABLE`, so PHP rejects
|
||||
* multiple `#[RequiresPlugin(...)]` on the same target at the language level. If a
|
||||
* future tool legitimately needs to require several plugins together, mark this
|
||||
* attribute repeatable and update the Jsonrpc dispatcher to iterate all instances
|
||||
* (AND-semantics — every named plugin must be enabled).
|
||||
*
|
||||
* Client surfaces (mobile, MCP) should query the core JSON-RPC `config.getSystemInfo` method
|
||||
* to gate UI client-side so the user never reaches a denied call. The attribute is the
|
||||
* server-side defense; the capabilities response is the client-side prevention.
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS)]
|
||||
class RequiresPlugin
|
||||
{
|
||||
public function __construct(public string $pluginName) {}
|
||||
}
|
||||
16
app/Core/Plugins/PluginManager.php
Normal file
16
app/Core/Plugins/PluginManager.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Core\Plugins;
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
public function __construct() {}
|
||||
|
||||
public function loadPlugin(string $pluginPath): void
|
||||
{
|
||||
$registerFile = $pluginPath.'/register.php';
|
||||
if (file_exists($registerFile)) {
|
||||
require_once $registerFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
app/Core/Plugins/Plugins.php
Normal file
146
app/Core/Plugins/Plugins.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Core\Plugins;
|
||||
|
||||
use Leantime\Core\Configuration;
|
||||
use Leantime\Core\Events\DispatchesEvents;
|
||||
|
||||
/**
|
||||
* Plugins class
|
||||
*/
|
||||
class Plugins
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* Enabled plugins
|
||||
*/
|
||||
private array $enabledPlugins = [];
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Configuration\Environment $config)
|
||||
{
|
||||
if (isset($config->plugins)) {
|
||||
$plugins = json_decode($config->plugins);
|
||||
} else {
|
||||
$plugins = [];
|
||||
}
|
||||
|
||||
$this->enabledPlugins = $this->standardize_plugin_keys(
|
||||
(array) $plugins
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes all plugin keys lowercase for easy comparisons
|
||||
*/
|
||||
private function standardize_plugin_keys(array $plugins): array
|
||||
{
|
||||
foreach ($plugins as $plugin_key => $plugin_enabled) {
|
||||
if ($plugin_key == strtolower($plugin_key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$plugins[strtolower($plugin_key)] = $plugin_enabled;
|
||||
unset($plugins[$plugin_key]);
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all plugin enabled/disabled settings
|
||||
*/
|
||||
public function getEnabledPlugins(): array
|
||||
{
|
||||
return $this->enabledPlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a plugin is enabled
|
||||
*/
|
||||
public function isPluginEnabled(string $plugin_name): bool
|
||||
{
|
||||
$plugin_name = strtolower($plugin_name);
|
||||
|
||||
if (
|
||||
in_array($plugin_name, array_keys($this->enabledPlugins)) && $this->enabledPlugins[$plugin_name]
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets paths for enabled plugins, supporting both folder and phar formats
|
||||
*
|
||||
* @return array Array of plugin paths with format information
|
||||
*/
|
||||
public function getEnabledPluginPaths(): array
|
||||
{
|
||||
$pluginPaths = [];
|
||||
$pluginDirectory = APP_ROOT.'/app/Plugins/';
|
||||
|
||||
// Get enabled plugins from the domain service
|
||||
try {
|
||||
$pluginService = app()->make(\Leantime\Domain\Plugins\Services\Plugins::class);
|
||||
$enabledPlugins = $pluginService->getEnabledPlugins();
|
||||
|
||||
foreach ($enabledPlugins as $plugin) {
|
||||
// Skip incomplete class objects
|
||||
if (is_a($plugin, '__PHP_Incomplete_Class') || $plugin == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$pluginPath = $pluginDirectory.$plugin->foldername;
|
||||
|
||||
if ($plugin->format == 'phar') {
|
||||
$pharPath = "phar://{$pluginPath}/{$plugin->foldername}.phar";
|
||||
|
||||
if (file_exists($pharPath)) {
|
||||
$pluginPaths[] = [
|
||||
'path' => $pharPath,
|
||||
'foldername' => $plugin->foldername,
|
||||
'format' => 'phar',
|
||||
'namespace' => "Leantime\\Plugins\\{$plugin->foldername}\\",
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// Folder-based plugin
|
||||
if (is_dir($pluginPath)) {
|
||||
$pluginPaths[] = [
|
||||
'path' => $pluginPath,
|
||||
'foldername' => $plugin->foldername,
|
||||
'format' => 'folder',
|
||||
'namespace' => "Leantime\\Plugins\\{$plugin->foldername}\\",
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Fall back to system plugins if service unavailable
|
||||
if (isset($this->enabledPlugins)) {
|
||||
foreach ($this->enabledPlugins as $pluginName => $enabled) {
|
||||
if ($enabled) {
|
||||
$pluginPath = $pluginDirectory.$pluginName;
|
||||
if (is_dir($pluginPath)) {
|
||||
$pluginPaths[] = [
|
||||
'path' => $pluginPath,
|
||||
'foldername' => $pluginName,
|
||||
'format' => 'folder',
|
||||
'namespace' => "Leantime\\Plugins\\{$pluginName}\\",
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $pluginPaths;
|
||||
}
|
||||
}
|
||||
18
app/Core/Plugins/PluginsServiceProvider.php
Normal file
18
app/Core/Plugins/PluginsServiceProvider.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Core\Plugins;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class PluginsServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton(\Leantime\Domain\Plugins\Services\Plugins::class, \Leantime\Domain\Plugins\Services\Plugins::class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user