- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
290 lines
11 KiB
PHP
290 lines
11 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Test script for the refactored Discovery module
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Cache\Driver\InMemoryCache;
|
|
use App\Framework\Cache\GeneralCache;
|
|
use App\Framework\Core\PathProvider;
|
|
use App\Framework\DateTime\SystemClock;
|
|
use App\Framework\Discovery\UnifiedDiscoveryService;
|
|
use App\Framework\Discovery\ValueObjects\DiscoveryOptions;
|
|
use App\Framework\Discovery\ValueObjects\ScanType;
|
|
use App\Framework\Filesystem\FileSystemService;
|
|
use App\Framework\Logging\DefaultLogger;
|
|
use App\Framework\Logging\Handlers\ConsoleHandler;
|
|
use App\Framework\Logging\LogLevel;
|
|
use App\Framework\Performance\MemoryMonitor;
|
|
use App\Framework\Reflection\CachedReflectionProvider;
|
|
use App\Framework\Serializer\Php\PhpSerializer;
|
|
|
|
echo "🔍 Testing Refactored Discovery Module\n";
|
|
echo "=====================================\n";
|
|
|
|
try {
|
|
// Setup dependencies
|
|
$pathProvider = new PathProvider(__DIR__ . '/../..');
|
|
$cacheDriver = new InMemoryCache();
|
|
$serializer = new PhpSerializer();
|
|
$cache = new GeneralCache($cacheDriver, $serializer);
|
|
$clock = new SystemClock();
|
|
$reflectionProvider = new CachedReflectionProvider();
|
|
$fileSystemService = new FileSystemService();
|
|
$memoryMonitor = new MemoryMonitor();
|
|
|
|
// Setup logger
|
|
$consoleHandler = new ConsoleHandler();
|
|
$logger = new DefaultLogger(LogLevel::INFO, [$consoleHandler]);
|
|
|
|
echo "✅ Dependencies initialized\n";
|
|
|
|
// Create discovery service with new architecture
|
|
$discoveryService = new UnifiedDiscoveryService(
|
|
pathProvider: $pathProvider,
|
|
cache: $cache,
|
|
clock: $clock,
|
|
reflectionProvider: $reflectionProvider,
|
|
attributeMappers: [], // Add specific mappers if needed
|
|
targetInterfaces: [], // Add specific interfaces if needed
|
|
useCache: false, // Disable cache for testing
|
|
contextSuffix: '_test',
|
|
logger: $logger,
|
|
eventDispatcher: null,
|
|
memoryMonitor: $memoryMonitor,
|
|
fileSystemService: $fileSystemService
|
|
);
|
|
|
|
// Test single directory to debug
|
|
echo "\n🔍 Debug: Let's first check if files are being processed properly\n";
|
|
|
|
// Test if the Admin directory has PHP files
|
|
$adminDir = $pathProvider->getBasePath() . '/src/Application/Admin';
|
|
echo "Testing directory: $adminDir\n";
|
|
|
|
if (is_dir($adminDir)) {
|
|
$phpFiles = glob($adminDir . '/*.php');
|
|
echo "PHP files found: " . count($phpFiles) . "\n";
|
|
if (count($phpFiles) > 0) {
|
|
echo "First few files:\n";
|
|
foreach (array_slice($phpFiles, 0, 3) as $file) {
|
|
echo " - " . basename($file) . "\n";
|
|
}
|
|
}
|
|
} else {
|
|
echo "Directory not found!\n";
|
|
}
|
|
|
|
echo "✅ Discovery service created with new architecture\n";
|
|
|
|
// Quick manual test of class extraction
|
|
echo "\n🔍 Manual class extraction test:\n";
|
|
$testFile = $adminDir . '/Dashboard.php';
|
|
if (file_exists($testFile)) {
|
|
echo "Testing class extraction on: " . basename($testFile) . "\n";
|
|
|
|
// Create a file object
|
|
$fileInfo = new \SplFileInfo($testFile);
|
|
$file = \App\Framework\Filesystem\File::fromSplFileInfo($fileInfo);
|
|
|
|
// Test class extraction
|
|
$extractor = new \App\Framework\Discovery\Processing\ClassExtractor($fileSystemService);
|
|
$classNames = $extractor->extractFromFile($file);
|
|
|
|
echo "Classes found: " . count($classNames) . "\n";
|
|
foreach ($classNames as $className) {
|
|
echo " - " . $className->getFullyQualified() . "\n";
|
|
}
|
|
|
|
// Debug: Let's read the file content directly and check patterns
|
|
echo "\n🔍 Debug file content:\n";
|
|
$content = $fileSystemService->readFile($file);
|
|
echo "File size: " . strlen($content) . " characters\n";
|
|
|
|
// Test if content has class keyword
|
|
if (str_contains($content, 'class ')) {
|
|
echo "✅ Contains 'class ' keyword\n";
|
|
} else {
|
|
echo "❌ Does NOT contain 'class ' keyword\n";
|
|
}
|
|
|
|
// Test namespace extraction
|
|
if (preg_match('/^\s*namespace\s+([^;]+);/m', $content, $matches)) {
|
|
echo "✅ Namespace found: " . $matches[1] . "\n";
|
|
} else {
|
|
echo "❌ No namespace found\n";
|
|
}
|
|
|
|
// Test class extraction pattern
|
|
$pattern = '/^\s*(?:final\s+)?(?:abstract\s+)?(?:readonly\s+)?class\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/mi';
|
|
if (preg_match_all($pattern, $content, $matches)) {
|
|
echo "✅ Class pattern matched: " . count($matches[1]) . " classes\n";
|
|
foreach ($matches[1] as $className) {
|
|
echo " - Class: $className\n";
|
|
}
|
|
} else {
|
|
echo "❌ Class pattern did not match\n";
|
|
}
|
|
|
|
// Test reflection on the class directly
|
|
echo "\n🔍 Manual reflection test on Dashboard class:\n";
|
|
|
|
try {
|
|
$dashboardClass = \App\Application\Admin\Dashboard::class;
|
|
$reflection = new \ReflectionClass($dashboardClass);
|
|
echo "✅ Reflection created for: $dashboardClass\n";
|
|
|
|
$methods = $reflection->getMethods();
|
|
echo "Methods found: " . count($methods) . "\n";
|
|
|
|
foreach ($methods as $method) {
|
|
$attributes = $method->getAttributes();
|
|
if (! empty($attributes)) {
|
|
echo " Method {$method->getName()} has " . count($attributes) . " attributes:\n";
|
|
foreach ($attributes as $attr) {
|
|
echo " - " . $attr->getName() . "\n";
|
|
if (str_contains($attr->getName(), 'Route')) {
|
|
echo " ✅ ROUTE ATTRIBUTE FOUND!\n";
|
|
|
|
try {
|
|
$instance = $attr->newInstance();
|
|
echo " - Instance created successfully\n";
|
|
if (method_exists($instance, 'path')) {
|
|
echo " - Path: " . $instance->path . "\n";
|
|
}
|
|
if (method_exists($instance, 'method')) {
|
|
echo " - Method: " . $instance->method->value . "\n";
|
|
}
|
|
} catch (\Throwable $e) {
|
|
echo " - Failed to create instance: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
echo "❌ Reflection failed: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
|
|
// Test health status
|
|
echo "\n📊 Health Status:\n";
|
|
$health = $discoveryService->getHealthStatus();
|
|
foreach ($health as $key => $value) {
|
|
if (is_array($value)) {
|
|
echo " $key:\n";
|
|
foreach ($value as $subKey => $subValue) {
|
|
echo " $subKey: " . (is_array($subValue) ? json_encode($subValue) : $subValue) . "\n";
|
|
}
|
|
} else {
|
|
echo " $key: $value\n";
|
|
}
|
|
}
|
|
|
|
// Test discovery with limited scope for faster testing
|
|
echo "\n🔍 Running Discovery (limited scope)...\n";
|
|
$startTime = microtime(true);
|
|
$startMemory = memory_get_usage(true);
|
|
|
|
$options = new DiscoveryOptions(
|
|
scanType: ScanType::FULL,
|
|
paths: [
|
|
$pathProvider->getBasePath() . '/src/Application/Admin',
|
|
],
|
|
useCache: false
|
|
);
|
|
|
|
$registry = $discoveryService->discoverWithOptions($options);
|
|
|
|
$endTime = microtime(true);
|
|
$endMemory = memory_get_usage(true);
|
|
|
|
echo "✅ Discovery completed!\n";
|
|
echo "\n📈 Results:\n";
|
|
echo " Total items: " . count($registry) . "\n";
|
|
echo " Attributes: " . count($registry->attributes) . "\n";
|
|
echo " Interfaces: " . count($registry->interfaces) . "\n";
|
|
echo " Routes: " . count($registry->routes) . "\n";
|
|
echo " Templates: " . count($registry->templates) . "\n";
|
|
|
|
echo "\n⏱️ Performance:\n";
|
|
echo " Duration: " . round(($endTime - $startTime) * 1000, 2) . "ms\n";
|
|
echo " Memory used: " . round(($endMemory - $startMemory) / 1024 / 1024, 2) . "MB\n";
|
|
echo " Peak memory: " . round(memory_get_peak_usage(true) / 1024 / 1024, 2) . "MB\n";
|
|
|
|
// Test registry statistics
|
|
echo "\n📊 Memory Statistics:\n";
|
|
$stats = $registry->getMemoryStats();
|
|
foreach ($stats as $type => $stat) {
|
|
if (is_array($stat)) {
|
|
echo " $type:\n";
|
|
foreach ($stat as $key => $value) {
|
|
echo " $key: $value\n";
|
|
}
|
|
} else {
|
|
echo " $type: $stat\n";
|
|
}
|
|
}
|
|
|
|
// Show some example discovered items
|
|
echo "\n🔍 Sample Discoveries:\n";
|
|
|
|
// Show attributes
|
|
$attributeTypes = $registry->attributes->getAllTypes();
|
|
if (! empty($attributeTypes)) {
|
|
echo " Attribute Types Found:\n";
|
|
foreach (array_slice($attributeTypes, 0, 5) as $type) {
|
|
$count = count($registry->attributes->get($type));
|
|
echo " - $type ($count instances)\n";
|
|
}
|
|
|
|
// Debug: Look for Route attributes specifically
|
|
echo "\n 🔍 Debug - Looking for Route attributes:\n";
|
|
foreach ($attributeTypes as $type) {
|
|
if (str_contains($type, 'Route')) {
|
|
echo " ✅ Route attribute found: $type\n";
|
|
$instances = $registry->attributes->get($type);
|
|
foreach ($instances as $instance) {
|
|
echo " - Method: " . ($instance->method ? $instance->method->toString() : 'class-level') . "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! array_filter($attributeTypes, fn ($type) => str_contains($type, 'Route'))) {
|
|
echo " ❌ No Route attributes found. Looking for all attribute types:\n";
|
|
foreach ($attributeTypes as $type) {
|
|
echo " - $type\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show routes
|
|
$routes = $registry->routes->getAll();
|
|
if (! empty($routes)) {
|
|
echo " Routes Found:\n";
|
|
foreach (array_slice($routes, 0, 3) as $route) {
|
|
echo " - {$route->method->value} {$route->path} -> {$route->class->getShortName()}::{$route->handler->toString()}\n";
|
|
}
|
|
}
|
|
|
|
echo "\n✅ Discovery refactoring test completed successfully!\n";
|
|
echo "\n🎯 Key Improvements:\n";
|
|
echo " ✅ Separated concerns into focused components\n";
|
|
echo " ✅ Shared reflection context (no duplication)\n";
|
|
echo " ✅ Stream-based processing for memory efficiency\n";
|
|
echo " ✅ Modern value object architecture\n";
|
|
echo " ✅ Improved caching strategy\n";
|
|
echo " ✅ Better error handling and logging\n";
|
|
|
|
} catch (Throwable $e) {
|
|
echo "\n❌ Error during discovery test:\n";
|
|
echo " Message: " . $e->getMessage() . "\n";
|
|
echo " File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
|
echo " Stack trace:\n" . $e->getTraceAsString() . "\n";
|
|
exit(1);
|
|
}
|