Protokoll #14810

ID14810
Zeitstempel2025-12-25 12:44:13.401980
Clientroot
IP145.224.72.140
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens3,339 (Input: 1,667, Output: 1,672)
Dauer90 ms
Request-Zeit2025-12-25 12:44:13.401980
Response-Zeit2025-12-25 12:44:13.491570

Request

{
    "event": "PreToolUse",
    "tool_name": "Write",
    "tool_input": {
        "file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Persistence\/DependencyGraphRepository.php",
        "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Persistence;\n\n\/\/ @responsibility: Persistenz für Dependency-Graph (code_dependencies Tabelle)\n\nuse Domain\\Repository\\DependencyGraphRepositoryInterface;\nuse PDO;\n\nclass DependencyGraphRepository implements DependencyGraphRepositoryInterface\n{\n    private PDO $pdo;\n\n    public function __construct(PDO $pdo)\n    {\n        $this->pdo = $pdo;\n    }\n\n    \/**\n     * Find all files that depend on a given FQCN (reverse lookup for impact analysis).\n     *\n     * @param string $fqcn The fully qualified class name to search for\n     * @param string|null $dependencyType Filter by type (use, extends, implements, trait, constructor)\n     * @return array<array{id: int, file_name: string, file_path: string, namespace: string|null, dependency_type: string}>\n     *\/\n    public function findDependents(string $fqcn, ?string $dependencyType = null): array\n    {\n        $sql = '\n            SELECT ca.id, ca.file_name, ca.file_path, ca.namespace, cd.dependency_type\n            FROM code_dependencies cd\n            JOIN code_analysis ca ON cd.analysis_id = ca.id\n            WHERE cd.target_fqcn = :fqcn\n        ';\n        $params = ['fqcn' => $fqcn];\n\n        if ($dependencyType !== null) {\n            $sql .= ' AND cd.dependency_type = :dep_type';\n            $params['dep_type'] = $dependencyType;\n        }\n\n        $sql .= ' ORDER BY ca.file_name';\n\n        $stmt = $this->pdo->prepare($sql);\n        $stmt->execute($params);\n\n        return $stmt->fetchAll(PDO::FETCH_ASSOC);\n    }\n\n    \/**\n     * Get all dependencies for a given analysis ID.\n     *\n     * @return array<array{dependency_type: string, target_fqcn: string}>\n     *\/\n    public function getDependencies(int $analysisId): array\n    {\n        $stmt = $this->pdo->prepare('\n            SELECT dependency_type, target_fqcn\n            FROM code_dependencies\n            WHERE analysis_id = :id\n            ORDER BY dependency_type, target_fqcn\n        ');\n        $stmt->execute(['id' => $analysisId]);\n\n        return $stmt->fetchAll(PDO::FETCH_ASSOC);\n    }\n\n    \/**\n     * Get dependency statistics.\n     *\n     * @return array{total_dependencies: int, by_type: array<string, int>, most_used: array<array{fqcn: string, count: int}>}\n     *\/\n    public function getDependencyStatistics(): array\n    {\n        \/\/ Total count\n        $stmt = $this->pdo->query('SELECT COUNT(*) FROM code_dependencies');\n        $total = (int) $stmt->fetchColumn();\n\n        \/\/ Count by type\n        $stmt = $this->pdo->query('\n            SELECT dependency_type, COUNT(*) as cnt\n            FROM code_dependencies\n            GROUP BY dependency_type\n        ');\n        $byType = [];\n        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {\n            $byType[$row['dependency_type']] = (int) $row['cnt'];\n        }\n\n        \/\/ Most used classes (top 20)\n        $stmt = $this->pdo->query('\n            SELECT target_fqcn as fqcn, COUNT(*) as count\n            FROM code_dependencies\n            GROUP BY target_fqcn\n            ORDER BY count DESC\n            LIMIT 20\n        ');\n        $mostUsed = $stmt->fetchAll(PDO::FETCH_ASSOC);\n\n        return [\n            'total_dependencies' => $total,\n            'by_type' => $byType,\n            'most_used' => $mostUsed,\n        ];\n    }\n\n    \/**\n     * Get global graph data for entire project.\n     *\n     * @return array{nodes: array<array<string, mixed>>, links: array<array<string, mixed>>, stats: array<string, int>}\n     *\/\n    public function getGlobalGraphData(): array\n    {\n        $nodes = [];\n        $links = [];\n        $nodeIndex = [];\n\n        \/\/ Get all files with classes\n        $stmt = $this->pdo->query('\n            SELECT id, file_name, namespace, classes, extends_class, extension\n            FROM code_analysis\n            WHERE classes IS NOT NULL AND classes != \"[]\"\n            ORDER BY namespace, file_name\n        ');\n\n        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {\n            $classes = json_decode($row['classes'], true);\n            if (empty($classes)) {\n                continue;\n            }\n\n            $className = $classes[0]['name'];\n            $fqcn = $row['namespace'] ? $row['namespace'] . '\\\\' . $className : $className;\n            $namespace = $row['namespace'] ?? 'global';\n\n            if (!isset($nodeIndex[$fqcn])) {\n                $nodeIndex[$fqcn] = count($nodes);\n                $nodes[] = [\n                    'id' => $fqcn,\n                    'label' => $className,\n                    'namespace' => $namespace,\n                    'fileId' => $row['id'],\n                    'type' => $classes[0]['type'] ?? 'class',\n                    'extension' => $row['extension'] ?? 'php',\n                ];\n            }\n        }\n\n        \/\/ Get all dependency relationships (internal only)\n        $stmt = $this->pdo->query('\n            SELECT cd.target_fqcn, cd.dependency_type, ca.namespace, ca.classes\n            FROM code_dependencies cd\n            JOIN code_analysis ca ON cd.analysis_id = ca.id\n            WHERE cd.dependency_type IN (\"extends\", \"implements\", \"constructor\", \"use\", \"trait\")\n        ');\n\n        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {\n            $classes = json_decode($row['classes'], true);\n            if (empty($classes)) {\n                continue;\n            }\n\n            $sourceClass = $classes[0]['name'];\n            $sourceFqcn = $row['namespace'] ? $row['namespace'] . '\\\\' . $sourceClass : $sourceClass;\n            $targetFqcn = $row['target_fqcn'];\n\n            \/\/ Only include if both nodes exist in project\n            if (isset($nodeIndex[$sourceFqcn]) && isset($nodeIndex[$targetFqcn])) {\n                $links[] = [\n                    'source' => $nodeIndex[$sourceFqcn],\n                    'target' => $nodeIndex[$targetFqcn],\n                    'type' => $row['dependency_type'],\n                ];\n            }\n        }\n\n        \/\/ Stats\n        $stats = [\n            'nodes' => count($nodes),\n            'links' => count($links),\n            'namespaces' => count(array_unique(array_column($nodes, 'namespace'))),\n        ];\n\n        return [\n            'nodes' => $nodes,\n            'links' => $links,\n            'stats' => $stats,\n        ];\n    }\n}\n"
    }
}

