vendor/contao/core-bundle/src/Resources/contao/controllers/FrontendIndex.php line 288

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Contao.
  4.  *
  5.  * (c) Leo Feyer
  6.  *
  7.  * @license LGPL-3.0-or-later
  8.  */
  9. namespace Contao;
  10. use Contao\CoreBundle\Exception\AccessDeniedException;
  11. use Contao\CoreBundle\Exception\InsufficientAuthenticationException;
  12. use Contao\CoreBundle\Exception\PageNotFoundException;
  13. use Contao\Model\Collection;
  14. use Symfony\Component\HttpFoundation\Response;
  15. /**
  16.  * Main front end controller.
  17.  *
  18.  * @author Leo Feyer <https://github.com/leofeyer>
  19.  */
  20. class FrontendIndex extends Frontend
  21. {
  22.     /**
  23.      * Initialize the object
  24.      */
  25.     public function __construct()
  26.     {
  27.         // Load the user object before calling the parent constructor
  28.         $this->import(FrontendUser::class, 'User');
  29.         parent::__construct();
  30.     }
  31.     /**
  32.      * Run the controller
  33.      *
  34.      * @return Response
  35.      *
  36.      * @throws PageNotFoundException
  37.      */
  38.     public function run()
  39.     {
  40.         $pageId $this->getPageIdFromUrl();
  41.         $objRootPage null;
  42.         // Load a website root page object if there is no page ID
  43.         if ($pageId === null)
  44.         {
  45.             $objRootPage $this->getRootPageFromUrl();
  46.             /** @var PageRoot $objHandler */
  47.             $objHandler = new $GLOBALS['TL_PTY']['root']();
  48.             $pageId $objHandler->generate($objRootPage->idtruetrue);
  49.         }
  50.         // Throw a 404 error if the request is not a Contao request (see #2864)
  51.         elseif ($pageId === false)
  52.         {
  53.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  54.         }
  55.         $pageModel PageModel::findPublishedByIdOrAlias($pageId);
  56.         // Throw a 404 error if the page could not be found
  57.         if ($pageModel === null)
  58.         {
  59.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  60.         }
  61.         return $this->renderPage($pageModel);
  62.     }
  63.     /**
  64.      * Render a page
  65.      *
  66.      * @param Collection|PageModel[]|PageModel $pageModel
  67.      *
  68.      * @return Response
  69.      *
  70.      * @throws \LogicException
  71.      * @throws PageNotFoundException
  72.      * @throws AccessDeniedException
  73.      */
  74.     public function renderPage($pageModel)
  75.     {
  76.         global $objPage;
  77.         $objPage $pageModel;
  78.         // Check the URL and language of each page if there are multiple results
  79.         if ($objPage instanceof Collection && $objPage->count() > 1)
  80.         {
  81.             @trigger_error('Using FrontendIndex::renderPage() with a model collection has been deprecated and will no longer work Contao 5.0. Use the Symfony routing instead.'E_USER_DEPRECATED);
  82.             $objNewPage null;
  83.             $arrPages = array();
  84.             // Order by domain and language
  85.             while ($objPage->next())
  86.             {
  87.                 /** @var PageModel $objModel */
  88.                 $objModel $objPage->current();
  89.                 $objCurrentPage $objModel->loadDetails();
  90.                 $domain $objCurrentPage->domain ?: '*';
  91.                 $arrPages[$domain][$objCurrentPage->rootLanguage] = $objCurrentPage;
  92.                 // Also store the fallback language
  93.                 if ($objCurrentPage->rootIsFallback)
  94.                 {
  95.                     $arrPages[$domain]['*'] = $objCurrentPage;
  96.                 }
  97.             }
  98.             $strHost Environment::get('host');
  99.             // Look for a root page whose domain name matches the host name
  100.             $arrLangs $arrPages[$strHost] ?? ($arrPages['*'] ?: array());
  101.             // Throw an exception if there are no matches (see #1522)
  102.             if (empty($arrLangs))
  103.             {
  104.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  105.             }
  106.             // Use the first result (see #4872)
  107.             if (!Config::get('addLanguageToUrl'))
  108.             {
  109.                 $objNewPage current($arrLangs);
  110.             }
  111.             // Try to find a page matching the language parameter
  112.             elseif (($lang Input::get('language')) && isset($arrLangs[$lang]))
  113.             {
  114.                 $objNewPage $arrLangs[$lang];
  115.             }
  116.             // Use the fallback language (see #8142)
  117.             elseif (isset($arrLangs['*']))
  118.             {
  119.                 $objNewPage $arrLangs['*'];
  120.             }
  121.             // Throw an exception if there is no matching page (see #1522)
  122.             else
  123.             {
  124.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  125.             }
  126.             // Store the page object
  127.             if (\is_object($objNewPage))
  128.             {
  129.                 $objPage $objNewPage;
  130.             }
  131.         }
  132.         // Throw a 500 error if the result is still ambiguous
  133.         if ($objPage instanceof Collection && $objPage->count() > 1)
  134.         {
  135.             $this->log('More than one page matches ' Environment::get('base') . Environment::get('request'), __METHOD__TL_ERROR);
  136.             throw new \LogicException('More than one page found: ' Environment::get('uri'));
  137.         }
  138.         // Make sure $objPage is a Model
  139.         if ($objPage instanceof Collection)
  140.         {
  141.             $objPage $objPage->current();
  142.         }
  143.         // If the page has an alias, it can no longer be called via ID (see #7661)
  144.         if ($objPage->alias)
  145.         {
  146.             $language Config::get('addLanguageToUrl') ? '[a-z]{2}(-[A-Z]{2})?/' '';
  147.             $suffix preg_quote(Config::get('urlSuffix'), '#');
  148.             if (preg_match('#^' $language $objPage->id '(' $suffix '($|\?)|/)#'Environment::get('relativeRequest')))
  149.             {
  150.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  151.             }
  152.         }
  153.         // Trigger the 404 page if an item is required but not given (see #8361)
  154.         if ($objPage->requireItem)
  155.         {
  156.             $hasItem false;
  157.             if (Config::get('useAutoItem'))
  158.             {
  159.                 $hasItem = isset($_GET['auto_item']);
  160.             }
  161.             else
  162.             {
  163.                 foreach ($GLOBALS['TL_AUTO_ITEM'] as $item)
  164.                 {
  165.                     if (isset($_GET[$item]))
  166.                     {
  167.                         $hasItem true;
  168.                         break;
  169.                     }
  170.                 }
  171.             }
  172.             if (!$hasItem)
  173.             {
  174.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  175.             }
  176.         }
  177.         // Inherit the settings from the parent pages
  178.         $objPage->loadDetails();
  179.         // Trigger the 404 page if the page is not published and the front end preview is not active (see #374)
  180.         if (!BE_USER_LOGGED_IN && !$objPage->isPublic)
  181.         {
  182.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  183.         }
  184.         // Load a website root page object (will redirect to the first active regular page)
  185.         if ($objPage->type == 'root')
  186.         {
  187.             /** @var PageRoot $objHandler */
  188.             $objHandler = new $GLOBALS['TL_PTY']['root']();
  189.             $objHandler->generate($objPage->id);
  190.         }
  191.         // Set the admin e-mail address
  192.         if ($objPage->adminEmail)
  193.         {
  194.             list($GLOBALS['TL_ADMIN_NAME'], $GLOBALS['TL_ADMIN_EMAIL']) = StringUtil::splitFriendlyEmail($objPage->adminEmail);
  195.         }
  196.         else
  197.         {
  198.             list($GLOBALS['TL_ADMIN_NAME'], $GLOBALS['TL_ADMIN_EMAIL']) = StringUtil::splitFriendlyEmail(Config::get('adminEmail'));
  199.         }
  200.         // Exit if the root page has not been published (see #2425)
  201.         // Do not try to load the 404 page, it can cause an infinite loop!
  202.         if (!BE_USER_LOGGED_IN && !$objPage->rootIsPublic)
  203.         {
  204.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  205.         }
  206.         // Check wether the language matches the root page language
  207.         if (isset($_GET['language']) && Config::get('addLanguageToUrl') && Input::get('language') != $objPage->rootLanguage)
  208.         {
  209.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  210.         }
  211.         // Check whether there are domain name restrictions
  212.         if ($objPage->domain && $objPage->domain != Environment::get('host'))
  213.         {
  214.             $this->log('Page ID "' $objPage->id '" was requested via "' Environment::get('host') . '" but can only be accessed via "' $objPage->domain '" (' Environment::get('base') . Environment::get('request') . ')'__METHOD__TL_ERROR);
  215.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  216.         }
  217.         // Authenticate the user if the page is protected
  218.         if ($objPage->protected)
  219.         {
  220.             $container System::getContainer();
  221.             $token $container->get('security.token_storage')->getToken();
  222.             if ($container->get('security.authentication.trust_resolver')->isAnonymous($token))
  223.             {
  224.                 throw new InsufficientAuthenticationException('Not authenticated: ' Environment::get('uri'));
  225.             }
  226.             if (!$container->get('security.authorization_checker')->isGranted('ROLE_MEMBER'))
  227.             {
  228.                 throw new AccessDeniedException('Access denied: ' Environment::get('uri'));
  229.             }
  230.             $arrGroups $objPage->groups// required for empty()
  231.             // Check the user groups
  232.             if (empty($arrGroups) || !\is_array($arrGroups) || !\is_array($this->User->groups) || !\count(array_intersect($arrGroups$this->User->groups)))
  233.             {
  234.                 $this->log('Page ID "' $objPage->id '" can only be accessed by groups "' implode(', ', (array) $objPage->groups) . '" (current user groups: ' implode(', '$this->User->groups) . ')'__METHOD__TL_ERROR);
  235.                 throw new AccessDeniedException('Access denied: ' Environment::get('uri'));
  236.             }
  237.         }
  238.         // Backup some globals (see #7659)
  239.         $arrHead $GLOBALS['TL_HEAD'];
  240.         $arrBody $GLOBALS['TL_BODY'];
  241.         $arrMootools $GLOBALS['TL_MOOTOOLS'];
  242.         $arrJquery $GLOBALS['TL_JQUERY'];
  243.         try
  244.         {
  245.             // Generate the page
  246.             switch ($objPage->type)
  247.             {
  248.                 case 'error_401':
  249.                     $objHandler = new $GLOBALS['TL_PTY']['error_401']();
  250.                     /** @var PageError401 $objHandler */
  251.                     return $objHandler->getResponse($objPage->rootId);
  252.                 case 'error_403':
  253.                     $objHandler = new $GLOBALS['TL_PTY']['error_403']();
  254.                     /** @var PageError403 $objHandler */
  255.                     return $objHandler->getResponse($objPage->rootId);
  256.                 case 'error_404':
  257.                     $objHandler = new $GLOBALS['TL_PTY']['error_404']();
  258.                     /** @var PageError404 $objHandler */
  259.                     return $objHandler->getResponse();
  260.                 default:
  261.                     $objHandler = new $GLOBALS['TL_PTY'][$objPage->type]();
  262.                     // Backwards compatibility
  263.                     if (!method_exists($objHandler'getResponse'))
  264.                     {
  265.                         ob_start();
  266.                         try
  267.                         {
  268.                             /** @var PageRegular $objHandler */
  269.                             $objHandler->generate($objPagetrue);
  270.                             $objResponse = new Response(ob_get_contents(), http_response_code());
  271.                         }
  272.                         finally
  273.                         {
  274.                             ob_end_clean();
  275.                         }
  276.                         return $objResponse;
  277.                     }
  278.                     /** @var PageRegular $objHandler */
  279.                     return $objHandler->getResponse($objPagetrue);
  280.             }
  281.         }
  282.         // Render the error page (see #5570)
  283.         catch (\UnusedArgumentsException $e)
  284.         {
  285.             // Restore the globals (see #7659)
  286.             $GLOBALS['TL_HEAD'] = $arrHead;
  287.             $GLOBALS['TL_BODY'] = $arrBody;
  288.             $GLOBALS['TL_MOOTOOLS'] = $arrMootools;
  289.             $GLOBALS['TL_JQUERY'] = $arrJquery;
  290.             /** @var PageError404 $objHandler */
  291.             $objHandler = new $GLOBALS['TL_PTY']['error_404']();
  292.             return $objHandler->getResponse();
  293.         }
  294.     }
  295.     /**
  296.      * Try to load the page from the cache
  297.      *
  298.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  299.      *             Use the kernel.request event instead.
  300.      */
  301.     protected function outputFromCache()
  302.     {
  303.         @trigger_error('Using FrontendIndex::outputFromCache() has been deprecated and will no longer work in Contao 5.0. Use the kernel.request event instead.'E_USER_DEPRECATED);
  304.     }
  305. }
  306. class_alias(FrontendIndex::class, 'FrontendIndex');