mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-03 14:10:57 +08:00
122 lines
4.6 KiB
PHP
122 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\PluginStore;
|
|
use App\Repositories\ToolRepository;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Symfony\Component\Process\Exception\ProcessFailedException;
|
|
use Symfony\Component\Process\Process;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class ServerSendEventController extends Controller
|
|
{
|
|
public function sse(Request $request)
|
|
{
|
|
$this->initSSE();
|
|
$response = response()->stream(function () use ($request) {
|
|
$action = $request->input('action');
|
|
$this->sendData("action: $action");
|
|
try {
|
|
if ($action == "install_plugin") {
|
|
$this->checkComposer();
|
|
$pluginId = $request->input('plugin_id');
|
|
$this->sendData("pluginId: $pluginId");
|
|
$this->doActionInstallPlugin($pluginId);
|
|
} else {
|
|
throw new \InvalidArgumentException("Invalid action: $action");
|
|
}
|
|
}catch (\Throwable $throwable) {
|
|
$this->sendData("error: " . $throwable->getMessage());
|
|
$this->sendData("close");
|
|
}
|
|
});
|
|
$response->headers->set('Content-Type', 'text/event-stream');
|
|
$response->headers->set('Cache-Control', 'no-cache');
|
|
$response->headers->set('Connection', 'keep-alive');
|
|
$response->headers->set('X-Accel-Buffering', 'no');
|
|
|
|
return $response;
|
|
}
|
|
|
|
private function initSSE(): void
|
|
{
|
|
@set_time_limit(0); // Disable time limit
|
|
|
|
// Prevent buffering
|
|
if(function_exists('apache_setenv')){
|
|
@apache_setenv('no-gzip', 1);
|
|
}
|
|
|
|
@ini_set('zlib.output_compression', 0);
|
|
@ini_set('implicit_flush', 1);
|
|
|
|
while (ob_get_level() != 0) {
|
|
ob_end_flush();
|
|
}
|
|
ob_implicit_flush(1);
|
|
}
|
|
|
|
private function sendData(string $data): void
|
|
{
|
|
echo sprintf("data: %s\n\n", $data);
|
|
@ob_flush();
|
|
@flush();
|
|
}
|
|
|
|
private function runCommand(string $command): void
|
|
{
|
|
$this->sendData("running $command, this may take a while...");
|
|
$process = Process::fromShellCommandline($command);
|
|
$process->setWorkingDirectory(base_path());
|
|
$process->setTimeout(null);
|
|
$process->mustRun(function ($type, $buffer) {
|
|
$this->sendData($buffer);
|
|
});
|
|
}
|
|
|
|
private function doActionInstallPlugin(string $pluginId): void
|
|
{
|
|
$pluginInfo = PluginStore::getInfo($pluginId);
|
|
if (!$pluginInfo) {
|
|
throw new \InvalidArgumentException("invalid plugin: $pluginId");
|
|
}
|
|
$this->sendData(sprintf("going to install plugin: %s, version: %s", $pluginInfo['title'], $pluginInfo['version']));
|
|
$commands = [];
|
|
$commands[] = sprintf("composer config repositories.%s git %s", $pluginInfo['plugin_id'], $pluginInfo['remote_url']);
|
|
$commands[] = sprintf("composer require %s:%s", $pluginInfo['package_name'], $pluginInfo['version']);
|
|
$commands[] = sprintf("php artisan plugin install %s", $pluginInfo['package_name']);
|
|
foreach ($commands as $command) {
|
|
$this->runCommand($command);
|
|
}
|
|
}
|
|
|
|
private function checkComposer(): void
|
|
{
|
|
$this->sendData("checking composer ...");
|
|
$composerCacheDir = executeCommand("composer config cache-vcs-dir -f " . base_path("composer.json"));
|
|
$this->sendData("composer cache-vcs-dir: $composerCacheDir");
|
|
if (!is_dir($composerCacheDir)) {
|
|
$this->sendData("going to mkdir: $composerCacheDir");
|
|
try {
|
|
mkdir($composerCacheDir, 0755, true);
|
|
$this->sendData("success create composer cache-vcs-dir: $composerCacheDir");
|
|
} catch (\Throwable $e) {
|
|
$this->sendData("fail to mkdir: " . $e->getMessage());
|
|
$this->sendData("Please execute the following command as root user:");
|
|
$this->sendData(sprintf("mkdir -p %s", $composerCacheDir));
|
|
throw new \RuntimeException("stop due to composer cache-vcs-dir: $composerCacheDir not exists");
|
|
}
|
|
}
|
|
if (!is_writable($composerCacheDir)) {
|
|
$this->sendData("cache directory: $composerCacheDir is not writable");
|
|
$this->sendData("Please execute the following command as root user:");
|
|
$user = executeCommand("whoami");
|
|
$this->sendData(sprintf("chown -R %s:%s %s", $user, $user, $composerCacheDir));
|
|
throw new \RuntimeException("stop due to composer cache-vcs-dir: $composerCacheDir not writable");
|
|
}
|
|
}
|
|
|
|
}
|