@@ -14,10 +14,12 @@ class VendorFileMapper
1414 /**
1515 * @param ComponentRegistrarInterface $componentRegistrar
1616 * @param DirectoryList $directoryList
17+ * @param \Magento\Framework\ObjectManagerInterface $objectManager
1718 */
1819 public function __construct (
1920 private readonly ComponentRegistrarInterface $ componentRegistrar ,
20- private readonly DirectoryList $ directoryList
21+ private readonly DirectoryList $ directoryList ,
22+ private readonly \Magento \Framework \ObjectManagerInterface $ objectManager
2123 ) {
2224 }
2325
@@ -56,6 +58,23 @@ public function mapToThemePath(string $sourcePath, string $themePath, ?string $t
5658 // Validate area and extract clean path
5759 $ cleanPath = $ this ->validateAndExtractViewPath ($ pathInsideModule , $ themeArea , $ sourcePath );
5860
61+ // Priority 1A: Check if this is a Hyva Compatibility Module
62+ // If so, map to its registered "original_module"
63+ $ originalModule = $ this ->getOriginalModuleFromCompatRegistry ($ moduleName );
64+ if ($ originalModule ) {
65+ // Start with clean path (e.g. templates/Original_Module/foo.phtml or templates/foo.phtml)
66+ $ targetPath = ltrim ($ cleanPath , '/ ' );
67+
68+ // If path contains the Original Module name as a subdirectory (Hyva convention), strip it
69+ // Example: templates/Mollie_Payment/foo.phtml -> templates/foo.phtml
70+ // This prevents Theme/Mollie_Payment/templates/Mollie_Payment/foo.phtml
71+ if (str_contains ($ targetPath , '/ ' . $ originalModule . '/ ' )) {
72+ $ targetPath = str_replace ('/ ' . $ originalModule . '/ ' , '/ ' , $ targetPath );
73+ }
74+
75+ return rtrim ($ themePath , '/ ' ) . '/ ' . $ originalModule . '/ ' . $ targetPath ;
76+ }
77+
5978 return rtrim ($ themePath , '/ ' ) . '/ ' . $ moduleName . '/ ' . ltrim ($ cleanPath , '/ ' );
6079 }
6180 }
@@ -174,4 +193,40 @@ private function isAreaCompatible(string $sourceArea, string $targetArea): bool
174193
175194 return false ;
176195 }
196+
197+ /**
198+ * Check if module is a registered Hyva compatibility module and retrieve its original module.
199+ *
200+ * @param string $compatModuleName
201+ * @return string|null
202+ */
203+ private function getOriginalModuleFromCompatRegistry (string $ compatModuleName ): ?string
204+ {
205+ // Check if Hyva Compat Registry class exists (soft dependency)
206+ // Note: class_exists takes a fully qualified class name string.
207+ if (!class_exists ('\Hyva\CompatModuleFallback\Model\CompatModuleRegistry ' )) {
208+ return null ;
209+ }
210+
211+ try {
212+ /** @var \Hyva\CompatModuleFallback\Model\CompatModuleRegistry $registry */
213+ $ registry = $ this ->objectManager ->get ('\Hyva\CompatModuleFallback\Model\CompatModuleRegistry ' );
214+
215+ // Iterate through original modules to find if current module is a registered compat module
216+ foreach ($ registry ->getOrigModules () as $ originalModule ) {
217+ // Get compat modules for this original module
218+ $ compatModules = $ registry ->getCompatModulesFor ($ originalModule );
219+
220+ // If our module is in the list, return the original module
221+ if (in_array ($ compatModuleName , $ compatModules , true )) {
222+ return $ originalModule ;
223+ }
224+ }
225+ } catch (\Throwable $ e ) {
226+ // If anything fails (e.g. DI config issues), fallback to standard mapping
227+ return null ;
228+ }
229+
230+ return null ;
231+ }
177232}
0 commit comments