OntologyRepository.php

Code Hygiene Score: 100

Keine Issues gefunden.

Dependencies 4

Klassen 1

Funktionen 10

Verwendet von 1

Versionen 3

Code

<?php

declare(strict_types=1);

namespace Infrastructure\Persistence;

// @responsibility: CRUD-Operationen für Ontologie-Klassen (Hierarchie + JSON-Properties)

use Domain\Repository\OntologyRepositoryInterface;
use PDO;

final class OntologyRepository implements OntologyRepositoryInterface
{
    private PDO $db;

    public function __construct(PDO $pdo)
    {
        $this->db = $pdo;
    }

    /**
     * {@inheritDoc}
     */
    public function findAll(): array
    {
        return $this->db->query(
            'SELECT oc.*,
                    COUNT(DISTINCT ec.entity_id) as entity_count,
                    (SELECT COUNT(*) FROM ontology_classes WHERE parent_class_id = oc.id) as subclass_count
             FROM ontology_classes oc
             LEFT JOIN entity_classifications ec ON oc.id = ec.ontology_class_id
             GROUP BY oc.id
             ORDER BY oc.name'
        )->fetchAll();
    }

    /**
     * {@inheritDoc}
     */
    public function getStats(): array
    {
        $result = $this->db->query(
            'SELECT
                (SELECT COUNT(*) FROM ontology_classes) as total_classes,
                (SELECT COUNT(*) FROM ontology_classes WHERE parent_class_id IS NULL) as root_classes,
                (SELECT COUNT(DISTINCT entity_id) FROM entity_classifications) as classified_entities'
        )->fetch();

        return $result !== false ? $result : [
            'total_classes' => 0,
            'root_classes' => 0,
            'classified_entities' => 0,
        ];
    }

    /**
     * {@inheritDoc}
     */
    public function find(int $id): ?array
    {
        $stmt = $this->db->prepare('SELECT * FROM ontology_classes WHERE id = :id');
        $stmt->execute(['id' => $id]);
        $result = $stmt->fetch();

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

    /**
     * {@inheritDoc}
     */
    public function create(string $name, ?int $parentId = null, ?string $description = null, array $properties = []): int
    {
        $stmt = $this->db->prepare(
            'INSERT INTO ontology_classes (name, parent_class_id, description, properties, created_at)
             VALUES (:name, :parent, :description, :properties, NOW())'
        );
        $stmt->execute([
            'name' => $name,
            'parent' => $parentId,
            'description' => $description,
            'properties' => json_encode($properties),
        ]);

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

    /**
     * {@inheritDoc}
     */
    public function update(int $id, string $name, ?int $parentId = null, ?string $description = null, array $properties = []): bool
    {
        $stmt = $this->db->prepare(
            'UPDATE ontology_classes SET name = :name, parent_class_id = :parent,
             description = :description, properties = :properties WHERE id = :id'
        );

        return $stmt->execute([
            'id' => $id,
            'name' => $name,
            'parent' => $parentId,
            'description' => $description,
            'properties' => json_encode($properties),
        ]);
    }

    /**
     * {@inheritDoc}
     */
    public function delete(int $id): bool
    {
        // Check for subclasses
        $stmt = $this->db->prepare('SELECT COUNT(*) FROM ontology_classes WHERE parent_class_id = :id');
        $stmt->execute(['id' => $id]);

        if ((int) $stmt->fetchColumn() > 0) {
            return false; // Has subclasses, cannot delete
        }

        // Delete entity classifications
        $stmt = $this->db->prepare('DELETE FROM entity_classifications WHERE ontology_class_id = :id');
        $stmt->execute(['id' => $id]);

        // Delete class
        $stmt = $this->db->prepare('DELETE FROM ontology_classes WHERE id = :id');

        return $stmt->execute(['id' => $id]);
    }

    /**
     * {@inheritDoc}
     */
    public function findForSelect(): array
    {
        return $this->db->query('SELECT id, name FROM ontology_classes ORDER BY name')->fetchAll();
    }

    /**
     * {@inheritDoc}
     */
    public function findClassifiedEntities(string $search = '', string $classFilter = '', int $limit = 50, int $offset = 0): array
    {
        $sql = 'SELECT e.id as entity_id, e.name as entity_name, e.type as entity_type,
                       e.description, e.canonical_name,
                       oc.id as class_id, oc.name as class_name,
                       ec.confidence,
                       GROUP_CONCAT(DISTINCT CONCAT(er.relation_type, ":", e2.name) SEPARATOR ", ") as relations
                FROM entities e
                INNER JOIN entity_classifications ec ON e.id = ec.entity_id
                INNER JOIN ontology_classes oc ON ec.ontology_class_id = oc.id
                LEFT JOIN entity_relations er ON e.id = er.source_entity_id
                LEFT JOIN entities e2 ON er.target_entity_id = e2.id
                WHERE 1=1';

        $params = [];

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

        if ($classFilter !== '') {
            $sql .= ' AND oc.id = :class_id';
            $params['class_id'] = $classFilter;
        }

        $sql .= ' GROUP BY e.id, e.name, e.type, e.description, e.canonical_name, oc.id, oc.name, ec.confidence';
        $sql .= ' ORDER BY oc.name, e.name LIMIT ' . $limit . ' OFFSET ' . $offset;

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

        return $stmt->fetchAll();
    }

    /**
     * {@inheritDoc}
     */
    public function countClassifiedEntities(string $search = '', string $classFilter = ''): int
    {
        $sql = 'SELECT COUNT(DISTINCT e.id)
                FROM entities e
                INNER JOIN entity_classifications ec ON e.id = ec.entity_id
                INNER JOIN ontology_classes oc ON ec.ontology_class_id = oc.id
                WHERE 1=1';

        $params = [];

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

        if ($classFilter !== '') {
            $sql .= ' AND oc.id = :class_id';
            $params['class_id'] = $classFilter;
        }

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

        return (int) $stmt->fetchColumn();
    }
}
← Übersicht Graph