← Code-Übersicht

ProzessDetailLader.php

Pfad: src/Infrastructure/Persistence/ProzessDetailLader.php

Ext: php

Größe: 5073 Bytes

Geändert: 2026-07-16 01:39:48+02

<?php
declare(strict_types=1);

namespace Demo\Infrastructure\Persistence;

use Demo\Domain\Prozess\Kante;
use Demo\Domain\Prozess\Schritt;
use Demo\Domain\Prozess\SchrittArtefakt;
use PDO;

/**
 * Laedt die Detailbestandteile eines Prozesses (Schritte inkl. Artefakte,
 * Kanten, Doku-Verweise) per PDO Prepared Statements. Reine Lesezugriffe.
 */
final class ProzessDetailLader
{
    /** @var PdoConnectionFactory Verbindungs-Fabrik. */
    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;
    }

    /**
     * Laedt die Schritte eines Prozesses inkl. ihrer Artefakte.
     *
     * @param int $pid Prozess-Id.
     * @return list<Schritt> Schritte.
     */
    public function schritte(int $pid): array
    {
        $artefakte = $this->artefakteJeSchritt($pid);
        $sql = 'SELECT ps.id, ps.name, ps.beschreibung, a.name AS akteur, sy.name AS system, '
            . 'r.name AS rolle, rp.slug AS ruft_slug, rp.titel AS ruft_titel '
            . 'FROM prozess_schritt ps '
            . 'JOIN akteur a ON a.id = ps.akteur_id '
            . 'JOIN system sy ON sy.id = ps.system_id '
            . 'LEFT JOIN rolle r ON r.id = ps.rolle_id '
            . 'LEFT JOIN prozesse rp ON rp.id = ps.ruft_prozess_id '
            . 'WHERE ps.prozess_id = :pid ORDER BY ps.id';
        $stmt = $this->pdo()->prepare($sql);
        $stmt->execute([':pid' => $pid]);
        $out = [];
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $id = (int) $row['id'];
            $out[] = new Schritt(
                $id,
                (string) $row['name'],
                (string) $row['beschreibung'],
                (string) $row['akteur'],
                (string) $row['system'],
                $row['rolle'] !== null ? (string) $row['rolle'] : null,
                $row['ruft_slug'] !== null ? (string) $row['ruft_slug'] : null,
                $row['ruft_titel'] !== null ? (string) $row['ruft_titel'] : null,
                $artefakte[$id] ?? []
            );
        }

        return $out;
    }

    /**
     * Gruppiert die Artefakt-Zuordnungen je Schritt.
     *
     * @param int $pid Prozess-Id.
     * @return array<int,list<SchrittArtefakt>> Artefakte je Schritt-Id.
     */
    private function artefakteJeSchritt(int $pid): array
    {
        $sql = 'SELECT sa.schritt_id, ar.typ, ar.bezeichner, sa.beziehung '
            . 'FROM schritt_artefakt sa '
            . 'JOIN artefakt ar ON ar.id = sa.artefakt_id '
            . 'JOIN prozess_schritt ps ON ps.id = sa.schritt_id '
            . 'WHERE ps.prozess_id = :pid ORDER BY sa.schritt_id, ar.typ, ar.bezeichner';
        $stmt = $this->pdo()->prepare($sql);
        $stmt->execute([':pid' => $pid]);
        $out = [];
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $out[(int) $row['schritt_id']][] = new SchrittArtefakt(
                (string) $row['typ'],
                (string) $row['bezeichner'],
                (string) $row['beziehung']
            );
        }

        return $out;
    }

    /**
     * Laedt die Ablauf-Kanten eines Prozesses.
     *
     * @param int $pid Prozess-Id.
     * @return list<Kante> Kanten.
     */
    public function kanten(int $pid): array
    {
        $sql = 'SELECT sv.vorgaenger_id, sv.schritt_id, sv.ausgang '
            . 'FROM schritt_vorgaenger sv '
            . 'JOIN prozess_schritt ps ON ps.id = sv.schritt_id '
            . 'WHERE ps.prozess_id = :pid';
        $stmt = $this->pdo()->prepare($sql);
        $stmt->execute([':pid' => $pid]);
        $out = [];
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $out[] = new Kante(
                (int) $row['vorgaenger_id'],
                (int) $row['schritt_id'],
                $row['ausgang'] !== null ? (string) $row['ausgang'] : null
            );
        }

        return $out;
    }

    /**
     * Laedt die verknuepften Dokumentationen eines Prozesses.
     *
     * @param int $pid Prozess-Id.
     * @return list<array{slug:string,titel:string}> Doku-Verweise.
     */
    public function dokus(int $pid): array
    {
        $sql = 'SELECT d.slug, d.titel FROM doku_prozess dp '
            . 'JOIN dokumentation d ON d.id = dp.doku_id '
            . 'WHERE dp.prozess_id = :pid ORDER BY d.titel';
        $stmt = $this->pdo()->prepare($sql);
        $stmt->execute([':pid' => $pid]);
        $out = [];
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $out[] = ['slug' => (string) $row['slug'], 'titel' => (string) $row['titel']];
        }

        return $out;
    }

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