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

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