|
8 | 8 | use Magento\Framework\Component\ComponentRegistrarInterface; |
9 | 9 | use Magento\Framework\Filesystem\DirectoryList; |
10 | 10 | use RuntimeException; |
| 11 | +use Magento\Framework\App\Area; |
11 | 12 |
|
12 | 13 | class VendorFileMapper |
13 | 14 | { |
14 | 15 | /** |
15 | 16 | * @param ComponentRegistrarInterface $componentRegistrar |
16 | 17 | * @param DirectoryList $directoryList |
17 | 18 | * @param \Magento\Framework\ObjectManagerInterface $objectManager |
| 19 | + * @param \Magento\Framework\App\State $appState |
18 | 20 | */ |
19 | 21 | public function __construct( |
20 | 22 | private readonly ComponentRegistrarInterface $componentRegistrar, |
21 | 23 | private readonly DirectoryList $directoryList, |
22 | | - private readonly \Magento\Framework\ObjectManagerInterface $objectManager |
| 24 | + private readonly \Magento\Framework\ObjectManagerInterface $objectManager, |
| 25 | + private readonly \Magento\Framework\App\State $appState |
23 | 26 | ) { |
24 | 27 | } |
25 | 28 |
|
@@ -61,15 +64,20 @@ public function mapToThemePath(string $sourcePath, string $themePath, ?string $t |
61 | 64 | // Priority 1A: Check if this is a Hyva Compatibility Module |
62 | 65 | // If so, map to its registered "original_module" |
63 | 66 | $originalModule = $this->getOriginalModuleFromCompatRegistry($moduleName); |
| 67 | + |
64 | 68 | if ($originalModule) { |
65 | 69 | // Start with clean path (e.g. templates/Original_Module/foo.phtml or templates/foo.phtml) |
66 | 70 | $targetPath = ltrim($cleanPath, '/'); |
67 | 71 |
|
68 | 72 | // If path contains the Original Module name as a subdirectory (Hyva convention), strip it |
69 | 73 | // Example: templates/Mollie_Payment/foo.phtml -> templates/foo.phtml |
70 | 74 | // This prevents Theme/Mollie_Payment/templates/Mollie_Payment/foo.phtml |
| 75 | + // Note: Check both strict and case-insensitive to be safe |
71 | 76 | if (str_contains($targetPath, '/' . $originalModule . '/')) { |
72 | 77 | $targetPath = str_replace('/' . $originalModule . '/', '/', $targetPath); |
| 78 | + } elseif (stripos($targetPath, '/' . $originalModule . '/') !== false) { |
| 79 | + // Case-insensitive replacement if strict failed |
| 80 | + $targetPath = str_ireplace('/' . $originalModule . '/', '/', $targetPath); |
73 | 81 | } |
74 | 82 |
|
75 | 83 | return rtrim($themePath, '/') . '/' . $originalModule . '/' . $targetPath; |
@@ -203,24 +211,39 @@ private function isAreaCompatible(string $sourceArea, string $targetArea): bool |
203 | 211 | private function getOriginalModuleFromCompatRegistry(string $compatModuleName): ?string |
204 | 212 | { |
205 | 213 | // Check if Hyva Compat Registry class exists (soft dependency) |
206 | | - // Note: class_exists takes a fully qualified class name string. |
207 | 214 | if (!class_exists('\Hyva\CompatModuleFallback\Model\CompatModuleRegistry')) { |
208 | 215 | return null; |
209 | 216 | } |
210 | 217 |
|
211 | 218 | try { |
212 | | - /** @var \Hyva\CompatModuleFallback\Model\CompatModuleRegistry $registry */ |
213 | | - $registry = $this->objectManager->get('\Hyva\CompatModuleFallback\Model\CompatModuleRegistry'); |
| 219 | + // Emulate frontend area to load proper DI configuration for CompatModuleRegistry |
| 220 | + // as CLI commands run in global scope where frontend/di.xml is ignored. |
| 221 | + $registry = $this->appState->emulateAreaCode( |
| 222 | + Area::AREA_FRONTEND, |
| 223 | + function () { |
| 224 | + // Use create() to ensure we get a fresh instance with the emulated configuration. |
| 225 | + // get() might return a cached instance from global scope (empty). |
| 226 | + return $this->objectManager->create('\Hyva\CompatModuleFallback\Model\CompatModuleRegistry'); |
| 227 | + } |
| 228 | + ); |
214 | 229 |
|
| 230 | + /** @var \Hyva\CompatModuleFallback\Model\CompatModuleRegistry $registry */ |
215 | 231 | // Iterate through original modules to find if current module is a registered compat module |
216 | 232 | foreach ($registry->getOrigModules() as $originalModule) { |
217 | 233 | // Get compat modules for this original module |
218 | 234 | $compatModules = $registry->getCompatModulesFor($originalModule); |
219 | 235 |
|
220 | | - // If our module is in the list, return the original module |
| 236 | + // Check exact match first |
221 | 237 | if (in_array($compatModuleName, $compatModules, true)) { |
222 | 238 | return $originalModule; |
223 | 239 | } |
| 240 | + |
| 241 | + // Fallback: Case-insensitive check (some modules handle naming inconsistently) |
| 242 | + foreach ($compatModules as $compatModule) { |
| 243 | + if (strnatcasecmp($compatModuleName, $compatModule) === 0) { |
| 244 | + return $originalModule; |
| 245 | + } |
| 246 | + } |
224 | 247 | } |
225 | 248 | } catch (\Throwable $e) { |
226 | 249 | // If anything fails (e.g. DI config issues), fallback to standard mapping |
|
0 commit comments