Files
michaelschiemer/tests/debug/test-discovery-issue.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

259 lines
8.7 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\Cache\CacheInitializer;
use App\Framework\Core\PathProvider;
use App\Framework\DateTime\SystemClock;
use App\Framework\DI\DefaultContainer;
use App\Framework\Discovery\DiscoveryServiceBootstrapper;
use App\Framework\Logging\DefaultLogger;
use App\Framework\Performance\Contracts\PerformanceCollectorInterface;
use App\Framework\Performance\PerformanceCategory;
use App\Framework\Performance\PerformanceMetric;
// Simple mock performance collector for testing
final class MockPerformanceCollector implements PerformanceCollectorInterface
{
public function startTiming(string $key, PerformanceCategory $category, array $context = []): void
{
}
public function endTiming(string $key): void
{
}
public function measure(string $key, PerformanceCategory $category, callable $callback, array $context = []): mixed
{
return $callback();
}
public function recordMetric(string $key, PerformanceCategory $category, float $value, array $context = []): void
{
}
public function increment(string $key, PerformanceCategory $category, int $amount = 1, array $context = []): void
{
}
public function getMetrics(?PerformanceCategory $category = null): array
{
return [];
}
public function getMetric(string $key): ?PerformanceMetric
{
return null;
}
public function getTotalRequestTime(): float
{
return 0.0;
}
public function getTotalRequestMemory(): int
{
return 0;
}
public function getPeakMemory(): int
{
return 0;
}
public function reset(): void
{
}
public function isEnabled(): bool
{
return false;
}
public function setEnabled(bool $enabled): void
{
}
}
try {
echo "=== Discovery Debug Test ===\n";
// Setup minimal container
$container = new DefaultContainer();
$basePath = realpath(__DIR__ . '/../..');
echo "Base path: $basePath\n";
// Add required services
$container->instance(\App\Framework\Logging\Logger::class, new DefaultLogger());
$container->instance(\App\Framework\Core\PathProvider::class, new PathProvider($basePath));
$container->instance(\App\Framework\DateTime\Clock::class, new SystemClock());
// Create performance collector and cache using CacheInitializer
$collector = new MockPerformanceCollector();
$container->instance(\App\Framework\Performance\Contracts\PerformanceCollectorInterface::class, $collector);
$cacheInitializer = new CacheInitializer($collector, $container);
$cache = $cacheInitializer();
$container->instance(\App\Framework\Cache\Cache::class, $cache);
// Force development environment for testing
if (! $container->has(\App\Framework\Config\AppConfig::class)) {
// Create a mock AppConfig for development
$appConfig = new class () {
public string $environment = 'development';
};
$container->instance(\App\Framework\Config\AppConfig::class, $appConfig);
}
// Create bootstrapper
$clock = $container->get(\App\Framework\DateTime\Clock::class);
$bootstrapper = new DiscoveryServiceBootstrapper($container, $clock);
echo "Starting discovery...\n";
// Clear cache first to force fresh discovery
$cache = $container->get(\App\Framework\Cache\Cache::class);
echo "Clearing all cache...\n";
// Try to clear all cache
try {
$reflection = new \ReflectionClass($cache);
if ($reflection->hasMethod('clear')) {
$cache->clear();
echo "Cache cleared successfully.\n";
} else {
echo "Cache doesn't have clear method.\n";
}
} catch (\Exception $e) {
echo "Cache clear failed: " . $e->getMessage() . "\n";
}
// Enable debug mode to see what's happening
ini_set('error_reporting', E_ALL);
ini_set('display_errors', '1');
// Try bootstrap
$results = $bootstrapper->bootstrap();
echo "Discovery completed successfully!\n";
// Get the discovery service to check configuration
$discoveryService = $container->get(\App\Framework\Discovery\UnifiedDiscoveryService::class);
// Get configuration from the service
// Since it's readonly, we can't access the config directly, so let's test the paths
echo "Testing if files exist in expected paths:\n";
$basePath = $container->get(\App\Framework\Core\PathProvider::class)->getBasePath();
$srcPath = $basePath . '/src';
$appPath = $basePath . '/app';
echo "Base path: $basePath\n";
echo "Src path exists: " . (is_dir($srcPath) ? 'YES' : 'NO') . "\n";
echo "App path exists: " . (is_dir($appPath) ? 'YES' : 'NO') . "\n";
if (is_dir($srcPath)) {
// Use recursive directory iterator instead of glob with **
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($srcPath, \RecursiveDirectoryIterator::SKIP_DOTS)
);
$phpFiles = [];
foreach ($iterator as $file) {
if ($file->getExtension() === 'php') {
$phpFiles[] = $file->getRealPath();
}
}
echo "PHP files in src/: " . count($phpFiles) . "\n";
// Check for specific ConsoleCommand files
$commandFiles = [];
foreach ($phpFiles as $file) {
if (strpos(file_get_contents($file), 'ConsoleCommand') !== false) {
$commandFiles[] = $file;
}
}
echo "Files with ConsoleCommand: " . count($commandFiles) . "\n";
foreach (array_slice($commandFiles, 0, 3) as $file) {
echo " - " . str_replace($basePath, '', $file) . "\n";
}
}
// Check what was discovered
echo "\nDiscovery results:\n";
echo "Attributes found: " . $results->attributes->count() . "\n";
echo "Routes found: " . $results->routes->count() . "\n";
echo "Interfaces found: " . $results->interfaces->count() . "\n";
// Show attribute types
echo "Attribute types found: " . implode(', ', $results->attributes->getAllTypes()) . "\n";
// Check for console commands specifically
$commandAttributes = $results->attributes->get('App\\Framework\\Console\\ConsoleCommand');
echo "Console commands found: " . count($commandAttributes) . "\n";
// Test: Manually check one specific file to see if it would be processed
echo "\n=== Manual File Processing Test ===\n";
$testFile = $basePath . '/src/Framework/Discovery/Commands/ClearDiscoveryCache.php';
if (file_exists($testFile)) {
echo "Test file exists: $testFile\n";
// Check if it contains ConsoleCommand attribute
$content = file_get_contents($testFile);
if (strpos($content, '#[ConsoleCommand') !== false) {
echo "File contains #[ConsoleCommand attribute\n";
} else {
echo "File does NOT contain #[ConsoleCommand attribute\n";
}
// Try to analyze the file structure
$tokens = token_get_all($content);
$classes = [];
$namespace = '';
for ($i = 0; $i < count($tokens); $i++) {
if (is_array($tokens[$i])) {
if ($tokens[$i][0] === T_NAMESPACE) {
// Get namespace
$j = $i + 1;
while ($j < count($tokens) && $tokens[$j] !== ';') {
if (is_array($tokens[$j]) && $tokens[$j][0] === T_NAME_QUALIFIED) {
$namespace = $tokens[$j][1];
}
$j++;
}
} elseif ($tokens[$i][0] === T_CLASS) {
// Get class name
$j = $i + 1;
while ($j < count($tokens)) {
if (is_array($tokens[$j]) && $tokens[$j][0] === T_STRING) {
$classes[] = $namespace . '\\' . $tokens[$j][1];
break;
}
$j++;
}
}
}
}
echo "Classes found in file: " . implode(', ', $classes) . "\n";
} else {
echo "Test file does not exist: $testFile\n";
}
// List some commands
foreach (array_slice($commandAttributes, 0, 5) as $commandMapping) {
$commandData = $commandMapping->mappedData;
$commandName = is_array($commandData) && isset($commandData['name'])
? $commandData['name']
: 'Unknown';
echo " - $commandName (class: {$commandMapping->class->getFullyQualified()})\n";
}
} catch (\Throwable $e) {
echo "ERROR: " . $e->getMessage() . "\n";
echo "Trace:\n" . $e->getTraceAsString() . "\n";
}