Backup #1178
| ID | 1178 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Infrastructure/Persistence/DokumentationRepository.php |
| Version | 6 |
| Typ |
modified |
| Größe | 9.1 KB |
| Hash | 99c363916eeaa17c869a159a98645aa6ee3a7d8a7693a820d27d7609a6009d7d |
| Datum | 2025-12-25 10:32:19 |
| Geändert von | claude-code-hook |
| Grund | Claude 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
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