configMapper = $configMapper; $this->logMapper = $logMapper; $this->calendarService = $calendarService; $this->mailService = $mailService; $this->syncService = $syncService; $this->userId = $userId; } /** * @NoAdminRequired * @NoCSRFRequired */ public function getConfig(): JSONResponse { try { $config = $this->configMapper->findByUserId($this->userId); return new JSONResponse($config->toArray()); } catch (DoesNotExistException $e) { return new JSONResponse([ 'enabled' => false, 'mailAccountId' => null, 'calendarUri' => null, 'autoAccept' => false, 'syncInterval' => 600, ]); } catch (\Throwable $e) { return new JSONResponse( ['error' => 'Failed to load config: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR ); } } /** * @NoAdminRequired * @NoCSRFRequired */ public function setConfig(): JSONResponse { try { // Parse JSON body $body = file_get_contents('php://input'); $data = json_decode($body, true); if (!is_array($data)) { return new JSONResponse( ['error' => 'Invalid request body'], Http::STATUS_BAD_REQUEST ); } $enabled = !empty($data['enabled']); $mailAccountId = $data['mailAccountId'] ?? null; $calendarUri = $data['calendarUri'] ?? null; $autoAccept = !empty($data['autoAccept']); $syncInterval = (int)($data['syncInterval'] ?? 600); // Clamp sync interval to valid range (5 min to 24 hours) $syncInterval = max(300, min(86400, $syncInterval)); // Normalize empty strings to null if ($mailAccountId === '' || $mailAccountId === '0') { $mailAccountId = null; } if ($calendarUri === '') { $calendarUri = null; } try { $config = $this->configMapper->findByUserId($this->userId); } catch (DoesNotExistException $e) { $config = new Config(); $config->setUserId($this->userId); $config->setCreatedAt(date('Y-m-d H:i:s')); } $config->setEnabled($enabled ? 1 : 0); $config->setMailAccountId($mailAccountId !== null ? (int)$mailAccountId : null); $config->setCalendarUri($calendarUri); $config->setAutoAccept($autoAccept ? 1 : 0); $config->setSyncInterval($syncInterval); $config->setUpdatedAt(date('Y-m-d H:i:s')); if ($config->getId() === null) { $config = $this->configMapper->insert($config); } else { $config = $this->configMapper->update($config); } return new JSONResponse($config->toArray()); } catch (\Throwable $e) { return new JSONResponse( ['error' => 'Failed to save: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR ); } } /** * @NoAdminRequired * @NoCSRFRequired */ public function getCalendars(): JSONResponse { try { $calendars = $this->calendarService->getWritableCalendars($this->userId); return new JSONResponse($calendars); } catch (\Throwable $e) { return new JSONResponse( ['error' => 'Failed to load calendars: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR ); } } /** * @NoAdminRequired * @NoCSRFRequired */ public function getMailAccounts(): JSONResponse { try { $accounts = $this->mailService->getMailAccounts($this->userId); return new JSONResponse($accounts); } catch (\Throwable $e) { return new JSONResponse( ['error' => 'Failed to load mail accounts: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR ); } } /** * @NoAdminRequired * @NoCSRFRequired */ public function getLog(): JSONResponse { try { $limit = (int)($this->request->getParam('limit', '50')); $offset = (int)($this->request->getParam('offset', '0')); $entries = $this->logMapper->findByUserId($this->userId, $limit, $offset); $data = array_map(fn($entry) => $entry->toArray(), $entries); return new JSONResponse($data); } catch (\Throwable $e) { return new JSONResponse( ['error' => 'Failed to load log: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR ); } } /** * @NoAdminRequired * @NoCSRFRequired * * Manually trigger a sync for the current user. */ public function triggerSync(): JSONResponse { try { $stats = $this->syncService->syncForUser($this->userId); return new JSONResponse([ 'status' => 'ok', 'stats' => $stats, ]); } catch (\Throwable $e) { return new JSONResponse( ['error' => 'Sync failed: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR ); } } }