insert( 'notifications', [ 'user_id' => $userId, 'type' => $type, 'message' => $message, 'data' => json_encode($data), 'is_read' => 0, 'created_at' => date('Y-m-d H:i:s') ] ); if (!$notificationId) { error_log('NotificationHelper: Failed to insert notification'); return false; } // Leer la notificación completa para enviarla $notification = $db->fetchOne( "SELECT id, user_id, type, message, data, is_read, created_at FROM notifications WHERE id = ?", [$notificationId] ); if ($notification) { // Enviar por SSE self::pushSSE($notification); } return $notificationId; } catch (Exception $e) { error_log('NotificationHelper::create error: ' . $e->getMessage()); return false; } } /** * Enviar notificación existente por SSE * * @param array $notification Array con datos de la notificación */ public static function pushSSE($notification) { try { // Usar el sistema de push_event.php para broadcast $pushUrl = 'http://localhost:' . ($_SERVER['SERVER_PORT'] ?? '8000') . '/api/push_event.php'; $payload = json_encode([ 'event' => 'notification', 'data' => $notification, 'target' => 'all' // Enviar a todos los operadores conectados ]); // Fire-and-forget (no esperar respuesta) $ch = curl_init($pushUrl); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . strlen($payload) ]); @curl_exec($ch); curl_close($ch); } catch (Exception $e) { error_log('NotificationHelper::pushSSE error: ' . $e->getMessage()); } } }