Backup #1178

ID1178
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Infrastructure/Persistence/DokumentationRepository.php
Version6
Typ modified
Größe9.1 KB
Hash99c363916eeaa17c869a159a98645aa6ee3a7d8a7693a820d27d7609a6009d7d
Datum2025-12-25 10:32:19
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

declare(strict_types=1);

namespace Infrastructure\Persistence;

// @responsibility: Persistenz für Dokumentations-Baum (hierarchisch, mit Chunks)

use Domain\Repository\DokumentationRepositoryInterface;
use Infrastructure\Config\DatabaseFactory;

class DokumentationRepository implements DokumentationRepositoryInterface
{
    private \PDO $pdo;

    public function __construct(?\PDO $pdo = null)
    {
        $this->pdo = $pdo ?? DatabaseFactory::dev();
    }

    public function findById(int $id): ?array
    {
        $stmt = $this->pdo->prepare('SELECT * FROM dokumentation WHERE id = :id');
        $stmt->execute(['id' => $id]);
        $result = $stmt->fetch();

        return $result !== false ? $result : null;
    }

    public function findByPath(string $path): ?array
    {
        $stmt = $this->pdo->prepare('SELECT * FROM dokumentation WHERE path = :path AND status = :status');
        $stmt->execute(['path' => $path, 'status' => 'published']);
        $result = $stmt->fetch();

        return $result !== false ? $result : null;
    }

    public function findBySlug(string $slug, ?int $parentId = null): ?array
    {
        if ($parentId === null) {
            $stmt = $this->pdo->prepare('SELECT * FROM dokumentation WHERE slug = :slug AND parent_id IS NULL AND status = :status');
            $stmt->execute(['slug' => $slug, 'status' => 'published']);
        } else {
            $stmt = $this->pdo->prepare('SELECT * FROM dokumentation WHERE slug = :slug AND parent_id = :parent_id AND status = :status');
            $stmt->execute(['slug' => $slug, 'parent_id' => $parentId, 'status' => 'published']);
        }
        $result = $stmt->fetch();

        return $result !== false ? $result : null;
    }

    public function findDocBySlug(string $slug): ?array
    {
        $stmt = $this->pdo->prepare('SELECT * FROM dokumentation WHERE slug = :slug AND status = :status LIMIT 1');
        $stmt->execute(['slug' => $slug, 'status' => 'published']);
        $result = $stmt->fetch();

        return $result !== false ? $result : null;
    }

