Backup #1602
| ID | 1602 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Infrastructure/Persistence/StopwordRepository.php |
| Version | 1 |
| Typ |
modified |
| Größe | 5.8 KB |
| Hash | 7e31dc8759dee6fc227bfc02d482f7f3f05464f3c00a4d346906b63d1f9694b8 |
| Datum | 2025-12-27 00:19:04 |
| 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: CRUD-Operationen für Stopwords (Entity-Extraction Filter)
use Domain\Repository\StopwordRepositoryInterface;
use PDO;
final class StopwordRepository implements StopwordRepositoryInterface
{
private PDO $db;
/** @var array<string>|null Cached canonical forms */
private ?array $canonicalCache = null;
public function __construct(PDO $pdo)
{
$this->db = $pdo;
}
/**
* {@inheritDoc}
*/
public function findAll(bool $activeOnly = true, ?string $category = null): array
{
$sql = 'SELECT * FROM stopwords WHERE 1=1';
$params = [];
if ($activeOnly) {
$sql .= ' AND is_active = 1';
}
if ($category !== null) {
$sql .= ' AND category = :category';
$params['category'] = $category;
}
$sql .= ' ORDER BY word ASC';
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
/**
* {@inheritDoc}
*/
public function find(int $id): ?array
{
$stmt = $this->db->prepare('SELECT * FROM stopwords WHERE id = :id');
$stmt->execute(['id' => $id]);
$result = $stmt->fetch();
return $result === false ? null : $result;
}
/**
* {@inheritDoc}
*/
public function getCanonicalForms(bool $activeOnly = true): array
{
if ($this->canonicalCache !== null && $activeOnly) {
return $this->canonicalCache;
}
$sql = 'SELECT canonical_form FROM stopwords';
if ($activeOnly) {
$sql .= ' WHERE is_active = 1';
}
$stmt = $this->db->query($sql);
$forms = $stmt->fetchAll(PDO::FETCH_COLUMN);
if ($activeOnly) {
$this->canonicalCache = $forms;
}
return $forms;
}
/**
* {@inheritDoc}
*/
public function isStopword(string $word): bool
{
$canonical = $this->normalize($word);
$forms = $this->getCanonicalForms();
return in_array($canonical, $forms, true);
}
/**
* {@inheritDoc}
*/
public function create(array $data): int
{
$canonical = $this->normalize($data['word'] ?? '');
$stmt = $this->db->prepare(
'INSERT INTO stopwords (word, canonical_form, category, reason, is_active)
VALUES (:word, :canonical, :category, :reason, :active)'
);
$stmt->execute([
'word' => $data['word'],
'canonical' => $canonical,
'category' => $data['category'] ?? 'generic',
'reason' => $data['reason'] ?? null,
'active' => $data['is_active'] ?? 1,
]);
$this->canonicalCache = null;
return (int) $this->db->lastInsertId();
}
/**
* {@inheritDoc}
*/
public function update(int $id, array $data): bool
{
$sets = [];
$params = ['id' => $id];
if (isset($data['word'])) {
$sets[] = 'word = :word';
$sets[] = 'canonical_form = :canonical';
$params['word'] = $data['word'];
$params['canonical'] = $this->normalize($data['word']);
}
if (isset($data['category'])) {
$sets[] = 'category = :category';
$params['category'] = $data['category'];
}
if (array_key_exists('reason', $data)) {
$sets[] = 'reason = :reason';
$params['reason'] = $data['reason'];
}
if (isset($data['is_active'])) {
$sets[] = 'is_active = :active';
$params['active'] = $data['is_active'];
}
if ($sets === []) {
return false;
}
$sql = 'UPDATE stopwords SET ' . implode(', ', $sets) . ' WHERE id = :id';
$stmt = $this->db->prepare($sql);
$result = $stmt->execute($params);
$this->canonicalCache = null;
return $result && $stmt->rowCount() > 0;
}
/**
* {@inheritDoc}
*/
public function delete(int $id): bool
{
$stmt = $this->db->prepare('DELETE FROM stopwords WHERE id = :id');
$result = $stmt->execute(['id' => $id]);
$this->canonicalCache = null;
return $result && $stmt->rowCount() > 0;
}
/**
* {@inheritDoc}
*/
public function toggleActive(int $id): bool
{
$stmt = $this->db->prepare(
'UPDATE stopwords SET is_active = NOT is_active WHERE id = :id'
);
$result = $stmt->execute(['id' => $id]);
$this->canonicalCache = null;
return $result && $stmt->rowCount() > 0;
}
/**
* {@inheritDoc}
*/
public function getStats(): array
{
$stmt = $this->db->query(
'SELECT category, COUNT(*) as count, SUM(is_active) as active
FROM stopwords GROUP BY category'
);
$stats = ['total' => 0, 'active' => 0, 'by_category' => []];
foreach ($stmt->fetchAll() as $row) {
$stats['by_category'][$row['category']] = [
'count' => (int) $row['count'],
'active' => (int) $row['active'],
];
$stats['total'] += (int) $row['count'];
$stats['active'] += (int) $row['active'];
}
return $stats;
}
/**
* Normalize word to canonical form.
*/
private function normalize(string $word): string
{
$result = mb_strtolower(trim($word));
// German umlauts
$replacements = [
'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'ß' => 'ss',
];
$result = str_replace(array_keys($replacements), array_values($replacements), $result);
// Remove special chars, keep only alphanumeric and underscore
$result = preg_replace('/[^a-z0-9_]/', '', $result);
return $result ?? '';
}
}
Vollständig herunterladen
Aktionen
← Zurück zur Übersicht