NOW() ORDER BY created_at DESC LIMIT 1', (string) $tenantId ); // MintyPHP wraps selectOne results in ['table_name' => [...]] $row = is_array($result) ? ($result['helpdesk_oauth_token_cache'] ?? $result) : null; if (!is_array($row) || !isset($row['access_token_encrypted'])) { return null; } $encrypted = trim((string) $row['access_token_encrypted']); if ($encrypted === '') { return null; } try { return $this->settingsCryptoGateway->decryptString($encrypted); } catch (\Throwable) { return null; } } /** * Delete all cached tokens (used when global BC config changes). */ public function deleteAll(): bool { return (bool) DB::delete('DELETE FROM helpdesk_oauth_token_cache WHERE 1=1'); } /** * Delete cached tokens for a specific tenant (used when tenant config changes). */ public function deleteByTenantId(int $tenantId): bool { if ($tenantId <= 0) { return false; } return (bool) DB::delete( 'DELETE FROM helpdesk_oauth_token_cache WHERE tenant_id = ?', (string) $tenantId ); } /** * Store a new token in the cache (encrypted, tenant-scoped). */ public function storeToken(int $tenantId, string $accessToken, \DateTimeInterface $expiresAt): bool { if ($tenantId <= 0 || $accessToken === '') { return false; } try { $encrypted = $this->settingsCryptoGateway->encryptString($accessToken); } catch (\Throwable) { return false; } // Remove existing tokens for this tenant first DB::delete( 'DELETE FROM helpdesk_oauth_token_cache WHERE tenant_id = ?', (string) $tenantId ); return (bool) DB::insert( 'INSERT INTO helpdesk_oauth_token_cache (tenant_id, access_token_encrypted, expires_at) VALUES (?, ?, ?)', (string) $tenantId, $encrypted, $expiresAt->format('Y-m-d H:i:s') ); } }