161 lines
5.0 KiB
PHP
161 lines
5.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Application\Http\Controllers;
|
|
|
|
use App\Framework\Attributes\Route;
|
|
use App\Framework\Auth\Auth;
|
|
use App\Framework\Http\Method;
|
|
use App\Framework\Http\SseStream;
|
|
use App\Framework\Http\Status;
|
|
use App\Framework\Router\Result\SseResult;
|
|
use App\Framework\Router\Result\SseResultWithCallback;
|
|
|
|
/**
|
|
* Controller für Echtzeit-Benachrichtigungen über Server-Sent Events
|
|
*/
|
|
final class NotificationController
|
|
{
|
|
/**
|
|
* Stellt einen SSE-Stream für allgemeine Benachrichtigungen bereit
|
|
*/
|
|
#[Auth]
|
|
#[Route(path: '/api/notifications/stream', method: Method::GET)]
|
|
public function notificationStream(): SseResult
|
|
{
|
|
// SSE-Result mit 3 Sekunden Retry-Intervall
|
|
$result = new SseResult(Status::OK, 3000);
|
|
|
|
// Initiale Verbindungsbestätigung
|
|
$result->addJsonEvent(
|
|
['message' => 'Verbunden mit dem Benachrichtigungsstream'],
|
|
'connected',
|
|
'conn-' . uniqid()
|
|
);
|
|
|
|
// Einige Beispiel-Benachrichtigungen beim Start senden
|
|
$result->addJsonEvent(
|
|
[
|
|
'type' => 'info',
|
|
'title' => 'Willkommen',
|
|
'message' => 'Sie sind jetzt mit Echtzeit-Updates verbunden.',
|
|
'timestamp' => time()
|
|
],
|
|
'notification',
|
|
'notif-' . uniqid()
|
|
);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Stellt einen benutzer-spezifischen SSE-Stream bereit
|
|
*/
|
|
#[Auth]
|
|
#[Route(path: '/api/notifications/user/{userId}', method: Method::GET)]
|
|
public function userNotifications(int $userId): SseResult
|
|
{
|
|
// SSE-Result mit benutzerdefinierten Headern
|
|
$result = new SseResult(Status::OK, 3000, [
|
|
'X-User-ID' => (string)$userId
|
|
]);
|
|
|
|
// Verbindungsbestätigung mit Benutzer-ID
|
|
$result->addJsonEvent(
|
|
[
|
|
'message' => 'Verbunden mit dem Benutzer-Stream',
|
|
'userId' => $userId,
|
|
'timestamp' => time()
|
|
],
|
|
'connected',
|
|
'conn-user-' . $userId
|
|
);
|
|
|
|
// Aktuelle Benachrichtigungen für den Benutzer laden
|
|
$notifications = $this->getUserNotifications($userId);
|
|
|
|
// Benachrichtigungen zum Stream hinzufügen
|
|
foreach ($notifications as $notification) {
|
|
$result->addJsonEvent($notification, 'notification', $notification['id']);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Gibt Benachrichtigungen für einen bestimmten Benutzer zurück
|
|
* In einer realen Anwendung würde diese Methode Daten aus einer Datenbank laden
|
|
*/
|
|
private function getUserNotifications(int $userId): array
|
|
{
|
|
// Beispiel-Benachrichtigungen
|
|
return [
|
|
[
|
|
'id' => 'notif-' . uniqid(),
|
|
'type' => 'message',
|
|
'title' => 'Neue Nachricht',
|
|
'message' => 'Sie haben eine neue Nachricht erhalten',
|
|
'timestamp' => time() - 300 // Vor 5 Minuten
|
|
],
|
|
[
|
|
'id' => 'notif-' . uniqid(),
|
|
'type' => 'system',
|
|
'title' => 'System-Update',
|
|
'message' => 'Das System wurde aktualisiert',
|
|
'timestamp' => time() - 3600 // Vor 1 Stunde
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Stellt einen Live-Stream mit dynamischen Updates bereit
|
|
*/
|
|
#[Auth]
|
|
#[Route(path: '/api/notifications/live', method: Method::GET)]
|
|
public function liveNotifications(): SseResult
|
|
{
|
|
// Erweiterte SSE-Konfiguration mit Callback
|
|
#$result = new SseResultWithCallback(Status::OK, 3000);
|
|
|
|
// Callback für dynamische Updates festlegen
|
|
$callback = function(SseStream $stream) {
|
|
// Simuliere neue Benachrichtigungen (mit 10% Wahrscheinlichkeit)
|
|
if (rand(1, 10) === 1) {
|
|
$notificationTypes = ['info', 'warning', 'update', 'message'];
|
|
$type = $notificationTypes[array_rand($notificationTypes)];
|
|
|
|
$notification = [
|
|
'id' => 'live-notif-' . uniqid(),
|
|
'type' => $type,
|
|
'title' => 'Neue ' . ucfirst($type) . '-Benachrichtigung',
|
|
'message' => 'Dies ist eine dynamisch generierte Benachrichtigung vom Typ ' . $type,
|
|
'timestamp' => time()
|
|
];
|
|
|
|
$stream->sendJson($notification, 'notification', $notification['id']);
|
|
|
|
// Kleine Pause nach dem Senden, um das Testszenario zu simulieren
|
|
sleep(1);
|
|
}
|
|
};
|
|
|
|
$result = new SseResult(
|
|
retryInterval: 500,
|
|
callback: $callback,
|
|
maxDuration: 300,
|
|
heartbeatInterval: 15,
|
|
);
|
|
|
|
// Initiale Verbindungsbestätigung
|
|
$result->addJsonEvent(
|
|
['message' => 'Verbunden mit dem Live-Stream', 'timestamp' => time()],
|
|
'connected',
|
|
'live-' . uniqid()
|
|
);
|
|
|
|
|
|
|
|
return $result;
|
|
}
|
|
}
|