{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/CodeAnalysisController.php",
"oldString": " private function shortClassName(string $fqcn): string",
"newString": " public function globalGraph(): void\n {\n $this->view('docs.code-graph-global', [\n 'title' => 'Projekt Dependency Graph',\n ]);\n }\n\n public function globalGraphData(): void\n {\n $stats = $this->useCase->getGlobalGraphData();\n $this->json($stats);\n }\n\n private function shortClassName(string $fqcn): string",
"originalFile": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Controller;\n\n\/\/ @responsibility: HTTP-Endpunkte für Code-Analyse\n\nuse Framework\\Controller;\nuse UseCases\\CodeAnalysis\\GetCodeAnalysisUseCase;\n\nclass CodeAnalysisController extends Controller\n{\n public function __construct(\n private GetCodeAnalysisUseCase $useCase\n ) {\n }\n\n public function index(): void\n {\n $filters = array_filter([\n 'directory' => $this->getString('directory'),\n 'namespace' => $this->getString('namespace'),\n 'extension' => $this->getString('extension'),\n 'search' => $this->getString('search'),\n 'has_classes' => $this->getString('has_classes'),\n ], fn ($v) => $v !== '');\n\n $this->view('docs.code', [\n 'title' => 'Code-Analyse',\n 'stats' => $this->useCase->getStatistics(),\n 'files' => $this->useCase->execute($filters, 200, 0),\n 'filterOptions' => $this->useCase->getFilterOptions(),\n 'currentFilters' => $filters,\n ]);\n }\n\n public function show(string $id): void\n {\n $file = $this->useCase->findById((int) $id);\n\n if ($file === null) {\n $this->notFound('Datei nicht gefunden');\n }\n\n $classes = json_decode($file['classes'] ?? '[]', true);\n $functions = json_decode($file['functions'] ?? '[]', true);\n $uses = json_decode($file['uses'] ?? '[]', true);\n $implements = json_decode($file['implements_interfaces'] ?? '[]', true);\n $traits = json_decode($file['traits_used'] ?? '[]', true);\n $constructorDeps = json_decode($file['constructor_deps'] ?? '[]', true);\n\n \/\/ Build FQCN for reverse lookup\n $dependents = [];\n if (!empty($classes)) {\n $namespace = $file['namespace'] ?? '';\n $className = $classes[0]['name'];\n $fqcn = $namespace ? $namespace . '\\\\' . $className : $className;\n $dependents = $this->useCase->findDependents($fqcn);\n }\n\n $this->view('docs.code-show', [\n 'title' => $file['file_name'],\n 'file' => $file,\n 'classes' => $classes,\n 'functions' => $functions,\n 'uses' => $uses,\n 'extendsClass' => $file['extends_class'],\n 'implements' => $implements,\n 'traits' => $traits,\n 'constructorDeps' => $constructorDeps,\n 'dependents' => $dependents,\n ]);\n }\n\n public function scan(): void\n {\n $this->requireCsrf();\n\n $result = $this->useCase->runScan('web');\n\n $this->json([\n 'success' => true,\n 'scan_id' => $result['scan_id'],\n 'files_scanned' => $result['files_scanned'],\n 'files_with_errors' => $result['files_with_errors'],\n 'total_classes' => $result['total_classes'],\n 'total_functions' => $result['total_functions'],\n 'duration_ms' => $result['duration_ms'],\n ]);\n }\n\n public function graph(string $id): void\n {\n $file = $this->useCase->findById((int) $id);\n\n if ($file === null) {\n $this->notFound('Datei nicht gefunden');\n }\n\n $classes = json_decode($file['classes'] ?? '[]', true);\n $namespace = $file['namespace'] ?? '';\n $className = !empty($classes) ? $classes[0]['name'] : $file['file_name'];\n $fqcn = $namespace ? $namespace . '\\\\' . $className : $className;\n\n $this->view('docs.code-graph', [\n 'title' => 'Dependency Graph: ' . $className,\n 'file' => $file,\n 'fqcn' => $fqcn,\n ]);\n }\n\n public function graphData(string $id): void\n {\n $file = $this->useCase->findById((int) $id);\n\n if ($file === null) {\n $this->json(['error' => 'Not found'], 404);\n\n return;\n }\n\n $classes = json_decode($file['classes'] ?? '[]', true);\n $uses = json_decode($file['uses'] ?? '[]', true);\n $namespace = $file['namespace'] ?? '';\n $className = !empty($classes) ? $classes[0]['name'] : $file['file_name'];\n $fqcn = $namespace ? $namespace . '\\\\' . $className : $className;\n\n $nodes = [];\n $links = [];\n\n \/\/ Central node\n $nodes[] = [\n 'id' => $fqcn,\n 'label' => $className,\n 'type' => 'center',\n 'fileId' => $file['id'],\n ];\n\n \/\/ Dependencies (outgoing)\n if ($file['extends_class']) {\n $shortName = $this->shortClassName($file['extends_class']);\n $nodes[] = ['id' => $file['extends_class'], 'label' => $shortName, 'type' => 'extends'];\n $links[] = ['source' => $fqcn, 'target' => $file['extends_class'], 'type' => 'extends'];\n }\n\n foreach (json_decode($file['implements_interfaces'] ?? '[]', true) as $iface) {\n $shortName = $this->shortClassName($iface);\n $nodes[] = ['id' => $iface, 'label' => $shortName, 'type' => 'implements'];\n $links[] = ['source' => $fqcn, 'target' => $iface, 'type' => 'implements'];\n }\n\n foreach (json_decode($file['constructor_deps'] ?? '[]', true) as $dep) {\n $shortName = $this->shortClassName($dep);\n $nodes[] = ['id' => $dep, 'label' => $shortName, 'type' => 'constructor'];\n $links[] = ['source' => $fqcn, 'target' => $dep, 'type' => 'constructor'];\n }\n\n \/\/ Dependents (incoming) - limit to 20\n $dependents = $this->useCase->findDependents($fqcn);\n $count = 0;\n foreach ($dependents as $dep) {\n if ($count >= 20) {\n break;\n }\n $depFqcn = $dep['namespace'] ? $dep['namespace'] . '\\\\' . pathinfo($dep['file_name'], PATHINFO_FILENAME) : $dep['file_name'];\n $shortName = pathinfo($dep['file_name'], PATHINFO_FILENAME);\n\n if (!$this->nodeExists($nodes, $depFqcn)) {\n $nodes[] = ['id' => $depFqcn, 'label' => $shortName, 'type' => 'dependent', 'fileId' => $dep['id']];\n }\n $links[] = ['source' => $depFqcn, 'target' => $fqcn, 'type' => $dep['dependency_type']];\n $count++;\n }\n\n \/\/ Deduplicate nodes\n $uniqueNodes = [];\n foreach ($nodes as $node) {\n $uniqueNodes[$node['id']] = $node;\n }\n\n $this->json([\n 'nodes' => array_values($uniqueNodes),\n 'links' => $links,\n 'center' => $fqcn,\n ]);\n }\n\n private function shortClassName(string $fqcn): string\n {\n $parts = explode('\\\\', $fqcn);\n\n return end($parts);\n }\n\n \/**\n * @param array<array<string, mixed>> $nodes\n *\/\n private function nodeExists(array $nodes, string $id): bool\n {\n foreach ($nodes as $node) {\n if ($node['id'] === $id) {\n return true;\n }\n }\n\n return false;\n }\n}\n",
"structuredPatch": [
{
"oldStart": 186,
"oldLines": 6,
"newStart": 186,
"newLines": 19,
"lines": [
" ]);",
" }",
" ",
"+ public function globalGraph(): void",
"+ {",
"+ $this->view('docs.code-graph-global', [",
"+ 'title' => 'Projekt Dependency Graph',",
"+ ]);",
"+ }",
"+",
"+ public function globalGraphData(): void",
"+ {",
"+ $stats = $this->useCase->getGlobalGraphData();",
"+ $this->json($stats);",
"+ }",
"+",
" private function shortClassName(string $fqcn): string",
" {",
" $parts = explode('\\\\', $fqcn);"
]
}
],
"userModified": false,
"replaceAll": false
}
}