private void scanPhpFile()

in doc-architect/doc-architect-core/src/main/java/com/docarchitect/core/scanner/impl/php/PhpInternalDependencyScanner.java [255:338]


    private void scanPhpFile(Path file, ScanContext context, List<Component> components,
                             List<Relationship> relationships, Set<String> processedClasses) throws IOException {
        String content = readFileContent(file);

        // Extract namespace
        String namespace = extractNamespace(content);

        // Build import map for resolving short class names
        Map<String, String> imports = buildImportMap(content);

        // Extract class definition
        Matcher classMatcher = findFirst(CLASS_DEFINITION_PATTERN, content);
        if (classMatcher == null) {
            return; // Not a class file
        }

        String classType = classMatcher.group(1); // class, interface, or trait
        String className = classMatcher.group(2);
        String extendsClause = classMatcher.group(3);
        String implementsClause = classMatcher.group(4);

        String fullyQualifiedName = buildFullyQualifiedName(namespace, className);

        // Skip if already processed
        if (processedClasses.contains(fullyQualifiedName)) {
            return;
        }
        processedClasses.add(fullyQualifiedName);

        // Create component
        Component component = createComponent(fullyQualifiedName, className, classType, file, context);
        components.add(component);

        // Extract dependencies

        // 1. Use statement imports (but only track the ones that are actually used)
        for (Map.Entry<String, String> importEntry : imports.entrySet()) {
            String importedClass = importEntry.getValue();
            // Only add import relationship if the imported class is used in the file
            // beyond just the use statement itself
            String shortName = importEntry.getKey();
            if (isClassUsed(content, shortName, importedClass)) {
                relationships.add(createRelationship(
                    fullyQualifiedName, importedClass, DEPENDENCY_TYPE_IMPORT,
                    "Imports " + importedClass
                ));
            }
        }

        // 2. Class inheritance
        if (extendsClause != null && !extendsClause.isBlank()) {
            String parentClass = resolveClassName(extendsClause.trim(), namespace, imports);
            relationships.add(createRelationship(
                fullyQualifiedName, parentClass, DEPENDENCY_TYPE_INHERITANCE,
                "Extends " + parentClass
            ));
        }

        // 3. Interface implementations
        if (implementsClause != null && !implementsClause.isBlank()) {
            for (String interfaceName : implementsClause.split(",")) {
                String trimmed = interfaceName.trim();
                if (!trimmed.isEmpty()) {
                    String resolvedInterface = resolveClassName(trimmed, namespace, imports);
                    relationships.add(createRelationship(
                        fullyQualifiedName, resolvedInterface, DEPENDENCY_TYPE_INTERFACE,
                        "Implements " + resolvedInterface
                    ));
                }
            }
        }

        // 4. Trait usage
        extractTraitDependencies(content, fullyQualifiedName, namespace, imports, relationships);

        // 5. Constructor injection
        extractConstructorDependencies(content, fullyQualifiedName, namespace, imports, relationships);

        // 6. Method injection (setter injection)
        extractMethodInjectionDependencies(content, fullyQualifiedName, namespace, imports, relationships);

        // 7. Laravel container bindings
        extractContainerBindings(content, fullyQualifiedName, namespace, imports, relationships);
    }