chore: complete update
This commit is contained in:
15
src/Framework/Router/Result/ContentNegotiationResult.php
Normal file
15
src/Framework/Router/Result/ContentNegotiationResult.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
final readonly class ContentNegotiationResult implements ActionResult
|
||||
{
|
||||
public function __construct(
|
||||
public array $jsonPayload = [],
|
||||
public ?string $redirectTo = null,
|
||||
public ?string $viewTemplate = null,
|
||||
public array $viewData = [],
|
||||
) {}
|
||||
}
|
||||
14
src/Framework/Router/Result/FileResult.php
Normal file
14
src/Framework/Router/Result/FileResult.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
final readonly class FileResult implements ActionResult
|
||||
{
|
||||
public function __construct(
|
||||
public string $filePath,
|
||||
public string $variant = 'original',
|
||||
public string $mimeType = 'application/image',
|
||||
) {}
|
||||
}
|
||||
15
src/Framework/Router/Result/JsonResult.php
Normal file
15
src/Framework/Router/Result/JsonResult.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
final class JsonResult implements ActionResult
|
||||
{
|
||||
public function __construct(
|
||||
public readonly array $data,
|
||||
public Status $status = Status::OK,
|
||||
) {}
|
||||
}
|
||||
15
src/Framework/Router/Result/Redirect.php
Normal file
15
src/Framework/Router/Result/Redirect.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
final class Redirect implements ActionResult
|
||||
{
|
||||
public Status $status = Status::FOUND;
|
||||
public function __construct(
|
||||
public readonly string $target,
|
||||
) {}
|
||||
}
|
||||
52
src/Framework/Router/Result/SseEvent.php
Normal file
52
src/Framework/Router/Result/SseEvent.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
/**
|
||||
* Repräsentiert ein einzelnes Server-Sent Event
|
||||
*/
|
||||
final readonly class SseEvent
|
||||
{
|
||||
/**
|
||||
* @param string $data Der Dateninhalt des Events
|
||||
* @param string|null $event Der Event-Typ (optional)
|
||||
* @param string|null $id Die Event-ID (optional)
|
||||
* @param int|null $retry Retry-Intervall in Millisekunden (optional)
|
||||
*/
|
||||
public function __construct(
|
||||
public string $data,
|
||||
public ?string $event = null,
|
||||
public ?string $id = null,
|
||||
public ?int $retry = null
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Formatiert das Event in das SSE-Protokollformat
|
||||
*/
|
||||
public function format(): string
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
if ($this->id !== null) {
|
||||
$formatted[] = "id: {$this->id}";
|
||||
}
|
||||
|
||||
if ($this->event !== null) {
|
||||
$formatted[] = "event: {$this->event}";
|
||||
}
|
||||
|
||||
if ($this->retry !== null) {
|
||||
$formatted[] = "retry: {$this->retry}";
|
||||
}
|
||||
|
||||
// Mehrzeilige Daten unterstützen
|
||||
foreach (explode("\n", $this->data) as $line) {
|
||||
$formatted[] = "data: {$line}";
|
||||
}
|
||||
|
||||
$formatted[] = ''; // Leere Zeile am Ende
|
||||
|
||||
return implode("\n", $formatted);
|
||||
}
|
||||
}
|
||||
72
src/Framework/Router/Result/SseResult.php
Normal file
72
src/Framework/Router/Result/SseResult.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Router\ActionResult;
|
||||
use Closure;
|
||||
|
||||
final class SseResult implements ActionResult
|
||||
{
|
||||
/**
|
||||
* @var array<SseEvent> Enthält die SSE-Events, die beim initialen Verbindungsaufbau gesendet werden
|
||||
*/
|
||||
private array $initialEvents = [];
|
||||
|
||||
/**
|
||||
* @param Status $status HTTP-Status-Code der Antwort
|
||||
* @param int|null $retryInterval Zeit in Millisekunden, nach der der Client bei Verbindungsverlust neu verbinden soll
|
||||
* @param array<string, string> $headers Zusätzliche HTTP-Header für die Response
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly Status $status = Status::OK,
|
||||
public readonly ?int $retryInterval = 3000,
|
||||
public readonly array $headers = [],
|
||||
|
||||
public readonly ?Closure $callback = null,
|
||||
public readonly int $maxDuration = 0,
|
||||
public readonly int $heartbeatInterval = 30,
|
||||
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Fügt ein Event hinzu, das beim initialen Verbindungsaufbau gesendet wird
|
||||
*/
|
||||
public function addEvent(
|
||||
string $data,
|
||||
?string $event = null,
|
||||
?string $id = null,
|
||||
?int $retry = null
|
||||
): self {
|
||||
$this->initialEvents[] = new SseEvent($data, $event, $id, $retry);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt ein JSON-formatiertes Event hinzu
|
||||
*/
|
||||
public function addJsonEvent(
|
||||
array $data,
|
||||
?string $event = null,
|
||||
?string $id = null,
|
||||
?int $retry = null
|
||||
): self {
|
||||
return $this->addEvent(json_encode($data), $event, $id, $retry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt alle initialen Events zurück
|
||||
*
|
||||
* @return array<SseEvent>
|
||||
*/
|
||||
public function getInitialEvents(): array
|
||||
{
|
||||
return $this->initialEvents;
|
||||
}
|
||||
|
||||
public function hasCallback(): bool
|
||||
{
|
||||
return $this->callback !== null;
|
||||
}
|
||||
}
|
||||
92
src/Framework/Router/Result/SseResultWithCallback.php
Normal file
92
src/Framework/Router/Result/SseResultWithCallback.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Http\SseStream;
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
/**
|
||||
* Erweiterte SSE-Klasse, die eine Callback-Funktion für Live-Updates unterstützt
|
||||
*/
|
||||
final class SseResultWithCallback implements ActionResult
|
||||
{
|
||||
/**
|
||||
* @var callable|null Callback-Funktion, die während des Streamings ausgeführt wird
|
||||
*/
|
||||
private $callback = null;
|
||||
|
||||
/**
|
||||
* @var int Maximale Streaming-Dauer in Sekunden (0 = unbegrenzt)
|
||||
*/
|
||||
private int $maxDuration = 0;
|
||||
|
||||
/**
|
||||
* @var int Intervall für Heartbeats in Sekunden
|
||||
*/
|
||||
private int $heartbeatInterval = 30;
|
||||
|
||||
public function __construct(
|
||||
public readonly Status $status = Status::OK,
|
||||
public readonly array $headers = []
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Setzt die Callback-Funktion, die während des Streamings aufgerufen wird
|
||||
* Der Callback erhält den SseStream als Parameter
|
||||
*
|
||||
* @param callable $callback Funktion mit Signatur: function(SseStream $stream): void
|
||||
*/
|
||||
public function setCallback(callable $callback): self
|
||||
{
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die maximale Streaming-Dauer
|
||||
*
|
||||
* @param int $seconds Maximale Dauer in Sekunden (0 = unbegrenzt)
|
||||
*/
|
||||
public function setMaxDuration(int $seconds): self
|
||||
{
|
||||
$this->maxDuration = $seconds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das Intervall für Heartbeats
|
||||
*
|
||||
* @param int $seconds Intervall in Sekunden
|
||||
*/
|
||||
public function setHeartbeatInterval(int $seconds): self
|
||||
{
|
||||
$this->heartbeatInterval = $seconds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Callback zurück
|
||||
*/
|
||||
public function getCallback(): ?callable
|
||||
{
|
||||
return $this->callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die maximale Streaming-Dauer zurück
|
||||
*/
|
||||
public function getMaxDuration(): int
|
||||
{
|
||||
return $this->maxDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt das Heartbeat-Intervall zurück
|
||||
*/
|
||||
public function getHeartbeatInterval(): int
|
||||
{
|
||||
return $this->heartbeatInterval;
|
||||
}
|
||||
}
|
||||
27
src/Framework/Router/Result/ViewResult.php
Normal file
27
src/Framework/Router/Result/ViewResult.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Meta\MetaData;
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
final readonly class ViewResult implements ActionResult
|
||||
{
|
||||
public function __construct(
|
||||
public string $template,
|
||||
public MetaData $metaData,
|
||||
public array $data = [],
|
||||
public Status $status = Status::OK,
|
||||
#public string $layout = '',
|
||||
public array $slots = [],
|
||||
public ?string $controllerClass = null,
|
||||
public ?object $model = null,
|
||||
) {}
|
||||
|
||||
/*public static function fromStrings():self
|
||||
{
|
||||
|
||||
}*/
|
||||
}
|
||||
130
src/Framework/Router/Result/WebSocketResult.php
Normal file
130
src/Framework/Router/Result/WebSocketResult.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Router\Result;
|
||||
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Router\ActionResult;
|
||||
|
||||
final class WebSocketResult implements ActionResult
|
||||
{
|
||||
/**
|
||||
* @var callable|null Handler für neue Verbindungen
|
||||
*/
|
||||
private $onConnect = null;
|
||||
|
||||
/**
|
||||
* @var callable|null Handler für eingehende Nachrichten
|
||||
*/
|
||||
private $onMessage = null;
|
||||
|
||||
/**
|
||||
* @var callable|null Handler für geschlossene Verbindungen
|
||||
*/
|
||||
private $onClose = null;
|
||||
|
||||
/**
|
||||
* @var callable|null Handler für Fehler
|
||||
*/
|
||||
private $onError = null;
|
||||
|
||||
/**
|
||||
* @var array Unterstützte Subprotokolle
|
||||
*/
|
||||
private array $subprotocols = [];
|
||||
|
||||
/**
|
||||
* @var int Maximale Nachrichtengröße in Bytes
|
||||
*/
|
||||
private int $maxMessageSize = 1048576; // 1MB
|
||||
|
||||
/**
|
||||
* @var int Ping-Intervall in Sekunden
|
||||
*/
|
||||
private int $pingInterval = 30;
|
||||
|
||||
public function __construct(
|
||||
public readonly Status $status = Status::SWITCHING_PROTOCOLS,
|
||||
public readonly array $headers = []
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Setzt den Handler für neue Verbindungen
|
||||
*
|
||||
* @param callable $handler function(WebSocketConnection $connection): void
|
||||
*/
|
||||
public function onConnect(callable $handler): self
|
||||
{
|
||||
$this->onConnect = $handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Handler für eingehende Nachrichten
|
||||
*
|
||||
* @param callable $handler function(WebSocketConnection $connection, string $message): void
|
||||
*/
|
||||
public function onMessage(callable $handler): self
|
||||
{
|
||||
$this->onMessage = $handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Handler für geschlossene Verbindungen
|
||||
*
|
||||
* @param callable $handler function(WebSocketConnection $connection, int $code, string $reason): void
|
||||
*/
|
||||
public function onClose(callable $handler): self
|
||||
{
|
||||
$this->onClose = $handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Handler für Fehler
|
||||
*
|
||||
* @param callable $handler function(WebSocketConnection $connection, \Throwable $error): void
|
||||
*/
|
||||
public function onError(callable $handler): self
|
||||
{
|
||||
$this->onError = $handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt unterstützte Subprotokolle
|
||||
*/
|
||||
public function withSubprotocols(array $subprotocols): self
|
||||
{
|
||||
$this->subprotocols = $subprotocols;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die maximale Nachrichtengröße
|
||||
*/
|
||||
public function withMaxMessageSize(int $bytes): self
|
||||
{
|
||||
$this->maxMessageSize = $bytes;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das Ping-Intervall
|
||||
*/
|
||||
public function withPingInterval(int $seconds): self
|
||||
{
|
||||
$this->pingInterval = $seconds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public function getOnConnect(): ?callable { return $this->onConnect; }
|
||||
public function getOnMessage(): ?callable { return $this->onMessage; }
|
||||
public function getOnClose(): ?callable { return $this->onClose; }
|
||||
public function getOnError(): ?callable { return $this->onError; }
|
||||
public function getSubprotocols(): array { return $this->subprotocols; }
|
||||
public function getMaxMessageSize(): int { return $this->maxMessageSize; }
|
||||
public function getPingInterval(): int { return $this->pingInterval; }
|
||||
}
|
||||
Reference in New Issue
Block a user