$paths */ public array $paths = [], /** @var array $attributeMappers */ public array $attributeMappers = [], /** @var array $targetInterfaces */ public array $targetInterfaces = [], public bool $useCache = true, ?Duration $cacheTimeout = null, public ?string $contextSuffix = null, public int $memoryLimitMB = 128, public bool $enableEventDispatcher = true, public bool $enableMemoryMonitoring = true, public bool $enablePerformanceTracking = true, public int $maxFilesPerBatch = 100, public float $memoryPressureThreshold = 0.8 ) { // Set default cache timeout if not provided $this->cacheTimeout = $cacheTimeout ?? Duration::fromHours(24); } /** * Create configuration for development environment */ public static function development(): self { return new self( useCache : true, // Disable cache for development memoryLimitMB : 512, // Much higher memory limit for development enableMemoryMonitoring : false, enablePerformanceTracking: true, // Disable memory monitoring for development to avoid false positives maxFilesPerBatch : 500, // Larger batches to ensure complete discovery memoryPressureThreshold : 0.95 // Much more relaxed memory pressure threshold for development ); } /** * Create configuration for production environment */ public static function production(): self { return new self( useCache: true, cacheTimeout: Duration::fromHours(24), memoryLimitMB: 128, enablePerformanceTracking: false, // Disable for performance maxFilesPerBatch: 200 // Larger batches for better performance ); } /** * Create configuration for testing environment * * Testing configuration now uses similar settings to development * to ensure consistent discovery behavior, especially for CLI commands */ public static function testing(): self { return new self( useCache: false, // Disable cache for testing to ensure fresh discovery memoryLimitMB: 256, // Increased memory limit for comprehensive discovery enableEventDispatcher: false, // Disable events for testing enableMemoryMonitoring: false, enablePerformanceTracking: false, maxFilesPerBatch: 200, // Larger batches like development/production memoryPressureThreshold: 0.9 // More relaxed memory pressure threshold ); } /** * Create configuration with specific paths (factory method) */ /** * Create configuration with specific paths (factory method) * @param array $paths */ public static function forPaths(array $paths): self { return new self(paths: $paths); } /** * Create configuration with specific mappers */ /** * Create configuration with specific mappers * @param array $attributeMappers * @param array $targetInterfaces */ public static function withMappers(array $attributeMappers, array $targetInterfaces = []): self { return new self( attributeMappers: $attributeMappers, targetInterfaces: $targetInterfaces ); } /** * Create a new configuration with modified cache settings */ public function withCache(bool $useCache, ?Duration $timeout = null): self { return new self( paths: $this->paths, attributeMappers: $this->attributeMappers, targetInterfaces: $this->targetInterfaces, useCache: $useCache, cacheTimeout: $timeout ?? $this->cacheTimeout, contextSuffix: $this->contextSuffix, memoryLimitMB: $this->memoryLimitMB, enableEventDispatcher: $this->enableEventDispatcher, enableMemoryMonitoring: $this->enableMemoryMonitoring, enablePerformanceTracking: $this->enablePerformanceTracking, maxFilesPerBatch: $this->maxFilesPerBatch, memoryPressureThreshold: $this->memoryPressureThreshold ); } /** * Create a new configuration with modified memory settings */ public function withMemorySettings(int $limitMB, float $pressureThreshold = 0.8): self { return new self( paths: $this->paths, attributeMappers: $this->attributeMappers, targetInterfaces: $this->targetInterfaces, useCache: $this->useCache, cacheTimeout: $this->cacheTimeout, contextSuffix: $this->contextSuffix, memoryLimitMB: $limitMB, enableEventDispatcher: $this->enableEventDispatcher, enableMemoryMonitoring: $this->enableMemoryMonitoring, enablePerformanceTracking: $this->enablePerformanceTracking, maxFilesPerBatch: $this->maxFilesPerBatch, memoryPressureThreshold: $pressureThreshold ); } /** * Create a new configuration with modified context suffix */ public function withContextSuffix(string $suffix): self { return new self( paths: $this->paths, attributeMappers: $this->attributeMappers, targetInterfaces: $this->targetInterfaces, useCache: $this->useCache, cacheTimeout: $this->cacheTimeout, contextSuffix: $suffix, memoryLimitMB: $this->memoryLimitMB, enableEventDispatcher: $this->enableEventDispatcher, enableMemoryMonitoring: $this->enableMemoryMonitoring, enablePerformanceTracking: $this->enablePerformanceTracking, maxFilesPerBatch: $this->maxFilesPerBatch, memoryPressureThreshold: $this->memoryPressureThreshold ); } /** * Create a new configuration with modified paths */ /** * Create a new configuration with modified paths * @param array $paths */ public function withPaths(array $paths): self { return new self( paths: $paths, attributeMappers: $this->attributeMappers, targetInterfaces: $this->targetInterfaces, useCache: $this->useCache, cacheTimeout: $this->cacheTimeout, contextSuffix: $this->contextSuffix, memoryLimitMB: $this->memoryLimitMB, enableEventDispatcher: $this->enableEventDispatcher, enableMemoryMonitoring: $this->enableMemoryMonitoring, enablePerformanceTracking: $this->enablePerformanceTracking, maxFilesPerBatch: $this->maxFilesPerBatch, memoryPressureThreshold: $this->memoryPressureThreshold ); } /** * Validate configuration settings */ public function validate(): void { if ($this->memoryLimitMB < 32) { throw new \InvalidArgumentException('Memory limit must be at least 32MB'); } if ($this->memoryPressureThreshold < 0.1 || $this->memoryPressureThreshold > 1.0) { throw new \InvalidArgumentException('Memory pressure threshold must be between 0.1 and 1.0'); } if ($this->maxFilesPerBatch < 1) { throw new \InvalidArgumentException('Max files per batch must be at least 1'); } if ($this->cacheTimeout->toSeconds() < 60) { throw new \InvalidArgumentException('Cache timeout must be at least 60 seconds'); } } /** * Get memory limit in bytes */ public function getMemoryLimitBytes(): int { return $this->memoryLimitMB * 1024 * 1024; } /** * Check if feature is enabled */ public function isFeatureEnabled(string $feature): bool { return match ($feature) { 'cache' => $this->useCache, 'events' => $this->enableEventDispatcher, 'memory_monitoring' => $this->enableMemoryMonitoring, 'performance_tracking' => $this->enablePerformanceTracking, default => false }; } /** * Convert to array for debugging/logging */ /** * Convert to array for debugging/logging * @return array */ public function toArray(): array { return [ 'paths_count' => count($this->paths), 'attribute_mappers_count' => count($this->attributeMappers), 'target_interfaces_count' => count($this->targetInterfaces), 'use_cache' => $this->useCache, 'cache_timeout_seconds' => $this->cacheTimeout->toSeconds(), 'context_suffix' => $this->contextSuffix, 'memory_limit_mb' => $this->memoryLimitMB, 'enable_event_dispatcher' => $this->enableEventDispatcher, 'enable_memory_monitoring' => $this->enableMemoryMonitoring, 'enable_performance_tracking' => $this->enablePerformanceTracking, 'max_files_per_batch' => $this->maxFilesPerBatch, 'memory_pressure_threshold' => $this->memoryPressureThreshold, ]; } }