'q', 'status' => 'status', 'assigned' => 'assigned', 'department_id' => 'departmentId', 'priority_id' => 'priorityId', 'sla' => 'sla', 'tab' => 'tab', 'quick' => 'quick', 'spam' => 'spam', 'tag_id' => 'tagId']; $out = []; foreach ($map as $webKey => $key) { $v = isset($get[$webKey]) && is_scalar($get[$webKey]) ? trim((string) $get[$webKey]) : ''; if ($v !== '') $out[$key] = mb_substr($v, 0, 200); } return $out; } /** Wandelt neutrale Filter zurück in GET-Parameter der Weboberfläche. */ function queue_filters_to_web(array $filters): array { $map = ['q' => 'q', 'status' => 'status', 'assigned' => 'assigned', 'departmentId' => 'department_id', 'priorityId' => 'priority_id', 'sla' => 'sla', 'tab' => 'tab', 'quick' => 'quick', 'spam' => 'spam', 'tagId' => 'tag_id']; $out = []; foreach ($map as $key => $webKey) { if (isset($filters[$key]) && $filters[$key] !== '') $out[$webKey] = (string) $filters[$key]; } // Apps speichern mehrere Status als Liste; die Weboberfläche kennt dafür die Reiter if (isset($out['status']) && str_contains($out['status'], ',')) { $out['tab'] = str_contains($out['status'], 'resolved') ? ($out['tab'] ?? 'all') : ($out['tab'] ?? 'open'); unset($out['status']); } return $out; } /** Übersetzt neutrale Filter in die Abfrageparameter der Mobile-API (tickets.php): status, assigned, sla, q, departmentId, priorityId. */ function queue_filters_to_api(array $filters): array { $out = []; foreach (['q', 'assigned', 'sla', 'departmentId', 'priorityId'] as $k) { if (isset($filters[$k]) && $filters[$k] !== '') $out[$k] = $filters[$k]; } $status = $filters['status'] ?? ''; if ($status === '') { $status = match ($filters['tab'] ?? '') { 'on_hold' => 'on_hold', 'resolved' => 'resolved', 'closed' => 'closed', 'all' => 'open,pending,answered,on_hold,resolved,closed', default => 'open,pending,answered', }; } $out['status'] = $status; switch ($filters['quick'] ?? '') { case 'me': $out['assigned'] = 'me'; break; case 'unassigned': $out['assigned'] = 'unassigned'; break; case 'overdue': $out['sla'] = 'overdue'; break; } return $out; } /** Bereinigt beliebige Eingaben auf die erlaubten Filter-Schlüssel. */ function queue_clean_filters($filters): array { $out = []; if (is_array($filters)) { // ältere Ansichten nutzten 'department'/'priority' if (isset($filters['department']) && !isset($filters['departmentId'])) $filters['departmentId'] = $filters['department']; if (isset($filters['priority']) && !isset($filters['priorityId'])) $filters['priorityId'] = $filters['priority']; } foreach (QUEUE_FILTER_KEYS as $key) { if (is_array($filters) && isset($filters[$key]) && is_scalar($filters[$key]) && trim((string) $filters[$key]) !== '') { $out[$key] = mb_substr(trim((string) $filters[$key]), 0, 200); } } return $out; } /** Eigene und geteilte Ansichten, eigene zuerst. Jede Zeile bekommt 'filters' (Array) und 'mine' (bool). */ function queues_for(PDO $pdo, int $staffId): array { $stmt = $pdo->prepare( 'SELECT q.*, s.name AS owner_name FROM saved_queues q LEFT JOIN staff s ON s.id = q.staff_id WHERE q.staff_id = ? OR q.is_shared = 1 ORDER BY (q.staff_id = ?) DESC, q.sort_order, q.name' ); $stmt->execute([$staffId, $staffId]); $rows = $stmt->fetchAll(); foreach ($rows as &$r) { $r['filters'] = queue_clean_filters(json_decode((string) $r['filters'], true)); $r['mine'] = (int) $r['staff_id'] === $staffId; } return $rows; } /** Legt eine Ansicht an. Gibt die ID zurück. */ function queue_create(PDO $pdo, int $staffId, string $name, array $filters, bool $shared): int { $name = trim($name); if ($name === '') throw new AdminModelException('Bitte einen Namen für die Ansicht angeben.', 'NAME_REQUIRED'); if (mb_strlen($name) > 80) throw new AdminModelException('Der Name ist zu lang (höchstens 80 Zeichen).', 'NAME_TOO_LONG'); $dup = $pdo->prepare('SELECT COUNT(*) FROM saved_queues WHERE staff_id = ? AND LOWER(name) = LOWER(?)'); $dup->execute([$staffId, $name]); if ((int) $dup->fetchColumn() > 0) throw new AdminModelException('Du hast bereits eine Ansicht mit diesem Namen.', 'NAME_TAKEN'); $max = $pdo->prepare('SELECT COALESCE(MAX(sort_order), 0) + 1 FROM saved_queues WHERE staff_id = ?'); $max->execute([$staffId]); $now = db_now(); $pdo->prepare('INSERT INTO saved_queues (staff_id, name, filters, is_shared, sort_order, created_at, updated_at) VALUES (?,?,?,?,?,?,?)') ->execute([$staffId, $name, json_encode(queue_clean_filters($filters), JSON_UNESCAPED_UNICODE), $shared ? 1 : 0, (int) $max->fetchColumn(), $now, $now]); return (int) $pdo->lastInsertId(); } /** Darf der Mitarbeiter die Ansicht ändern/löschen? Eigene Ansichten immer; fremde nur Administratoren. */ function queue_can_edit(array $queueRow, array $staff): bool { return (int) $queueRow['staff_id'] === (int) $staff['id'] || $staff['role'] === 'admin'; }