diff --git a/src/Console/Command/Hyva/CompatibilityCheckCommand.php b/src/Console/Command/Hyva/CompatibilityCheckCommand.php index 68b4c34..7575ace 100644 --- a/src/Console/Command/Hyva/CompatibilityCheckCommand.php +++ b/src/Console/Command/Hyva/CompatibilityCheckCommand.php @@ -13,6 +13,12 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +/** + * Command to check Magento modules for Hyvä theme compatibility issues + * + * Scans modules for RequireJS, Knockout.js, jQuery, and UI Components usage + * that would be incompatible with Hyvä themes. + */ class CompatibilityCheckCommand extends AbstractCommand { private const OPTION_SHOW_ALL = 'show-all'; @@ -169,10 +175,11 @@ private function runScan( OutputInterface $output ): int { - // Determine filter logic: - // - Default (no flags): Scan third-party only (exclude Magento_* but include vendor third-party) - // - With --include-vendor: Scan everything including Magento_* - // - With --third-party-only: Explicitly scan only third-party + // Determine filter logic for vendor and third-party modules: + // - excludeVendor controls whether to scan modules in the vendor/ directory + // - By default (no flags): scan third-party modules including those in vendor/ + // - With --include-vendor: scan everything including Magento_* core modules + // - With --third-party-only: explicitly scan only third-party modules $scanThirdPartyOnly = $thirdPartyOnly || (!$includeVendor && !$thirdPartyOnly); $excludeVendor = false; // Always include vendor for third-party scanning diff --git a/src/Service/Hyva/CompatibilityChecker.php b/src/Service/Hyva/CompatibilityChecker.php index 0b23735..219475c 100644 --- a/src/Service/Hyva/CompatibilityChecker.php +++ b/src/Service/Hyva/CompatibilityChecker.php @@ -9,6 +9,12 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +/** + * Service that orchestrates Hyvä compatibility checking across Magento modules + * + * This service scans modules, detects incompatibilities with Hyvä theme framework, + * and provides formatted results with summary statistics. + */ class CompatibilityChecker { public function __construct( @@ -21,6 +27,11 @@ public function __construct( /** * Check all modules for Hyvä compatibility * + * @param SymfonyStyle $io Symfony Style IO for output + * @param OutputInterface $output Console output interface + * @param bool $showAll Whether to show all modules (including compatible ones) + * @param bool $thirdPartyOnly Whether to scan only third-party modules (excludes Magento_* modules) + * @param bool $excludeVendor Whether to exclude modules from the vendor/ directory (true = exclude, false = include) * @return array Results with structure: ['modules' => [], 'summary' => [], 'hasIncompatibilities' => bool] */ public function check( @@ -90,7 +101,9 @@ public function check( } $results['summary']['criticalIssues'] += $scanResult['criticalIssues']; - $results['summary']['warningIssues'] += ($scanResult['totalIssues'] - $scanResult['criticalIssues']); + // Calculate warnings explicitly to support future severity levels + $warningCount = max(0, $scanResult['totalIssues'] - $scanResult['criticalIssues']); + $results['summary']['warningIssues'] += $warningCount; } return $results; @@ -172,7 +185,8 @@ private function getIssuesDisplay(array $moduleData): string $parts[] = sprintf('%d critical', $scanResult['criticalIssues']); } - $warnings = $scanResult['totalIssues'] - $scanResult['criticalIssues']; + // Calculate warnings explicitly to ensure non-negative values + $warnings = max(0, $scanResult['totalIssues'] - $scanResult['criticalIssues']); if ($warnings > 0) { $parts[] = sprintf('%d warning(s)', $warnings); } @@ -185,7 +199,17 @@ private function getIssuesDisplay(array $moduleData): string */ public function getDetailedIssues(string $moduleName, array $moduleData): array { - $files = $moduleData['scanResult']['files'] ?? []; + // Safely access nested array structure + $scanResult = $moduleData['scanResult'] ?? []; + if (!is_array($scanResult)) { + return []; + } + + $files = $scanResult['files'] ?? []; + if (!is_array($files)) { + return []; + } + $details = []; foreach ($files as $filePath => $issues) { diff --git a/src/Service/Hyva/IncompatibilityDetector.php b/src/Service/Hyva/IncompatibilityDetector.php index 3ee906a..3c8e145 100644 --- a/src/Service/Hyva/IncompatibilityDetector.php +++ b/src/Service/Hyva/IncompatibilityDetector.php @@ -6,6 +6,12 @@ use Magento\Framework\Filesystem\Driver\File; +/** + * Service that detects Hyvä incompatibility patterns in JavaScript, XML, and PHTML files + * + * Uses pattern matching to identify RequireJS, Knockout.js, jQuery, and UI Components + * usage that would be problematic in a Hyvä environment. + */ class IncompatibilityDetector { private const SEVERITY_CRITICAL = 'critical'; diff --git a/src/Service/Hyva/ModuleScanner.php b/src/Service/Hyva/ModuleScanner.php index a39ae80..9a956a4 100644 --- a/src/Service/Hyva/ModuleScanner.php +++ b/src/Service/Hyva/ModuleScanner.php @@ -6,6 +6,12 @@ use Magento\Framework\Filesystem\Driver\File; +/** + * Service that scans module directories for files containing Hyvä compatibility issues + * + * Recursively scans JavaScript, XML, and PHTML files within module directories + * to identify patterns that may be incompatible with Hyvä themes. + */ class ModuleScanner { private const SCAN_EXTENSIONS = ['js', 'xml', 'phtml']; @@ -87,14 +93,45 @@ private function findRelevantFiles(string $directory): array } } } catch (\Exception $e) { - // Silently skip directories that can't be read + // Skip directories that can't be read, but log details when debugging + if (getenv('MAGEFORGE_DEBUG')) { + error_log(sprintf( + '[MageForge][ModuleScanner] Failed to read directory "%s": %s', + $directory, + $e->getMessage() + )); + } } return $relevantFiles; } /** - * Check if module has Hyvä compatibility package + * Check if module has Hyvä compatibility package based on composer data + * + * @param array $composerData Parsed composer.json data + */ + private function isHyvaCompatibilityPackage(array $composerData): bool + { + // Check if this IS a Hyvä compatibility package + $packageName = $composerData['name'] ?? ''; + if (str_starts_with($packageName, 'hyva-themes/') && str_contains($packageName, '-compat')) { + return true; + } + + // Check dependencies for Hyvä packages + $requires = $composerData['require'] ?? []; + foreach ($requires as $package => $version) { + if (str_starts_with($package, 'hyva-themes/')) { + return true; + } + } + + return false; + } + + /** + * Check if module has Hyvä compatibility package (public wrapper) */ public function hasHyvaCompatibilityPackage(string $modulePath): bool { @@ -112,24 +149,18 @@ public function hasHyvaCompatibilityPackage(string $modulePath): bool return false; } - // Check if this IS a Hyvä compatibility package - $packageName = $composerData['name'] ?? ''; - if (str_starts_with($packageName, 'hyva-themes/') && str_contains($packageName, '-compat')) { - return true; - } - - // Check dependencies for Hyvä packages - $requires = $composerData['require'] ?? []; - foreach ($requires as $package => $version) { - if (str_starts_with($package, 'hyva-themes/')) { - return true; - } - } + return $this->isHyvaCompatibilityPackage($composerData); } catch (\Exception $e) { + // Log error when debugging to help identify JSON or file read issues + if (getenv('MAGEFORGE_DEBUG')) { + error_log(sprintf( + '[MageForge][ModuleScanner] Failed to read composer.json at "%s": %s', + $composerPath, + $e->getMessage() + )); + } return false; } - - return false; } /** @@ -147,12 +178,24 @@ public function getModuleInfo(string $modulePath): array $content = $this->fileDriver->fileGetContents($composerPath); $composerData = json_decode($content, true); + if (!is_array($composerData)) { + return ['name' => 'Unknown', 'version' => 'Unknown', 'isHyvaAware' => false]; + } + return [ 'name' => $composerData['name'] ?? 'Unknown', 'version' => $composerData['version'] ?? 'Unknown', - 'isHyvaAware' => $this->hasHyvaCompatibilityPackage($modulePath), + 'isHyvaAware' => $this->isHyvaCompatibilityPackage($composerData), ]; } catch (\Exception $e) { + // Log error when debugging to help identify JSON parsing or file read issues + if (getenv('MAGEFORGE_DEBUG')) { + error_log(sprintf( + '[MageForge][ModuleScanner] Failed to read module info at "%s": %s', + $composerPath, + $e->getMessage() + )); + } return ['name' => 'Unknown', 'version' => 'Unknown', 'isHyvaAware' => false]; } }