|
- <?php
-
- declare(strict_types=1);
-
- namespace App\Controllers;
-
- use App\Repositories\BoardRepository;
- use App\Services\AuthService;
- use Core\Controller;
- use Core\Request;
-
- class AdminController extends Controller
- {
- private const SETTINGS_FILE = '/storage/cron-settings.json';
- private const LOG_LINES = 300;
-
- private function settingsPath(): string
- {
- return dirname(__DIR__, 2) . self::SETTINGS_FILE;
- }
-
- private function logPath(): string
- {
- return dirname(__DIR__, 2) . '/storage/import.log';
- }
-
- private function loadCronSettings(): array
- {
- $path = $this->settingsPath();
- if (!file_exists($path)) {
- return ['enabled' => true, 'interval_minutes' => 30, 'last_run' => null];
- }
- return json_decode((string) file_get_contents($path), true)
- ?? ['enabled' => true, 'interval_minutes' => 30, 'last_run' => null];
- }
-
- private function writeCronSettings(array $settings): void
- {
- file_put_contents(
- $this->settingsPath(),
- json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"
- );
- }
-
- private function boards(): BoardRepository
- {
- return new BoardRepository(database());
- }
-
- private function readLog(): string
- {
- $path = $this->logPath();
- if (!file_exists($path) || !is_readable($path)) {
- return '';
- }
- $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
- $slice = array_slice($lines, -self::LOG_LINES);
- return implode("\n", array_reverse($slice));
- }
-
- public function index(): mixed
- {
- if ($guard = AuthService::requireLogin()) {
- return $guard;
- }
-
- return $this->view('admin.cron', [
- 'pageTitle' => 'PrintStream Import',
- 'boards' => $this->boards()->getAll(),
- 'settings' => $this->loadCronSettings(),
- 'log' => $this->readLog(),
- 'logLines' => self::LOG_LINES,
- ]);
- }
-
- public function saveSettings(Request $request): mixed
- {
- if ($guard = AuthService::requireLogin()) {
- return $guard;
- }
-
- $settings = $this->loadCronSettings();
- $settings['enabled'] = $request->input('enabled') === 'on';
- $settings['interval_minutes'] = max(1, min(120, (int) $request->input('interval_minutes', 30)));
-
- $this->writeCronSettings($settings);
-
- return $this->redirect('/admin/cron');
- }
-
- public function runNow(): mixed
- {
- if ($guard = AuthService::requireLogin()) {
- return $guard;
- }
-
- // Prefer the known Docker CLI binary; fall back to PHP_BINARY for other environments.
- $php = is_executable('/usr/local/bin/php') ? '/usr/local/bin/php' : PHP_BINARY;
-
- $script = dirname(__DIR__, 2) . '/scripts/import-printstream.php';
- $log = $this->logPath();
-
- set_time_limit(120);
-
- $output = [];
- $returnCode = 0;
- exec(escapeshellarg($php) . ' ' . escapeshellarg($script) . ' --force 2>&1', $output, $returnCode);
-
- if (!empty($output)) {
- file_put_contents($log, implode("\n", $output) . "\n", FILE_APPEND | LOCK_EX);
- }
-
- return $this->redirect('/admin/cron');
- }
-
- public function toggleBoard(int $id): mixed
- {
- if ($guard = AuthService::requireLogin()) {
- return $guard;
- }
-
- $db = database();
- $row = $db->first('SELECT import_from_printstream FROM boards WHERE id = :id', ['id' => $id]);
-
- if ($row === null) {
- return $this->redirect('/admin/cron');
- }
-
- $newVal = ((int) $row['import_from_printstream']) === 0 ? 1 : 0;
- $db->execute(
- 'UPDATE boards
- SET import_from_printstream = :v, updated_at = :t, updated_by = :u
- WHERE id = :id',
- [
- 'v' => $newVal,
- 't' => date('Y-m-d H:i:s'),
- 'u' => AuthService::getCurrentUsername(),
- 'id' => $id,
- ]
- );
-
- return $this->redirect('/admin/cron');
- }
- }
|