Project

General

Profile

Bug #90648

Updated by Christian Eßl about 4 years ago

We have a multidomain website that is structured like: 

 * Website A 
 ** mounted-subpage (Original) 

 * Website B 
 ** mounted-subpage (Mount of the page in Website A) 

 * Website C (hidden) 
 ** mounted-subpage (Mount of the page in Website A) 

 Basically every website has the subpage "mounted-subpage" with identical slugs. Website A has the original page, all the other websites use a mountpoint set to this page. 
 Now    when I open the subpage in the frontend from Website A like: 
 
 https://website-a.com/mounted-subpage 

 we seem to get an infinite recursion here. (Nginx just logs an "Allowed memory size exhausted" here). 
 This happens in SiteFinder::getSiteByPageId() in the last line: 

 <pre><code class="php"> 
 /** 
      * Traverses the rootline of a page up until a Site was found. 
      * 
      * @param int $pageId 
      * @param array $rootLine 
      * @param string|null $mountPointParameter 
      * @return Site 
      * @throws SiteNotFoundException 
      */ 
     public function getSiteByPageId(int $pageId, array $rootLine = null, string $mountPointParameter = null): Site 
     { 
         if ($pageId === 0) { 
             // page uid 0 has no root line. We don't need to ask the root line resolver to know that. 
             $rootLine = []; 
         } 
         if (!is_array($rootLine)) { 
             try { 
                 $rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $pageId, $mountPointParameter)->get(); 
             } catch (PageNotFoundException $e) { 
                 // Usually when a page was hidden or disconnected 
                 // This could be improved by handing in a Context object and decide whether hidden pages 
                 // Should be linkeable too 
                 $rootLine = []; 
             } 
         } 
         foreach ($rootLine as $pageInRootLine) { 
             if (isset($this->mappingRootPageIdToIdentifier[(int)$pageInRootLine['uid']])) { 
                 return $this->sites[$this->mappingRootPageIdToIdentifier[(int)$pageInRootLine['uid']]]; 
             } 
         } 
         throw new SiteNotFoundException('No site found in root line of page ' . $pageId, 1521716622); 
     } 
 </code></pre> 

 The SiteNotFoundException is thrown, when we get the error about the memory exhaustion (what exactly happens recursion-wise, I can't say yet). 

 * Now look at the example page tree above. When I debugged the problem, I found out, that one of our websites root page was hidden. (Website C is not in use). But according to the stacktrace, the PageRouter inside matchRequest() looks up possible candidates in getPagesFromDatabaseForCandidates().  
 * In there happens the new mount point magic. The function now returns our possible candidates for the slug "mounted-subpage", including the one of the hidden Website C.  
 * Later, SiteFinder::getSiteByPageId() tries to find the site for this page, but fails doing so (Expected, the website is hidden) and throws a SiteNotFoundException. 
 * SiteMatcher::matchByPageId catches the exception and falls back to "$this->pseudoSiteFinder->getSiteByPageId()). It successfully returns a PseudoSite for our hidden Website C; 
 * Later in PageRouter::getPagesFromDatabaseForCandidates(), if $mountPageInformation is set (yes in this case), the recursion happens when $this->findPageCandidatesOfMountPoint() is called. Why it ends up in an infinite recursion I am not really sure yet. From what I see it constantly juggles between the mountpoints of Website B and Website C. (Which both point to the original page in Website A)

Back