@@ -73,18 +73,39 @@ public function mapToThemePath(string $sourcePath, string $themePath, ?string $t
7373 // Start with clean path (e.g. templates/Original_Module/foo.phtml or templates/foo.phtml)
7474 $ targetPath = ltrim ($ cleanPath , '/ ' );
7575
76- // If path contains the Original Module name as a subdirectory (Hyva convention), strip it
77- // Example: templates/Mollie_Payment/foo.phtml -> templates/foo.phtml
78- // This prevents Theme/Mollie_Payment/templates/Mollie_Payment/foo.phtml
79- // Note: Check both strict and case-insensitive to be safe
80- if (str_contains ($ targetPath , '/ ' . $ originalModule . '/ ' )) {
81- $ targetPath = str_replace ('/ ' . $ originalModule . '/ ' , '/ ' , $ targetPath );
82- } elseif (stripos ($ targetPath , '/ ' . $ originalModule . '/ ' ) !== false ) {
83- // Case-insensitive replacement if strict failed
84- $ targetPath = str_ireplace ('/ ' . $ originalModule . '/ ' , '/ ' , $ targetPath );
76+ // Check if file actually exists in the original module's path
77+ $ originalModulePath = $ this ->componentRegistrar ->getPath (ComponentRegistrar::MODULE , $ originalModule );
78+ $ existsInOriginal = false ;
79+
80+ if ($ originalModulePath ) {
81+ $ pathInOriginal = $ originalModulePath . '/ ' . $ pathInsideModule ;
82+ $ existsInOriginal = $ this ->fileDriver ->isExists ($ pathInOriginal );
83+
84+ // If not found in current area (e.g. frontend), check if original uses 'base' area instead
85+ if (!$ existsInOriginal && str_starts_with ($ pathInsideModule , 'view/ ' . $ themeArea . '/ ' )) {
86+ $ basePathInOriginal = $ originalModulePath . '/ ' . str_replace ('view/ ' . $ themeArea . '/ ' , 'view/base/ ' , $ pathInsideModule );
87+ $ existsInOriginal = $ this ->fileDriver ->isExists ($ basePathInOriginal );
88+ }
8589 }
8690
87- return rtrim ($ themePath , '/ ' ) . '/ ' . $ originalModule . '/ ' . $ targetPath ;
91+ if ($ existsInOriginal ) {
92+ // File exists in original module: resolve path with original module namespace
93+ // If path contains the Original Module name as a subdirectory (Hyva convention), strip it
94+ // Example: templates/Mollie_Payment/foo.phtml -> templates/foo.phtml
95+ // This prevents Theme/Mollie_Payment/templates/Mollie_Payment/foo.phtml
96+ if (str_contains ($ targetPath , '/ ' . $ originalModule . '/ ' )) {
97+ $ targetPath = str_replace ('/ ' . $ originalModule . '/ ' , '/ ' , $ targetPath );
98+ } elseif (stripos ($ targetPath , '/ ' . $ originalModule . '/ ' ) !== false ) {
99+ // Case-insensitive replacement if strict failed
100+ $ targetPath = str_ireplace ('/ ' . $ originalModule . '/ ' , '/ ' , $ targetPath );
101+ }
102+
103+ return rtrim ($ themePath , '/ ' ) . '/ ' . $ originalModule . '/ ' . $ targetPath ;
104+ }
105+
106+ // File does NOT exist in original module (e.g. compat-specific template):
107+ // resolve path with compat module namespace
108+ return rtrim ($ themePath , '/ ' ) . '/ ' . $ moduleName . '/ ' . $ targetPath ;
88109 }
89110
90111 return rtrim ($ themePath , '/ ' ) . '/ ' . $ moduleName . '/ ' . ltrim ($ cleanPath , '/ ' );
@@ -358,54 +379,18 @@ private function parseDiFileForCompatModule(string $diPath, string $moduleName):
358379 libxml_use_internal_errors ($ libxmlState );
359380
360381 $ xpath = new \DOMXPath ($ dom );
361- $ query = "//argument[@name='compatModules'][@xsi:type='array']/item[@xsi:type='array'] " ;
362- $ items = $ xpath ->query ($ query );
363-
364- if ($ items === false || $ items ->length === 0 ) {
365- return null ;
366- }
367-
368- /** @var \DOMNodeList<\DOMNode> $items */
369- return $ this ->findOriginalModuleInXmlItems ($ items , $ xpath , $ moduleName );
370- }
371-
372- /**
373- * Find original module in XML items
374- *
375- * @param \DOMNodeList<\DOMNode> $items
376- * @param \DOMXPath $xpath
377- * @param string $moduleName
378- * @return string|null
379- */
380- private function findOriginalModuleInXmlItems (\DOMNodeList $ items , \DOMXPath $ xpath , string $ moduleName ): ?string
381- {
382- foreach ($ items as $ item ) {
383- $ compatModuleValue = null ;
384- $ originalModuleValue = null ;
385-
386- /** @var \DOMElement $item */
387- $ childNodes = $ xpath ->query ('item ' , $ item );
388- if ($ childNodes === false ) {
389- continue ;
390- }
391-
392- foreach ($ childNodes as $ childNode ) {
393- /** @var \DOMElement $childNode */
394- $ nameAttr = $ childNode ->getAttribute ('name ' );
395- $ value = trim ((string ) $ childNode ->nodeValue );
396-
397- if ($ nameAttr === 'compat_module ' ) {
398- $ compatModuleValue = $ value ;
399- } elseif ($ nameAttr === 'original_module ' ) {
400- $ originalModuleValue = $ value ;
401- }
402- }
403-
404- if ($ compatModuleValue === $ moduleName && $ originalModuleValue ) {
405- return $ originalModuleValue ;
382+ // Look for original_module specifically within CompatModuleRegistry arguments
383+ $ query = "//type[@name='Hyva\CompatModuleFallback\Model\CompatModuleRegistry']//item[@name='original_module'] " ;
384+ $ nodes = $ xpath ->query ($ query );
385+
386+ if ($ nodes !== false && $ nodes ->length > 0 ) {
387+ $ node = $ nodes ->item (0 );
388+ if ($ node ) {
389+ return trim ((string ) $ node ->nodeValue );
406390 }
407391 }
408392
393+ // Fallback to older logic if needed or just return null
409394 return null ;
410395 }
411396}
0 commit comments