CollectionRepository.php
- Pfad:
src/Infrastructure/Persistence/CollectionRepository.php - Namespace: Infrastructure\Persistence
- Zeilen: 243 | Größe: 7,025 Bytes
- Geändert: 2025-12-25 10:35:38 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 98
- Dependencies: 100 (25%)
- LOC: 100 (20%)
- Methods: 90 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 4
- implements Domain\Repository\CollectionRepositoryInterface
- constructor PDO
- use Domain\Repository\CollectionRepositoryInterface
- use PDO
Klassen 1
-
CollectionRepositoryclass Zeile 12
Funktionen 11
-
__construct()public Zeile 17 -
find()public Zeile 28 -
findByIds()public Zeile 46 -
getSearchable()public Zeile 67 -
getActive()public Zeile 84 -
getAll()public Zeile 101 -
exists()public Zeile 114 -
updateMetadata()public Zeile 129 -
create()public Zeile 157 -
deactivate()public Zeile 186 -
checkReferences()public Zeile 201
Verwendet von 5
- CollectionValidator.php constructor
- CollectionValidator.php use
- ContentCollectionService.php constructor
- ContentCollectionService.php use
- ContentServiceProvider.php use
Versionen 8
-
v8
2025-12-25 10:35 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v7
2025-12-25 10:35 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v6
2025-12-25 10:34 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v5
2025-12-25 10:32 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v4
2025-12-23 08:04 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v3
2025-12-22 01:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-21 14:38 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-21 14:38 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation
Code
<?php
declare(strict_types=1);
namespace Infrastructure\Persistence;
// @responsibility: Persistenz für RAG-Collections (Qdrant-Metadaten)
use Domain\Repository\CollectionRepositoryInterface;
use PDO;
final class CollectionRepository implements CollectionRepositoryInterface
{
private PDO $pdo;
private ?PDO $pdoContent;
public function __construct(PDO $pdo, ?PDO $pdoContent = null)
{
$this->pdo = $pdo;
$this->pdoContent = $pdoContent;
}
/**
* Find a collection by its Qdrant collection_id.
*
* @return array<string, mixed>|null
*/
public function find(string $collectionId): ?array
{
$stmt = $this->pdo->prepare('
SELECT * FROM rag_collections
WHERE collection_id = ?
');
$stmt->execute([$collectionId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ?: null;
}
/**
* Find multiple collections by their IDs.
*
* @param array<string> $collectionIds
* @return array<int, array<string, mixed>>
*/
public function findByIds(array $collectionIds): array
{
if (empty($collectionIds)) {
return [];
}
$placeholders = implode(',', array_fill(0, count($collectionIds), '?'));
$stmt = $this->pdo->prepare("
SELECT * FROM rag_collections
WHERE collection_id IN ($placeholders)
");
$stmt->execute($collectionIds);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Get all active and searchable collections for dropdowns.
*
* @return array<int, array<string, mixed>>
*/
public function getSearchable(): array
{
$stmt = $this->pdo->query('
SELECT collection_id, display_name, points_count, vector_size
FROM rag_collections
WHERE is_active = 1 AND is_searchable = 1
ORDER BY sort_order ASC, display_name ASC
');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Get all active collections (including non-searchable).
*
* @return array<int, array<string, mixed>>
*/
public function getActive(): array
{
$stmt = $this->pdo->query('
SELECT collection_id, display_name, points_count, vector_size, is_searchable
FROM rag_collections
WHERE is_active = 1
ORDER BY sort_order ASC, display_name ASC
');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Get all collections (for admin).
*
* @return array<int, array<string, mixed>>
*/
public function getAll(): array
{
$stmt = $this->pdo->query('
SELECT * FROM rag_collections
ORDER BY sort_order ASC, display_name ASC
');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Check if a collection exists.
*/
public function exists(string $collectionId): bool
{
$stmt = $this->pdo->prepare('
SELECT 1 FROM rag_collections WHERE collection_id = ?
');
$stmt->execute([$collectionId]);
return $stmt->fetchColumn() !== false;
}
/**
* Update collection metadata (from Qdrant sync).
*
* @param array<string, mixed> $data
*/
public function updateMetadata(string $collectionId, array $data): void
{
$allowed = ['vector_size', 'distance_metric', 'points_count', 'last_synced_at'];
$updates = [];
$params = [];
foreach ($allowed as $field) {
if (array_key_exists($field, $data)) {
$updates[] = "$field = ?";
$params[] = $data[$field];
}
}
if (empty($updates)) {
return;
}
$params[] = $collectionId;
$sql = 'UPDATE rag_collections SET ' . implode(', ', $updates) . ' WHERE collection_id = ?';
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
}
/**
* Create a new collection entry.
*
* @param array<string, mixed> $data
*/
public function create(array $data): int
{
$stmt = $this->pdo->prepare('
INSERT INTO rag_collections
(collection_id, display_name, description, vector_size, distance_metric,
points_count, embedding_model, source_type, is_active, is_searchable, sort_order)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
');
$stmt->execute([
$data['collection_id'],
$data['display_name'] ?? $data['collection_id'],
$data['description'] ?? null,
$data['vector_size'] ?? null,
$data['distance_metric'] ?? 'Cosine',
$data['points_count'] ?? 0,
$data['embedding_model'] ?? null,
$data['source_type'] ?? 'manual',
$data['is_active'] ?? true,
$data['is_searchable'] ?? true,
$data['sort_order'] ?? 0,
]);
return (int) $this->pdo->lastInsertId();
}
/**
* Deactivate a collection (soft delete).
*/
public function deactivate(string $collectionId): void
{
$stmt = $this->pdo->prepare('
UPDATE rag_collections
SET is_active = 0, is_searchable = 0
WHERE collection_id = ?
');
$stmt->execute([$collectionId]);
}
/**
* Check if collection is referenced by sessions, orders, or preferences.
*
* @return array{has_references: bool, references: array<int, array{type: string, count: int}>}
*/
public function checkReferences(string $collectionId): array
{
$references = [];
if ($this->pdoContent === null) {
return ['has_references' => false, 'references' => $references];
}
$jsonValue = json_encode($collectionId);
// Check chat_sessions (ki_content)
try {
$stmt = $this->pdoContent->prepare("
SELECT COUNT(*) FROM chat_sessions
WHERE JSON_CONTAINS(collections, ?, '$')
");
$stmt->execute([$jsonValue]);
$count = (int) $stmt->fetchColumn();
if ($count > 0) {
$references[] = ['type' => 'chat_sessions', 'count' => $count];
}
// Check content_orders (ki_content)
$stmt = $this->pdoContent->prepare("
SELECT COUNT(*) FROM content_orders
WHERE JSON_CONTAINS(collections, ?, '$')
");
$stmt->execute([$jsonValue]);
$count = (int) $stmt->fetchColumn();
if ($count > 0) {
$references[] = ['type' => 'content_orders', 'count' => $count];
}
} catch (\PDOException $e) {
// Tables might not exist yet
}
return [
'has_references' => count($references) > 0,
'references' => $references,
];
}
}