chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View 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 = [],
) {}
}

View 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',
) {}
}

View 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,
) {}
}

View 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,
) {}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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
{
}*/
}

View 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; }
}