PostgresDokumentationHistorie.php
Pfad: src/Infrastructure/Persistence/PostgresDokumentationHistorie.php
Ext: php
Größe: 3051 Bytes
Geändert: 2026-07-16 08:33:20+02
<?php
declare(strict_types=1);
namespace Demo\Infrastructure\Persistence;
use Demo\Domain\Dokumentation\Dokumentation;
use Demo\Domain\Dokumentation\DokumentationHistorie;
use Demo\Domain\Dokumentation\Version;
use PDO;
/**
* Postgres-Adapter des DokumentationHistorie-Ports. Nur lesend, Prepared Statements.
* Quelle ist public.history_dokumentation (System-Versioning-Pre-Images).
*/
final class PostgresDokumentationHistorie implements DokumentationHistorie
{
/** @var PdoConnectionFactory Fabrik fuer die Verbindung. */
private PdoConnectionFactory $factory;
/** @var PDO|null Zwischengespeicherte Verbindung. */
private ?PDO $pdo = null;
/**
* @param PdoConnectionFactory $factory Injizierte Verbindungs-Fabrik.
*/
public function __construct(PdoConnectionFactory $factory)
{
$this->factory = $factory;
}
/**
* @inheritDoc
*/
public function versionen(string $slug): array
{
$sql = 'SELECT history_id, operation, geaendert_am FROM history_dokumentation '
. "WHERE daten->>'slug' = :slug ORDER BY geaendert_am DESC, history_id DESC";
$stmt = $this->pdo()->prepare($sql);
$stmt->execute([':slug' => $slug]);
$versionen = [];
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$versionen[] = new Version(
(int) $row['history_id'],
(string) $row['geaendert_am'],
(string) $row['operation']
);
}
return $versionen;
}
/**
* @inheritDoc
*/
public function beiVersion(string $slug, int $id): ?Dokumentation
{
$sql = 'SELECT daten FROM history_dokumentation '
. "WHERE history_id = :id AND daten->>'slug' = :slug";
$stmt = $this->pdo()->prepare($sql);
$stmt->execute([':id' => $id, ':slug' => $slug]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
return null;
}
$daten = json_decode((string) $row['daten'], true);
return is_array($daten) ? $this->hydrate($daten) : null;
}
/**
* Baut aus einem JSONB-Snapshot eine Dokumentation.
*
* @param array<string,mixed> $daten Dekodierter Snapshot.
* @return Dokumentation Hydrierte Entity.
*/
private function hydrate(array $daten): Dokumentation
{
$tags = $daten['tags'] ?? [];
return new Dokumentation(
(int) ($daten['id'] ?? 0),
(string) ($daten['slug'] ?? ''),
(string) ($daten['titel'] ?? ''),
(string) ($daten['body'] ?? ''),
is_array($tags) ? array_values(array_map('strval', $tags)) : [],
(string) ($daten['created_at'] ?? ''),
(string) ($daten['updated_at'] ?? '')
);
}
/**
* Liefert die zwischengespeicherte Verbindung (lazy).
*
* @return PDO Aktive Verbindung.
*/
private function pdo(): PDO
{
return $this->pdo ??= $this->factory->create();
}
}