    public function findChildren(int $parentId): array
    {
        $stmt = $this->pdo->prepare('
            SELECT * FROM dokumentation
            WHERE parent_id = :parent_id AND status = :status
            ORDER BY sort_order ASC
        ');
        $stmt->execute(['parent_id' => $parentId, 'status' => 'published']);

        return $stmt->fetchAll();
    }

    public function findRootDocuments(): array
    {
        $stmt = $this->pdo->prepare('
            SELECT * FROM dokumentation
            WHERE parent_id IS NULL AND status = :status
            ORDER BY sort_order ASC
        ');
        $stmt->execute(['status' => 'published']);

        return $stmt->fetchAll();
    }

    public function getHierarchy(): array
    {
        $roots = $this->findRootDocuments();

        return $this->buildTree($roots);
    }

    private function buildTree(array $items): array
    {
        $result = [];
        foreach ($items as $item) {
            $children = $this->findChildren((int) $item['id']);
            $item['children'] = $this->buildTree($children);
            $result[] = $item;
        }

        return $result;
    }

    public function getBreadcrumb(int $docId): array
    {
        $breadcrumb = [];
        $doc = $this->findById($docId);

        while ($doc !== null) {
            array_unshift($breadcrumb, [
                'title' => $doc['title'],
                'path' => $doc['path'],
            ]);

            if ($doc['parent_id'] !== null) {
                $doc = $this->findById((int) $doc['parent_id']);
            } else {
                $doc = null;
            }
        }

        return $breadcrumb;
    }

    public function getSiblings(int $docId): array
    {
        $doc = $this->findById($docId);
        if ($doc === null) {
            return [];
        }

        if ($doc['parent_id'] === null) {
            return $this->findRootDocuments();
        }

        return $this->findChildren((int) $doc['parent_id']);
    }

    public function getStatistics(): array
    {
        $stats = [];

        $stmt = $this->pdo->query('SELECT COUNT(*) FROM dokumentation');
        $stats['total'] = (int) $stmt->fetchColumn();

        $stmt = $this->pdo->query('SELECT depth, COUNT(*) as count FROM dokumentation GROUP BY depth ORDER BY depth');
        $stats['by_depth'] = $stmt->fetchAll();

        $stmt = $this->pdo->query('SELECT status, COUNT(*) as count FROM dokumentation GROUP BY status');
        $stats['by_status'] = $stmt->fetchAll();

        return $stats;
    }

    /**
     * Find all documents with optional filters.
     */
    public function findAll(
        ?string $status = null,
        ?int $parentId = null,
        ?string $search = null,
        int $limit = 50,
        int $offset = 0
    ): array {
        $sql = 'SELECT * FROM dokumentation WHERE 1=1';
        $params = [];

        if ($status !== null) {
            $sql .= ' AND status = :status';
            $params['status'] = $status;
        }

        if ($parentId !== null) {
            $sql .= ' AND parent_id = :parent_id';
            $params['parent_id'] = $parentId;
        }

        if ($search !== null) {
            $sql .= ' AND (title LIKE :search OR description LIKE :search2)';
            $params['search'] = '%' . $search . '%';
            $params['search2'] = '%' . $search . '%';
        }

        $sql .= ' ORDER BY depth ASC, sort_order ASC LIMIT :limit OFFSET :offset';

        $stmt = $this->pdo->prepare($sql);

        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }

        $stmt->bindValue('limit', $limit, \PDO::PARAM_INT);
        $stmt->bindValue('offset', $offset, \PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetchAll();
    }

    /**
     * Count documents with optional filters.
     */
    public function count(
        ?string $status = null,
        ?int $parentId = null,
        ?string $search = null
    ): int {
        $sql = 'SELECT COUNT(*) FROM dokumentation WHERE 1=1';
        $params = [];

        if ($status !== null) {
            $sql .= ' AND status = :status';
            $params['status'] = $status;
        }

        if ($parentId !== null) {
            $sql .= ' AND parent_id = :parent_id';
            $params['parent_id'] = $parentId;
        }

        if ($search !== null) {
            $sql .= ' AND (title LIKE :search OR description LIKE :search2)';
            $params['search'] = '%' . $search . '%';
            $params['search2'] = '%' . $search . '%';
        }

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);

        return (int) $stmt->fetchColumn();
    }

    /**
     * Create a new document.
     */
    public function create(array $data): int
    {
        // Determine path and depth
        $parentId = $data['parent_id'] ?? null;
        $slug = $data['slug'];

        if ($parentId !== null) {
            $parent = $this->findById((int) $parentId);
            $path = ($parent['path'] ?? '') . '/' . $slug;
            $depth = ($parent['depth'] ?? 0) + 1;
        } else {
            $path = '/' . $slug;
            $depth = 0;
        }

        $stmt = $this->pdo->prepare('
            INSERT INTO dokumentation (parent_id, slug, path, depth, title, description, content, content_format, status, sort_order, created_at, updated_at)
            VALUES (:parent_id, :slug, :path, :depth, :title, :description, :content, :format, :status, :sort_order, NOW(), NOW())
        ');

        $stmt->execute([
            'parent_id' => $parentId,
            'slug' => $slug,
            'path' => $path,
            'depth' => $depth,
            'title' => $data['title'],
            'description' => $data['description'] ?? null,
            'content' => $data['content'] ?? '',
            'format' => $data['content_format'] ?? 'html',
            'status' => $data['status'] ?? 'draft',
            'sort_order' => $data['sort_order'] ?? 0,
        ]);

        return (int) $this->pdo->lastInsertId();
    }

    /**
     * Update a document.
     */
    public function update(int $id, array $data): void
    {
        $fields = [];
        $params = ['id' => $id];

        foreach (['title', 'content', 'description', 'status'] as $field) {
            if (array_key_exists($field, $data)) {
                $fields[] = "{$field} = :{$field}";
                $params[$field] = $data[$field];
            }
        }

        if (empty($fields)) {
            return;
        }

        $fields[] = 'updated_at = NOW()';
        $fields[] = 'version = version + 1';

        $sql = 'UPDATE dokumentation SET ' . implode(', ', $fields) . ' WHERE id = :id';

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
    }

    /**
     * Delete a document.
     */
    public function delete(int $id): void
    {
        $stmt = $this->pdo->prepare('DELETE FROM dokumentation WHERE id = :id');
        $stmt->execute(['id' => $id]);
    }

    /**
     * Get document tree (alias for getHierarchy).
     */
    public function getTree(): array
    {
        return $this->getHierarchy();
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
1195 7 modified 9.0 KB 2025-12-25 10:34
1178 6 modified 9.1 KB 2025-12-25 10:32
769 5 modified 8.9 KB 2025-12-23 08:04
579 4 modified 8.9 KB 2025-12-23 04:22
569 3 modified 4.4 KB 2025-12-23 03:41
249 2 modified 4.3 KB 2025-12-22 01:48
32 1 modified 5.0 KB 2025-12-20 17:23

← Zurück zur Übersicht