Fix consistentie benamingen.
This commit is contained in:
+338
-38
@@ -43,7 +43,7 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
$aiRes = fociz_ai_categorize_cards($session['title'], $session['theme'] ?? 'Algemeen', $cards);
|
||||
$aiRes = fociz_ai_categorize_cards($session['title'], $session['theme'] ?? 'Algemeen', $cards, $user['id']);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
echo json_encode(['error' => $aiRes['error']]);
|
||||
@@ -87,7 +87,7 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
$aiRes = fociz_ai_generate_ideas($session['title'], $session['theme'] ?? 'Algemeen', $count);
|
||||
$aiRes = fociz_ai_generate_ideas($session['title'], $session['theme'] ?? 'Algemeen', $count, $user['id']);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
echo json_encode(['error' => $aiRes['error']]);
|
||||
@@ -132,7 +132,7 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
$aiRes = fociz_ai_summarize_to_roadmap($content, $sessionTitle);
|
||||
$aiRes = fociz_ai_summarize_to_roadmap($content, $sessionTitle, $user['id']);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
echo json_encode(['error' => $aiRes['error']]);
|
||||
@@ -143,7 +143,283 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
// 4. Slimme dagindeling berekenen voor taken rondom Outlook afspraken
|
||||
// 3b. AI Brainstorm Idee Uitwerken tot concrete behapbare items
|
||||
if ($action === 'breakdown_idea') {
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
$content = trim($data['content'] ?? '');
|
||||
$sessionId = (int)($data['session_id'] ?? 0);
|
||||
$sessionTitle = trim($data['session_title'] ?? '');
|
||||
$theme = trim($data['theme'] ?? '');
|
||||
|
||||
if (empty($content)) {
|
||||
echo json_encode(['error' => 'Geen inhoud opgegeven om uit te werken.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($sessionId > 0 && (empty($sessionTitle) || empty($theme))) {
|
||||
$stmtS = $db->prepare("SELECT title, theme FROM brainstorm_sessions WHERE id = ?");
|
||||
$stmtS->execute([$sessionId]);
|
||||
$sRow = $stmtS->fetch();
|
||||
if ($sRow) {
|
||||
if (empty($sessionTitle)) $sessionTitle = $sRow['title'] ?? '';
|
||||
if (empty($theme)) $theme = $sRow['theme'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
$aiRes = fociz_ai_breakdown_idea($content, $sessionTitle, $theme, $user['id']);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
echo json_encode(['error' => $aiRes['error']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'summary' => $aiRes['summary'],
|
||||
'items' => $aiRes['items'],
|
||||
'model' => $aiRes['model'] ?? 'Gemini Pro',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 3c. Opgesplitste AI items exporteren naar Kanban Bord, Tijdlijn of Dagplanner
|
||||
if ($action === 'save_breakdown_items') {
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
$destination = trim($data['destination'] ?? 'kanban'); // 'kanban', 'timeline', 'planner'
|
||||
$items = $data['items'] ?? [];
|
||||
|
||||
if (empty($items) || !is_array($items)) {
|
||||
echo json_encode(['error' => 'Geen items geselecteerd om op te slaan.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$isAdmin = ($user['role'] === 'ADMIN');
|
||||
$createdCount = 0;
|
||||
|
||||
if ($destination === 'kanban' || $destination === 'timeline') {
|
||||
$boardId = (int)($data['board_id'] ?? 0);
|
||||
$laneId = (int)($data['lane_id'] ?? 0);
|
||||
|
||||
if ($boardId <= 0) {
|
||||
// Pak het eerste actieve bord van de gebruiker
|
||||
if ($isAdmin) {
|
||||
$boardId = (int)$db->query("SELECT id FROM boards WHERE is_archived = 0 ORDER BY id ASC LIMIT 1")->fetchColumn();
|
||||
} else {
|
||||
$stmtB = $db->prepare("SELECT b.id FROM boards b JOIN board_members bm ON b.id = bm.board_id WHERE bm.user_id = ? AND b.is_archived = 0 ORDER BY b.id ASC LIMIT 1");
|
||||
$stmtB->execute([$user['id']]);
|
||||
$boardId = (int)$stmtB->fetchColumn();
|
||||
}
|
||||
}
|
||||
|
||||
if ($boardId <= 0) {
|
||||
echo json_encode(['error' => 'Geen actief Kanban-bord gevonden om taken aan toe te voegen.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Toegangscontrole
|
||||
if (!$isAdmin) {
|
||||
$stmtCheck = $db->prepare("SELECT COUNT(*) FROM board_members WHERE board_id = ? AND user_id = ?");
|
||||
$stmtCheck->execute([$boardId, $user['id']]);
|
||||
if ((int)$stmtCheck->fetchColumn() === 0) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Geen toegang tot dit bord.']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Als lane_id niet geldig is, pak de eerste kolom (bijv. 'To Do' of 'Backlog')
|
||||
if ($laneId <= 0) {
|
||||
$stmtLane = $db->prepare("SELECT id FROM board_lanes WHERE board_id = ? ORDER BY position ASC, id ASC LIMIT 1");
|
||||
$stmtLane->execute([$boardId]);
|
||||
$laneId = (int)$stmtLane->fetchColumn();
|
||||
}
|
||||
|
||||
if ($laneId <= 0) {
|
||||
echo json_encode(['error' => 'Het geselecteerde bord heeft geen kolommen.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Datumbereik voor Tijdlijn
|
||||
$startDate = !empty($data['start_date']) ? trim($data['start_date']) : date('Y-m-d');
|
||||
$endDate = !empty($data['end_date']) ? trim($data['end_date']) : date('Y-m-d', strtotime('+3 days'));
|
||||
|
||||
$stmtMax = $db->prepare("SELECT COALESCE(MAX(position), -1) FROM board_cards WHERE lane_id = ?");
|
||||
$stmtInsertCard = $db->prepare("
|
||||
INSERT INTO board_cards (board_id, lane_id, title, description, assignee_id, priority, color, position, created_by_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
|
||||
$stmtSchedule = $db->prepare("
|
||||
INSERT INTO board_card_schedules (card_id, schedule_type, start_date, end_date, start_time, end_time, days_of_week)
|
||||
VALUES (?, 'DAILY_RANGE', ?, ?, '09:00', '17:00', '1,2,3,4,5')
|
||||
");
|
||||
|
||||
$priorityMap = ['P1' => 'HIGH', 'P2' => 'MEDIUM', 'P3' => 'LOW'];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$title = trim($item['title'] ?? '');
|
||||
if (empty($title)) continue;
|
||||
|
||||
$desc = trim($item['description'] ?? '');
|
||||
$rawPri = strtoupper(trim($item['priority'] ?? 'P2'));
|
||||
$priority = $priorityMap[$rawPri] ?? ($rawPri === 'HIGH' || $rawPri === 'LOW' ? $rawPri : 'MEDIUM');
|
||||
$color = trim($item['color'] ?? 'indigo');
|
||||
|
||||
$stmtMax->execute([$laneId]);
|
||||
$maxPos = (int)$stmtMax->fetchColumn();
|
||||
|
||||
$stmtInsertCard->execute([
|
||||
$boardId,
|
||||
$laneId,
|
||||
$title,
|
||||
$desc,
|
||||
$user['id'],
|
||||
$priority,
|
||||
$color,
|
||||
$maxPos + 1,
|
||||
$user['id'],
|
||||
]);
|
||||
|
||||
$cardId = (int)$db->lastInsertId();
|
||||
|
||||
if ($destination === 'timeline' && $cardId > 0) {
|
||||
$stmtSchedule->execute([$cardId, $startDate, $endDate]);
|
||||
}
|
||||
|
||||
$createdCount++;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'destination' => $destination,
|
||||
'created_count' => $createdCount,
|
||||
'board_id' => $boardId,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($destination === 'planner') {
|
||||
$planDate = !empty($data['plan_date']) ? trim($data['plan_date']) : date('Y-m-d');
|
||||
|
||||
// Zoek of maak daily plan
|
||||
$stmtPlan = $db->prepare("SELECT id FROM daily_plans WHERE user_id = ? AND plan_date = ?");
|
||||
$stmtPlan->execute([$user['id'], $planDate]);
|
||||
$planId = (int)$stmtPlan->fetchColumn();
|
||||
|
||||
if ($planId <= 0) {
|
||||
$stmtNewPlan = $db->prepare("INSERT INTO daily_plans (user_id, plan_date, focus_goal) VALUES (?, ?, 'Brainstorm actiepunten oppakken')");
|
||||
$stmtNewPlan->execute([$user['id'], $planDate]);
|
||||
$planId = (int)$db->lastInsertId();
|
||||
}
|
||||
|
||||
$stmtInsertTask = $db->prepare("
|
||||
INSERT INTO tasks (user_id, daily_plan_id, title, priority, duration_minutes, status, source)
|
||||
VALUES (?, ?, ?, ?, ?, 'TODO', 'BRAINSTORM')
|
||||
");
|
||||
|
||||
foreach ($items as $item) {
|
||||
$title = trim($item['title'] ?? '');
|
||||
if (empty($title)) continue;
|
||||
|
||||
$rawPri = strtoupper(trim($item['priority'] ?? 'P2'));
|
||||
$priority = in_array($rawPri, ['P1', 'P2', 'P3']) ? $rawPri : 'P2';
|
||||
$duration = max(15, min(240, (int)($item['estimated_minutes'] ?? 30)));
|
||||
|
||||
$stmtInsertTask->execute([
|
||||
$user['id'],
|
||||
$planId,
|
||||
$title,
|
||||
$priority,
|
||||
$duration,
|
||||
]);
|
||||
|
||||
$createdCount++;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'destination' => 'planner',
|
||||
'created_count' => $createdCount,
|
||||
'plan_date' => $planDate,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['error' => 'Onbekende bestemming: ' . htmlspecialchars($destination)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 3d. Test AI Verbinding (Gemini Pro / OpenAI)
|
||||
if ($action === 'test_connection') {
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
|
||||
$tempProvider = !empty($data['provider']) ? trim($data['provider']) : null;
|
||||
$tempKey = !empty($data['api_key']) ? trim($data['api_key']) : null;
|
||||
$tempModel = !empty($data['model']) ? trim($data['model']) : null;
|
||||
|
||||
// Als er test credentials zijn meegegeven, test direct met die credentials
|
||||
if (!empty($tempKey)) {
|
||||
$testSettings = [
|
||||
'ai_provider' => $tempProvider ?: 'gemini',
|
||||
'ai_api_key' => $tempKey,
|
||||
'ai_model' => $tempModel ?: ($tempProvider === 'openai' ? 'gpt-4o-mini' : 'gemini-1.5-pro'),
|
||||
];
|
||||
} else {
|
||||
// Anders haal de geconfigureerde instellingen op van user of org
|
||||
$testSettings = get_ai_settings($user['id']);
|
||||
}
|
||||
|
||||
if (empty($testSettings['ai_api_key'])) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => 'Geen API-sleutel ingevuld of geconfigureerd om te testen.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$provider = strtolower($testSettings['ai_provider'] ?? 'gemini');
|
||||
$model = $testSettings['ai_model'] ?? ($provider === 'openai' ? 'gpt-4o-mini' : 'gemini-1.5-pro');
|
||||
|
||||
$t0 = microtime(true);
|
||||
|
||||
$testMessages = [
|
||||
['role' => 'user', 'content' => 'Fociz connectiviteitstest. Reageer enkel met het woord OK.'],
|
||||
];
|
||||
|
||||
if ($provider === 'gemini' || strpos(strtolower($model), 'gemini') !== false) {
|
||||
$aiRes = fociz_ai_chat_gemini($testMessages, ['max_tokens' => 20, 'temperature' => 0.1], $testSettings);
|
||||
} else {
|
||||
$aiRes = fociz_ai_chat_openai($testMessages, ['max_tokens' => 20, 'temperature' => 0.1], $testSettings);
|
||||
}
|
||||
|
||||
$latency = round((microtime(true) - $t0) * 1000);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => $aiRes['error'] ?? 'Verbindingstest mislukt.',
|
||||
'latency_ms' => $latency,
|
||||
'provider' => $provider,
|
||||
'model' => $model,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$providerName = ($provider === 'gemini' || strpos(strtolower($model), 'gemini') !== false) ? 'Google Gemini Pro' : 'OpenAI';
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => "Verbinding met {$providerName} is succesvol tot stand gebracht! (Response tijd: {$latency}ms)",
|
||||
'latency_ms' => $latency,
|
||||
'provider' => $provider,
|
||||
'model' => $aiRes['model'] ?? $model,
|
||||
'zero_leak' => true,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 4. Slimme dagindeling berekenen voor taken rondom bezette tijdblokken
|
||||
// ZERO-DATA LEAKAGE: Geen meetingsdetails of externe tickets worden verzonden!
|
||||
if ($action === 'smart_schedule') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$date = !empty($data['date']) ? trim($data['date']) : date('Y-m-d');
|
||||
@@ -154,27 +430,46 @@ try {
|
||||
$plan = $stmtPlan->fetch();
|
||||
$planId = $plan['id'] ?? 0;
|
||||
|
||||
// Haal openstaande taken op voor de dag (inclusief fallback voor ongebonden taken op de huidige dag)
|
||||
// ZERO-DATA LEAKAGE: Sluit expliciet alle taken uit die afkomstig zijn van Jira, Mail of Teams!
|
||||
$isToday = ($date === date('Y-m-d'));
|
||||
$stmtTasks = $db->prepare("
|
||||
SELECT t.id, t.title, t.priority, t.duration_minutes
|
||||
FROM tasks t
|
||||
WHERE t.user_id = ? AND (t.daily_plan_id = ? " . ($isToday ? "OR t.daily_plan_id IS NULL" : "") . ") AND t.is_completed = 0
|
||||
WHERE t.user_id = ?
|
||||
AND (t.daily_plan_id = ? " . ($isToday ? "OR t.daily_plan_id IS NULL" : "") . ")
|
||||
AND t.is_completed = 0
|
||||
AND (t.source IS NULL OR t.source NOT IN ('JIRA', 'MAIL', 'EMAIL', 'OUTLOOK', 'TEAMS'))
|
||||
AND t.external_id IS NULL
|
||||
ORDER BY t.priority ASC, t.created_at ASC
|
||||
");
|
||||
$stmtTasks->execute([$user['id'], $planId]);
|
||||
$tasks = $stmtTasks->fetchAll();
|
||||
|
||||
if (empty($tasks)) {
|
||||
echo json_encode(['error' => 'Geen openstaande taken gevonden om in te delen']);
|
||||
echo json_encode(['error' => 'Geen openstaande Fociz taken gevonden om in te delen']);
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../includes/integrations/microsoft.php';
|
||||
$events = microsoft_fetch_today_events($user['id'], $date);
|
||||
// ZERO-DATA LEAKAGE: Haal meetings op maar geef UITSLUITEND start/eindtijd door (geen titel/deelnemers)
|
||||
$busyBlocks = [];
|
||||
try {
|
||||
require_once __DIR__ . '/../includes/integrations/microsoft.php';
|
||||
$rawEvents = microsoft_fetch_today_events($user['id'], $date);
|
||||
foreach ($rawEvents as $ev) {
|
||||
if (!empty($ev['start']) && !empty($ev['end'])) {
|
||||
$busyBlocks[] = [
|
||||
'start' => substr($ev['start'], 0, 5),
|
||||
'end' => substr($ev['end'], 0, 5),
|
||||
];
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// Microsoft niet gekoppeld
|
||||
}
|
||||
|
||||
$workdaySettings = get_workday_settings();
|
||||
|
||||
$aiRes = fociz_ai_smart_schedule($tasks, $events, $workdaySettings);
|
||||
$aiRes = fociz_ai_smart_schedule($tasks, $busyBlocks, $workdaySettings, $user['id']);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
echo json_encode(['error' => $aiRes['error']]);
|
||||
@@ -206,12 +501,13 @@ try {
|
||||
}
|
||||
|
||||
// 5. Persoonlijke AI Dagbriefing genereren
|
||||
// ZERO-DATA LEAKAGE: Absoluut GEEN Jira, Mail of Teams data!
|
||||
if ($action === 'daily_briefing') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$date = !empty($data['date']) ? trim($data['date']) : date('Y-m-d');
|
||||
$today = date('Y-m-d');
|
||||
|
||||
// Haal openstaande taken van vandaag op
|
||||
// Haal openstaande taken van vandaag op (ZERO-DATA LEAKAGE: GEEN externe Jira/Mail taken)
|
||||
$stmtPlan = $db->prepare("SELECT id FROM daily_plans WHERE user_id = ? AND plan_date = ?");
|
||||
$stmtPlan->execute([$user['id'], $date]);
|
||||
$planId = $stmtPlan->fetchColumn();
|
||||
@@ -221,15 +517,21 @@ try {
|
||||
? "t.daily_plan_id = " . (int)$planId . ($isToday ? " OR t.daily_plan_id IS NULL" : "")
|
||||
: ($isToday ? "t.daily_plan_id IS NULL" : "1=0");
|
||||
|
||||
$tasks = $db->query("
|
||||
$stmtTasks = $db->prepare("
|
||||
SELECT id, title, priority, time_block_start, duration_minutes
|
||||
FROM tasks
|
||||
WHERE user_id = {$user['id']} AND is_completed = 0 AND ({$taskFilter})
|
||||
ORDER BY priority ASC, time_block_start ASC
|
||||
FROM tasks t
|
||||
WHERE t.user_id = ?
|
||||
AND t.is_completed = 0
|
||||
AND ({$taskFilter})
|
||||
AND (t.source IS NULL OR t.source NOT IN ('JIRA', 'MAIL', 'EMAIL', 'OUTLOOK', 'TEAMS'))
|
||||
AND t.external_id IS NULL
|
||||
ORDER BY t.priority ASC, t.time_block_start ASC
|
||||
LIMIT 15
|
||||
")->fetchAll();
|
||||
");
|
||||
$stmtTasks->execute([$user['id']]);
|
||||
$tasks = $stmtTasks->fetchAll();
|
||||
|
||||
// Haal gisteren niet-voltooide taken op
|
||||
// Haal gisteren niet-voltooide interne taken op
|
||||
$yesterday = date('Y-m-d', strtotime('-1 day', strtotime($date)));
|
||||
$stmtYest = $db->prepare("SELECT id FROM daily_plans WHERE user_id = ? AND plan_date = ?");
|
||||
$stmtYest->execute([$user['id'], $yesterday]);
|
||||
@@ -239,35 +541,32 @@ try {
|
||||
$stmtUnf = $db->prepare("
|
||||
SELECT title FROM tasks
|
||||
WHERE user_id = ? AND daily_plan_id = ? AND is_completed = 0
|
||||
AND (source IS NULL OR source NOT IN ('JIRA', 'MAIL', 'EMAIL', 'OUTLOOK', 'TEAMS'))
|
||||
AND external_id IS NULL
|
||||
LIMIT 5
|
||||
");
|
||||
$stmtUnf->execute([$user['id'], $yesterdayPlanId]);
|
||||
$unfinishedYest = $stmtUnf->fetchAll();
|
||||
}
|
||||
|
||||
// Haal Outlook meetings op als beschikbaar
|
||||
$meetings = [];
|
||||
// ZERO-DATA LEAKAGE: Alleen geanonimiseerde bezette tijdblokken (geen subject/afzender)
|
||||
$busyBlocks = [];
|
||||
try {
|
||||
require_once __DIR__ . '/../includes/integrations/microsoft.php';
|
||||
$meetings = microsoft_fetch_today_events($user['id'], $date);
|
||||
$rawEvents = microsoft_fetch_today_events($user['id'], $date);
|
||||
foreach ($rawEvents as $ev) {
|
||||
if (!empty($ev['start']) && !empty($ev['end'])) {
|
||||
$busyBlocks[] = [
|
||||
'start' => substr($ev['start'], 0, 5),
|
||||
'end' => substr($ev['end'], 0, 5),
|
||||
];
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// meetings niet beschikbaar, geen probleem
|
||||
// Geen agenda beschikbaar
|
||||
}
|
||||
|
||||
// Haal urgente Jira tickets op als beschikbaar
|
||||
$jiraIssues = [];
|
||||
try {
|
||||
require_once __DIR__ . '/../includes/integrations/jira.php';
|
||||
$jiraData = jira_get_dashboard_data($user['id'], false);
|
||||
$jiraIssues = array_merge(
|
||||
$jiraData['assigned_issues'] ?? [],
|
||||
$jiraData['team_issues'] ?? []
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
// Jira niet beschikbaar, geen probleem
|
||||
}
|
||||
|
||||
$aiSettings = get_ai_settings();
|
||||
$aiSettings = get_ai_settings($user['id']);
|
||||
if (empty($aiSettings['ai_enabled']) || empty($aiSettings['has_key'])) {
|
||||
echo json_encode(['error' => 'AI Co-Pilot is niet geconfigureerd']);
|
||||
exit;
|
||||
@@ -277,9 +576,9 @@ try {
|
||||
$user['name'] ?? 'Jij',
|
||||
$date,
|
||||
$tasks,
|
||||
$meetings,
|
||||
$jiraIssues,
|
||||
$unfinishedYest
|
||||
$busyBlocks,
|
||||
$unfinishedYest,
|
||||
$user['id']
|
||||
);
|
||||
|
||||
if (!$aiRes['success']) {
|
||||
@@ -294,6 +593,7 @@ try {
|
||||
'tip' => $aiRes['tip'],
|
||||
'warnings' => $aiRes['warnings'],
|
||||
'date' => $date,
|
||||
'model' => $aiRes['model'] ?? 'Gemini Pro',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,12 @@ $now = time();
|
||||
if ($action === 'keepalive' || $action === 'ping') {
|
||||
// Verleng de activiteitstimer van de sessie
|
||||
$_SESSION['last_activity'] = $now;
|
||||
$_SESSION['last_db_activity_update'] = $now;
|
||||
try {
|
||||
$db = get_db_connection();
|
||||
$stmtAct = $db->prepare("UPDATE users SET last_activity_at = NOW() WHERE id = ?");
|
||||
$stmtAct->execute([$userId]);
|
||||
} catch (Throwable $e) {}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
|
||||
Reference in New Issue
Block a user