Backup #946

ID946
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/CodeAnalysisController.php
Version9
Typ modified
Größe7.6 KB
Hasha16436bc3069804d50686eebce9a6c07c61719ecd86dfd48b5fb6d267e99853c
Datum2025-12-23 22:06:07
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

declare(strict_types=1);

namespace Controller;

// @responsibility: HTTP-Endpunkte für Code-Analyse

use Framework\Controller;
use Infrastructure\Persistence\FileBackupRepository;
use UseCases\CodeAnalysis\GetCodeAnalysisUseCase;

class CodeAnalysisController extends Controller
{
    public function __construct(
        private GetCodeAnalysisUseCase $useCase,
        private FileBackupRepository $backupRepo
    ) {
    }

    public function index(): void
    {
        $filters = array_filter([
            'directory' => $this->getString('directory'),
            'namespace' => $this->getString('namespace'),
            'extension' => $this->getString('extension'),
            'search' => $this->getString('search'),
            'has_classes' => $this->getString('has_classes'),
        ], fn ($v) => $v !== '');

        $this->view('docs.code', [
            'title' => 'Code-Analyse',
            'stats' => $this->useCase->getStatistics(),
            'files' => $this->useCase->execute($filters, 200, 0),
            'filterOptions' => $this->useCase->getFilterOptions(),
            'currentFilters' => $filters,
        ]);
    }

    public function show(string $id): void
    {
        $file = $this->useCase->findById((int) $id);

        if ($file === null) {
            $this->notFound('Datei nicht gefunden');
        }

        $classes = json_decode($file['classes'] ?? '[]', true);
        $functions = json_decode($file['functions'] ?? '[]', true);
        $uses = json_decode($file['uses'] ?? '[]', true);
        $implements = json_decode($file['implements_interfaces'] ?? '[]', true);
        $traits = json_decode($file['traits_used'] ?? '[]', true);
        $constructorDeps = json_decode($file['constructor_deps'] ?? '[]', true);

        // Build FQCN for reverse lookup
        $dependents = [];
        if (!empty($classes)) {
            $namespace = $file['namespace'] ?? '';
            $className = $classes[0]['name'];
            $fqcn = $namespace ? $namespace . '\\' . $className : $className;
            $dependents = $this->useCase->findDependents($fqcn);
        }

        // Current file content
        $fileContent = '';
        if (file_exists($file['file_path'])) {
            $fileContent = file_get_contents($file['file_path']);
        }

        // Backup history
        $backupHistory = $this->backupRepo->findByFilePath($file['file_path']);

        $this->view('docs.code-show', [
            'title' => $file['file_name'],
            'file' => $file,
            'classes' => $classes,
            'functions' => $functions,
            'uses' => $uses,
            'extendsClass' => $file['extends_class'],
            'implements' => $implements,
            'traits' => $traits,
            'constructorDeps' => $constructorDeps,
            'dependents' => $dependents,
            'fileContent' => $fileContent,
            'backupHistory' => $backupHistory,
        ]);
    }

    public function scan(): void
    {
        $this->requireCsrf();

        $result = $this->useCase->runScan('web');

        $this->json([
            'success' => true,
            'scan_id' => $result['scan_id'],
            'files_scanned' => $result['files_scanned'],
            'files_with_errors' => $result['files_with_errors'],
            'total_classes' => $result['total_classes'],
            'total_functions' => $result['total_functions'],
            'duration_ms' => $result['duration_ms'],
        ]);
    }

    public function graph(string $id): void
    {
        $file = $this->useCase->findById((int) $id);

        if ($file === null) {
            $this->notFound('Datei nicht gefunden');
        }

        $classes = json_decode($file['classes'] ?? '[]', true);
        $namespace = $file['namespace'] ?? '';
        $className = !empty($classes) ? $classes[0]['name'] : $file['file_name'];
        $fqcn = $namespace ? $namespace . '\\' . $className : $className;

        $this->view('docs.code-graph', [
            'title' => 'Dependency Graph: ' . $className,
            'file' => $file,
            'fqcn' => $fqcn,
        ]);
    }

