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

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\CoreBundle\Security\ContaoCorePermissions;
  15. use Contao\CoreBundle\Util\LocaleUtil;
  16. use Contao\Model\Collection;
  17. use Symfony\Component\HttpFoundation\Response;
  18. /**
  19.  * Main front end controller.
  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.         trigger_deprecation('contao/core-bundle''4.10''Using "Contao\FrontendIndex::run()" has been deprecated and will no longer work in Contao 5.0. Use the Symfony routing instead.');
  42.         $pageId $this->getPageIdFromUrl();
  43.         // Load a website root page object if there is no page ID
  44.         if ($pageId === null)
  45.         {
  46.             $objRootPage $this->getRootPageFromUrl();
  47.             /** @var PageRoot $objHandler */
  48.             $objHandler = new $GLOBALS['TL_PTY']['root']();
  49.             $pageId $objHandler->generate($objRootPage->idtruetrue);
  50.         }
  51.         // Throw a 404 error if the request is not a Contao request (see #2864)
  52.         elseif ($pageId === false)
  53.         {
  54.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  55.         }
  56.         $pageModel PageModel::findPublishedByIdOrAlias($pageId);
  57.         // Throw a 404 error if the page could not be found
  58.         if ($pageModel === null)
  59.         {
  60.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  61.         }
  62.         return $this->renderPage($pageModel);
  63.     }
  64.     /**
  65.      * Render a page
  66.      *
  67.      * @param Collection|PageModel[]|PageModel $pageModel
  68.      *
  69.      * @return Response
  70.      *
  71.      * @throws \LogicException
  72.      * @throws PageNotFoundException
  73.      * @throws AccessDeniedException
  74.      */
  75.     public function renderPage($pageModel)
  76.     {
  77.         /** @var PageModel $objPage */
  78.         global $objPage;
  79.         $objPage $pageModel;
  80.         // Check the URL and language of each page if there are multiple results
  81.         if ($objPage instanceof Collection && $objPage->count() > 1)
  82.         {
  83.             trigger_deprecation('contao/core-bundle''4.7''Using "Contao\FrontendIndex::renderPage()" with a model collection has been deprecated and will no longer work Contao 5.0. Use the Symfony routing instead.');
  84.             $arrPages = array();
  85.             // Order by domain and language
  86.             while ($objPage->next())
  87.             {
  88.                 /** @var PageModel $objModel */
  89.                 $objModel $objPage->current();
  90.                 $objCurrentPage $objModel->loadDetails();
  91.                 $domain $objCurrentPage->domain ?: '*';
  92.                 $arrPages[$domain][$objCurrentPage->rootLanguage] = $objCurrentPage;
  93.                 // Also store the fallback language
  94.                 if ($objCurrentPage->rootIsFallback)
  95.                 {
  96.                     $arrPages[$domain]['*'] = $objCurrentPage;
  97.                 }
  98.             }
  99.             $strHost Environment::get('host');
  100.             // Look for a root page whose domain name matches the host name
  101.             $arrLangs $arrPages[$strHost] ?? ($arrPages['*'] ?: array());
  102.             // Throw an exception if there are no matches (see #1522)
  103.             if (empty($arrLangs))
  104.             {
  105.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  106.             }
  107.             // Use the first result (see #4872)
  108.             if (!System::getContainer()->getParameter('contao.legacy_routing') || !System::getContainer()->getParameter('contao.prepend_locale'))
  109.             {
  110.                 $objNewPage current($arrLangs);
  111.             }
  112.             // Try to find a page matching the language parameter
  113.             elseif (($lang Input::get('language')) && isset($arrLangs[$lang]))
  114.             {
  115.                 $objNewPage $arrLangs[$lang];
  116.             }
  117.             // Use the fallback language (see #8142)
  118.             elseif (isset($arrLangs['*']))
  119.             {
  120.                 $objNewPage $arrLangs['*'];
  121.             }
  122.             // Throw an exception if there is no matching page (see #1522)
  123.             else
  124.             {
  125.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  126.             }
  127.             // Store the page object
  128.             if (\is_object($objNewPage))
  129.             {
  130.                 $objPage $objNewPage;
  131.             }
  132.         }
  133.         // Throw a 500 error if the result is still ambiguous
  134.         if ($objPage instanceof Collection && $objPage->count() > 1)
  135.         {
  136.             System::getContainer()->get('monolog.logger.contao.error')->error('More than one page matches ' Environment::get('base') . Environment::get('request'));
  137.             throw new \LogicException('More than one page found: ' Environment::get('uri'));
  138.         }
  139.         // Make sure $objPage is a Model
  140.         if ($objPage instanceof Collection)
  141.         {
  142.             $objPage $objPage->current();
  143.         }
  144.         // If the page has an alias, it can no longer be called via ID (see #7661)
  145.         if ($objPage->alias)
  146.         {
  147.             $language $objPage->urlPrefix preg_quote($objPage->urlPrefix '/''#') : '';
  148.             $suffix preg_quote($objPage->urlSuffix'#');
  149.             if (preg_match('#^' $language $objPage->id '(' $suffix '($|\?)|/)#'Environment::get('relativeRequest')))
  150.             {
  151.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  152.             }
  153.         }
  154.         // Trigger the 404 page if an item is required but not given (see #8361)
  155.         if ($objPage->requireItem)
  156.         {
  157.             $hasItem false;
  158.             if (Config::get('useAutoItem'))
  159.             {
  160.                 $hasItem = isset($_GET['auto_item']);
  161.             }
  162.             else
  163.             {
  164.                 foreach ($GLOBALS['TL_AUTO_ITEM'] as $item)
  165.                 {
  166.                     if (isset($_GET[$item]))
  167.                     {
  168.                         $hasItem true;
  169.                         break;
  170.                     }
  171.                 }
  172.             }
  173.             if (!$hasItem)
  174.             {
  175.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  176.             }
  177.         }
  178.         // Inherit the settings from the parent pages
  179.         $objPage->loadDetails();
  180.         $blnShowUnpublished System::getContainer()->get('contao.security.token_checker')->isPreviewMode();
  181.         // Trigger the 404 page if the page is not published and the front end preview is not active (see #374)
  182.         if (!$blnShowUnpublished && !$objPage->isPublic)
  183.         {
  184.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  185.         }
  186.         // Load a website root page object (will redirect to the first active regular page)
  187.         if ($objPage->type == 'root')
  188.         {
  189.             /** @var PageRoot $objHandler */
  190.             $objHandler = new $GLOBALS['TL_PTY']['root']();
  191.             throw new ResponseException($objHandler->getResponse($objPage->id));
  192.         }
  193.         // Set the admin e-mail address
  194.         if ($objPage->adminEmail)
  195.         {
  196.             list($GLOBALS['TL_ADMIN_NAME'], $GLOBALS['TL_ADMIN_EMAIL']) = StringUtil::splitFriendlyEmail($objPage->adminEmail);
  197.         }
  198.         else
  199.         {
  200.             list($GLOBALS['TL_ADMIN_NAME'], $GLOBALS['TL_ADMIN_EMAIL']) = StringUtil::splitFriendlyEmail(Config::get('adminEmail'));
  201.         }
  202.         // Exit if the root page has not been published (see #2425)
  203.         // Do not try to load the 404 page, it can cause an infinite loop!
  204.         if (!$blnShowUnpublished && !$objPage->rootIsPublic)
  205.         {
  206.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  207.         }
  208.         // Check whether the language matches the root page language
  209.         if (isset($_GET['language']) && $objPage->urlPrefix && Input::get('language') != LocaleUtil::formatAsLanguageTag($objPage->rootLanguage))
  210.         {
  211.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  212.         }
  213.         // Check whether there are domain name restrictions
  214.         if ($objPage->domain && $objPage->domain != Environment::get('host'))
  215.         {
  216.             System::getContainer()->get('monolog.logger.contao.error')->error('Page ID "' $objPage->id '" was requested via "' Environment::get('host') . '" but can only be accessed via "' $objPage->domain '" (' Environment::get('base') . Environment::get('request') . ')');
  217.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  218.         }
  219.         // Authenticate the user if the page is protected
  220.         if ($objPage->protected)
  221.         {
  222.             $security System::getContainer()->get('security.helper');
  223.             if (!$security->isGranted(ContaoCorePermissions::MEMBER_IN_GROUPS$objPage->groups))
  224.             {
  225.                 if (($token $security->getToken()) === null || System::getContainer()->get('security.authentication.trust_resolver')->isAnonymous($token))
  226.                 {
  227.                     throw new InsufficientAuthenticationException('Not authenticated: ' Environment::get('uri'));
  228.                 }
  229.                 $user $security->getUser();
  230.                 if ($user instanceof FrontendUser)
  231.                 {
  232.                     System::getContainer()->get('monolog.logger.contao.error')->error('Page ID "' $objPage->id '" can only be accessed by groups "' implode(', '$objPage->groups) . '" (current user groups: ' implode(', 'StringUtil::deserialize($user->groupstrue)) . ')');
  233.                 }
  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.             $pageType $GLOBALS['TL_PTY'][$objPage->type] ?? PageRegular::class;
  249.             $objHandler = new $pageType();
  250.             // Backwards compatibility
  251.             if (!method_exists($objHandler'getResponse'))
  252.             {
  253.                 ob_start();
  254.                 try
  255.                 {
  256.                     $objHandler->generate($objPagetrue);
  257.                     $objResponse = new Response(ob_get_contents(), http_response_code());
  258.                 }
  259.                 finally
  260.                 {
  261.                     ob_end_clean();
  262.                 }
  263.                 return $objResponse;
  264.             }
  265.             return $objHandler->getResponse($objPagetrue);
  266.         }
  267.         // Render the error page (see #5570)
  268.         catch (UnusedArgumentsException $e)
  269.         {
  270.             // Restore the globals (see #7659)
  271.             list(
  272.                 $GLOBALS['TL_HEAD'],
  273.                 $GLOBALS['TL_BODY'],
  274.                 $GLOBALS['TL_MOOTOOLS'],
  275.                 $GLOBALS['TL_JQUERY'],
  276.                 $GLOBALS['TL_USER_CSS'],
  277.                 $GLOBALS['TL_FRAMEWORK_CSS']
  278.             ) = $arrBackup;
  279.             throw $e;
  280.         }
  281.     }
  282.     /**
  283.      * Try to load the page from the cache
  284.      *
  285.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  286.      *             Use the kernel.request event instead.
  287.      */
  288.     protected function outputFromCache()
  289.     {
  290.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\FrontendIndex::outputFromCache()" has been deprecated and will no longer work in Contao 5.0. Use the "kernel.request" event instead.');
  291.     }
  292. }
  293. class_alias(FrontendIndex::class, 'FrontendIndex');