Response

{
    "tool_response": {
        "type": "create",
        "filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Persistence\/DependencyGraphRepository.php",
        "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Persistence;\n\n\/\/ @responsibility: Persistenz für Dependency-Graph (code_dependencies Tabelle)\n\nuse Domain\\Repository\\DependencyGraphRepositoryInterface;\nuse PDO;\n\nclass DependencyGraphRepository implements DependencyGraphRepositoryInterface\n{\n    private PDO $pdo;\n\n    public function __construct(PDO $pdo)\n    {\n        $this->pdo = $pdo;\n    }\n\n    \/**\n     * Find all files that depend on a given FQCN (reverse lookup for impact analysis).\n     *\n     * @param string $fqcn The fully qualified class name to search for\n     * @param string|null $dependencyType Filter by type (use, extends, implements, trait, constructor)\n     * @return array<array{id: int, file_name: string, file_path: string, namespace: string|null, dependency_type: string}>\n     *\/\n    public function findDependents(string $fqcn, ?string $dependencyType = null): array\n    {\n        $sql = '\n            SELECT ca.id, ca.file_name, ca.file_path, ca.namespace, cd.dependency_type\n            FROM code_dependencies cd\n            JOIN code_analysis ca ON cd.analysis_id = ca.id\n            WHERE cd.target_fqcn = :fqcn\n        ';\n        $params = ['fqcn' => $fqcn];\n\n        if ($dependencyType !== null) {\n            $sql .= ' AND cd.dependency_type = :dep_type';\n            $params['dep_type'] = $dependencyType;\n        }\n\n        $sql .= ' ORDER BY ca.file_name';\n\n        $stmt = $this->pdo->prepare($sql);\n        $stmt->execute($params);\n\n        return $stmt->fetchAll(PDO::FETCH_ASSOC);\n    }\n\n    \/**\n     * Get all dependencies for a given analysis ID.\n     *\n     * @return array<array{dependency_type: string, target_fqcn: string}>\n     *\/\n    public function getDependencies(int $analysisId): array\n    {\n        $stmt = $this->pdo->prepare('\n            SELECT dependency_type, target_fqcn\n            FROM code_dependencies\n            WHERE analysis_id = :id\n            ORDER BY dependency_type, target_fqcn\n        ');\n        $stmt->execute(['id' => $analysisId]);\n\n        return $stmt->fetchAll(PDO::FETCH_ASSOC);\n    }\n\n    \/**\n     * Get dependency statistics.\n     *\n     * @return array{total_dependencies: int, by_type: array<string, int>, most_used: array<array{fqcn: string, count: int}>}\n     *\/\n    public function getDependencyStatistics(): array\n    {\n        \/\/ Total count\n        $stmt = $this->pdo->query('SELECT COUNT(*) FROM code_dependencies');\n        $total = (int) $stmt->fetchColumn();\n\n        \/\/ Count by type\n        $stmt = $this->pdo->query('\n            SELECT dependency_type, COUNT(*) as cnt\n            FROM code_dependencies\n            GROUP BY dependency_type\n        ');\n        $byType = [];\n        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {\n            $byType[$row['dependency_type']] = (int) $row['cnt'];\n        }\n\n        \/\/ Most used classes (top 20)\n        $stmt = $this->pdo->query('\n            SELECT target_fqcn as fqcn, COUNT(*) as count\n            FROM code_dependencies\n            GROUP BY target_fqcn\n            ORDER BY count DESC\n            LIMIT 20\n        ');\n        $mostUsed = $stmt->fetchAll(PDO::FETCH_ASSOC);\n\n        return [\n            'total_dependencies' => $total,\n            'by_type' => $byType,\n            'most_used' => $mostUsed,\n        ];\n    }\n\n    \/**\n     * Get global graph data for entire project.\n     *\n     * @return array{nodes: array<array<string, mixed>>, links: array<array<string, mixed>>, stats: array<string, int>}\n     *\/\n    public function getGlobalGraphData(): array\n    {\n        $nodes = [];\n        $links = [];\n        $nodeIndex = [];\n\n        \/\/ Get all files with classes\n        $stmt = $this->pdo->query('\n            SELECT id, file_name, namespace, classes, extends_class, extension\n            FROM code_analysis\n            WHERE classes IS NOT NULL AND classes != \"[]\"\n            ORDER BY namespace, file_name\n        ');\n\n        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {\n            $classes = json_decode($row['classes'], true);\n            if (empty($classes)) {\n                continue;\n            }\n\n            $className = $classes[0]['name'];\n            $fqcn = $row['namespace'] ? $row['namespace'] . '\\\\' . $className : $className;\n            $namespace = $row['namespace'] ?? 'global';\n\n            if (!isset($nodeIndex[$fqcn])) {\n                $nodeIndex[$fqcn] = count($nodes);\n                $nodes[] = [\n                    'id' => $fqcn,\n                    'label' => $className,\n                    'namespace' => $namespace,\n                    'fileId' => $row['id'],\n                    'type' => $classes[0]['type'] ?? 'class',\n                    'extension' => $row['extension'] ?? 'php',\n                ];\n            }\n        }\n\n        \/\/ Get all dependency relationships (internal only)\n        $stmt = $this->pdo->query('\n            SELECT cd.target_fqcn, cd.dependency_type, ca.namespace, ca.classes\n            FROM code_dependencies cd\n            JOIN code_analysis ca ON cd.analysis_id = ca.id\n            WHERE cd.dependency_type IN (\"extends\", \"implements\", \"constructor\", \"use\", \"trait\")\n        ');\n\n        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {\n            $classes = json_decode($row['classes'], true);\n            if (empty($classes)) {\n                continue;\n            }\n\n            $sourceClass = $classes[0]['name'];\n            $sourceFqcn = $row['namespace'] ? $row['namespace'] . '\\\\' . $sourceClass : $sourceClass;\n            $targetFqcn = $row['target_fqcn'];\n\n            \/\/ Only include if both nodes exist in project\n            if (isset($nodeIndex[$sourceFqcn]) && isset($nodeIndex[$targetFqcn])) {\n                $links[] = [\n                    'source' => $nodeIndex[$sourceFqcn],\n                    'target' => $nodeIndex[$targetFqcn],\n                    'type' => $row['dependency_type'],\n                ];\n            }\n        }\n\n        \/\/ Stats\n        $stats = [\n            'nodes' => count($nodes),\n            'links' => count($links),\n            'namespaces' => count(array_unique(array_column($nodes, 'namespace'))),\n        ];\n\n        return [\n            'nodes' => $nodes,\n            'links' => $links,\n            'stats' => $stats,\n        ];\n    }\n}\n",
        "structuredPatch": [],
        "originalFile": null
    }
}
← Vorheriger Zur Liste Nächster →