|
5 | 5 | final class NotificationService |
6 | 6 | { |
7 | 7 | private const PRIORITIES = ['low', 'normal', 'high', 'critical']; |
| 8 | + private static ?bool $hasLinkColumn = null; |
| 9 | + |
| 10 | + private static function hasLinkColumn(PDO $pdo): bool |
| 11 | + { |
| 12 | + if (self::$hasLinkColumn !== null) { |
| 13 | + return self::$hasLinkColumn; |
| 14 | + } |
| 15 | + |
| 16 | + try { |
| 17 | + $stmt = $pdo->query("SHOW COLUMNS FROM notifications LIKE 'link'"); |
| 18 | + self::$hasLinkColumn = $stmt !== false && $stmt->fetch() !== false; |
| 19 | + } catch (PDOException $e) { |
| 20 | + self::$hasLinkColumn = true; |
| 21 | + } |
| 22 | + |
| 23 | + return self::$hasLinkColumn; |
| 24 | + } |
8 | 25 |
|
9 | 26 | public static function create( |
10 | 27 | PDO $pdo, |
@@ -46,26 +63,41 @@ public static function create( |
46 | 63 | } |
47 | 64 | } |
48 | 65 |
|
49 | | - $stmt = $pdo->prepare( |
50 | | - "INSERT INTO notifications |
51 | | - (recipient_user_id, event_key, title, message, link, priority, |
52 | | - related_type, related_id, dedupe_key, email_status) |
53 | | - VALUES |
54 | | - (:uid, :event_key, :title, :message, :link, :priority, |
55 | | - :related_type, :related_id, :dedupe_key, :email_status)" |
56 | | - ); |
57 | | - $stmt->execute([ |
| 66 | + $hasLinkColumn = self::hasLinkColumn($pdo); |
| 67 | + if ($hasLinkColumn) { |
| 68 | + $stmt = $pdo->prepare( |
| 69 | + "INSERT INTO notifications |
| 70 | + (recipient_user_id, event_key, title, message, link, priority, |
| 71 | + related_type, related_id, dedupe_key, email_status) |
| 72 | + VALUES |
| 73 | + (:uid, :event_key, :title, :message, :link, :priority, |
| 74 | + :related_type, :related_id, :dedupe_key, :email_status)" |
| 75 | + ); |
| 76 | + } else { |
| 77 | + $stmt = $pdo->prepare( |
| 78 | + "INSERT INTO notifications |
| 79 | + (recipient_user_id, event_key, title, message, priority, |
| 80 | + related_type, related_id, dedupe_key, email_status) |
| 81 | + VALUES |
| 82 | + (:uid, :event_key, :title, :message, :priority, |
| 83 | + :related_type, :related_id, :dedupe_key, :email_status)" |
| 84 | + ); |
| 85 | + } |
| 86 | + $params = [ |
58 | 87 | ':uid' => $recipientUserId, |
59 | 88 | ':event_key' => $eventKey, |
60 | 89 | ':title' => $title, |
61 | 90 | ':message' => $message, |
62 | | - ':link' => self::sanitizeLink($link), |
63 | 91 | ':priority' => $priority, |
64 | 92 | ':related_type' => $relatedType !== null ? mb_substr($relatedType, 0, 80) : null, |
65 | 93 | ':related_id' => $relatedId, |
66 | 94 | ':dedupe_key' => $dedupeKey, |
67 | 95 | ':email_status' => $email ? 'skipped' : 'not_required', |
68 | | - ]); |
| 96 | + ]; |
| 97 | + if ($hasLinkColumn) { |
| 98 | + $params[':link'] = self::sanitizeLink($link); |
| 99 | + } |
| 100 | + $stmt->execute($params); |
69 | 101 | $notificationId = (int) $pdo->lastInsertId(); |
70 | 102 |
|
71 | 103 | if ($email) { |
@@ -406,18 +438,33 @@ public static function unreadCount(PDO $pdo, int $userId): int |
406 | 438 | public static function latest(PDO $pdo, int $userId, int $limit = 10): array |
407 | 439 | { |
408 | 440 | $limit = max(1, min(30, $limit)); |
409 | | - $stmt = $pdo->prepare( |
410 | | - "SELECT id, event_key, title, message, link, priority, is_read, created_at |
411 | | - FROM notifications |
412 | | - WHERE recipient_user_id = :uid |
413 | | - ORDER BY created_at DESC |
414 | | - LIMIT :limit" |
415 | | - ); |
416 | | - $stmt->bindValue(':uid', $userId, PDO::PARAM_INT); |
417 | | - $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); |
418 | | - $stmt->execute(); |
| 441 | + try { |
| 442 | + if (self::hasLinkColumn($pdo)) { |
| 443 | + $stmt = $pdo->prepare( |
| 444 | + "SELECT id, event_key, title, message, link, priority, is_read, created_at |
| 445 | + FROM notifications |
| 446 | + WHERE recipient_user_id = :uid |
| 447 | + ORDER BY created_at DESC |
| 448 | + LIMIT :limit" |
| 449 | + ); |
| 450 | + } else { |
| 451 | + $stmt = $pdo->prepare( |
| 452 | + "SELECT id, event_key, title, message, NULL AS link, priority, is_read, created_at |
| 453 | + FROM notifications |
| 454 | + WHERE recipient_user_id = :uid |
| 455 | + ORDER BY created_at DESC |
| 456 | + LIMIT :limit" |
| 457 | + ); |
| 458 | + } |
| 459 | + $stmt->bindValue(':uid', $userId, PDO::PARAM_INT); |
| 460 | + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); |
| 461 | + $stmt->execute(); |
419 | 462 |
|
420 | | - return array_map([self::class, 'decorate'], $stmt->fetchAll()); |
| 463 | + return array_map([self::class, 'decorate'], $stmt->fetchAll()); |
| 464 | + } catch (PDOException $e) { |
| 465 | + error_log('[SECAP][NOTIFY] Bildirim listesi okunamadı: ' . $e->getMessage()); |
| 466 | + return []; |
| 467 | + } |
421 | 468 | } |
422 | 469 |
|
423 | 470 | public static function markRead(PDO $pdo, int $userId, int $notificationId): bool |
|
0 commit comments