← Code-Übersicht

PostgresDokumentationRepository.php

Pfad: src/Infrastructure/Persistence/PostgresDokumentationRepository.php

Ext: php

Größe: 2901 Bytes

Geändert: 2026-07-15T21:46:42+02:00

Frühere Version vom 2026-07-15T21:46:42+02:00 · zur aktuellen Fassung

<?php
declare(strict_types=1);

namespace Demo\Infrastructure\Persistence;

use Demo\Domain\Dokumentation\Dokumentation;
use Demo\Domain\Dokumentation\DokumentationRepository;
use PDO;

/**
 * Postgres-Adapter des DokumentationRepository. Ausschliesslich Prepared Statements.
 */
final class PostgresDokumentationRepository implements DokumentationRepository
{
    /** @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 liste(): array
    {
        $sql = 'SELECT id, slug, titel, body, array_to_json(tags) AS tags, '
            . 'created_at, updated_at FROM dokumentation ORDER BY updated_at DESC';
        $stmt = $this->pdo()->query($sql);
        $eintraege = [];
        foreach ($stmt === false ? [] : $stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $eintraege[] = $this->hydrate($row);
        }

        return $eintraege;
    }

    /**
     * @inheritDoc
     */
    public function bySlug(string $slug): ?Dokumentation
    {
        $sql = 'SELECT id, slug, titel, body, array_to_json(tags) AS tags, '
            . 'created_at, updated_at FROM dokumentation WHERE slug = :slug';
        $stmt = $this->pdo()->prepare($sql);
        $stmt->execute([':slug' => $slug]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        return $row === false ? null : $this->hydrate($row);
    }

    /**
     * @inheritDoc
     */
    public function speichereInhalt(string $slug, string $markdownBody): bool
    {
        $stmt = $this->pdo()->prepare('UPDATE dokumentation SET body = :body WHERE slug = :slug');
        $stmt->execute([':body' => $markdownBody, ':slug' => $slug]);

        return $stmt->rowCount() > 0;
    }

    /**
     * Baut aus einer DB-Zeile eine Dokumentation.
     *
     * @param array<string,mixed> $row Ergebniszeile.
     * @return Dokumentation Hydrierte Entity.
     */
    private function hydrate(array $row): Dokumentation
    {
        $tags = json_decode((string) $row['tags'], true);

        return new Dokumentation(
            (int) $row['id'],
            (string) $row['slug'],
            (string) $row['titel'],
            (string) $row['body'],
            is_array($tags) ? array_values(array_map('strval', $tags)) : [],
            (string) $row['created_at'],
            (string) $row['updated_at']
        );
    }

    /**
     * Liefert die zwischengespeicherte Verbindung (lazy).
     *
     * @return PDO Aktive Verbindung.
     */
    private function pdo(): PDO
    {
        return $this->pdo ??= $this->factory->create();
    }
}