#!/usr/bin/env php getExtension()), $extensions)) { $files[] = $file->getPathname(); } } return $files; } function extract_declarations($content) { $declarations = []; // Extract classes if (preg_match_all('/^\s*(?:abstract\s+)?class\s+(\w+)/m', $content, $matches)) { foreach ($matches[1] as $class) { $declarations['classes'][$class][] = 'class'; } } // Extract interfaces if (preg_match_all('/^\s*interface\s+(\w+)/m', $content, $matches)) { foreach ($matches[1] as $interface) { $declarations['interfaces'][$interface][] = 'interface'; } } // Extract traits if (preg_match_all('/^\s*trait\s+(\w+)/m', $content, $matches)) { foreach ($matches[1] as $trait) { $declarations['traits'][$trait][] = 'trait'; } } // Extract functions (non-namespaced) if (preg_match_all('/^\s*function\s+(\w+)/m', $content, $matches)) { foreach ($matches[1] as $function) { if (!isset($declarations['functions'][$function])) { $declarations['functions'][$function] = []; } } } return $declarations; } function check_duplicate_classes($files) { $all_classes = []; $duplicates = []; foreach ($files as $file) { $content = file_get_contents($file); // Check for classes if (preg_match_all('/^\s*(?:abstract\s+)?class\s+(\w+)/m', $content, $matches)) { foreach ($matches[1] as $class) { if (!isset($all_classes[$class])) { $all_classes[$class] = []; } $all_classes[$class][] = $file; } } // Check for interfaces if (preg_match_all('/^\s*interface\s+(\w+)/m', $content, $matches)) { foreach ($matches[1] as $interface) { $key = strtolower($interface); if (!isset($all_classes[$key])) { $all_classes[$key] = []; } $all_classes[$key][] = $file; } } } foreach ($all_classes as $name => $files_list) { if (count($files_list) > 1) { $duplicates['classes'][$name] = $files_list; } } return $duplicates; } function check_duplicate_functions($files) { $all_functions = []; $duplicates = []; foreach ($files as $file) { $content = file_get_contents($file); // Skip content inside classes, interfaces, and traits $content = preg_replace('/class\s+\w+\s*\{[^}]*\}/s', '', $content); $content = preg_replace('/interface\s+\w+\s*\{[^}]*\}/s', '', $content); $content = preg_replace('/trait\s+\w+\s*\{[^}]*\}/s', '', $content); if (preg_match_all('/^\s*function\s+(\w+)\s*\(/m', $content, $matches)) { foreach ($matches[1] as $function) { if (!isset($all_functions[$function])) { $all_functions[$function] = []; } $all_functions[$function][] = $file; } } } foreach ($all_functions as $name => $files_list) { if (count($files_list) > 1) { $duplicates['functions'][$name] = $files_list; } } return $duplicates; } echo "Scanning directory: $plugin_dir\n"; $files = scan_directory($plugin_dir); echo "Found " . count($files) . " PHP files\n\n"; $class_duplicates = check_duplicate_classes($files); $function_duplicates = check_duplicate_functions($files); $has_issues = false; if (!empty($class_duplicates['classes'])) { $has_issues = true; echo "❌ Duplicate class/interface declarations found:\n"; foreach ($class_duplicates['classes'] as $name => $files_list) { echo " - $name found in:\n"; foreach ($files_list as $file) { echo " $file\n"; } } echo "\n"; } if (!empty($function_duplicates['functions'])) { $has_issues = true; echo "⚠️ Potential duplicate function declarations:\n"; foreach ($function_duplicates['functions'] as $name => $files_list) { echo " - $name() found in:\n"; foreach ($files_list as $file) { echo " $file\n"; } } echo "\n"; } if (!$has_issues) { echo "✅ No duplicate declarations found\n"; } else { echo "⚠️ Please review the duplicates above and fix them.\n"; echo " Solutions:\n"; echo " - Use class_exists() guards around class definitions\n"; echo " - Consolidate duplicate declarations into one file\n"; echo " - Namespace conflicting classes differently\n"; } echo "\n=== Check Complete ===\n"; exit($has_issues ? 1 : 0);