OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
<?php
namespace Leantime\Core\Console;
use Illuminate\Console\Command as IlluminateCommand;
use Illuminate\Console\Events\ArtisanStarting;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\ProcessUtils;
use Leantime\Core\Events\DispatchesEvents;
use Symfony\Component\Console\Command\Command as SymfonyCommand;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Application extends \Illuminate\Console\Application
{
use DispatchesEvents;
protected $commandsLoaded = false;
public function __construct(Container $laravel, Dispatcher $events, $version)
{
$parent = get_parent_class(\Illuminate\Console\Application::class);
$parent::__construct('Leantime CLI (extends Laravel)', $version);
$this->laravel = $laravel;
$this->events = $events;
$this->setAutoExit(false);
$this->setCatchExceptions(false);
$this->events->dispatch(new ArtisanStarting($this));
$this->bootstrap();
}
/**
* Inject the Laravel container into commands as they are registered.
*
* symfony/console 7.4 renamed add() to addCommand() and routes the lazy command-loader
* path (Application::has() -> commandLoader->get()) through addCommand(), but
* Illuminate\Console\Application only overrides the deprecated add() — the single place
* setLaravel() is called. The result is that lazily-resolved #[AsCommand] commands run
* with a null $laravel and fatal in Command::run(). Mirroring Illuminate's add() here on
* addCommand() closes that gap for every registration path (add() delegates here too).
*/
public function addCommand(callable|SymfonyCommand $command): ?SymfonyCommand
{
if ($command instanceof IlluminateCommand) {
$command->setLaravel($this->laravel);
}
return parent::addCommand($command);
}
/**
* Runs the current application.
*
* @return int 0 if everything went fine, or an error code
*/
public function doRun(InputInterface $input, OutputInterface $output): int
{
// $this->setDomain($input);
self::dispatchEvent('beforeRun', ['application' => $this, 'input' => $input, 'output' => $output]);
/* wrapper for future use */
return parent::doRun($input, $output);
}
protected function getDefaultInputDefinition(): InputDefinition
{
$definition = parent::getDefaultInputDefinition();
$definition->addOption(new InputOption('--domain', null, InputOption::VALUE_OPTIONAL, 'Set domain for config'));
return $definition;
}
protected function bootstrap()
{
foreach (static::$bootstrappers as $bootstrapper) {
$bootstrapper($this);
}
}
public static function artisanBinary()
{
return ProcessUtils::escapeArgument('bin/leantime');
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Leantime\Core\Console;
use Leantime\Core\Http\IncomingRequest;
class CliRequest extends IncomingRequest
{
//
public function handle() {}
}

View File

@@ -0,0 +1,835 @@
<?php
namespace Leantime\Core\Console;
use Illuminate\Auth\Console\ClearResetsCommand;
use Illuminate\Cache\Console\CacheTableCommand;
use Illuminate\Cache\Console\ClearCommand as CacheClearCommand;
use Illuminate\Cache\Console\ForgetCommand as CacheForgetCommand;
use Illuminate\Cache\Console\PruneStaleTagsCommand;
use Illuminate\Console\Scheduling\ScheduleClearCacheCommand;
use Illuminate\Console\Scheduling\ScheduleFinishCommand;
use Illuminate\Console\Scheduling\ScheduleInterruptCommand;
use Illuminate\Console\Scheduling\ScheduleListCommand;
use Illuminate\Console\Scheduling\ScheduleRunCommand;
use Illuminate\Console\Scheduling\ScheduleTestCommand;
use Illuminate\Console\Scheduling\ScheduleWorkCommand;
use Illuminate\Console\Signals;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Database\Console\DbCommand;
use Illuminate\Database\Console\DumpCommand;
use Illuminate\Database\Console\Factories\FactoryMakeCommand;
use Illuminate\Database\Console\MonitorCommand as DatabaseMonitorCommand;
use Illuminate\Database\Console\PruneCommand;
use Illuminate\Database\Console\Seeds\SeedCommand;
use Illuminate\Database\Console\Seeds\SeederMakeCommand;
use Illuminate\Database\Console\ShowCommand;
use Illuminate\Database\Console\ShowModelCommand;
use Illuminate\Database\Console\TableCommand as DatabaseTableCommand;
use Illuminate\Database\Console\WipeCommand;
use Illuminate\Foundation\Console\AboutCommand;
use Illuminate\Foundation\Console\CastMakeCommand;
use Illuminate\Foundation\Console\ChannelListCommand;
use Illuminate\Foundation\Console\ChannelMakeCommand;
use Illuminate\Foundation\Console\ClearCompiledCommand;
use Illuminate\Foundation\Console\ComponentMakeCommand;
use Illuminate\Foundation\Console\ConfigCacheCommand;
use Illuminate\Foundation\Console\ConfigClearCommand;
use Illuminate\Foundation\Console\ConfigShowCommand;
use Illuminate\Foundation\Console\ConsoleMakeCommand;
use Illuminate\Foundation\Console\DocsCommand;
use Illuminate\Foundation\Console\DownCommand;
use Illuminate\Foundation\Console\EnvironmentCommand;
use Illuminate\Foundation\Console\EnvironmentDecryptCommand;
use Illuminate\Foundation\Console\EnvironmentEncryptCommand;
use Illuminate\Foundation\Console\EventCacheCommand;
use Illuminate\Foundation\Console\EventClearCommand;
use Illuminate\Foundation\Console\EventGenerateCommand;
use Illuminate\Foundation\Console\EventListCommand;
use Illuminate\Foundation\Console\EventMakeCommand;
use Illuminate\Foundation\Console\ExceptionMakeCommand;
use Illuminate\Foundation\Console\JobMakeCommand;
use Illuminate\Foundation\Console\KeyGenerateCommand;
use Illuminate\Foundation\Console\LangPublishCommand;
use Illuminate\Foundation\Console\ListenerMakeCommand;
use Illuminate\Foundation\Console\MailMakeCommand;
use Illuminate\Foundation\Console\ModelMakeCommand;
use Illuminate\Foundation\Console\NotificationMakeCommand;
use Illuminate\Foundation\Console\ObserverMakeCommand;
use Illuminate\Foundation\Console\OptimizeClearCommand;
use Illuminate\Foundation\Console\OptimizeCommand;
use Illuminate\Foundation\Console\PackageDiscoverCommand;
use Illuminate\Foundation\Console\PolicyMakeCommand;
use Illuminate\Foundation\Console\ProviderMakeCommand;
use Illuminate\Foundation\Console\RequestMakeCommand;
use Illuminate\Foundation\Console\ResourceMakeCommand;
use Illuminate\Foundation\Console\RouteCacheCommand;
use Illuminate\Foundation\Console\RouteClearCommand;
use Illuminate\Foundation\Console\RouteListCommand;
use Illuminate\Foundation\Console\RuleMakeCommand;
use Illuminate\Foundation\Console\ScopeMakeCommand;
use Illuminate\Foundation\Console\ServeCommand;
use Illuminate\Foundation\Console\StorageLinkCommand;
use Illuminate\Foundation\Console\StorageUnlinkCommand;
use Illuminate\Foundation\Console\StubPublishCommand;
use Illuminate\Foundation\Console\TestMakeCommand;
use Illuminate\Foundation\Console\UpCommand;
use Illuminate\Foundation\Console\VendorPublishCommand;
use Illuminate\Foundation\Console\ViewCacheCommand;
use Illuminate\Foundation\Console\ViewClearCommand;
use Illuminate\Foundation\Console\ViewMakeCommand;
use Illuminate\Notifications\Console\NotificationTableCommand;
use Illuminate\Queue\Console\BatchesTableCommand;
use Illuminate\Queue\Console\ClearCommand as QueueClearCommand;
use Illuminate\Queue\Console\FailedTableCommand;
use Illuminate\Queue\Console\FlushFailedCommand as FlushFailedQueueCommand;
use Illuminate\Queue\Console\ForgetFailedCommand as ForgetFailedQueueCommand;
use Illuminate\Queue\Console\ListenCommand as QueueListenCommand;
use Illuminate\Queue\Console\ListFailedCommand as ListFailedQueueCommand;
use Illuminate\Queue\Console\MonitorCommand as QueueMonitorCommand;
use Illuminate\Queue\Console\PruneBatchesCommand as QueuePruneBatchesCommand;
use Illuminate\Queue\Console\PruneFailedJobsCommand as QueuePruneFailedJobsCommand;
use Illuminate\Queue\Console\RestartCommand as QueueRestartCommand;
use Illuminate\Queue\Console\RetryBatchCommand as QueueRetryBatchCommand;
use Illuminate\Queue\Console\RetryCommand as QueueRetryCommand;
use Illuminate\Queue\Console\TableCommand;
use Illuminate\Queue\Console\WorkCommand as QueueWorkCommand;
use Illuminate\Routing\Console\ControllerMakeCommand;
use Illuminate\Routing\Console\MiddlewareMakeCommand;
use Illuminate\Session\Console\SessionTableCommand;
use Illuminate\Support\ServiceProvider;
class CliServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* The commands to be registered.
*
* @var array
*/
protected $commands = [
'About' => AboutCommand::class,
'CacheClear' => CacheClearCommand::class,
'CacheForget' => CacheForgetCommand::class,
'ClearCompiled' => ClearCompiledCommand::class,
'ClearResets' => ClearResetsCommand::class,
'ConfigCache' => ConfigCacheCommand::class,
'ConfigClear' => ConfigClearCommand::class,
'ConfigShow' => ConfigShowCommand::class,
'Db' => DbCommand::class,
'DbMonitor' => DatabaseMonitorCommand::class,
'DbPrune' => PruneCommand::class,
'DbShow' => ShowCommand::class,
'DbTable' => DatabaseTableCommand::class,
// 'DbWipe' => WipeCommand::class,
'Down' => DownCommand::class,
'Environment' => EnvironmentCommand::class,
'EnvironmentDecrypt' => EnvironmentDecryptCommand::class,
'EnvironmentEncrypt' => EnvironmentEncryptCommand::class,
'EventCache' => EventCacheCommand::class,
'EventClear' => EventClearCommand::class,
'EventList' => EventListCommand::class,
'KeyGenerate' => KeyGenerateCommand::class,
'Optimize' => OptimizeCommand::class,
'OptimizeClear' => OptimizeClearCommand::class,
'PackageDiscover' => PackageDiscoverCommand::class,
'PruneStaleTagsCommand' => PruneStaleTagsCommand::class,
'QueueClear' => QueueClearCommand::class,
'QueueFailed' => ListFailedQueueCommand::class,
'QueueFlush' => FlushFailedQueueCommand::class,
'QueueForget' => ForgetFailedQueueCommand::class,
// 'QueueListen' => QueueListenCommand::class,
// 'QueueMonitor' => QueueMonitorCommand::class,
// 'QueuePruneBatches' => QueuePruneBatchesCommand::class,
// 'QueuePruneFailedJobs' => QueuePruneFailedJobsCommand::class,
// 'QueueRestart' => QueueRestartCommand::class,
// 'QueueRetry' => QueueRetryCommand::class,
// 'QueueRetryBatch' => QueueRetryBatchCommand::class,
// 'QueueWork' => QueueWorkCommand::class,
// 'RouteCache' => RouteCacheCommand::class,
// 'RouteClear' => RouteClearCommand::class,
// 'RouteList' => RouteListCommand::class,
'SchemaDump' => DumpCommand::class,
'Seed' => SeedCommand::class,
'ScheduleFinish' => ScheduleFinishCommand::class,
'ScheduleList' => ScheduleListCommand::class,
'ScheduleRun' => ScheduleRunCommand::class,
'ScheduleClearCache' => ScheduleClearCacheCommand::class,
'ScheduleTest' => ScheduleTestCommand::class,
'ScheduleWork' => ScheduleWorkCommand::class,
'ScheduleInterrupt' => ScheduleInterruptCommand::class,
'ShowModel' => ShowModelCommand::class,
'StorageLink' => StorageLinkCommand::class,
'StorageUnlink' => StorageUnlinkCommand::class,
'Up' => UpCommand::class,
'ViewCache' => ViewCacheCommand::class,
'ViewClear' => ViewClearCommand::class,
];
/**
* The commands to be registered.
*
* @var array
*/
protected $devCommands = [
'CacheTable' => CacheTableCommand::class,
'CastMake' => CastMakeCommand::class,
'ChannelList' => ChannelListCommand::class,
'ChannelMake' => ChannelMakeCommand::class,
'ComponentMake' => ComponentMakeCommand::class,
'ConsoleMake' => ConsoleMakeCommand::class,
'ControllerMake' => ControllerMakeCommand::class,
'Docs' => DocsCommand::class,
'EventGenerate' => EventGenerateCommand::class,
'EventMake' => EventMakeCommand::class,
'ExceptionMake' => ExceptionMakeCommand::class,
'FactoryMake' => FactoryMakeCommand::class,
'JobMake' => JobMakeCommand::class,
'LangPublish' => LangPublishCommand::class,
'ListenerMake' => ListenerMakeCommand::class,
'MailMake' => MailMakeCommand::class,
'MiddlewareMake' => MiddlewareMakeCommand::class,
'ModelMake' => ModelMakeCommand::class,
'NotificationMake' => NotificationMakeCommand::class,
'NotificationTable' => NotificationTableCommand::class,
'ObserverMake' => ObserverMakeCommand::class,
'PolicyMake' => PolicyMakeCommand::class,
'ProviderMake' => ProviderMakeCommand::class,
'QueueFailedTable' => FailedTableCommand::class,
'QueueTable' => TableCommand::class,
'QueueBatchesTable' => BatchesTableCommand::class,
'RequestMake' => RequestMakeCommand::class,
'ResourceMake' => ResourceMakeCommand::class,
'RuleMake' => RuleMakeCommand::class,
'ScopeMake' => ScopeMakeCommand::class,
'SeederMake' => SeederMakeCommand::class,
'SessionTable' => SessionTableCommand::class,
'Serve' => ServeCommand::class,
'StubPublish' => StubPublishCommand::class,
'TestMake' => TestMakeCommand::class,
'VendorPublish' => VendorPublishCommand::class,
'ViewMake' => ViewMakeCommand::class,
];
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerCommands(array_merge(
$this->commands,
$this->devCommands
));
Signals::resolveAvailabilityUsing(function () {
return $this->app->runningInConsole()
&& ! $this->app->runningUnitTests()
&& extension_loaded('pcntl');
});
}
/**
* Register the given commands.
*
* @return void
*/
protected function registerCommands(array $commands)
{
foreach ($commands as $commandName => $command) {
$method = "register{$commandName}Command";
if (method_exists($this, $method)) {
$this->{$method}();
} else {
$this->app->singleton($command);
}
}
$this->commands(array_values($commands));
}
/**
* Register the command.
*
* @return void
*/
protected function registerAboutCommand()
{
$this->app->singleton(AboutCommand::class, function ($app) {
return new AboutCommand($app['composer']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerCacheClearCommand()
{
$this->app->singleton(CacheClearCommand::class, function ($app) {
return new CacheClearCommand($app['cache'], $app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerCacheForgetCommand()
{
$this->app->singleton(CacheForgetCommand::class, function ($app) {
return new CacheForgetCommand($app['cache']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerCacheTableCommand()
{
$this->app->singleton(CacheTableCommand::class, function ($app) {
return new CacheTableCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerCastMakeCommand()
{
$this->app->singleton(CastMakeCommand::class, function ($app) {
return new CastMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerChannelMakeCommand()
{
$this->app->singleton(ChannelMakeCommand::class, function ($app) {
return new ChannelMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerComponentMakeCommand()
{
$this->app->singleton(ComponentMakeCommand::class, function ($app) {
return new ComponentMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerConfigCacheCommand()
{
$this->app->singleton(ConfigCacheCommand::class, function ($app) {
return new ConfigCacheCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerConfigClearCommand()
{
$this->app->singleton(ConfigClearCommand::class, function ($app) {
return new ConfigClearCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerConsoleMakeCommand()
{
$this->app->singleton(ConsoleMakeCommand::class, function ($app) {
return new ConsoleMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerControllerMakeCommand()
{
$this->app->singleton(ControllerMakeCommand::class, function ($app) {
return new ControllerMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerEventMakeCommand()
{
$this->app->singleton(EventMakeCommand::class, function ($app) {
return new EventMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerExceptionMakeCommand()
{
$this->app->singleton(ExceptionMakeCommand::class, function ($app) {
return new ExceptionMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerFactoryMakeCommand()
{
$this->app->singleton(FactoryMakeCommand::class, function ($app) {
return new FactoryMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerEventClearCommand()
{
$this->app->singleton(EventClearCommand::class, function ($app) {
return new EventClearCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerJobMakeCommand()
{
$this->app->singleton(JobMakeCommand::class, function ($app) {
return new JobMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerListenerMakeCommand()
{
$this->app->singleton(ListenerMakeCommand::class, function ($app) {
return new ListenerMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerMailMakeCommand()
{
$this->app->singleton(MailMakeCommand::class, function ($app) {
return new MailMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerMiddlewareMakeCommand()
{
$this->app->singleton(MiddlewareMakeCommand::class, function ($app) {
return new MiddlewareMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerModelMakeCommand()
{
$this->app->singleton(ModelMakeCommand::class, function ($app) {
return new ModelMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerNotificationMakeCommand()
{
$this->app->singleton(NotificationMakeCommand::class, function ($app) {
return new NotificationMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerNotificationTableCommand()
{
$this->app->singleton(NotificationTableCommand::class, function ($app) {
return new NotificationTableCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerObserverMakeCommand()
{
$this->app->singleton(ObserverMakeCommand::class, function ($app) {
return new ObserverMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerPolicyMakeCommand()
{
$this->app->singleton(PolicyMakeCommand::class, function ($app) {
return new PolicyMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerProviderMakeCommand()
{
$this->app->singleton(ProviderMakeCommand::class, function ($app) {
return new ProviderMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueForgetCommand()
{
$this->app->singleton(ForgetFailedQueueCommand::class);
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueListenCommand()
{
$this->app->singleton(QueueListenCommand::class, function ($app) {
return new QueueListenCommand($app['queue.listener']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueMonitorCommand()
{
$this->app->singleton(QueueMonitorCommand::class, function ($app) {
return new QueueMonitorCommand($app['queue'], $app['events']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueuePruneBatchesCommand()
{
$this->app->singleton(QueuePruneBatchesCommand::class, function () {
return new QueuePruneBatchesCommand;
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueuePruneFailedJobsCommand()
{
$this->app->singleton(QueuePruneFailedJobsCommand::class, function () {
return new QueuePruneFailedJobsCommand;
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueRestartCommand()
{
$this->app->singleton(QueueRestartCommand::class, function ($app) {
return new QueueRestartCommand($app['cache.store']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueWorkCommand()
{
$this->app->singleton(QueueWorkCommand::class, function ($app) {
return new QueueWorkCommand($app['queue.worker'], $app['cache.store']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueFailedTableCommand()
{
$this->app->singleton(FailedTableCommand::class, function ($app) {
return new FailedTableCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueTableCommand()
{
$this->app->singleton(TableCommand::class, function ($app) {
return new TableCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerQueueBatchesTableCommand()
{
$this->app->singleton(BatchesTableCommand::class, function ($app) {
return new BatchesTableCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerRequestMakeCommand()
{
$this->app->singleton(RequestMakeCommand::class, function ($app) {
return new RequestMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerResourceMakeCommand()
{
$this->app->singleton(ResourceMakeCommand::class, function ($app) {
return new ResourceMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerRuleMakeCommand()
{
$this->app->singleton(RuleMakeCommand::class, function ($app) {
return new RuleMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerScopeMakeCommand()
{
$this->app->singleton(ScopeMakeCommand::class, function ($app) {
return new ScopeMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerSeederMakeCommand()
{
$this->app->singleton(SeederMakeCommand::class, function ($app) {
return new SeederMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerSessionTableCommand()
{
$this->app->singleton(SessionTableCommand::class, function ($app) {
return new SessionTableCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerRouteCacheCommand()
{
$this->app->singleton(RouteCacheCommand::class, function ($app) {
return new RouteCacheCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerRouteClearCommand()
{
$this->app->singleton(RouteClearCommand::class, function ($app) {
return new RouteClearCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerRouteListCommand()
{
$this->app->singleton(RouteListCommand::class, function ($app) {
return new RouteListCommand($app['router']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerSeedCommand()
{
$this->app->singleton(SeedCommand::class, function ($app) {
return new SeedCommand($app['db']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerTestMakeCommand()
{
$this->app->singleton(TestMakeCommand::class, function ($app) {
return new TestMakeCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerVendorPublishCommand()
{
$this->app->singleton(VendorPublishCommand::class, function ($app) {
return new VendorPublishCommand($app['files']);
});
}
/**
* Register the command.
*
* @return void
*/
protected function registerViewClearCommand()
{
$this->app->singleton(ViewClearCommand::class, function ($app) {
return new ViewClearCommand($app['files']);
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array_merge(array_values($this->commands), array_values($this->devCommands));
}
}

View File

@@ -0,0 +1,256 @@
<?php
namespace Leantime\Core\Console;
use Illuminate\Console\Application as Artisan;
use Illuminate\Console\Command;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Console\Kernel;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Leantime\Core\Console\Application as LeantimeCli;
use Leantime\Core\Events\DispatchesEvents;
use Leantime\Core\Events\EventDispatcher;
use Symfony\Component\Finder\Finder;
class ConsoleKernel extends Kernel implements ConsoleKernelContract
{
use DispatchesEvents;
protected $app;
protected $artisan;
protected $commandStartedAt;
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Leantime\Core\Bootstrap\LoadConfig::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Leantime\Core\Bootstrap\SetRequestForConsole::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
public function __construct(Application $app, Dispatcher $events)
{
if (! defined('ARTISAN_BINARY')) {
define('ARTISAN_BINARY', 'bin/leantime');
}
parent::__construct($app, $events);
}
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
$this->app->bootstrapWith($this->bootstrappers());
}
$this->app->loadDeferredProviders();
if (! $this->commandsLoaded) {
$this->commands();
if ($this->shouldDiscoverCommands()) {
$this->discoverCommands();
}
$this->commandsLoaded = true;
}
}
/**
* Handle an incoming console command.
*
* @return int
*/
public function handle($input, $output = null)
{
$this->commandStartedAt = Carbon::now();
try {
if (in_array($input->getFirstArgument(), ['env:encrypt', 'env:decrypt'], true)) {
$this->bootstrapWithoutBootingProviders();
}
if ($domain = $input->getParameterOption('--domain')) {
$this->setDomain($domain);
}
$this->bootstrap();
self::dispatch_event('console.bootstrapped', ['kernel' => $this, 'command' => $input]);
return $this->getArtisan()->run($input, $output);
} catch (\Throwable $e) {
$this->reportException($e);
$this->renderException($output, $e);
return 1;
}
}
// We need to overwrite this because for some reason Laravel decided to only do command discovery if being called
// from the original kernel
protected function shouldDiscoverCommands()
{
return get_class($this) === __CLASS__;
}
protected function discoverCommands()
{
// Update standard commandPath
$this->commandPaths = [
APP_ROOT.'/app/Command/',
];
foreach ($this->commandPaths as $path) {
$this->load($path);
}
// Load Dynamic command paths for leantime
$ltCommands = collect(glob(APP_ROOT.'/app/Domain/**/Command/'));
// Load commands from enabled plugins
try {
$pluginService = app()->make(\Leantime\Core\Plugins\Plugins::class);
$enabledPluginPaths = $pluginService->getEnabledPluginPaths();
foreach ($enabledPluginPaths as $pluginInfo) {
$commandPath = $pluginInfo['path'].'/Command/';
if (is_dir($commandPath)) {
if ($pluginInfo['format'] == 'phar') {
include_once $pluginInfo['path'];
$this->loadPhar($commandPath, $pluginInfo['foldername'].'.phar');
}
$this->load($commandPath);
}
}
} catch (\Exception $e) {
// Fallback to scanning all plugin directories if service unavailable
$ltPluginCommands = collect(glob(APP_ROOT.'/app/Plugins/**/Command/'));
foreach ($ltPluginCommands as $pluginPath) {
$this->load($pluginPath);
}
}
foreach ($this->commandRoutePaths as $path) {
if (file_exists($path)) {
require $path;
}
}
}
public function call($command, array $parameters = [], $outputBuffer = null)
{
if (array_key_exists('--domain', $parameters)) {
$this->setDomain($parameters['--domain']);
}
if (in_array($command, ['env:encrypt', 'env:decrypt'], true)) {
$this->bootstrapWithoutBootingProviders();
}
$this->bootstrap();
self::dispatch_event('console.bootstrapped', ['kernel' => $this, 'command' => $command]);
return $this->getArtisan()->call($command, $parameters, $outputBuffer);
}
public function getArtisan()
{
if (is_null($this->artisan)) {
$this->artisan = (new LeantimeCli($this->app, $this->events, $this->app->version()))
->resolveCommands($this->commands)
->setContainerCommandLoader();
if ($this->symfonyDispatcher instanceof EventDispatcher) {
$this->artisan->setDispatcher($this->symfonyDispatcher);
$this->artisan->setSignalsToDispatchEvent();
}
}
return $this->artisan;
}
protected function schedule(Schedule $schedule)
{
// Set default timezone
// config(['app.timezone' => config('defaultTimezone')]);
config(['schedule_timezone' => 'UTC']);
self::dispatch_event('cron', ['schedule' => $schedule], 'schedule');
}
public function setDomain(string $domain)
{
if ($domain) {
putenv('LEAN_APP_URL='.$domain);
putenv('APP_URL='.$domain);
// When calling commands inside the app we can switch domains
if (isset($this->app['config'])) {
config(['app.url' => $domain]);
config(['appUrl' => $domain]);
}
}
}
protected function loadPhar($paths, $pharName)
{
$paths = array_unique(Arr::wrap($paths));
$paths = array_filter($paths, function ($path) {
return is_dir($path);
});
if (empty($paths)) {
return;
}
$this->loadedPaths = array_values(
array_unique(array_merge($this->loadedPaths, $paths))
);
$namespace = $this->app->getNamespace();
foreach (Finder::create()->in($paths)->files() as $file) {
$command = $namespace.str_replace(
['/', '.php', '\\'.$pharName],
['\\', '', ''],
Str::after($file->getPath().DIRECTORY_SEPARATOR.$file->getFilename(), realpath(app_path()).DIRECTORY_SEPARATOR)
);
if (is_subclass_of($command, Command::class) &&
! (new \ReflectionClass($command))->isAbstract()) {
Artisan::starting(function ($artisan) use ($command) {
$artisan->resolve($command);
});
}
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Leantime\Core\Console;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Foundation\Providers\ComposerServiceProvider;
use Illuminate\Foundation\Providers\ConsoleSupportServiceProvider;
class ConsoleSupportProvider extends ConsoleSupportServiceProvider implements DeferrableProvider
{
/**
* The provider class names.
*
* @var string[]
*/
protected $providers = [
CliServiceProvider::class,
ComposerServiceProvider::class,
];
}