    public function graphData(string $id): void
    {
        $file = $this->useCase->findById((int) $id);

        if ($file === null) {
            $this->json(['error' => 'Not found'], 404);

            return;
        }

        $classes = json_decode($file['classes'] ?? '[]', true);
        $uses = json_decode($file['uses'] ?? '[]', true);
        $namespace = $file['namespace'] ?? '';
        $className = !empty($classes) ? $classes[0]['name'] : $file['file_name'];
        $fqcn = $namespace ? $namespace . '\\' . $className : $className;

        $nodes = [];
        $links = [];

        // Central node
        $nodes[] = [
            'id' => $fqcn,
            'label' => $className,
            'type' => 'center',
            'fileId' => $file['id'],
        ];

        // Dependencies (outgoing)
        if ($file['extends_class']) {
            $shortName = $this->shortClassName($file['extends_class']);
            $nodes[] = ['id' => $file['extends_class'], 'label' => $shortName, 'type' => 'extends'];
            $links[] = ['source' => $fqcn, 'target' => $file['extends_class'], 'type' => 'extends'];
        }

        foreach (json_decode($file['implements_interfaces'] ?? '[]', true) as $iface) {
            $shortName = $this->shortClassName($iface);
            $nodes[] = ['id' => $iface, 'label' => $shortName, 'type' => 'implements'];
            $links[] = ['source' => $fqcn, 'target' => $iface, 'type' => 'implements'];
        }

        foreach (json_decode($file['constructor_deps'] ?? '[]', true) as $dep) {
            $shortName = $this->shortClassName($dep);
            $nodes[] = ['id' => $dep, 'label' => $shortName, 'type' => 'constructor'];
            $links[] = ['source' => $fqcn, 'target' => $dep, 'type' => 'constructor'];
        }

        // Dependents (incoming) - limit to 20
        $dependents = $this->useCase->findDependents($fqcn);
        $count = 0;
        foreach ($dependents as $dep) {
            if ($count >= 20) {
                break;
            }
            $depFqcn = $dep['namespace'] ? $dep['namespace'] . '\\' . pathinfo($dep['file_name'], PATHINFO_FILENAME) : $dep['file_name'];
            $shortName = pathinfo($dep['file_name'], PATHINFO_FILENAME);

            if (!$this->nodeExists($nodes, $depFqcn)) {
                $nodes[] = ['id' => $depFqcn, 'label' => $shortName, 'type' => 'dependent', 'fileId' => $dep['id']];
            }
            $links[] = ['source' => $depFqcn, 'target' => $fqcn, 'type' => $dep['dependency_type']];
            $count++;
        }

        // Deduplicate nodes
        $uniqueNodes = [];
        foreach ($nodes as $node) {
            $uniqueNodes[$node['id']] = $node;
        }

        $this->json([
            'nodes' => array_values($uniqueNodes),
            'links' => $links,
            'center' => $fqcn,
        ]);
    }

    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);

        return end($parts);
    }

    /**
     * @param array<array<string, mixed>> $nodes
     */
    private function nodeExists(array $nodes, string $id): bool
    {
        foreach ($nodes as $node) {
            if ($node['id'] === $id) {
                return true;
            }
        }

        return false;
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
1993 14 modified 7.3 KB 2025-12-28 09:41
1355 13 modified 7.3 KB 2025-12-25 16:31
1269 12 modified 7.3 KB 2025-12-25 12:51
952 11 modified 8.0 KB 2025-12-23 22:08
947 10 modified 8.0 KB 2025-12-23 22:06
946 9 modified 7.6 KB 2025-12-23 22:06
944 8 modified 7.6 KB 2025-12-23 22:00
943 7 modified 7.2 KB 2025-12-23 21:59
942 6 modified 7.1 KB 2025-12-23 21:59
891 5 modified 6.8 KB 2025-12-23 15:40
889 4 modified 2.9 KB 2025-12-23 15:35
885 3 modified 2.6 KB 2025-12-23 15:27
882 2 modified 2.1 KB 2025-12-23 15:21
876 1 modified 2.1 KB 2025-12-23 09:35

← Zurück zur Übersicht