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

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\Security\ContaoCorePermissions;
  14. use Contao\CoreBundle\Util\LocaleUtil;
  15. use Contao\Model\Collection;
  16. use Symfony\Component\HttpFoundation\Response;
  17. /**
  18.  * Main front end controller.
  19.  *
  20.  * @author Leo Feyer <https://github.com/leofeyer>
  21.  */
  22. class FrontendIndex extends Frontend
  23. {
  24.     /**
  25.      * Initialize the object
  26.      */
  27.     public function __construct()
  28.     {
  29.         // Load the user object before calling the parent constructor
  30.         $this->import(FrontendUser::class, 'User');
  31.         parent::__construct();
  32.     }
  33.     /**
  34.      * Run the controller
  35.      *
  36.      * @return Response
  37.      *
  38.      * @throws PageNotFoundException
  39.      */
  40.     public function run()
  41.     {
  42.         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.');
  43.         $pageId $this->getPageIdFromUrl();
  44.         // Load a website root page object if there is no page ID
  45.         if ($pageId === null)
  46.         {
  47.             $objRootPage $this->getRootPageFromUrl();
  48.             /** @var PageRoot $objHandler */
  49.             $objHandler = new $GLOBALS['TL_PTY']['root']();
  50.             $pageId $objHandler->generate($objRootPage->idtruetrue);
  51.         }
  52.         // Throw a 404 error if the request is not a Contao request (see #2864)
  53.         elseif ($pageId === false)
  54.         {
  55.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  56.         }
  57.         $pageModel PageModel::findPublishedByIdOrAlias($pageId);
  58.         // Throw a 404 error if the page could not be found
  59.         if ($pageModel === null)
  60.         {
  61.             throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  62.         }
  63.         return $this->renderPage($pageModel);
  64.     }
  65.     /**
  66.      * Render a page
  67.      *
  68.      * @param Collection|PageModel[]|PageModel $pageModel
  69.      *
  70.      * @return Response
  71.      *
  72.      * @throws \LogicException
  73.      * @throws PageNotFoundException
  74.      * @throws AccessDeniedException
  75.      */
  76.     public function renderPage($pageModel)
  77.     {
  78.         /** @var PageModel $objPage */
  79.         global $objPage;
  80.         $objPage $pageModel;
  81.         // Check the URL and language of each page if there are multiple results
  82.         if ($objPage instanceof Collection && $objPage->count() > 1)
  83.         {
  84.             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.');
  85.             $arrPages = array();
  86.             // Order by domain and language
  87.             while ($objPage->next())
  88.             {
  89.                 /** @var PageModel $objModel */
  90.                 $objModel $objPage->current();
  91.                 $objCurrentPage $objModel->loadDetails();
  92.                 $domain $objCurrentPage->domain ?: '*';
  93.                 $arrPages[$domain][$objCurrentPage->rootLanguage] = $objCurrentPage;
  94.                 // Also store the fallback language
  95.                 if ($objCurrentPage->rootIsFallback)
  96.                 {
  97.                     $arrPages[$domain]['*'] = $objCurrentPage;
  98.                 }
  99.             }
  100.             $strHost Environment::get('host');
  101.             // Look for a root page whose domain name matches the host name
  102.             $arrLangs $arrPages[$strHost] ?? ($arrPages['*'] ?: array());
  103.             // Throw an exception if there are no matches (see #1522)
  104.             if (empty($arrLangs))
  105.             {
  106.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  107.             }
  108.             // Use the first result (see #4872)
  109.             if (!System::getContainer()->getParameter('contao.legacy_routing') || !System::getContainer()->getParameter('contao.prepend_locale'))
  110.             {
  111.                 $objNewPage current($arrLangs);
  112.             }
  113.             // Try to find a page matching the language parameter
  114.             elseif (($lang Input::get('language')) && isset($arrLangs[$lang]))
  115.             {
  116.                 $objNewPage $arrLangs[$lang];
  117.             }
  118.             // Use the fallback language (see #8142)
  119.             elseif (isset($arrLangs['*']))
  120.             {
  121.                 $objNewPage $arrLangs['*'];
  122.             }
  123.             // Throw an exception if there is no matching page (see #1522)
  124.             else
  125.             {
  126.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  127.             }
  128.             // Store the page object
  129.             if (\is_object($objNewPage))
  130.             {
  131.                 $objPage $objNewPage;
  132.             }
  133.         }
  134.         // Throw a 500 error if the result is still ambiguous
  135.         if ($objPage instanceof Collection && $objPage->count() > 1)
  136.         {
  137.             $this->log('More than one page matches ' Environment::get('base') . Environment::get('request'), __METHOD__TL_ERROR);
  138.             throw new \LogicException('More than one page found: ' Environment::get('uri'));
  139.         }
  140.         // Make sure $objPage is a Model
  141.         if ($objPage instanceof Collection)
  142.         {
  143.             $objPage $objPage->current();
  144.         }
  145.         // If the page has an alias, it can no longer be called via ID (see #7661)
  146.         if ($objPage->alias)
  147.         {
  148.             $language $objPage->urlPrefix preg_quote($objPage->urlPrefix '/''#') : '';
  149.             $suffix preg_quote($objPage->urlSuffix'#');
  150.             if (preg_match('#^' $language $objPage->id '(' $suffix '($|\?)|/)#'Environment::get('relativeRequest')))
  151.             {
  152.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  153.             }
  154.         }
  155.         // Trigger the 404 page if an item is required but not given (see #8361)
  156.         if ($objPage->requireItem)
  157.         {
  158.             $hasItem false;
  159.             if (Config::get('useAutoItem'))
  160.             {
  161.                 $hasItem = isset($_GET['auto_item']);
  162.             }
  163.             else
  164.             {
  165.                 foreach ($GLOBALS['TL_AUTO_ITEM'] as $item)
  166.                 {
  167.                     if (isset($_GET[$item]))
  168.                     {
  169.                         $hasItem true;
  170.                         break;
  171.                     }
  172.                 }
  173.             }
  174.             if (!$hasItem)
  175.             {
  176.                 throw new PageNotFoundException('Page not found: ' Environment::get('uri'));
  177.             }
  178.         }
  179.         // Inherit the settings from the parent pages
  180.         $objPage->loadDetails();
  181.         // Trigger the 404 page if the page is not published and the front end preview is not active (see #374)
  182.         if (!BE_USER_LOGGED_IN && !$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.             $objHandler->generate($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 (!BE_USER_LOGGED_IN && !$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.             $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);
  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.                     $this->log('Page ID "' $objPage->id '" can only be accessed by groups "' implode(', '$objPage->groups) . '" (current user groups: ' implode(', 'StringUtil::deserialize($user->groupstrue)) . ')'__METHOD__TL_ERROR);
  233.                 }
  234.                 throw new AccessDeniedException('Access denied: ' Environment::get('uri'));
  235.             }
  236.         }
  237.         // Backup some globals (see #7659)
  238.         $arrHead $GLOBALS['TL_HEAD'] ?? null;
  239.         $arrBody $GLOBALS['TL_BODY'] ?? null;
  240.         $arrMootools $GLOBALS['TL_MOOTOOLS'] ?? null;
  241.         $arrJquery $GLOBALS['TL_JQUERY'] ?? null;
  242.         try
  243.         {
  244.             // Generate the page
  245.             switch ($objPage->type)
  246.             {
  247.                 case 'error_401':
  248.                     $objHandler = new $GLOBALS['TL_PTY']['error_401']();
  249.                     /** @var PageError401 $objHandler */
  250.                     return $objHandler->getResponse($objPage->rootId);
  251.                 case 'error_403':
  252.                     $objHandler = new $GLOBALS['TL_PTY']['error_403']();
  253.                     /** @var PageError403 $objHandler */
  254.                     return $objHandler->getResponse($objPage->rootId);
  255.                 case 'error_404':
  256.                     $objHandler = new $GLOBALS['TL_PTY']['error_404']();
  257.                     /** @var PageError404 $objHandler */
  258.                     return $objHandler->getResponse();
  259.                 default:
  260.                     $pageType $GLOBALS['TL_PTY'][$objPage->type] ?? PageRegular::class;
  261.                     $objHandler = new $pageType();
  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.             throw $e;
  291.         }
  292.     }
  293.     /**
  294.      * Try to load the page from the cache
  295.      *
  296.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  297.      *             Use the kernel.request event instead.
  298.      */
  299.     protected function outputFromCache()
  300.     {
  301.         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.');
  302.     }
  303. }
  304. class_alias(FrontendIndex::class, 'FrontendIndex');