‪TYPO3CMS  11.5
TypoScriptFrontendController.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use Psr\Log\LoggerAwareInterface;
21 use Psr\Log\LoggerAwareTrait;
22 use Psr\Log\LogLevel;
62 use TYPO3\CMS\Core\Page\PageRenderer;
83 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
87 
103 class ‪TypoScriptFrontendController implements LoggerAwareInterface
104 {
105  use LoggerAwareTrait;
111  'ATagParams' => 'Using ATagParams will not be possible anymore in TYPO3 v12.0. Use TSFE->config[config][ATagParams] instead.',
112  ];
113 
118  public ‪$id = '';
119 
124  public ‪$type = '';
125 
129  protected ‪$site;
130 
134  protected ‪$language;
135 
140  protected ‪$pageArguments;
141 
147  public ‪$no_cache = false;
148 
153  public ‪$rootLine = [];
154 
159  public ‪$page = [];
160 
166  public ‪$contentPid = 0;
167 
175  protected ‪$originalMountPointPage;
176 
185  protected ‪$originalShortcutPage;
186 
192  public ‪$sys_page = '';
193 
199  public ‪$pageNotFound = 0;
200 
205  protected ‪$pageAccessFailureHistory = [];
206 
211  public ‪$MP = '';
212 
218  public ‪$fe_user;
219 
224  protected ‪$loginAllowedInBranch = true;
225 
232 
238  public ‪$simUserGroup = 0;
239 
245  public ‪$config = [];
246 
252  public ‪$tmpl;
253 
260  protected ‪$cacheTimeOutDefault = 86400;
261 
268  protected ‪$cacheContentFlag = false;
269 
275  protected ‪$cacheExpires = 0;
276 
282  protected ‪$isClientCachable = false;
283 
291  public ‪$all = [];
292 
298  public ‪$sPre = '';
299 
306  public ‪$pSetup = '';
307 
314  public ‪$newHash = '';
315 
324  protected ‪$no_cacheBeforePageGen = false;
325 
331  protected ‪$pagesTSconfig = '';
332 
346  public ‪$additionalHeaderData = [];
347 
352  public ‪$additionalFooterData = [];
353 
358  public ‪$intTarget = '';
359 
364  public ‪$extTarget = '';
365 
370  public ‪$fileTarget = '';
371 
377 
382  public ‪$absRefPrefix = '';
383 
389  protected ‪$ATagParams = '';
390 
398  public ‪$sWordRegEx = '';
399 
406  public ‪$sWordList = '';
407 
414  public ‪$linkVars = '';
415 
422  public ‪$displayEditIcons = '';
423 
431  public ‪$displayFieldEditIcons = '';
432 
438  public ‪$applicationData = [];
439 
443  public ‪$register = [];
444 
450  public ‪$registerStack = [];
451 
458  public ‪$cObjectDepthCounter = 50;
459 
465  public ‪$recordRegister = [];
466 
474  public ‪$currentRecord = '';
475 
481  public ‪$accessKey = [];
482 
489  protected ‪$uniqueCounter = 0;
490 
495  protected ‪$uniqueString = '';
496 
503  public ‪$indexedDocTitle = '';
504 
509  public ‪$baseUrl = '';
510 
516  public ‪$cObj;
517 
522  public ‪$content = '';
523 
528  public ?array ‪$lastImgResourceInfo = null;
529 
536  public ‪$metaCharset = 'utf-8';
537 
543  protected ‪$languageService;
544 
548  protected ‪$locks = [];
549 
553  protected ‪$pageRenderer;
554 
561  protected ‪$pageCache;
562 
566  protected ‪$pageCacheTags = [];
567 
575  protected ‪$contentType = 'text/html';
576 
582  public ‪$xhtmlDoctype = '';
583 
587  public ‪$xhtmlVersion;
588 
594  protected ‪$requestedId;
595 
602  protected ‪$context;
603 
608  protected string ‪$debugInformationHeader = '';
609 
626  {
627  $this->‪initializeContext($context);
628  $this->site = ‪$site;
629  $this->language = $siteLanguage;
630  $this->‪setPageArguments($pageArguments);
631  $this->fe_user = $frontendUser;
632  $this->uniqueString = md5(microtime());
634  $this->‪initCaches();
635  // Initialize LLL behaviour
636  $this->‪setOutputLanguage();
637  }
638 
639  private function ‪initializeContext(‪Context ‪$context): void
640  {
641  $this->context = ‪$context;
642  if (!$this->context->hasAspect('frontend.preview')) {
643  $this->context->‪setAspect('frontend.preview', GeneralUtility::makeInstance(PreviewAspect::class));
644  }
645  }
646 
650  protected function ‪initPageRenderer()
651  {
652  if ($this->pageRenderer !== null) {
653  return;
654  }
655  $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
656  $this->pageRenderer->setTemplateFile('EXT:frontend/Resources/Private/Templates/MainPage.html');
657  // As initPageRenderer could be called in constructor and for USER_INTs, this information is only set
658  // once - in order to not override any previous settings of PageRenderer.
659  if ($this->language instanceof SiteLanguage) {
660  $this->pageRenderer->setLanguage($this->language->getTypo3Language());
661  }
662  }
663 
668  public function ‪setContentType(‪$contentType)
669  {
670  $this->contentType = ‪$contentType;
671  }
672 
673  /********************************************
674  *
675  * Initializing, resolving page id
676  *
677  ********************************************/
681  protected function ‪initCaches()
682  {
683  $this->pageCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('pages');
684  }
685 
690  public function ‪initUserGroups()
691  {
692  $userAspect = $this->fe_user->createUserAspect((bool)$this->loginAllowedInBranch);
693  $this->context->setAspect('frontend.user', $userAspect);
694  }
695 
701  public function ‪isUserOrGroupSet()
702  {
704  $userAspect = $this->context->getAspect('frontend.user');
705  return $userAspect->isUserOrGroupSet();
706  }
707 
713  public function ‪clear_preview()
714  {
715  if ($this->‪isInPreviewMode()) {
716  ‪$GLOBALS['SIM_EXEC_TIME'] = ‪$GLOBALS['EXEC_TIME'];
717  ‪$GLOBALS['SIM_ACCESS_TIME'] = ‪$GLOBALS['ACCESS_TIME'];
718  $this->context->setAspect('frontend.preview', GeneralUtility::makeInstance(PreviewAspect::class));
719  $this->context->setAspect('date', GeneralUtility::makeInstance(DateTimeAspect::class, new \DateTimeImmutable('@' . ‪$GLOBALS['SIM_EXEC_TIME'])));
720  $this->context->setAspect('visibility', GeneralUtility::makeInstance(VisibilityAspect::class));
721  }
722  }
723 
729  public function ‪isBackendUserLoggedIn()
730  {
731  return (bool)$this->context->getPropertyFromAspect('backend.user', 'isLoggedIn', false);
732  }
733 
742  public function ‪determineId(ServerRequestInterface $request = null)
743  {
744  $request = $request ?? ‪$GLOBALS['TYPO3_REQUEST'] ?? ‪ServerRequestFactory::fromGlobals();
745  // Call pre processing function for id determination
746  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PreProcessing'] ?? [] as $functionReference) {
747  $parameters = ['parentObject' => $this];
748  GeneralUtility::callUserFunction($functionReference, $parameters, $this);
749  }
750  // If there is a Backend login we are going to check for any preview settings
751  $originalFrontendUserGroups = $this->‪applyPreviewSettings($this->‪getBackendUser());
752  // If the front-end is showing a preview, caching MUST be disabled.
753  $isPreview = $this->‪isInPreviewMode();
754  if ($isPreview) {
755  $this->‪disableCache();
756  }
757  // Now, get the id, validate access etc:
758  $this->‪fetch_the_id($request);
759  // Check if backend user has read access to this page. If not, recalculate the id.
760  if ($this->‪isBackendUserLoggedIn() && $isPreview && !$this->‪getBackendUser()->doesUserHaveAccess($this->page, ‪Permission::PAGE_SHOW)) {
761  $this->‪unsetBackendUser();
762  // Resetting
763  $this->‪clear_preview();
764  $this->fe_user->user[$this->fe_user->usergroup_column] = $originalFrontendUserGroups;
765  // Fetching the id again, now with the preview settings reset.
766  $this->‪fetch_the_id($request);
767  }
768  // Checks if user logins are blocked for a certain branch and if so, will unset user login and re-fetch ID.
769  $this->loginAllowedInBranch = $this->‪checkIfLoginAllowedInBranch();
770  // Logins are not allowed, but there is a login, so will we run this.
771  if (!$this->loginAllowedInBranch && $this->‪isUserOrGroupSet()) {
772  // Clear out user, and the group will be re-set in >initUserGroups() due to
773  // $this->loginAllowedInBranch = false
774  if ($this->loginAllowedInBranch_mode === 'all') {
775  $this->fe_user->hideActiveLogin();
776  }
777  // Fetching the id again, now with the preview settings reset and respecting $this->loginAllowedInBranch = false
778  $this->‪fetch_the_id($request);
779  }
780  // Final cleaning.
781  // Make sure it's an integer
782  $this->id = ($this->contentPid = (int)$this->id);
783  // Make sure it's an integer
784  $this->type = (int)$this->type;
785  // Setting language and fetch translated page
786  $this->‪settingLanguage($request);
787  // Call post processing function for id determination:
788  $_params = ['pObj' => &$this];
789  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PostProc'] ?? [] as $_funcRef) {
790  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
791  }
792  }
793 
794  protected function ‪unsetBackendUser(): void
795  {
796  // Register an empty backend user as aspect
797  unset(‪$GLOBALS['BE_USER']);
798  $this->context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class));
799  $this->context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class));
800  }
801 
815  protected function ‪applyPreviewSettings($backendUser = null)
816  {
817  if (!$backendUser) {
818  return null;
819  }
820  $originalFrontendUserGroup = null;
821  if ($this->fe_user->user) {
822  $originalFrontendUserGroup = $this->context->getPropertyFromAspect('frontend.user', 'groupIds');
823  }
824 
825  // The preview flag is set if the current page turns out to be hidden
826  if ($this->id && $this->‪determineIdIsHiddenPage()) {
827  $this->context->setAspect('frontend.preview', GeneralUtility::makeInstance(PreviewAspect::class, true));
829  $aspect = $this->context->getAspect('visibility');
830  $newAspect = GeneralUtility::makeInstance(VisibilityAspect::class, true, $aspect->includeHiddenContent(), $aspect->includeDeletedRecords());
831  $this->context->setAspect('visibility', $newAspect);
832  }
833  // The preview flag will be set if an offline workspace will be previewed
834  if ($this->‪whichWorkspace() > 0) {
835  $this->context->setAspect('frontend.preview', GeneralUtility::makeInstance(PreviewAspect::class, true));
836  }
837  return $this->context->getPropertyFromAspect('frontend.preview', 'preview', false) ? $originalFrontendUserGroup : null;
838  }
839 
846  protected function ‪determineIdIsHiddenPage()
847  {
848  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
849  ->getQueryBuilderForTable('pages');
850  $queryBuilder
851  ->getRestrictions()
852  ->removeAll()
853  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
854 
855  $queryBuilder
856  ->select('uid', 'hidden', 'starttime', 'endtime')
857  ->from('pages')
858  ->where(
859  $queryBuilder->expr()->gte('pid', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT))
860  )
861  ->setMaxResults(1);
862 
863  // $this->id always points to the ID of the default language page, so we check
864  // the current site language to determine if we need to fetch a translation but consider fallbacks
865  if ($this->language->getLanguageId() > 0) {
866  $languagesToCheck = array_merge([$this->language->getLanguageId()], $this->language->getFallbackLanguageIds());
867  // Check for the language and all its fallbacks
868  $constraint = $queryBuilder->expr()->andX(
869  $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT)),
870  $queryBuilder->expr()->in('sys_language_uid', $queryBuilder->createNamedParameter(array_filter($languagesToCheck), Connection::PARAM_INT_ARRAY))
871  );
872  // If the fallback language Ids also contains the default language, this needs to be considered
873  if (in_array(0, $languagesToCheck, true)) {
874  $constraint = $queryBuilder->expr()->orX(
875  $constraint,
876  // Ensure to also fetch the default record
877  $queryBuilder->expr()->andX(
878  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT)),
879  $queryBuilder->expr()->in('sys_language_uid', 0)
880  )
881  );
882  }
883  // Ensure that the translated records are shown first (maxResults is set to 1)
884  $queryBuilder->orderBy('sys_language_uid', 'DESC');
885  } else {
886  $constraint = $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT));
887  }
888  $queryBuilder->andWhere($constraint);
889 
890  ‪$page = $queryBuilder->executeQuery()->fetchAssociative();
891 
892  if ($this->‪whichWorkspace() > 0) {
893  // Fetch overlay of page if in workspace and check if it is hidden
894  $customContext = clone ‪$this->context;
895  $customContext->‪setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $this->‪whichWorkspace()));
896  $customContext->setAspect('visibility', GeneralUtility::makeInstance(VisibilityAspect::class));
897  $pageSelectObject = GeneralUtility::makeInstance(PageRepository::class, $customContext);
898  $targetPage = $pageSelectObject->getWorkspaceVersionOfRecord($this->‪whichWorkspace(), 'pages', ‪$page['uid']);
899  // Also checks if the workspace version is NOT hidden but the live version is in fact still hidden
900  $result = $targetPage === -1 || $targetPage === -2 || (is_array($targetPage) && $targetPage['hidden'] == 0 && ‪$page['hidden'] == 1);
901  } else {
902  $result = is_array(‪$page) && (‪$page['hidden'] || ‪$page['starttime'] > ‪$GLOBALS['SIM_EXEC_TIME'] || ‪$page['endtime'] != 0 && ‪$page['endtime'] <= ‪$GLOBALS['SIM_EXEC_TIME']);
903  }
904  return $result;
905  }
906 
966  protected function ‪fetch_the_id(ServerRequestInterface $request = null)
967  {
968  $request = $request ?? ‪$GLOBALS['TYPO3_REQUEST'] ?? ‪ServerRequestFactory::fromGlobals();
969  $timeTracker = $this->‪getTimeTracker();
970  $timeTracker->push('fetch_the_id initialize/');
971  // Set the valid usergroups for FE
972  $this->‪initUserGroups();
973  // Initialize the PageRepository has to be done after the frontend usergroups are initialized / resolved, as
974  // frontend group aspect is modified before
975  $this->sys_page = GeneralUtility::makeInstance(PageRepository::class, $this->context);
976  // The id and type is set to the integer-value - just to be sure...
977  $this->id = (int)$this->id;
978  $this->type = (int)$this->type;
979  $timeTracker->pull();
980  // We find the first page belonging to the current domain
981  $timeTracker->push('fetch_the_id domain/');
982  if (!$this->id) {
983  // If the id was not previously set, set it to the root page id of the site.
984  $this->id = $this->site->getRootPageId();
985  }
986  $timeTracker->pull();
987  $timeTracker->push('fetch_the_id rootLine/');
988  // We store the originally requested id
989  $this->requestedId = ‪$this->id;
990  try {
991  $this->‪getPageAndRootlineWithDomain($this->site->getRootPageId(), $request);
992  } catch (ShortcutTargetPageNotFoundException $e) {
993  $this->pageNotFound = 1;
994  }
995  $timeTracker->pull();
996  if ($this->pageNotFound) {
997  switch ($this->pageNotFound) {
998  case 1:
999  $response = GeneralUtility::makeInstance(ErrorController::class)->accessDeniedAction(
1000  $request,
1001  'ID was not an accessible page',
1003  );
1004  break;
1005  case 2:
1006  $response = GeneralUtility::makeInstance(ErrorController::class)->accessDeniedAction(
1007  $request,
1008  'Subsection was found and not accessible',
1010  );
1011  break;
1012  case 3:
1013  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1014  $request,
1015  'ID was outside the domain',
1017  );
1018  break;
1019  default:
1020  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1021  $request,
1022  'Unspecified error',
1024  );
1025  }
1026  throw new ‪PropagateResponseException($response, 1533931329);
1027  }
1028 
1029  $this->‪setRegisterValueForSysLastChanged($this->page);
1030 
1031  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['fetchPageId-PostProcessing'] ?? [] as $functionReference) {
1032  $parameters = ['parentObject' => $this];
1033  GeneralUtility::callUserFunction($functionReference, $parameters, $this);
1034  }
1035  }
1036 
1081  protected function ‪getPageAndRootline(ServerRequestInterface $request)
1082  {
1083  $requestedPageRowWithoutGroupCheck = [];
1084  $this->‪resolveTranslatedPageId();
1085  if (empty($this->page)) {
1086  // If no page, we try to find the page above in the rootLine.
1087  // Page is 'not found' in case the id itself was not an accessible page. code 1
1088  $this->pageNotFound = 1;
1089  $requestedPageIsHidden = false;
1090  try {
1091  $hiddenField = ‪$GLOBALS['TCA']['pages']['ctrl']['enablecolumns']['disabled'] ?? '';
1092  $includeHiddenPages = $this->context->getPropertyFromAspect('visibility', 'includeHiddenPages') || $this->‪isBackendUserLoggedIn();
1093  if (!empty($hiddenField) && !$includeHiddenPages) {
1094  // Page is "hidden" => 404 (deliberately done in default language, as this cascades to language overlays)
1095  $rawPageRecord = $this->sys_page->getPage_noCheck($this->id);
1096 
1097  // If page record could not be resolved throw exception
1098  if ($rawPageRecord === []) {
1099  $message = 'The requested page does not exist!';
1100  try {
1101  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1102  $request,
1103  $message,
1105  );
1106  throw new PropagateResponseException($response, 1674144383);
1107  } catch (PageNotFoundException $e) {
1108  throw new PageNotFoundException($message, 1674539331);
1109  }
1110  }
1111 
1112  $requestedPageIsHidden = (bool)$rawPageRecord[$hiddenField];
1113  }
1114 
1115  $requestedPageRowWithoutGroupCheck = $this->sys_page->getPage($this->id, true);
1116  if (!empty($requestedPageRowWithoutGroupCheck)) {
1117  $this->pageAccessFailureHistory['direct_access'][] = $requestedPageRowWithoutGroupCheck;
1118  }
1119  $this->rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $this->id, $this->MP, $this->context)->get();
1120  if (!empty($this->rootLine)) {
1121  $c = count($this->rootLine) - 1;
1122  while ($c > 0) {
1123  // Add to page access failure history:
1124  $this->pageAccessFailureHistory['direct_access'][] = $this->rootLine[$c];
1125  // Decrease to next page in rootline and check the access to that, if OK, set as page record and ID value.
1126  $c--;
1127  $this->id = $this->rootLine[$c]['uid'];
1128  $this->page = $this->sys_page->getPage($this->id);
1129  if (!empty($this->page)) {
1130  break;
1131  }
1132  }
1133  }
1134  } catch (RootLineException $e) {
1135  $this->rootLine = [];
1136  }
1137  // If still no page...
1138  if ($requestedPageIsHidden || (empty($requestedPageRowWithoutGroupCheck) && empty($this->page))) {
1139  $message = 'The requested page does not exist!';
1140  try {
1141  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1142  $request,
1143  $message,
1145  );
1146  throw new PropagateResponseException($response, 1533931330);
1147  } catch (PageNotFoundException $e) {
1148  throw new PageNotFoundException($message, 1301648780);
1149  }
1150  }
1151  }
1152  // Spacer and sysfolders is not accessible in frontend
1153  $pageDoktype = (int)($this->page['doktype'] ?? 0);
1154  $isSpacerOrSysfolder = $pageDoktype === ‪PageRepository::DOKTYPE_SPACER || $pageDoktype === ‪PageRepository::DOKTYPE_SYSFOLDER;
1155  // Page itself is not accessible, but the parent page is a spacer/sysfolder
1156  if ($isSpacerOrSysfolder && !empty($requestedPageRowWithoutGroupCheck)) {
1157  try {
1158  $response = GeneralUtility::makeInstance(ErrorController::class)->accessDeniedAction(
1159  $request,
1160  'Subsection was found and not accessible',
1162  );
1163  throw new PropagateResponseException($response, 1633171038);
1164  } catch (PageNotFoundException $e) {
1165  throw new PageNotFoundException('Subsection was found and not accessible', 1633171172);
1166  }
1167  }
1168 
1169  if ($isSpacerOrSysfolder) {
1170  $message = 'The requested page does not exist!';
1171  try {
1172  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1173  $request,
1174  $message,
1176  );
1177  throw new PropagateResponseException($response, 1533931343);
1178  } catch (PageNotFoundException $e) {
1179  throw new PageNotFoundException($message, 1301648781);
1180  }
1181  }
1182  // Is the ID a link to another page??
1183  if ($pageDoktype === ‪PageRepository::DOKTYPE_SHORTCUT) {
1184  // We need to clear MP if the page is a shortcut. Reason is if the shortcut goes to another page, then we LEAVE the rootline which the MP expects.
1185  $this->MP = '';
1186  // saving the page so that we can check later - when we know
1187  // about languages - whether we took the correct shortcut or
1188  // whether a translation of the page overwrites the shortcut
1189  // target and we need to follow the new target
1190  $this->originalShortcutPage = ‪$this->page;
1191  $this->page = $this->sys_page->resolveShortcutPage($this->page, true);
1192  $this->id = (int)$this->page['uid'];
1193  $pageDoktype = (int)($this->page['doktype'] ?? 0);
1194  }
1195  // If the page is a mountpoint which should be overlaid with the contents of the mounted page,
1196  // it must never be accessible directly, but only in the mountpoint context. Therefore we change
1197  // the current ID and the user is redirected by checkPageForMountpointRedirect().
1198  if ($pageDoktype === ‪PageRepository::DOKTYPE_MOUNTPOINT && $this->page['mount_pid_ol']) {
1199  $this->originalMountPointPage = ‪$this->page;
1200  $this->page = $this->sys_page->getPage($this->page['mount_pid']);
1201  if (empty($this->page)) {
1202  $message = 'This page (ID ' . $this->originalMountPointPage['uid'] . ') is of type "Mount point" and '
1203  . 'mounts a page which is not accessible (ID ' . $this->originalMountPointPage['mount_pid'] . ').';
1204  throw new PageNotFoundException($message, 1402043263);
1205  }
1206  // If the current page is a shortcut, the MP parameter will be replaced
1207  if ($this->MP === '' || !empty($this->originalShortcutPage)) {
1208  $this->MP = $this->page['uid'] . '-' . $this->originalMountPointPage['uid'];
1209  } else {
1210  $this->MP .= ',' . $this->page['uid'] . '-' . $this->originalMountPointPage['uid'];
1211  }
1212  $this->id = (int)$this->page['uid'];
1213  $pageDoktype = (int)($this->page['doktype'] ?? 0);
1214  }
1215  // Gets the rootLine
1216  try {
1217  $this->rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $this->id, $this->MP, $this->context)->get();
1218  } catch (RootLineException $e) {
1219  $this->rootLine = [];
1220  }
1221  // If not rootline we're off...
1222  if (empty($this->rootLine)) {
1223  $message = 'The requested page didn\'t have a proper connection to the tree-root!';
1224  $this->‪logPageAccessFailure($message, $request);
1225  try {
1226  $response = GeneralUtility::makeInstance(ErrorController::class)->internalErrorAction(
1227  $request,
1228  $message,
1230  );
1231  throw new PropagateResponseException($response, 1533931350);
1232  } catch (AbstractServerErrorException $e) {
1233  $this->logger->error($message, ['exception' => $e]);
1234  $exceptionClass = get_class($e);
1235  throw new $exceptionClass($message, 1301648167);
1236  }
1237  }
1238  // Checking for include section regarding the hidden/starttime/endtime/fe_user (that is access control of a whole subbranch!)
1239  if ($this->‪checkRootlineForIncludeSection()) {
1240  if (empty($this->rootLine)) {
1241  $message = 'The requested page does not exist!';
1242  try {
1243  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1244  $request,
1245  $message,
1247  );
1248  throw new ‪PropagateResponseException($response, 1533931351);
1249  } catch (‪AbstractServerErrorException $e) {
1250  $this->logger->warning($message);
1251  $exceptionClass = get_class($e);
1252  throw new $exceptionClass($message, 1301648234);
1253  }
1254  } else {
1255  $el = reset($this->rootLine);
1256  $this->id = $el['uid'];
1257  $this->page = $this->sys_page->getPage($this->id);
1258  try {
1259  $this->rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $this->id, $this->MP, $this->context)->get();
1260  } catch (RootLineException $e) {
1261  $this->rootLine = [];
1262  }
1263  }
1264  }
1265  }
1266 
1273  protected function ‪resolveTranslatedPageId()
1274  {
1275  $this->page = $this->sys_page->getPage($this->id);
1276  // Accessed a default language page record, nothing to resolve
1277  if (empty($this->page) || (int)$this->page[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']] === 0) {
1278  return;
1279  }
1280  $languageId = (int)$this->page[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']];
1281  $this->page = $this->sys_page->getPage($this->page[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']]);
1282  $this->context->setAspect('language', GeneralUtility::makeInstance(LanguageAspect::class, $languageId));
1283  $this->id = $this->page['uid'] ?? 0;
1284  }
1285 
1310  protected function ‪checkRootlineForIncludeSection(): bool
1311  {
1312  $c = count($this->rootLine);
1313  $removeTheRestFlag = false;
1314  for ($a = 0; $a < $c; $a++) {
1315  if (!$this->‪checkPagerecordForIncludeSection($this->rootLine[$a])) {
1316  // Add to page access failure history and mark the page as not found
1317  // Keep the rootline however to trigger an access denied error instead of a service unavailable error
1318  $this->pageAccessFailureHistory['sub_section'][] = $this->rootLine[$a];
1319  $this->pageNotFound = 2;
1320  }
1321 
1322  if ((int)$this->rootLine[$a]['doktype'] === ‪PageRepository::DOKTYPE_BE_USER_SECTION) {
1323  // If there is a backend user logged in, check if they have read access to the page:
1324  if ($this->‪isBackendUserLoggedIn()) {
1325  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1326  ->getQueryBuilderForTable('pages');
1327 
1328  $queryBuilder
1329  ->getRestrictions()
1330  ->removeAll();
1331 
1332  $row = $queryBuilder
1333  ->select('uid')
1334  ->from('pages')
1335  ->where(
1336  $queryBuilder->expr()->eq(
1337  'uid',
1338  $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT)
1339  ),
1340  $this->getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW)
1341  )
1342  ->executeQuery()
1343  ->fetchAssociative();
1344 
1345  // versionOL()?
1346  if (!$row) {
1347  // If there was no page selected, the user apparently did not have read access to the current PAGE (not position in rootline) and we set the remove-flag...
1348  $removeTheRestFlag = true;
1349  }
1350  } else {
1351  // Don't go here, if there is no backend user logged in.
1352  $removeTheRestFlag = true;
1353  }
1354  } elseif ((int)$this->rootLine[$a]['doktype'] === ‪PageRepository::DOKTYPE_RECYCLER) {
1355  // page is in a recycler
1356  $removeTheRestFlag = true;
1357  }
1358  if ($removeTheRestFlag) {
1359  // Page is 'not found' in case a subsection was found and not accessible, code 2
1360  $this->pageNotFound = 2;
1361  unset($this->rootLine[$a]);
1362  }
1363  }
1364  return $removeTheRestFlag;
1365  }
1366 
1378  public function ‪checkEnableFields($row, $bypassGroupCheck = false)
1379  {
1380  $_params = ['pObj' => $this, 'row' => &$row, 'bypassGroupCheck' => &$bypassGroupCheck];
1381  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_checkEnableFields'] ?? [] as $_funcRef) {
1382  // Call hooks: If one returns FALSE, method execution is aborted with result "This record is not available"
1383  $return = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1384  if ($return === false) {
1385  return false;
1386  }
1387  }
1388  if ((!$row['hidden'] || $this->context->getPropertyFromAspect('visibility', 'includeHiddenPages', false))
1389  && $row['starttime'] <= ‪$GLOBALS['SIM_ACCESS_TIME']
1390  && ($row['endtime'] == 0 || $row['endtime'] > ‪$GLOBALS['SIM_ACCESS_TIME'])
1391  && ($bypassGroupCheck || $this->checkPageGroupAccess($row))) {
1392  return true;
1393  }
1394  return false;
1395  }
1396 
1404  public function ‪checkPageGroupAccess($row)
1405  {
1407  $userAspect = $this->context->getAspect('frontend.user');
1408  $pageGroupList = explode(',', $row['fe_group'] ?: 0);
1409  return count(array_intersect($userAspect->getGroupIds(), $pageGroupList)) > 0;
1410  }
1411 
1427  public function ‪checkPagerecordForIncludeSection(array $row): bool
1428  {
1429  return !$row['extendToSubpages'] || $this->‪checkEnableFields($row);
1430  }
1431 
1437  public function ‪checkIfLoginAllowedInBranch()
1438  {
1439  // Initialize:
1440  $c = count($this->rootLine);
1441  $loginAllowed = true;
1442  // Traverse root line from root and outwards:
1443  for ($a = 0; $a < $c; $a++) {
1444  // If a value is set for login state:
1445  if ($this->rootLine[$a]['fe_login_mode'] > 0) {
1446  // Determine state from value:
1447  if ((int)$this->rootLine[$a]['fe_login_mode'] === 1) {
1448  $loginAllowed = false;
1449  $this->loginAllowedInBranch_mode = 'all';
1450  } elseif ((int)$this->rootLine[$a]['fe_login_mode'] === 3) {
1451  $loginAllowed = false;
1452  $this->loginAllowedInBranch_mode = 'groups';
1453  } else {
1454  $loginAllowed = true;
1455  }
1456  }
1457  }
1458  return $loginAllowed;
1459  }
1460 
1467  public function ‪getPageAccessFailureReasons(string $failureReasonCode = null)
1468  {
1469  ‪$output = [];
1470  if ($failureReasonCode) {
1471  ‪$output['code'] = $failureReasonCode;
1472  }
1473  $combinedRecords = array_merge(
1474  is_array($this->pageAccessFailureHistory['direct_access'] ?? false) ? $this->pageAccessFailureHistory['direct_access'] : [['fe_group' => 0]],
1475  is_array($this->pageAccessFailureHistory['sub_section'] ?? false) ? $this->pageAccessFailureHistory['sub_section'] : []
1476  );
1477  if (!empty($combinedRecords)) {
1478  foreach ($combinedRecords as $k => $pagerec) {
1479  // If $k=0 then it is the very first page the original ID was pointing at and that will get a full check of course
1480  // If $k>0 it is parent pages being tested. They are only significant for the access to the first page IF they had the extendToSubpages flag set, hence checked only then!
1481  if (!$k || $pagerec['extendToSubpages']) {
1482  if ($pagerec['hidden'] ?? false) {
1483  ‪$output['hidden'][$pagerec['uid']] = true;
1484  }
1485  if (isset($pagerec['starttime']) && $pagerec['starttime'] > ‪$GLOBALS['SIM_ACCESS_TIME']) {
1486  ‪$output['starttime'][$pagerec['uid']] = $pagerec['starttime'];
1487  }
1488  if (isset($pagerec['endtime']) && $pagerec['endtime'] != 0 && $pagerec['endtime'] <= ‪$GLOBALS['SIM_ACCESS_TIME']) {
1489  ‪$output['endtime'][$pagerec['uid']] = $pagerec['endtime'];
1490  }
1491  if (!$this->‪checkPageGroupAccess($pagerec)) {
1492  ‪$output['fe_group'][$pagerec['uid']] = $pagerec['fe_group'];
1493  }
1494  }
1495  }
1496  }
1497  return ‪$output;
1498  }
1499 
1507  protected function ‪getPageAndRootlineWithDomain($rootPageId, ServerRequestInterface $request)
1508  {
1509  $this->‪getPageAndRootline($request);
1510  $rootPageId = (int)$rootPageId;
1511  // Checks if the $domain-startpage is in the rootLine. This is necessary so that references to page-id's via ?id=123 from other sites are not possible.
1512  if (is_array($this->rootLine) && $this->rootLine !== []) {
1513  $idFound = false;
1514  foreach ($this->rootLine as $pageInRootLine) {
1515  if ((int)$pageInRootLine['uid'] === $rootPageId) {
1516  $idFound = true;
1517  break;
1518  }
1519  }
1520  if (!$idFound) {
1521  // Page is 'not found' in case the id was outside the domain, code 3
1522  // This can only happen if there was a shortcut. So $this->page is now the shortcut target
1523  // But the original page is in $this->originalShortcutPage.
1524  // This only happens if people actually call TYPO3 with index.php?id=123 where 123 is in a different
1525  // page tree. This is not allowed.
1526  $directlyRequestedId = (int)($request->getQueryParams()['id'] ?? 0);
1527  if ($directlyRequestedId && (int)($this->originalShortcutPage['uid'] ?? 0) !== $directlyRequestedId) {
1528  $this->pageNotFound = 3;
1529  $this->id = $rootPageId;
1530  // re-get the page and rootline if the id was not found.
1531  $this->‪getPageAndRootline($request);
1532  }
1533  }
1534  }
1535  }
1536 
1537  /********************************************
1538  *
1539  * Template and caching related functions.
1540  *
1541  *******************************************/
1542 
1543  protected function ‪setPageArguments(PageArguments ‪$pageArguments): void
1544  {
1545  $this->pageArguments = ‪$pageArguments;
1546  $this->id = $pageArguments->‪getPageId();
1547  $this->type = ‪$pageArguments->‪getPageType() ?: 0;
1548  if (‪$GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids']) {
1549  $this->MP = (string)(‪$pageArguments->getArguments()['MP'] ?? '');
1550  // Ensure no additional arguments are given via the &MP=123-345,908-172 (e.g. "/")
1551  $this->MP = preg_replace('/[^0-9,-]/', '', $this->MP);
1552  }
1553  }
1554 
1562  protected function ‪getRelevantParametersForCachingFromPageArguments(PageArguments ‪$pageArguments): array
1563  {
1564  $queryParams = ‪$pageArguments->getDynamicArguments();
1565  if (!empty($queryParams) && (‪$pageArguments->getArguments()['cHash'] ?? false)) {
1566  $queryParams['id'] = ‪$pageArguments->‪getPageId();
1567  return GeneralUtility::makeInstance(CacheHashCalculator::class)
1568  ->getRelevantParameters(‪HttpUtility::buildQueryString($queryParams));
1569  }
1570  return [];
1571  }
1572 
1580  public function ‪getFromCache(ServerRequestInterface $request = null)
1581  {
1582  // clearing the content-variable, which will hold the pagecontent
1583  $this->content = '';
1584  // Unsetting the lowlevel config
1585  $this->config = [];
1586  $this->cacheContentFlag = false;
1587 
1588  if ($this->no_cache) {
1589  return;
1590  }
1591 
1592  if (!$this->tmpl instanceof TemplateService) {
1593  $this->tmpl = GeneralUtility::makeInstance(TemplateService::class, $this->context, null, $this);
1594  }
1595 
1596  $pageSectionCacheContent = $this->tmpl->getCurrentPageData((int)$this->id, (string)$this->MP);
1597  if (!is_array($pageSectionCacheContent)) {
1598  // Nothing in the cache, we acquire an "exclusive lock" for the key now.
1599  // We use the Registry to store this lock centrally,
1600  // but we protect the access again with a global exclusive lock to avoid race conditions
1601 
1602  $this->‪acquireLock('pagesection', $this->id . '::' . $this->MP);
1603  //
1604  // from this point on we're the only one working on that page ($key)
1605  //
1606 
1607  // query the cache again to see if the page data are there meanwhile
1608  $pageSectionCacheContent = $this->tmpl->getCurrentPageData((int)$this->id, (string)$this->MP);
1609  if (is_array($pageSectionCacheContent)) {
1610  // we have the content, nice that some other process did the work for us already
1611  $this->‪releaseLock('pagesection');
1612  }
1613  // We keep the lock set, because we are the ones generating the page now and filling the cache.
1614  // This indicates that we have to release the lock later in releaseLocks()
1615  }
1617  if (is_array($pageSectionCacheContent)) {
1618  // BE CAREFUL to change the content of the cc-array. This array is serialized and an md5-hash based on this is used for caching the page.
1619  // If this hash is not the same in here in this section and after page-generation, then the page will not be properly cached!
1620  // This array is an identification of the template. If $this->all is empty it's because the template-data is not cached, which it must be.
1621  $pageSectionCacheContent = $this->tmpl->matching($pageSectionCacheContent);
1622  ksort($pageSectionCacheContent);
1623  $this->all = $pageSectionCacheContent;
1624  }
1625 
1626  // Look for page in cache only if a shift-reload is not sent to the server.
1627  $lockHash = $this->‪getLockHash();
1628  if (!$this->‪headerNoCache($request) && $this->all) {
1629  // we got page section information (TypoScript), so lets see if there is also a cached version
1630  // of this page in the pages cache.
1631  $this->newHash = $this->‪getHash();
1632  $this->‪getTimeTracker()->‪push('Cache Row');
1633  $row = $this->‪getFromCache_queryRow();
1634  if (!is_array($row)) {
1635  // nothing in the cache, we acquire an exclusive lock now
1636  $this->‪acquireLock('pages', $lockHash);
1637  //
1638  // from this point on we're the only one working on that page ($lockHash)
1639  //
1640 
1641  // query the cache again to see if the data are there meanwhile
1642  $row = $this->‪getFromCache_queryRow();
1643  if (is_array($row)) {
1644  // we have the content, nice that some other process did the work for us
1645  $this->‪releaseLock('pages');
1646  }
1647  // We keep the lock set, because we are the ones generating the page now and filling the cache.
1648  // This indicates that we have to release the lock later in releaseLocks()
1649  }
1650  if (is_array($row)) {
1651  $this->‪populatePageDataFromCache($row);
1652  }
1653  $this->‪getTimeTracker()->‪pull();
1654  } else {
1655  // the user forced rebuilding the page cache or there was no pagesection information
1656  // get a lock for the page content so other processes will not interrupt the regeneration
1657  $this->‪acquireLock('pages', $lockHash);
1658  }
1659  }
1660 
1666  public function ‪getFromCache_queryRow()
1667  {
1668  $this->‪getTimeTracker()->‪push('Cache Query');
1669  $row = $this->pageCache->get($this->newHash);
1670  $this->‪getTimeTracker()->‪pull();
1671  return $row;
1672  }
1673 
1684  protected function ‪populatePageDataFromCache(array $cachedData): void
1685  {
1686  // Call hook when a page is retrieved from cache
1687  $_params = ['pObj' => &$this, 'cache_pages_row' => &$cachedData];
1688  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageLoadedFromCache'] ?? [] as $_funcRef) {
1689  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1690  }
1691  // Fetches the lowlevel config stored with the cached data
1692  $this->config = $cachedData['cache_data'];
1693  // Getting the content
1694  $this->content = $cachedData['content'];
1695  // Getting the content type
1696  $this->contentType = $cachedData['contentType'] ?? ‪$this->contentType;
1697  // Setting flag, so we know, that some cached content has been loaded
1698  $this->cacheContentFlag = true;
1699  $this->cacheExpires = $cachedData['expires'];
1700  // Restore the current tags as they can be retrieved by getPageCacheTags()
1701  $this->pageCacheTags = $cachedData['cacheTags'] ?? [];
1702 
1703  // Restore page title information, this is needed to generate the page title for
1704  // partially cached pages.
1705  $this->page['title'] = $cachedData['pageTitleInfo']['title'];
1706  $this->indexedDocTitle = $cachedData['pageTitleInfo']['indexedDocTitle'];
1707 
1708  if (isset($this->config['config']['debug'])) {
1709  $debugCacheTime = (bool)$this->config['config']['debug'];
1710  } else {
1711  $debugCacheTime = !empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['debug']);
1712  }
1713  if ($debugCacheTime) {
1714  $this->‪prepareDebugInformationForCachedPage($cachedData);
1715  }
1716  }
1717 
1718  protected function ‪prepareDebugInformationForCachedPage(array $cachedData): void
1719  {
1720  $dateFormat = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
1721  $timeFormat = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
1722  $this->debugInformationHeader = 'Cached page generated ' . date($dateFormat . ' ' . $timeFormat, $cachedData['tstamp']) . '. Expires ' . date($dateFormat . ' ' . $timeFormat, $cachedData['expires']);
1723  }
1733  public function ‪headerNoCache(ServerRequestInterface $request = null)
1734  {
1735  if ($request instanceof ServerRequestInterface) {
1736  $serverParams = $request->getServerParams();
1737  } else {
1738  $serverParams = $_SERVER;
1739  }
1740  $disableAcquireCacheData = false;
1741  if ($this->‪isBackendUserLoggedIn()) {
1742  if (strtolower($serverParams['HTTP_CACHE_CONTROL'] ?? '') === 'no-cache' || strtolower($serverParams['HTTP_PRAGMA'] ?? '') === 'no-cache') {
1743  $disableAcquireCacheData = true;
1744  }
1745  }
1746  // Call hook for possible by-pass of requiring of page cache (for recaching purpose)
1747  $_params = ['pObj' => &$this, 'disableAcquireCacheData' => &$disableAcquireCacheData];
1748  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['headerNoCache'] ?? [] as $_funcRef) {
1749  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1750  }
1751  return $disableAcquireCacheData;
1752  }
1753 
1763  protected function ‪getHash()
1764  {
1765  return $this->id . '_' . md5($this->‪createHashBase(false));
1766  }
1767 
1776  protected function ‪getLockHash()
1777  {
1778  $lockHash = $this->‪createHashBase(true);
1779  return $this->id . '_' . md5($lockHash);
1780  }
1781 
1792  protected function ‪createHashBase($createLockHashBase = false)
1793  {
1794  // Fetch the list of user groups
1796  $userAspect = $this->context->getAspect('frontend.user');
1797  $hashParameters = [
1798  'id' => (int)$this->id,
1799  'type' => (int)‪$this->type,
1800  'groupIds' => (string)implode(',', $userAspect->getGroupIds()),
1801  'MP' => (string)‪$this->MP,
1802  'site' => $this->site->getIdentifier(),
1803  // Ensure the language base is used for the hash base calculation as well, otherwise TypoScript and page-related rendering
1804  // is not cached properly as we don't have any language-specific conditions anymore
1805  'siteBase' => (string)$this->language->getBase(),
1806  // additional variation trigger for static routes
1807  'staticRouteArguments' => $this->pageArguments->getStaticArguments(),
1808  // dynamic route arguments (if route was resolved)
1809  'dynamicArguments' => $this->‪getRelevantParametersForCachingFromPageArguments($this->pageArguments),
1810  ];
1811  // Include the template information if we shouldn't create a lock hash
1812  if (!$createLockHashBase) {
1813  $hashParameters['all'] = ‪$this->all;
1814  }
1815  // Call hook to influence the hash calculation
1816  $_params = [
1817  'hashParameters' => &$hashParameters,
1818  'createLockHashBase' => $createLockHashBase,
1819  ];
1820  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['createHashBase'] ?? [] as $_funcRef) {
1821  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1822  }
1823  return serialize($hashParameters);
1824  }
1825 
1833  public function ‪getConfigArray(ServerRequestInterface $request = null)
1834  {
1835  $request = $request ?? ‪$GLOBALS['TYPO3_REQUEST'] ?? ‪ServerRequestFactory::fromGlobals();
1836  if (!$this->tmpl instanceof TemplateService) {
1837  $this->tmpl = GeneralUtility::makeInstance(TemplateService::class, $this->context, null, $this);
1838  }
1839 
1840  // If config is not set by the cache (which would be a major mistake somewhere) OR if INTincScripts-include-scripts have been registered, then we must parse the template in order to get it
1841  if (empty($this->config) || $this->‪isINTincScript() || $this->context->getPropertyFromAspect('typoscript', 'forcedTemplateParsing')) {
1842  $timeTracker = $this->‪getTimeTracker();
1843  $timeTracker->push('Parse template');
1844  // Start parsing the TS template. Might return cached version.
1845  $this->tmpl->start($this->rootLine);
1846  $timeTracker->pull();
1847  // At this point we have a valid pagesection_cache (generated in $this->tmpl->start()),
1848  // so let all other processes proceed now. (They are blocked at the pagessection_lock in getFromCache())
1849  $this->‪releaseLock('pagesection');
1850  if ($this->tmpl->loaded) {
1851  $timeTracker->push('Setting the config-array');
1852  // toplevel - objArrayName
1853  $typoScriptPageTypeName = $this->tmpl->setup['types.'][‪$this->type] ?? '';
1854  $this->sPre = $typoScriptPageTypeName;
1855  $this->pSetup = $this->tmpl->setup[$typoScriptPageTypeName . '.'] ?? '';
1856  if (!is_array($this->pSetup)) {
1857  $this->logger->alert('The page is not configured! [type={type}][{type_name}].', ['type' => $this->type, 'type_name' => $typoScriptPageTypeName]);
1858  try {
1859  $message = 'The page is not configured! [type=' . $this->type . '][' . $typoScriptPageTypeName . '].';
1860  $response = GeneralUtility::makeInstance(ErrorController::class)->internalErrorAction(
1861  $request,
1862  $message,
1864  );
1865  throw new PropagateResponseException($response, 1533931374);
1866  } catch (AbstractServerErrorException $e) {
1867  $explanation = 'This means that there is no TypoScript object of type PAGE with typeNum=' . $this->type . ' configured.';
1868  $exceptionClass = get_class($e);
1869  throw new $exceptionClass($message . ' ' . $explanation, 1294587217);
1870  }
1871  } else {
1872  if (!isset($this->config['config'])) {
1873  $this->config['config'] = [];
1874  }
1875  // Filling the config-array, first with the main "config." part
1876  if (is_array($this->tmpl->setup['config.'] ?? null)) {
1877  ‪ArrayUtility::mergeRecursiveWithOverrule($this->tmpl->setup['config.'], $this->config['config']);
1878  $this->config['config'] = $this->tmpl->setup['config.'];
1879  }
1880  // override it with the page/type-specific "config."
1881  if (is_array($this->pSetup['config.'] ?? null)) {
1882  ‪ArrayUtility::mergeRecursiveWithOverrule($this->config['config'], $this->pSetup['config.']);
1883  }
1884  // Set default values for removeDefaultJS and inlineStyle2TempFile so CSS and JS are externalized if compatversion is higher than 4.0
1885  if (!isset($this->config['config']['removeDefaultJS'])) {
1886  $this->config['config']['removeDefaultJS'] = 'external';
1887  }
1888  if (!isset($this->config['config']['inlineStyle2TempFile'])) {
1889  $this->config['config']['inlineStyle2TempFile'] = 1;
1890  }
1891 
1892  if (!isset($this->config['config']['compressJs'])) {
1893  $this->config['config']['compressJs'] = 0;
1894  }
1895  // Rendering charset of HTML page.
1896  if (isset($this->config['config']['metaCharset']) && $this->config['config']['metaCharset'] !== 'utf-8') {
1897  $this->metaCharset = $this->config['config']['metaCharset'];
1898  }
1899  // Setting default cache_timeout
1900  if (isset($this->config['config']['cache_period'])) {
1901  $this->‪set_cache_timeout_default((int)$this->config['config']['cache_period']);
1902  }
1903 
1904  // Processing for the config_array:
1905  $this->config['rootLine'] = $this->tmpl->rootLine;
1906  // Class for render Header and Footer parts
1907  if ($this->pSetup['pageHeaderFooterTemplateFile'] ?? false) {
1908  try {
1909  $file = GeneralUtility::makeInstance(FilePathSanitizer::class)
1910  ->sanitize((string)$this->pSetup['pageHeaderFooterTemplateFile'], true);
1911  $this->pageRenderer->setTemplateFile($file);
1912  } catch (Exception $e) {
1913  // do nothing
1914  }
1915  }
1916  }
1917  $timeTracker->pull();
1918  } else {
1919  $message = 'No TypoScript template found!';
1920  $this->logger->alert($message);
1921  try {
1922  $response = GeneralUtility::makeInstance(ErrorController::class)->internalErrorAction(
1923  $request,
1924  $message,
1926  );
1927  throw new PropagateResponseException($response, 1533931380);
1928  } catch (AbstractServerErrorException $e) {
1929  $exceptionClass = get_class($e);
1930  throw new $exceptionClass($message, 1294587218);
1931  }
1932  }
1933  }
1934 
1935  // No cache
1936  // Set $this->no_cache TRUE if the config.no_cache value is set!
1937  if ($this->config['config']['no_cache'] ?? false) {
1938  $this->‪set_no_cache('config.no_cache is set', true);
1939  }
1940 
1941  // Auto-configure settings when a site is configured
1942  $this->config['config']['absRefPrefix'] = $this->config['config']['absRefPrefix'] ?? 'auto';
1943 
1944  // Hook for postProcessing the configuration array
1945  $params = ['config' => &$this->config['config']];
1946  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['configArrayPostProc'] ?? [] as $funcRef) {
1947  GeneralUtility::callUserFunction($funcRef, $params, $this);
1948  }
1949  }
1950 
1951  /********************************************
1952  *
1953  * Further initialization and data processing
1954  *
1955  *******************************************/
1963  protected function ‪settingLanguage(ServerRequestInterface $request)
1964  {
1965  $_params = [];
1966  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_preProcess'] ?? [] as $_funcRef) {
1967  $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
1968  GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
1969  }
1970 
1971  // Get values from site language
1972  $languageAspect = ‪LanguageAspectFactory::createFromSiteLanguage($this->language);
1973 
1974  $languageId = $languageAspect->getId();
1975  $languageContentId = $languageAspect->getContentId();
1976 
1977  $pageTranslationVisibility = new PageTranslationVisibility((int)($this->page['l18n_cfg'] ?? 0));
1978  // If sys_language_uid is set to another language than default:
1979  if ($languageAspect->getId() > 0) {
1980  // check whether a shortcut is overwritten by a translated page
1981  // we can only do this now, as this is the place where we get
1982  // to know about translations
1983  $this->‪checkTranslatedShortcut($languageAspect->getId(), $request);
1984  // Request the overlay record for the sys_language_uid:
1985  $olRec = $this->sys_page->getPageOverlay($this->id, $languageAspect->getId());
1986  if (empty($olRec)) {
1987  // If requested translation is not available:
1988  if ($pageTranslationVisibility->shouldHideTranslationIfNoTranslatedRecordExists()) {
1989  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1990  $request,
1991  'Page is not available in the requested language.',
1993  );
1994  throw new PropagateResponseException($response, 1533931388);
1995  }
1996  switch ((string)$languageAspect->getLegacyLanguageMode()) {
1997  case 'strict':
1998  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
1999  $request,
2000  'Page is not available in the requested language (strict).',
2002  );
2003  throw new PropagateResponseException($response, 1533931395);
2004  case 'fallback':
2005  case 'content_fallback':
2006  // Setting content uid (but leaving the sys_language_uid) when a content_fallback
2007  // value was found.
2008  foreach ($languageAspect->getFallbackChain() ?? [] as $orderValue) {
2009  if ($orderValue === '0' || $orderValue === 0 || $orderValue === '') {
2010  $languageContentId = 0;
2011  break;
2012  }
2013  if (‪MathUtility::canBeInterpretedAsInteger($orderValue) && !empty($this->sys_page->getPageOverlay($this->id, (int)$orderValue))) {
2014  $languageContentId = (int)$orderValue;
2015  break;
2016  }
2017  if ($orderValue === 'pageNotFound') {
2018  // The existing fallbacks have not been found, but instead of continuing
2019  // page rendering with default language, a "page not found" message should be shown
2020  // instead.
2021  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
2022  $request,
2023  'Page is not available in the requested language (fallbacks did not apply).',
2025  );
2026  throw new ‪PropagateResponseException($response, 1533931402);
2027  }
2028  }
2029  break;
2030  case 'ignore':
2031  $languageContentId = $languageAspect->getId();
2032  break;
2033  default:
2034  // Default is that everything defaults to the default language...
2035  $languageId = ($languageContentId = 0);
2036  }
2037  }
2038 
2039  // Define the language aspect again now
2040  $languageAspect = GeneralUtility::makeInstance(
2041  LanguageAspect::class,
2042  $languageId,
2043  $languageContentId,
2044  $languageAspect->getOverlayType(),
2045  $languageAspect->getFallbackChain()
2046  );
2047 
2048  // Setting sys_language if an overlay record was found (which it is only if a language is used)
2049  // We'll do this every time since the language aspect might have changed now
2050  // Doing this ensures that page properties like the page title are returned in the correct language
2051  $this->page = $this->sys_page->getPageOverlay($this->page, $languageAspect->getContentId());
2052 
2053  // Update SYS_LASTCHANGED for localized page record
2054  $this->‪setRegisterValueForSysLastChanged($this->page);
2055  }
2056 
2057  // Set the language aspect
2058  $this->context->setAspect('language', $languageAspect);
2059 
2060  // Setting sys_language_uid inside sys-page by creating a new page repository
2061  $this->sys_page = GeneralUtility::makeInstance(PageRepository::class, $this->context);
2062  // If default language is not available:
2063  if ((!$languageAspect->getContentId() || !$languageAspect->getId())
2064  && $pageTranslationVisibility->shouldBeHiddenInDefaultLanguage()
2065  ) {
2066  $message = 'Page is not available in default language.';
2067  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
2068  $request,
2069  $message,
2071  );
2072  throw new ‪PropagateResponseException($response, 1533931423);
2073  }
2074 
2075  if ($languageAspect->getId() > 0) {
2077  }
2078 
2079  $_params = [];
2080  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_postProcess'] ?? [] as $_funcRef) {
2081  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2082  }
2083  }
2084 
2088  protected function ‪updateRootLinesWithTranslations()
2089  {
2090  try {
2091  $this->rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $this->id, $this->MP, $this->context)->get();
2092  } catch (RootLineException $e) {
2093  $this->rootLine = [];
2094  }
2095  }
2096 
2105  protected function ‪checkTranslatedShortcut(int $languageId, ServerRequestInterface $request)
2106  {
2107  if (!is_null($this->originalShortcutPage)) {
2108  $originalShortcutPageOverlay = $this->sys_page->getPageOverlay($this->originalShortcutPage['uid'], $languageId);
2109  if (!empty($originalShortcutPageOverlay['shortcut']) && $originalShortcutPageOverlay['shortcut'] != $this->id) {
2110  // the translation of the original shortcut page has a different shortcut target!
2111  // set the correct page and id
2112  $shortcut = $this->sys_page->resolveShortcutPage($originalShortcutPageOverlay, true);
2113  $this->id = ($this->contentPid = $shortcut['uid']);
2114  $this->page = $this->sys_page->getPage($this->id);
2115  // Fix various effects on things like menus f.e.
2116  $this->‪fetch_the_id($request);
2117  $this->tmpl->rootLine = array_reverse($this->rootLine);
2118  }
2119  }
2120  }
2121 
2128  public function ‪calculateLinkVars(array $queryParams)
2129  {
2130  $this->linkVars = '';
2131  $adminCommand = $queryParams['ADMCMD_prev'] ?? '';
2132  // This allows to keep the current logged-in workspace when navigating through the Frontend from a Backend link, and keep the logged-in state
2133  if (($adminCommand === 'LIVE' || $adminCommand === 'IGNORE') && $this->‪isBackendUserLoggedIn()) {
2134  $this->config['config']['linkVars'] = ltrim(($this->config['config']['linkVars'] ?? '') . ',ADMCMD_prev', ',');
2135  }
2136  // This allows to keep the "ADMCMD_simUser" parameter when navigating through the Frontend from a Backend link, and keep the logged-in state
2137  if (!empty($queryParams['ADMCMD_simUser']) && $this->‪isBackendUserLoggedIn()) {
2138  $this->config['config']['linkVars'] = ltrim(($this->config['config']['linkVars'] ?? '') . ',ADMCMD_simUser', ',');
2139  }
2140  // This allows to keep the "ADMCMD_simUser" parameter when navigating through the Frontend from a Backend link, and keep the logged-in state
2141  if (!empty($queryParams['ADMCMD_simTime']) && $this->‪isBackendUserLoggedIn()) {
2142  $this->config['config']['linkVars'] = ltrim(($this->config['config']['linkVars'] ?? '') . ',ADMCMD_simTime', ',');
2143  }
2144  if (empty($this->config['config']['linkVars'])) {
2145  return;
2146  }
2147 
2148  ‪$linkVars = $this->‪splitLinkVarsString((string)$this->config['config']['linkVars']);
2149 
2150  if (empty(‪$linkVars)) {
2151  return;
2152  }
2153  foreach (‪$linkVars as $linkVar) {
2154  $test = '';
2155  if (preg_match('/^(.*)\\((.+)\\)$/', $linkVar, $match)) {
2156  $linkVar = trim($match[1]);
2157  $test = trim($match[2]);
2158  }
2159 
2160  $keys = explode('|', $linkVar);
2161  $numberOfLevels = count($keys);
2162  $rootKey = trim($keys[0]);
2163  if (!isset($queryParams[$rootKey])) {
2164  continue;
2165  }
2166  $value = $queryParams[$rootKey];
2167  for ($i = 1; $i < $numberOfLevels; $i++) {
2168  $currentKey = trim($keys[$i]);
2169  if (isset($value[$currentKey])) {
2170  $value = $value[$currentKey];
2171  } else {
2172  $value = false;
2173  break;
2174  }
2175  }
2176  if ($value !== false) {
2177  $parameterName = $keys[0];
2178  for ($i = 1; $i < $numberOfLevels; $i++) {
2179  $parameterName .= '[' . $keys[$i] . ']';
2180  }
2181  if (!is_array($value)) {
2182  $temp = rawurlencode($value);
2183  if ($test !== '' && !$this->‪isAllowedLinkVarValue($temp, $test)) {
2184  // Error: This value was not allowed for this key
2185  continue;
2186  }
2187  $value = '&' . $parameterName . '=' . $temp;
2188  } else {
2189  if ($test !== '' && $test !== 'array') {
2190  // Error: This key must not be an array!
2191  continue;
2192  }
2193  $value = ‪HttpUtility::buildQueryString([$parameterName => $value], '&');
2194  }
2195  $this->linkVars .= $value;
2196  }
2197  }
2198  }
2199 
2207  protected function ‪splitLinkVarsString(string $string): array
2208  {
2209  $tempCommaReplacementString = '###KASPER###';
2210 
2211  // replace every "," wrapped in "()" by a "unique" string
2212  $string = preg_replace_callback('/\‍((?>[^()]|(?R))*\‍)/', static function ($result) use ($tempCommaReplacementString) {
2213  return str_replace(',', $tempCommaReplacementString, $result[0]);
2214  }, $string) ?? '';
2215 
2216  $string = ‪GeneralUtility::trimExplode(',', $string);
2217 
2218  // replace all "unique" strings back to ","
2219  return str_replace($tempCommaReplacementString, ',', $string);
2220  }
2221 
2230  protected function ‪isAllowedLinkVarValue(string $haystack, string $needle): bool
2231  {
2232  $isAllowed = false;
2233  // Integer
2234  if ($needle === 'int' || $needle === 'integer') {
2236  $isAllowed = true;
2237  }
2238  } elseif (preg_match('/^\\/.+\\/[imsxeADSUXu]*$/', $needle)) {
2239  // Regular expression, only "//" is allowed as delimiter
2240  if (@preg_match($needle, $haystack)) {
2241  $isAllowed = true;
2242  }
2243  } elseif (str_contains($needle, '-')) {
2244  // Range
2246  $range = explode('-', $needle);
2247  if ($range[0] <= $haystack && $range[1] >= $haystack) {
2248  $isAllowed = true;
2249  }
2250  }
2251  } elseif (str_contains($needle, '|')) {
2252  // List
2253  // Trim the input
2254  $haystack = str_replace(' ', '', $haystack);
2255  if (str_contains('|' . $needle . '|', '|' . $haystack . '|')) {
2256  $isAllowed = true;
2257  }
2258  } elseif ((string)$needle === (string)$haystack) {
2259  // String comparison
2260  $isAllowed = true;
2261  }
2262  return $isAllowed;
2263  }
2264 
2274  public function ‪getRedirectUriForMountPoint(ServerRequestInterface $request): ?string
2275  {
2276  if (!empty($this->originalMountPointPage) && (int)$this->originalMountPointPage['doktype'] === ‪PageRepository::DOKTYPE_MOUNTPOINT) {
2277  return $this->‪getUriToCurrentPageForRedirect($request);
2278  }
2279 
2280  return null;
2281  }
2282 
2293  public function ‪getRedirectUriForShortcut(ServerRequestInterface $request): ?string
2294  {
2295  if (!empty($this->originalShortcutPage) && $this->originalShortcutPage['doktype'] == ‪PageRepository::DOKTYPE_SHORTCUT) {
2296  // Check if the shortcut page is actually on the current site, if not, this is a "page not found"
2297  // because the request was www.mydomain.com/?id=23 where page ID 23 (which is a shortcut) is on another domain/site.
2298  if ((int)($request->getQueryParams()['id'] ?? 0) > 0) {
2299  try {
2300  ‪$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($this->originalShortcutPage['l10n_parent'] ?: $this->originalShortcutPage['uid']);
2301  } catch (SiteNotFoundException $e) {
2302  ‪$site = null;
2303  }
2304  if (‪$site !== $this->site) {
2305  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
2306  $request,
2307  'ID was outside the domain',
2309  );
2310  throw new ImmediateResponseException($response, 1638022483);
2311  }
2312  }
2313  return $this->‪getUriToCurrentPageForRedirect($request);
2314  }
2315 
2316  return null;
2317  }
2318 
2325  protected function ‪getUriToCurrentPageForRedirect(ServerRequestInterface $request): string
2326  {
2327  $this->‪calculateLinkVars($request->getQueryParams());
2328  $parameter = $this->page['uid'];
2329  if ($this->type && ‪MathUtility::canBeInterpretedAsInteger($this->type)) {
2330  $parameter .= ',' . ‪$this->type;
2331  }
2332  return GeneralUtility::makeInstance(ContentObjectRenderer::class, $this)->typoLink_URL([
2333  'parameter' => $parameter,
2334  'addQueryString' => true,
2335  'addQueryString.' => ['exclude' => 'id,type'],
2336  'forceAbsoluteUrl' => true,
2337  ]);
2338  }
2339 
2340  /********************************************
2341  *
2342  * Page generation; cache handling
2343  *
2344  *******************************************/
2351  public function ‪isGeneratePage()
2352  {
2354  }
2355 
2359  protected function ‪realPageCacheContent()
2360  {
2361  // seconds until a cached page is too old
2362  $cacheTimeout = $this->‪get_cache_timeout();
2363  $timeOutTime = ‪$GLOBALS['EXEC_TIME'] + $cacheTimeout;
2364  $usePageCache = true;
2365  // Hook for deciding whether page cache should be written to the cache backend or not
2366  // NOTE: as hooks are called in a loop, the last hook will have the final word (however each
2367  // hook receives the current status of the $usePageCache flag)
2368  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['usePageCache'] ?? [] as $className) {
2369  $usePageCache = GeneralUtility::makeInstance($className)->usePageCache($this, $usePageCache);
2370  }
2371  // Write the page to cache, if necessary
2372  if ($usePageCache) {
2373  $this->‪setPageCacheContent($this->content, $this->config, $timeOutTime);
2374  }
2375  // Hook for cache post processing (eg. writing static files!)
2376  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['insertPageIncache'] ?? [] as $className) {
2377  GeneralUtility::makeInstance($className)->insertPageIncache($this, $timeOutTime);
2378  }
2379  }
2380 
2389  protected function ‪setPageCacheContent(‪$content, $data, $expirationTstamp)
2390  {
2391  $cacheData = [
2392  'identifier' => ‪$this->newHash,
2393  'page_id' => ‪$this->id,
2394  'content' => ‪$content,
2395  'contentType' => ‪$this->contentType,
2396  'cache_data' => $data,
2397  'expires' => $expirationTstamp,
2398  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
2399  'pageTitleInfo' => [
2400  'title' => $this->page['title'],
2401  'indexedDocTitle' => ‪$this->indexedDocTitle,
2402  ],
2403  ];
2404  $this->cacheExpires = $expirationTstamp;
2405  $this->pageCacheTags[] = 'pageId_' . $cacheData['page_id'];
2406  // Respect the page cache when content of pid is shown
2407  if ($this->id !== $this->contentPid) {
2408  $this->pageCacheTags[] = 'pageId_' . ‪$this->contentPid;
2409  }
2410  if (!empty($this->page['cache_tags'])) {
2411  $tags = ‪GeneralUtility::trimExplode(',', $this->page['cache_tags'], true);
2412  $this->pageCacheTags = array_merge($this->pageCacheTags, $tags);
2413  }
2414  // Add the cache themselves as well, because they are fetched by getPageCacheTags()
2415  $cacheData['cacheTags'] = ‪$this->pageCacheTags;
2416  $this->pageCache->set($this->newHash, $cacheData, $this->pageCacheTags, $expirationTstamp - ‪$GLOBALS['EXEC_TIME']);
2417  }
2418 
2422  public function ‪clearPageCacheContent()
2423  {
2424  $this->pageCache->remove($this->newHash);
2425  }
2426 
2433  protected function ‪setSysLastChanged()
2434  {
2435  // We only update the info if browsing the live workspace
2436  if ($this->page['SYS_LASTCHANGED'] < (int)($this->register['SYS_LASTCHANGED'] ?? 0) && !$this->‪doWorkspacePreview()) {
2437  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
2438  ->getConnectionForTable('pages');
2439  $pageId = $this->page['_PAGES_OVERLAY_UID'] ?? ‪$this->id;
2440  $connection->update(
2441  'pages',
2442  [
2443  'SYS_LASTCHANGED' => (int)$this->register['SYS_LASTCHANGED'],
2444  ],
2445  [
2446  'uid' => (int)$pageId,
2447  ]
2448  );
2449  }
2450  }
2451 
2459  protected function ‪setRegisterValueForSysLastChanged(array ‪$page): void
2460  {
2461  $this->register['SYS_LASTCHANGED'] = (int)‪$page['tstamp'];
2462  if ($this->register['SYS_LASTCHANGED'] < (int)$page['SYS_LASTCHANGED']) {
2463  $this->register['SYS_LASTCHANGED'] = (int)‪$page['SYS_LASTCHANGED'];
2464  }
2465  }
2466 
2472  public function ‪releaseLocks()
2473  {
2474  $this->‪releaseLock('pagesection');
2475  $this->‪releaseLock('pages');
2476  }
2477 
2484  public function ‪addCacheTags(array $tags)
2485  {
2486  $this->pageCacheTags = array_merge($this->pageCacheTags, $tags);
2487  }
2488 
2492  public function ‪getPageCacheTags(): array
2493  {
2494  return ‪$this->pageCacheTags;
2495  }
2496 
2497  /********************************************
2498  *
2499  * Page generation; rendering and inclusion
2500  *
2501  *******************************************/
2505  public function ‪generatePage_preProcessing()
2506  {
2507  // Same codeline as in getFromCache(). But $this->all has been changed by
2508  // \TYPO3\CMS\Core\TypoScript\TemplateService::start() in the meantime, so this must be called again!
2509  $this->newHash = $this->‪getHash();
2510 
2511  // Used as a safety check in case a PHP script is falsely disabling $this->no_cache during page generation.
2512  $this->no_cacheBeforePageGen = ‪$this->no_cache;
2513  }
2514 
2525  protected function ‪resolveContentPid(ServerRequestInterface $request): int
2526  {
2527  if (!isset($this->page['content_from_pid']) || empty($this->page['content_from_pid'])) {
2528  return (int)‪$this->id;
2529  }
2530  // make REAL copy of TSFE object - not reference!
2531  $temp_copy_TSFE = clone $this;
2532  // Set ->id to the content_from_pid value - we are going to evaluate this pid as was it a given id for a page-display!
2533  $temp_copy_TSFE->id = $this->page['content_from_pid'];
2534  $temp_copy_TSFE->MP = '';
2535  $temp_copy_TSFE->getPageAndRootline($request);
2536  return (int)$temp_copy_TSFE->id;
2537  }
2543  public function ‪preparePageContentGeneration(ServerRequestInterface $request)
2544  {
2545  $this->‪getTimeTracker()->‪push('Prepare page content generation');
2546  $this->contentPid = $this->‪resolveContentPid($request);
2547  // Global vars...
2548  $this->indexedDocTitle = $this->page['title'] ?? null;
2549  // Base url:
2550  if (isset($this->config['config']['baseURL'])) {
2551  $this->baseUrl = $this->config['config']['baseURL'];
2552  }
2553  // Internal and External target defaults
2554  $this->intTarget = (string)($this->config['config']['intTarget'] ?? '');
2555  $this->extTarget = (string)($this->config['config']['extTarget'] ?? '');
2556  $this->fileTarget = (string)($this->config['config']['fileTarget'] ?? '');
2557  $this->spamProtectEmailAddresses = $this->config['config']['spamProtectEmailAddresses'] ?? 0;
2558  if ($this->spamProtectEmailAddresses !== 'ascii') {
2559  $this->spamProtectEmailAddresses = ‪MathUtility::forceIntegerInRange($this->spamProtectEmailAddresses, -10, 10, 0);
2560  }
2561  // calculate the absolute path prefix
2562  if (!empty($this->absRefPrefix = trim($this->config['config']['absRefPrefix'] ?? ''))) {
2563  if ($this->absRefPrefix === 'auto') {
2564  $this->absRefPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
2565  }
2566  }
2567  // @deprecated. This line can be removed with TYPO3 v12.0.
2568  $this->ATagParams = trim($this->config['config']['ATagParams'] ?? '') ? ' ' . trim($this->config['config']['ATagParams']) : '';
2569  $this->‪initializeSearchWordData($request->getParsedBody()['sword_list'] ?? $request->getQueryParams()['sword_list'] ?? null);
2570  // linkVars
2571  $this->‪calculateLinkVars($request->getQueryParams());
2572  // Setting XHTML-doctype from doctype
2573  if (!isset($this->config['config']['xhtmlDoctype']) || !$this->config['config']['xhtmlDoctype']) {
2574  $this->config['config']['xhtmlDoctype'] = $this->config['config']['doctype'] ?? '';
2575  }
2576  if ($this->config['config']['xhtmlDoctype']) {
2577  $this->xhtmlDoctype = $this->config['config']['xhtmlDoctype'];
2578  // Checking XHTML-docytpe
2579  switch ((string)$this->config['config']['xhtmlDoctype']) {
2580  case 'xhtml_trans':
2581  case 'xhtml_strict':
2582  $this->xhtmlVersion = 100;
2583  break;
2584  case 'xhtml_basic':
2585  $this->xhtmlVersion = 105;
2586  break;
2587  case 'xhtml_11':
2588  case 'xhtml+rdfa_10':
2589  $this->xhtmlVersion = 110;
2590  break;
2591  default:
2592  $this->pageRenderer->setRenderXhtml(false);
2593  $this->xhtmlDoctype = '';
2594  $this->xhtmlVersion = 0;
2595  }
2596  } else {
2597  $this->pageRenderer->setRenderXhtml(false);
2598  }
2599 
2600  // Global content object
2601  $this->‪newCObj($request);
2603  }
2604 
2613  protected function ‪initializeSearchWordData($searchWords)
2614  {
2615  $this->sWordRegEx = '';
2616  $this->sWordList = $searchWords ?? '';
2617  if (is_array($this->sWordList)) {
2618  $space = !empty($this->config['config']['sword_standAlone'] ?? null) ? '[[:space:]]' : '';
2619  $regexpParts = [];
2620  foreach ($this->sWordList as $val) {
2621  if (trim($val) !== '') {
2622  $regexpParts[] = $space . preg_quote($val, '/') . $space;
2623  }
2624  }
2625  $this->sWordRegEx = implode('|', $regexpParts);
2626  }
2627  }
2628 
2634  public function ‪generatePage_postProcessing()
2635  {
2636  $this->‪setAbsRefPrefix();
2637  // This is to ensure, that the page is NOT cached if the no_cache parameter was set before the page was generated. This is a safety precaution, as it could have been unset by some script.
2638  if ($this->no_cacheBeforePageGen) {
2639  $this->‪set_no_cache('no_cache has been set before the page was generated - safety check', true);
2640  }
2641  // Hook for post-processing of page content cached/non-cached:
2642  $_params = ['pObj' => &$this];
2643  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-all'] ?? [] as $_funcRef) {
2644  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2645  }
2646  // Processing if caching is enabled:
2647  if (!$this->no_cache) {
2648  // Hook for post-processing of page content before being cached:
2649  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-cached'] ?? [] as $_funcRef) {
2650  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2651  }
2652  }
2653  // Convert charset for output. Any hooks before (including indexed search) will have to convert from UTF-8 to the target
2654  // charset as well.
2655  $this->content = $this->‪convOutputCharset($this->content);
2656  // Storing for cache:
2657  if (!$this->no_cache) {
2658  $this->‪realPageCacheContent();
2659  }
2660  // Sets sys-last-change:
2661  $this->‪setSysLastChanged();
2662  }
2663 
2670  public function ‪generatePageTitle(): string
2671  {
2672  // Check for a custom pageTitleSeparator, and perform stdWrap on it
2673  $pageTitleSeparator = (string)$this->cObj->stdWrapValue('pageTitleSeparator', $this->config['config'] ?? []);
2674  if ($pageTitleSeparator !== '' && $pageTitleSeparator === ($this->config['config']['pageTitleSeparator'] ?? '')) {
2675  $pageTitleSeparator .= ' ';
2676  }
2677 
2678  $titleProvider = GeneralUtility::makeInstance(PageTitleProviderManager::class);
2679  if (!empty($this->config['config']['pageTitleCache'])) {
2680  $titleProvider->setPageTitleCache($this->config['config']['pageTitleCache']);
2681  }
2682  $pageTitle = $titleProvider->getTitle();
2683  $this->config['config']['pageTitleCache'] = $titleProvider->getPageTitleCache();
2684 
2685  if ($pageTitle !== '') {
2686  $this->indexedDocTitle = $pageTitle;
2687  }
2688 
2689  $titleTagContent = $this->‪printTitle(
2690  $pageTitle,
2691  (bool)($this->config['config']['noPageTitle'] ?? false),
2692  (bool)($this->config['config']['pageTitleFirst'] ?? false),
2693  $pageTitleSeparator
2694  );
2695  $this->config['config']['pageTitle'] = $titleTagContent;
2696  // stdWrap around the title tag
2697  $titleTagContent = $this->cObj->stdWrapValue('pageTitle', $this->config['config']);
2698 
2699  // config.noPageTitle = 2 - means do not render the page title
2700  if (isset($this->config['config']['noPageTitle']) && (int)$this->config['config']['noPageTitle'] === 2) {
2701  $titleTagContent = '';
2702  }
2703  if ($titleTagContent !== '') {
2704  $this->pageRenderer->setTitle($titleTagContent);
2705  }
2706  return (string)$titleTagContent;
2707  }
2708 
2719  protected function ‪printTitle(string $pageTitle, bool $noTitle = false, bool $showTitleFirst = false, string $pageTitleSeparator = ''): string
2720  {
2721  $websiteTitle = $this->‪getWebsiteTitle();
2722  $pageTitle = $noTitle ? '' : $pageTitle;
2723  if ($showTitleFirst) {
2724  $temp = $websiteTitle;
2725  $websiteTitle = $pageTitle;
2726  $pageTitle = $temp;
2727  }
2728  // only show a separator if there are both site title and page title
2729  if ($pageTitle === '' || $websiteTitle === '') {
2730  $pageTitleSeparator = '';
2731  } elseif (empty($pageTitleSeparator)) {
2732  // use the default separator if non given
2733  $pageTitleSeparator = ': ';
2734  }
2735  return $websiteTitle . $pageTitleSeparator . $pageTitle;
2736  }
2737 
2741  protected function ‪getWebsiteTitle(): string
2742  {
2743  if ($this->language instanceof SiteLanguage
2744  && trim($this->language->getWebsiteTitle()) !== ''
2745  ) {
2746  return trim($this->language->getWebsiteTitle());
2747  }
2748  if ($this->site instanceof SiteInterface
2749  && trim($this->site->getConfiguration()['websiteTitle'] ?? '') !== ''
2750  ) {
2751  return trim($this->site->getConfiguration()['websiteTitle']);
2752  }
2753 
2754  return '';
2755  }
2756 
2762  public function ‪INTincScript(ServerRequestInterface $request = null)
2763  {
2764  $request = $request ?? ‪$GLOBALS['TYPO3_REQUEST'];
2765  $this->additionalHeaderData = $this->config['INTincScript_ext']['additionalHeaderData'] ?? [];
2766  $this->additionalFooterData = $this->config['INTincScript_ext']['additionalFooterData'] ?? [];
2767  if (empty($this->config['INTincScript_ext']['pageRenderer'])) {
2768  $this->‪initPageRenderer();
2769  } else {
2771  ‪$pageRenderer = unserialize($this->config['INTincScript_ext']['pageRenderer']);
2772  $this->pageRenderer->updateState(‪$pageRenderer->getState());
2773  }
2774  if (!empty($this->config['INTincScript_ext']['assetCollector'])) {
2776  $assetCollector = unserialize($this->config['INTincScript_ext']['assetCollector'], ['allowed_classes' => [AssetCollector::class]]);
2777  GeneralUtility::makeInstance(AssetCollector::class)->updateState($assetCollector->getState());
2778  }
2779 
2781  $this->‪getTimeTracker()->‪push('Substitute header section');
2782  $this->‪INTincScript_loadJSCode();
2783  $this->‪generatePageTitle();
2784 
2785  $this->content = str_replace(
2786  [
2787  '<!--HD_' . $this->config['INTincScript_ext']['divKey'] . '-->',
2788  '<!--FD_' . $this->config['INTincScript_ext']['divKey'] . '-->',
2789  ],
2790  [
2791  $this->‪convOutputCharset(implode(LF, $this->additionalHeaderData)),
2792  $this->‪convOutputCharset(implode(LF, $this->additionalFooterData)),
2793  ],
2794  $this->pageRenderer->renderJavaScriptAndCssForProcessingOfUncachedContentObjects($this->content, $this->config['INTincScript_ext']['divKey'])
2795  );
2796  // Replace again, because header and footer data and page renderer replacements may introduce additional placeholders (see #44825)
2798  $this->‪setAbsRefPrefix();
2799  $this->‪getTimeTracker()->‪pull();
2800  }
2801 
2807  protected function ‪recursivelyReplaceIntPlaceholdersInContent(ServerRequestInterface $request)
2808  {
2809  do {
2810  $nonCacheableData = $this->config['INTincScript'];
2811  $this->‪processNonCacheableContentPartsAndSubstituteContentMarkers($nonCacheableData, $request);
2812  // Check if there were new items added to INTincScript during the previous execution:
2813  // array_diff_assoc throws notices if values are arrays but not strings. We suppress this here.
2814  $nonCacheableData = @array_diff_assoc($this->config['INTincScript'], $nonCacheableData);
2815  $reprocess = count($nonCacheableData) > 0;
2816  } while ($reprocess);
2817  }
2818 
2828  protected function ‪processNonCacheableContentPartsAndSubstituteContentMarkers(array $nonCacheableData, ServerRequestInterface $request)
2829  {
2830  $timeTracker = $this->‪getTimeTracker();
2831  $timeTracker->push('Split content');
2832  // Splits content with the key.
2833  $contentSplitByUncacheableMarkers = explode('<!--INT_SCRIPT.', $this->content);
2834  $this->content = '';
2835  $timeTracker->setTSlogMessage('Parts: ' . count($contentSplitByUncacheableMarkers), LogLevel::INFO);
2836  $timeTracker->pull();
2837  foreach ($contentSplitByUncacheableMarkers as $counter => $contentPart) {
2838  // If the split had a comment-end after 32 characters it's probably a split-string
2839  if (substr($contentPart, 32, 3) === '-->') {
2840  $nonCacheableKey = 'INT_SCRIPT.' . substr($contentPart, 0, 32);
2841  if (is_array($nonCacheableData[$nonCacheableKey] ?? false)) {
2842  $label = 'Include ' . $nonCacheableData[$nonCacheableKey]['type'];
2843  $timeTracker->push($label);
2844  $nonCacheableContent = '';
2845  $contentObjectRendererForNonCacheable = unserialize($nonCacheableData[$nonCacheableKey]['cObj']);
2846  /* @var ContentObjectRenderer $contentObjectRendererForNonCacheable */
2847  $contentObjectRendererForNonCacheable->setRequest($request);
2848  switch ($nonCacheableData[$nonCacheableKey]['type']) {
2849  case 'COA':
2850  $nonCacheableContent = $contentObjectRendererForNonCacheable->cObjGetSingle('COA', $nonCacheableData[$nonCacheableKey]['conf']);
2851  break;
2852  case 'FUNC':
2853  $nonCacheableContent = $contentObjectRendererForNonCacheable->cObjGetSingle('USER', $nonCacheableData[$nonCacheableKey]['conf']);
2854  break;
2855  case 'POSTUSERFUNC':
2856  $nonCacheableContent = $contentObjectRendererForNonCacheable->callUserFunction($nonCacheableData[$nonCacheableKey]['postUserFunc'], $nonCacheableData[$nonCacheableKey]['conf'], $nonCacheableData[$nonCacheableKey]['content']);
2857  break;
2858  }
2859  $this->content .= $this->‪convOutputCharset($nonCacheableContent);
2860  $this->content .= substr($contentPart, 35);
2861  $timeTracker->pull($nonCacheableContent);
2862  } else {
2863  $this->content .= substr($contentPart, 35);
2864  }
2865  } elseif ($counter) {
2866  // If it's not the first entry (which would be "0" of the array keys), then re-add the INT_SCRIPT part
2867  $this->content .= '<!--INT_SCRIPT.' . $contentPart;
2868  } else {
2869  $this->content .= $contentPart;
2870  }
2871  }
2872  }
2873 
2880  public function ‪INTincScript_loadJSCode()
2881  {
2882  // Prepare code and placeholders for additional header and footer files (and make sure that this isn't called twice)
2883  if ($this->‪isINTincScript() && !isset($this->config['INTincScript_ext'])) {
2884  $substituteHash = $this->‪uniqueHash();
2885  $this->config['INTincScript_ext']['divKey'] = $substituteHash;
2886  // Storing the header-data array
2887  $this->config['INTincScript_ext']['additionalHeaderData'] = ‪$this->additionalHeaderData;
2888  // Storing the footer-data array
2889  $this->config['INTincScript_ext']['additionalFooterData'] = ‪$this->additionalFooterData;
2890  // Clearing the array
2891  $this->additionalHeaderData = ['<!--HD_' . $substituteHash . '-->'];
2892  // Clearing the array
2893  $this->additionalFooterData = ['<!--FD_' . $substituteHash . '-->'];
2894  }
2895  }
2896 
2902  public function ‪isINTincScript()
2903  {
2904  return !empty($this->config['INTincScript']) && is_array($this->config['INTincScript']);
2905  }
2906 
2913  public function ‪applyHttpHeadersToResponse(ResponseInterface $response): ResponseInterface
2914  {
2915  // Set header for charset-encoding unless disabled
2916  if (empty($this->config['config']['disableCharsetHeader']) && !str_contains($this->contentType, 'charset=')) {
2917  $response = $response->withHeader('Content-Type', $this->contentType . '; charset=' . trim($this->metaCharset));
2918  } elseif ($this->contentType && $this->contentType !== 'text/html') {
2919  // send the contentType, if defined differently than text/html
2920  $response = $response->withHeader('Content-Type', $this->contentType);
2921  }
2922  // Set header for content language unless disabled
2923  $contentLanguage = $this->language->getTwoLetterIsoCode();
2924  if (empty($this->config['config']['disableLanguageHeader']) && !empty($contentLanguage)) {
2925  $response = $response->withHeader('Content-Language', trim($contentLanguage));
2926  }
2927 
2928  // Add a Response header to show debug information if a page was fetched from cache
2929  if ($this->debugInformationHeader) {
2930  $response = $response->withHeader('X-TYPO3-Debug-Cache', $this->debugInformationHeader);
2931  }
2932 
2933  // Set cache related headers to client (used to enable proxy / client caching!)
2934  if (!empty($this->config['config']['sendCacheHeaders'])) {
2935  $headers = $this->‪getCacheHeaders();
2936  foreach ($headers as $header => $value) {
2937  $response = $response->withHeader($header, $value);
2938  }
2939  }
2940  // Set additional headers if any have been configured via TypoScript
2941  $additionalHeaders = $this->‪getAdditionalHeaders();
2942  foreach ($additionalHeaders as $headerConfig) {
2943  [$header, $value] = ‪GeneralUtility::trimExplode(':', $headerConfig['header'], false, 2);
2944  if ($headerConfig['statusCode']) {
2945  $response = $response->withStatus((int)$headerConfig['statusCode']);
2946  }
2947  if ($headerConfig['replace']) {
2948  $response = $response->withHeader($header, $value);
2949  } else {
2950  $response = $response->withAddedHeader($header, $value);
2951  }
2952  }
2953  return $response;
2954  }
2955 
2961  protected function ‪getCacheHeaders(): array
2962  {
2963  // Getting status whether we can send cache control headers for proxy caching:
2964  $doCache = $this->‪isStaticCacheble();
2965  // This variable will be TRUE unless cache headers are configured to be sent ONLY if a branch does not allow logins and logins turns out to be allowed anyway...
2966  $loginsDeniedCfg = empty($this->config['config']['sendCacheHeaders_onlyWhenLoginDeniedInBranch']) || empty($this->loginAllowedInBranch);
2967  // Finally, when backend users are logged in, do not send cache headers at all (Admin Panel might be displayed for instance).
2968  $this->isClientCachable = $doCache && !$this->‪isBackendUserLoggedIn() && !$this->‪doWorkspacePreview() && $loginsDeniedCfg;
2969  if ($this->isClientCachable) {
2970  $headers = [
2971  'Expires' => gmdate('D, d M Y H:i:s T', $this->cacheExpires),
2972  'ETag' => '"' . md5($this->content) . '"',
2973  'Cache-Control' => 'max-age=' . ($this->cacheExpires - ‪$GLOBALS['EXEC_TIME']),
2974  // no-cache
2975  'Pragma' => 'public',
2976  ];
2977  } else {
2978  // "no-store" is used to ensure that the client HAS to ask the server every time, and is not allowed to store anything at all
2979  $headers = [
2980  'Cache-Control' => 'private, no-store',
2981  ];
2982  // Now, if a backend user is logged in, tell him in the Admin Panel log what the caching status would have been:
2983  if ($this->‪isBackendUserLoggedIn()) {
2984  if ($doCache) {
2985  $this->‪getTimeTracker()->‪setTSlogMessage('Cache-headers with max-age "' . ($this->cacheExpires - ‪$GLOBALS['EXEC_TIME']) . '" would have been sent');
2986  } else {
2987  $reasonMsg = [];
2988  if ($this->no_cache) {
2989  $reasonMsg[] = 'Caching disabled (no_cache).';
2990  }
2991  if ($this->‪isINTincScript()) {
2992  $reasonMsg[] = '*_INT object(s) on page.';
2993  }
2994  if (is_array($this->fe_user->user)) {
2995  $reasonMsg[] = 'Frontend user logged in.';
2996  }
2997  $this->‪getTimeTracker()->‪setTSlogMessage('Cache-headers would disable proxy caching! Reason(s): "' . implode(' ', $reasonMsg) . '"', LogLevel::NOTICE);
2998  }
2999  }
3000  }
3001  return $headers;
3002  }
3003 
3014  public function ‪isStaticCacheble()
3015  {
3016  return !$this->no_cache && !$this->‪isINTincScript() && !$this->‪isUserOrGroupSet();
3017  }
3018 
3019  /********************************************
3020  *
3021  * Various internal API functions
3022  *
3023  *******************************************/
3030  public function ‪newCObj(ServerRequestInterface $request = null)
3031  {
3032  $this->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class, $this);
3033  $this->cObj->start($this->page, 'pages', $request);
3034  }
3035 
3043  protected function ‪setAbsRefPrefix()
3044  {
3045  if (!$this->absRefPrefix) {
3046  return;
3047  }
3048  $encodedAbsRefPrefix = htmlspecialchars($this->absRefPrefix, ENT_QUOTES | ENT_HTML5);
3049  $search = [
3050  '"_assets/',
3051  '"typo3temp/',
3055  ];
3056  $replace = [
3057  '"' . $encodedAbsRefPrefix . '_assets/',
3058  '"' . $encodedAbsRefPrefix . 'typo3temp/',
3059  '"' . $encodedAbsRefPrefix . ‪PathUtility::stripPathSitePrefix(‪Environment::getExtensionsPath()) . '/',
3060  '"' . $encodedAbsRefPrefix . ‪PathUtility::stripPathSitePrefix(‪Environment::getBackendPath()) . '/ext/',
3061  '"' . $encodedAbsRefPrefix . ‪PathUtility::stripPathSitePrefix(‪Environment::getFrameworkBasePath()) . '/',
3062  ];
3063  // Process additional directories
3064  $directories = ‪GeneralUtility::trimExplode(',', ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['additionalAbsRefPrefixDirectories'], true);
3065  foreach ($directories as $directory) {
3066  $search[] = '"' . $directory;
3067  $replace[] = '"' . $encodedAbsRefPrefix . $directory;
3068  }
3069  $this->content = str_replace(
3070  $search,
3071  $replace,
3072  $this->content
3073  );
3074  }
3075 
3083  public function ‪baseUrlWrap($url)
3084  {
3085  if ($this->baseUrl) {
3086  $urlParts = parse_url($url);
3087  if (empty($urlParts['scheme']) && $url[0] !== '/') {
3088  $url = $this->baseUrl . $url;
3089  }
3090  }
3091  return $url;
3092  }
3093 
3102  public function ‪logDeprecatedTyposcript($typoScriptProperty, $explanation = '')
3103  {
3104  $explanationText = $explanation !== '' ? ' - ' . $explanation : '';
3105  $this->‪getTimeTracker()->‪setTSlogMessage($typoScriptProperty . ' is deprecated.' . $explanationText, LogLevel::WARNING);
3106  trigger_error('TypoScript property ' . $typoScriptProperty . ' is deprecated' . $explanationText, E_USER_DEPRECATED);
3107  }
3108 
3109  /********************************************
3110  * PUBLIC ACCESSIBLE WORKSPACES FUNCTIONS
3111  *******************************************/
3112 
3118  public function ‪doWorkspacePreview()
3119  {
3120  return $this->context->getPropertyFromAspect('workspace', 'isOffline', false);
3121  }
3122 
3128  public function ‪whichWorkspace(): int
3129  {
3130  return $this->context->getPropertyFromAspect('workspace', 'id', 0);
3131  }
3132 
3133  /********************************************
3134  *
3135  * Various external API functions - for use in plugins etc.
3136  *
3137  *******************************************/
3138 
3144  public function ‪getPagesTSconfig()
3145  {
3146  if (!is_array($this->pagesTSconfig)) {
3147  $contentHashCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('hash');
3148  $loader = GeneralUtility::makeInstance(PageTsConfigLoader::class);
3149  $tsConfigString = $loader->load(array_reverse($this->rootLine));
3150  ‪$parser = GeneralUtility::makeInstance(
3151  PageTsConfigParser::class,
3152  GeneralUtility::makeInstance(TypoScriptParser::class),
3153  $contentHashCache
3154  );
3155  $this->pagesTSconfig = ‪$parser->parse(
3156  $tsConfigString,
3157  GeneralUtility::makeInstance(ConditionMatcher::class, $this->context, $this->id, $this->rootLine),
3158  $this->site
3159  );
3160  }
3161  return ‪$this->pagesTSconfig;
3162  }
3163 
3171  public function ‪uniqueHash($str = '')
3172  {
3173  return md5($this->uniqueString . '_' . $str . $this->uniqueCounter++);
3174  }
3175 
3182  public function ‪set_no_cache($reason = '', $internalRequest = false)
3183  {
3184  ‪$context = [];
3185  if ($reason !== '') {
3186  $warning = '$TSFE->set_no_cache() was triggered. Reason: {reason}.';
3187  ‪$context['reason'] = $reason;
3188  } else {
3189  $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
3190  // This is a hack to work around ___FILE___ resolving symbolic links
3191  $realWebPath = ‪PathUtility::dirname((string)realpath(‪Environment::getBackendPath())) . '/';
3192  $file = $trace[0]['file'];
3193  if (strpos($file, $realWebPath) === 0) {
3194  $file = str_replace($realWebPath, '', $file);
3195  } else {
3196  $file = str_replace(‪Environment::getPublicPath() . '/', '', $file);
3197  }
3198  $warning = '$GLOBALS[\'TSFE\']->set_no_cache() was triggered by {file} on line {line}.';
3199  ‪$context['file'] = $file;
3200  ‪$context['line'] = $trace[0]['line'];
3201  }
3202  if (!$internalRequest && ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['disableNoCacheParameter']) {
3203  $warning .= ' However, $TYPO3_CONF_VARS[\'FE\'][\'disableNoCacheParameter\'] is set, so it will be ignored!';
3204  $this->‪getTimeTracker()->‪setTSlogMessage($warning, LogLevel::NOTICE);
3205  } else {
3206  $warning .= ' Caching is disabled!';
3207  $this->‪disableCache();
3208  }
3209  $this->logger->notice($warning, ‪$context);
3210  }
3211 
3217  protected function ‪disableCache()
3218  {
3219  $this->no_cache = true;
3220  }
3227  public function ‪set_cache_timeout_default($seconds)
3228  {
3229  $seconds = (int)$seconds;
3230  if ($seconds > 0) {
3231  $this->cacheTimeOutDefault = $seconds;
3232  }
3233  }
3234 
3240  public function ‪get_cache_timeout()
3241  {
3243  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
3244  $cachedCacheLifetimeIdentifier = 'core-tslib_fe-get_cache_timeout';
3245  $cachedCacheLifetime = $runtimeCache->get($cachedCacheLifetimeIdentifier);
3246  if ($cachedCacheLifetime === false) {
3247  if ($this->page['cache_timeout']) {
3248  // Cache period was set for the page:
3249  $cacheTimeout = $this->page['cache_timeout'];
3250  } else {
3251  // Cache period was set via TypoScript "config.cache_period",
3252  // otherwise it's the default of 24 hours
3253  $cacheTimeout = ‪$this->cacheTimeOutDefault;
3254  }
3255  if (!empty($this->config['config']['cache_clearAtMidnight'])) {
3256  $timeOutTime = ‪$GLOBALS['EXEC_TIME'] + $cacheTimeout;
3257  $midnightTime = mktime(0, 0, 0, (int)date('m', $timeOutTime), (int)date('d', $timeOutTime), (int)date('Y', $timeOutTime));
3258  // If the midnight time of the expire-day is greater than the current time,
3259  // we may set the timeOutTime to the new midnighttime.
3260  if ($midnightTime > ‪$GLOBALS['EXEC_TIME']) {
3261  $cacheTimeout = $midnightTime - ‪$GLOBALS['EXEC_TIME'];
3262  }
3263  }
3264 
3265  // Calculate the timeout time for records on the page and adjust cache timeout if necessary
3266  $cacheTimeout = min($this->‪calculatePageCacheTimeout(), $cacheTimeout);
3267 
3268  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['get_cache_timeout'] ?? [] as $_funcRef) {
3269  $params = ['cacheTimeout' => $cacheTimeout];
3270  $cacheTimeout = GeneralUtility::callUserFunction($_funcRef, $params, $this);
3271  }
3272  $runtimeCache->set($cachedCacheLifetimeIdentifier, $cacheTimeout);
3273  $cachedCacheLifetime = $cacheTimeout;
3274  }
3275  return $cachedCacheLifetime;
3276  }
3277 
3278  /*********************************************
3279  *
3280  * Localization and character set conversion
3281  *
3282  *********************************************/
3289  public function ‪sL($input)
3290  {
3291  return $this->languageService->sL($input);
3292  }
3293 
3298  protected function ‪setOutputLanguage()
3299  {
3300  $this->languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class)->createFromSiteLanguage($this->language);
3301  // Always disable debugging for TSFE
3302  $this->languageService->debugKey = false;
3303  }
3304 
3312  public function ‪convOutputCharset(‪$content)
3313  {
3314  if ($this->metaCharset !== 'utf-8') {
3315  $charsetConverter = GeneralUtility::makeInstance(CharsetConverter::class);
3316  try {
3317  ‪$content = $charsetConverter->conv(‪$content, 'utf-8', $this->metaCharset);
3319  throw new \RuntimeException('Invalid config.metaCharset: ' . $e->getMessage(), 1508916185);
3320  }
3321  }
3322  return ‪$content;
3323  }
3324 
3330  protected function ‪calculatePageCacheTimeout()
3331  {
3332  $result = PHP_INT_MAX;
3333  // Get the configuration
3334  $tablesToConsider = $this->‪getCurrentPageCacheConfiguration();
3335  // Get the time, rounded to the minute (do not pollute MySQL cache!)
3336  // It is ok that we do not take seconds into account here because this
3337  // value will be subtracted later. So we never get the time "before"
3338  // the cache change.
3339  $now = ‪$GLOBALS['ACCESS_TIME'];
3340  // Find timeout by checking every table
3341  foreach ($tablesToConsider as $tableDef) {
3342  $result = min($result, $this->‪getFirstTimeValueForRecord($tableDef, $now));
3343  }
3344  // We return + 1 second just to ensure that cache is definitely regenerated
3345  return $result === PHP_INT_MAX ? PHP_INT_MAX : $result - $now + 1;
3346  }
3347 
3365  protected function ‪getCurrentPageCacheConfiguration()
3366  {
3367  $result = ['tt_content:' . ‪$this->id];
3368  if (isset($this->config['config']['cache.'][$this->id])) {
3369  $result = array_merge($result, ‪GeneralUtility::trimExplode(',', str_replace(':current', ':' . $this->id, $this->config['config']['cache.'][$this->id])));
3370  }
3371  if (isset($this->config['config']['cache.']['all'])) {
3372  $result = array_merge($result, ‪GeneralUtility::trimExplode(',', str_replace(':current', ':' . $this->id, $this->config['config']['cache.']['all'])));
3373  }
3374  return array_unique($result);
3375  }
3376 
3386  protected function ‪getFirstTimeValueForRecord($tableDef, $now)
3387  {
3388  $now = (int)$now;
3389  $result = PHP_INT_MAX;
3390  [$tableName, $pid] = ‪GeneralUtility::trimExplode(':', $tableDef);
3391  if (empty($tableName) || empty($pid)) {
3392  throw new \InvalidArgumentException('Unexpected value for parameter $tableDef. Expected <tablename>:<pid>, got \'' . htmlspecialchars($tableDef) . '\'.', 1307190365);
3393  }
3395  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3396  ->getQueryBuilderForTable($tableName);
3397  $queryBuilder->getRestrictions()
3398  ->removeByType(StartTimeRestriction::class)
3399  ->removeByType(EndTimeRestriction::class);
3400  $timeFields = [];
3401  $timeConditions = $queryBuilder->expr()->orX();
3402  foreach (['starttime', 'endtime'] as $field) {
3403  if (isset($GLOBALS['TCA'][$tableName]['ctrl']['enablecolumns'][$field])) {
3404  $timeFields[$field] = $GLOBALS['TCA'][$tableName]['ctrl']['enablecolumns'][$field];
3405  $queryBuilder->addSelectLiteral(
3406  'MIN('
3407  . 'CASE WHEN '
3408  . $queryBuilder->expr()->lte(
3409  $timeFields[$field],
3410  $queryBuilder->createNamedParameter($now, Connection::PARAM_INT)
3411  )
3412  . ' THEN NULL ELSE ' . $queryBuilder->quoteIdentifier($timeFields[$field]) . ' END'
3413  . ') AS ' . $queryBuilder->quoteIdentifier($timeFields[$field])
3414  );
3415  $timeConditions->add(
3416  $queryBuilder->expr()->gt(
3417  $timeFields[$field],
3418  $queryBuilder->createNamedParameter($now, Connection::PARAM_INT)
3419  )
3420  );
3421  }
3422  }
3423 
3424  // if starttime or endtime are defined, evaluate them
3425  if (!empty($timeFields)) {
3426  // find the timestamp, when the current page's content changes the next time
3427  $row = $queryBuilder
3428  ->from($tableName)
3429  ->where(
3430  $queryBuilder->expr()->eq(
3431  'pid',
3432  $queryBuilder->createNamedParameter($pid, ‪Connection::PARAM_INT)
3433  ),
3434  $timeConditions
3435  )
3436  ->executeQuery()
3437  ->fetchAssociative();
3438 
3439  ‪if ($row) {
3440  foreach ($timeFields as $timeField => $_) {
3441  // if a MIN value is found, take it into account for the
3442  // cache lifetime we have to filter out start/endtimes < $now,
3443  // as the SQL query also returns rows with starttime < $now
3444  // and endtime > $now (and using a starttime from the past
3445  // would be wrong)
3446  if ($row[$timeField] !== null && (int)$row[$timeField] > $now) {
3447  $result = min($result, (int)$row[$timeField]);
3448  }
3449  }
3450  }
3451  }
3452 
3453  return $result;
3454  }
3455 
3462  public function ‪getRequestedId()
3463  {
3464  return $this->requestedId ?: ‪$this->id;
3465  }
3466 
3501  protected function ‪acquireLock(‪$type, $key)
3502  {
3503  $lockFactory = GeneralUtility::makeInstance(LockFactory::class);
3504  $this->locks[‪$type]['accessLock'] = $lockFactory->createLocker(‪$type);
3505 
3506  $this->locks[‪$type]['pageLock'] = $lockFactory->createLocker(
3507  $key,
3509  );
3510 
3511  do {
3512  if (!$this->locks[‪$type]['accessLock']->acquire()) {
3513  throw new \RuntimeException('Could not acquire access lock for "' . ‪$type . '"".', 1294586098);
3514  }
3515 
3516  try {
3517  $locked = $this->locks[‪$type]['pageLock']->acquire(
3519  );
3520  } catch (LockAcquireWouldBlockException $e) {
3521  // somebody else has the lock, we keep waiting
3523  // first release the access lock
3524  $this->locks[‪$type]['accessLock']->release();
3525  // now lets make a short break (100ms) until we try again, since
3526  // the page generation by the lock owner will take a while anyways
3527  usleep(100000);
3528  continue;
3529  }
3530  $this->locks[‪$type]['accessLock']->release();
3531  if ($locked) {
3532  break;
3533  }
3534  throw new \RuntimeException('Could not acquire page lock for ' . $key . '.', 1460975877);
3535  } while (true);
3536  }
3537 
3546  protected function ‪releaseLock(‪$type)
3547  {
3548  if ($this->locks[‪$type]['accessLock'] ?? false) {
3549  if (!$this->locks[‪$type]['accessLock']->acquire()) {
3550  throw new \RuntimeException('Could not acquire access lock for "' . ‪$type . '"".', 1460975902);
3551  }
3552 
3553  $this->locks[‪$type]['pageLock']->release();
3554  $this->locks[‪$type]['pageLock']->destroy();
3555  $this->locks[‪$type]['pageLock'] = null;
3556 
3557  $this->locks[‪$type]['accessLock']->release();
3558  $this->locks[‪$type]['accessLock'] = null;
3559  }
3560  }
3561 
3565  protected function ‪getAdditionalHeaders(): array
3566  {
3567  if (!isset($this->config['config']['additionalHeaders.'])) {
3568  return [];
3569  }
3570  $additionalHeaders = [];
3571  ksort($this->config['config']['additionalHeaders.']);
3572  foreach ($this->config['config']['additionalHeaders.'] as $options) {
3573  if (!is_array($options)) {
3574  continue;
3575  }
3576  $header = trim($options['header'] ?? '');
3577  if ($header === '') {
3578  continue;
3579  }
3580  $additionalHeaders[] = [
3581  'header' => $header,
3582  // "replace existing headers" is turned on by default, unless turned off
3583  'replace' => ($options['replace'] ?? '') !== '0',
3584  'statusCode' => (int)($options['httpResponseCode'] ?? 0) ?: null,
3585  ];
3586  }
3587  return $additionalHeaders;
3588  }
3589 
3590  protected function ‪isInPreviewMode(): bool
3591  {
3592  return $this->context->getPropertyFromAspect('frontend.preview', 'isPreview', false)
3593  || ‪$GLOBALS['EXEC_TIME'] !== ‪$GLOBALS['SIM_EXEC_TIME']
3594  || $this->context->getPropertyFromAspect('visibility', 'includeHiddenPages', false)
3595  || $this->context->getPropertyFromAspect('visibility', 'includeHiddenContent', false);
3596  }
3597 
3604  protected function ‪logPageAccessFailure(string $message, ServerRequestInterface $request): void
3605  {
3606  ‪$context = ['pageId' => ‪$this->id];
3607  if (($normalizedParams = $request->getAttribute('normalizedParams')) instanceof ‪NormalizedParams) {
3608  ‪$context['requestUrl'] = $normalizedParams->getRequestUrl();
3609  }
3610  $this->logger->error($message, ‪$context);
3611  }
3612 
3618  protected function ‪getBackendUser()
3619  {
3620  return ‪$GLOBALS['BE_USER'] ?? null;
3621  }
3622 
3626  protected function ‪getTimeTracker()
3627  {
3628  return GeneralUtility::makeInstance(TimeTracker::class);
3629  }
3630 
3642  public static function ‪getGlobalInstance(): ?self
3643  {
3644  if ((‪$GLOBALS['TSFE'] ?? null) instanceof self) {
3645  return ‪$GLOBALS['TSFE'];
3646  }
3647 
3648  if (!(‪$GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
3649  || !‪ApplicationType::fromRequest(‪$GLOBALS['TYPO3_REQUEST'])->isFrontend()
3650  ) {
3651  // Return null for now (together with shared: false in Services.yaml) as TSFE might not be available in backend context
3652  // That's not an error then
3653  return null;
3654  }
3655 
3656  throw new \LogicException('TypoScriptFrontendController was tried to be injected before initial creation', 1538370377);
3657  }
3658 
3659  public function ‪getLanguage(): SiteLanguage
3660  {
3661  return ‪$this->language;
3662  }
3663 
3664  public function ‪getSite(): SiteInterface
3665  {
3666  return ‪$this->site;
3667  }
3668 
3669  public function ‪getContext(): Context
3670  {
3671  return ‪$this->context;
3672  }
3673 
3674  public function ‪getPageArguments(): PageArguments
3675  {
3676  return ‪$this->pageArguments;
3677  }
3678 }
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$tmpl
‪TemplateService $tmpl
Definition: TypoScriptFrontendController.php:231
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$requestedId
‪int $requestedId
Definition: TypoScriptFrontendController.php:527
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\LANGUAGE_AND_FALLBACKS_NOT_AVAILABLE
‪const LANGUAGE_AND_FALLBACKS_NOT_AVAILABLE
Definition: PageAccessFailureReasons.php:43
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getCurrentPageCacheConfiguration
‪array getCurrentPageCacheConfiguration()
Definition: TypoScriptFrontendController.php:3297
‪TYPO3\CMS\Core\Routing\PageArguments\getPageType
‪string getPageType()
Definition: PageArguments.php:119
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$xhtmlDoctype
‪string $xhtmlDoctype
Definition: TypoScriptFrontendController.php:517
‪TYPO3\CMS\Core\Http\ApplicationType\fromRequest
‪static static fromRequest(ServerRequestInterface $request)
Definition: ApplicationType.php:62
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\initPageRenderer
‪initPageRenderer()
Definition: TypoScriptFrontendController.php:582
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setAbsRefPrefix
‪setAbsRefPrefix()
Definition: TypoScriptFrontendController.php:2975
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:999
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:26
‪TYPO3\CMS\Core\Routing\PageArguments
Definition: PageArguments.php:26
‪TYPO3\CMS\Core\Context\VisibilityAspect
Definition: VisibilityAspect.php:31
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\convOutputCharset
‪string convOutputCharset($content)
Definition: TypoScriptFrontendController.php:3244
‪TYPO3\CMS\Core\Page\AssetCollector
Definition: AssetCollector.php:42
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\doWorkspacePreview
‪bool doWorkspacePreview()
Definition: TypoScriptFrontendController.php:3050
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$contentType
‪string $contentType
Definition: TypoScriptFrontendController.php:511
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$no_cacheBeforePageGen
‪bool $no_cacheBeforePageGen
Definition: TypoScriptFrontendController.php:294
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:25
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:49
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:31
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$uniqueCounter
‪int $uniqueCounter
Definition: TypoScriptFrontendController.php:437
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$simUserGroup
‪int $simUserGroup
Definition: TypoScriptFrontendController.php:219
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getRedirectUriForMountPoint
‪string null getRedirectUriForMountPoint(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2206
‪TYPO3\CMS\Core\Context\LanguageAspectFactory
Definition: LanguageAspectFactory.php:27
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:206
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$currentRecord
‪string $currentRecord
Definition: TypoScriptFrontendController.php:424
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\checkIfLoginAllowedInBranch
‪bool checkIfLoginAllowedInBranch()
Definition: TypoScriptFrontendController.php:1369
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$displayFieldEditIcons
‪string $displayFieldEditIcons
Definition: TypoScriptFrontendController.php:387
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\recursivelyReplaceIntPlaceholdersInContent
‪recursivelyReplaceIntPlaceholdersInContent(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2739
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$cacheExpires
‪int $cacheExpires
Definition: TypoScriptFrontendController.php:251
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getAdditionalHeaders
‪getAdditionalHeaders()
Definition: TypoScriptFrontendController.php:3497
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pagesTSconfig
‪array string $pagesTSconfig
Definition: TypoScriptFrontendController.php:300
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\splitLinkVarsString
‪array splitLinkVarsString(string $string)
Definition: TypoScriptFrontendController.php:2139
‪TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction
Definition: EndTimeRestriction.php:27
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$applicationData
‪array $applicationData
Definition: TypoScriptFrontendController.php:393
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setOutputLanguage
‪setOutputLanguage()
Definition: TypoScriptFrontendController.php:3230
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:251
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\sL
‪string sL($input)
Definition: TypoScriptFrontendController.php:3221
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$linkVars
‪string $linkVars
Definition: TypoScriptFrontendController.php:372
‪TYPO3\CMS\Backend\FrontendBackendUserAuthentication
Definition: FrontendBackendUserAuthentication.php:31
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:36
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\generatePageTitle
‪string generatePageTitle()
Definition: TypoScriptFrontendController.php:2602
‪TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction
Definition: StartTimeRestriction.php:27
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\applyPreviewSettings
‪string null applyPreviewSettings($backendUser=null)
Definition: TypoScriptFrontendController.php:747
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getLockHash
‪string getLockHash()
Definition: TypoScriptFrontendController.php:1708
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\generatePage_preProcessing
‪generatePage_preProcessing()
Definition: TypoScriptFrontendController.php:2437
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\checkEnableFields
‪bool checkEnableFields($row, $bypassGroupCheck=false)
Definition: TypoScriptFrontendController.php:1310
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:445
‪TYPO3\CMS\Core\TimeTracker\TimeTracker\setTSlogMessage
‪setTSlogMessage($content, $logLevel=LogLevel::INFO)
Definition: TimeTracker.php:226
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getPageAccessFailureReasons
‪array getPageAccessFailureReasons(string $failureReasonCode=null)
Definition: TypoScriptFrontendController.php:1399
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getSite
‪getSite()
Definition: TypoScriptFrontendController.php:3596
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getPageAndRootlineWithDomain
‪getPageAndRootlineWithDomain($rootPageId, ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:1439
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\applyHttpHeadersToResponse
‪ResponseInterface applyHttpHeadersToResponse(ResponseInterface $response)
Definition: TypoScriptFrontendController.php:2845
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$no_cache
‪bool $no_cache
Definition: TypoScriptFrontendController.php:141
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$cacheContentFlag
‪bool $cacheContentFlag
Definition: TypoScriptFrontendController.php:245
‪TYPO3\CMS\Core\Locking\LockingStrategyInterface\LOCK_CAPABILITY_NOBLOCK
‪const LOCK_CAPABILITY_NOBLOCK
Definition: LockingStrategyInterface.php:40
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setContentType
‪setContentType($contentType)
Definition: TypoScriptFrontendController.php:600
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$MP
‪string $MP
Definition: TypoScriptFrontendController.php:196
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$indexedDocTitle
‪string $indexedDocTitle
Definition: TypoScriptFrontendController.php:449
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\clear_preview
‪clear_preview()
Definition: TypoScriptFrontendController.php:645
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\disableCache
‪disableCache()
Definition: TypoScriptFrontendController.php:3149
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\uniqueHash
‪string uniqueHash($str='')
Definition: TypoScriptFrontendController.php:3103
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$register
‪array $register
Definition: TypoScriptFrontendController.php:397
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer
Definition: FilePathSanitizer.php:39
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:32
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\__construct
‪__construct(Context $context, SiteInterface $site, SiteLanguage $siteLanguage, PageArguments $pageArguments, FrontendUserAuthentication $frontendUser)
Definition: TypoScriptFrontendController.php:557
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\populatePageDataFromCache
‪populatePageDataFromCache(array $cachedData)
Definition: TypoScriptFrontendController.php:1616
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:112
‪TYPO3\CMS\Core\Configuration\Loader\PageTsConfigLoader
Definition: PageTsConfigLoader.php:39
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\baseUrlWrap
‪string baseUrlWrap($url)
Definition: TypoScriptFrontendController.php:3015
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isInPreviewMode
‪isInPreviewMode()
Definition: TypoScriptFrontendController.php:3522
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pageArguments
‪PageArguments $pageArguments
Definition: TypoScriptFrontendController.php:135
‪TYPO3\CMS\Core\Utility\RootlineUtility
Definition: RootlineUtility.php:38
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$additionalFooterData
‪array $additionalFooterData
Definition: TypoScriptFrontendController.php:319
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$extTarget
‪string $extTarget
Definition: TypoScriptFrontendController.php:329
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$metaCharset
‪string $metaCharset
Definition: TypoScriptFrontendController.php:478
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$intTarget
‪string $intTarget
Definition: TypoScriptFrontendController.php:324
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪$parser
‪$parser
Definition: annotationChecker.php:110
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getContext
‪getContext()
Definition: TypoScriptFrontendController.php:3601
‪TYPO3\CMS\Core\Locking\LockingStrategyInterface
Definition: LockingStrategyInterface.php:26
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\createHashBase
‪string createHashBase($createLockHashBase=false)
Definition: TypoScriptFrontendController.php:1724
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$lastImgResourceInfo
‪array $lastImgResourceInfo
Definition: TypoScriptFrontendController.php:471
‪TYPO3\CMS\Core\Charset\CharsetConverter
Definition: CharsetConverter.php:54
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setRegisterValueForSysLastChanged
‪setRegisterValueForSysLastChanged(array $page)
Definition: TypoScriptFrontendController.php:2391
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$type
‪int string $type
Definition: TypoScriptFrontendController.php:122
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\Context\LanguageAspectFactory\createFromSiteLanguage
‪static LanguageAspect createFromSiteLanguage(SiteLanguage $language)
Definition: LanguageAspectFactory.php:34
‪TYPO3\CMS\Core\Type\Bitmask\PageTranslationVisibility
Definition: PageTranslationVisibility.php:30
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$fileTarget
‪string $fileTarget
Definition: TypoScriptFrontendController.php:334
‪TYPO3\CMS\Core\Locking\LockingStrategyInterface\LOCK_CAPABILITY_EXCLUSIVE
‪const LOCK_CAPABILITY_EXCLUSIVE
Definition: LockingStrategyInterface.php:30
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isUserOrGroupSet
‪bool isUserOrGroupSet()
Definition: TypoScriptFrontendController.php:633
‪TYPO3\CMS\Core\Http\ApplicationType
Definition: ApplicationType.php:52
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pageAccessFailureHistory
‪array $pageAccessFailureHistory
Definition: TypoScriptFrontendController.php:191
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\ACCESS_DENIED_INVALID_PAGETYPE
‪const ACCESS_DENIED_INVALID_PAGETYPE
Definition: PageAccessFailureReasons.php:51
‪TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException
Definition: LockAcquireWouldBlockException.php:21
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:53
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getGlobalInstance
‪static TypoScriptFrontendController getGlobalInstance()
Definition: TypoScriptFrontendController.php:3574
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$xhtmlVersion
‪int $xhtmlVersion
Definition: TypoScriptFrontendController.php:521
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isStaticCacheble
‪bool isStaticCacheble()
Definition: TypoScriptFrontendController.php:2946
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getHash
‪string getHash()
Definition: TypoScriptFrontendController.php:1695
‪TYPO3\CMS\Core\Core\Environment\getFrameworkBasePath
‪static string getFrameworkBasePath()
Definition: Environment.php:287
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\settingLanguage
‪settingLanguage(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:1895
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$page
‪array $page
Definition: TypoScriptFrontendController.php:151
‪TYPO3\CMS\Core\Context\Context\setAspect
‪setAspect(string $name, AspectInterface $aspect)
Definition: Context.php:167
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\clearPageCacheContent
‪clearPageCacheContent()
Definition: TypoScriptFrontendController.php:2354
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$registerStack
‪array $registerStack
Definition: TypoScriptFrontendController.php:403
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getRedirectUriForShortcut
‪string null getRedirectUriForShortcut(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2225
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$additionalHeaderData
‪array $additionalHeaderData
Definition: TypoScriptFrontendController.php:314
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getCacheHeaders
‪array getCacheHeaders()
Definition: TypoScriptFrontendController.php:2893
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\realPageCacheContent
‪realPageCacheContent()
Definition: TypoScriptFrontendController.php:2291
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_MOUNTPOINT
‪const DOKTYPE_MOUNTPOINT
Definition: PageRepository.php:114
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getLanguage
‪getLanguage()
Definition: TypoScriptFrontendController.php:3591
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isINTincScript
‪bool isINTincScript()
Definition: TypoScriptFrontendController.php:2834
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\processNonCacheableContentPartsAndSubstituteContentMarkers
‪processNonCacheableContentPartsAndSubstituteContentMarkers(array $nonCacheableData, ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2760
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\initUserGroups
‪initUserGroups()
Definition: TypoScriptFrontendController.php:622
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\determineIdIsHiddenPage
‪bool determineIdIsHiddenPage()
Definition: TypoScriptFrontendController.php:778
‪TYPO3\CMS\Core\Error\Http\PageNotFoundException
Definition: PageNotFoundException.php:24
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$locks
‪LockingStrategyInterface[][] $locks
Definition: TypoScriptFrontendController.php:488
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\ACCESS_DENIED_HOST_PAGE_MISMATCH
‪const ACCESS_DENIED_HOST_PAGE_MISMATCH
Definition: PageAccessFailureReasons.php:50
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$fe_user
‪FrontendUserAuthentication $fe_user
Definition: TypoScriptFrontendController.php:202
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$deprecatedPublicProperties
‪array $deprecatedPublicProperties
Definition: TypoScriptFrontendController.php:110
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getPageArguments
‪getPageArguments()
Definition: TypoScriptFrontendController.php:3606
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\ACCESS_DENIED_PAGE_NOT_RESOLVED
‪const ACCESS_DENIED_PAGE_NOT_RESOLVED
Definition: PageAccessFailureReasons.php:48
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$accessKey
‪array $accessKey
Definition: TypoScriptFrontendController.php:430
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getPageCacheTags
‪array getPageCacheTags()
Definition: TypoScriptFrontendController.php:2424
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$loginAllowedInBranch_mode
‪string $loginAllowedInBranch_mode
Definition: TypoScriptFrontendController.php:213
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\checkRootlineForIncludeSection
‪bool checkRootlineForIncludeSection()
Definition: TypoScriptFrontendController.php:1242
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getFromCache_queryRow
‪array getFromCache_queryRow()
Definition: TypoScriptFrontendController.php:1598
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\calculateLinkVars
‪calculateLinkVars(array $queryParams)
Definition: TypoScriptFrontendController.php:2060
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\LANGUAGE_DEFAULT_NOT_AVAILABLE
‪const LANGUAGE_DEFAULT_NOT_AVAILABLE
Definition: PageAccessFailureReasons.php:44
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getFirstTimeValueForRecord
‪int getFirstTimeValueForRecord($tableDef, $now)
Definition: TypoScriptFrontendController.php:3318
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$site
‪SiteInterface $site
Definition: TypoScriptFrontendController.php:126
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\determineId
‪determineId(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:674
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pageRenderer
‪PageRenderer $pageRenderer
Definition: TypoScriptFrontendController.php:492
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pageCache
‪FrontendInterface $pageCache
Definition: TypoScriptFrontendController.php:499
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\unsetBackendUser
‪unsetBackendUser()
Definition: TypoScriptFrontendController.php:726
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getBackendUser
‪FrontendBackendUserAuthentication null getBackendUser()
Definition: TypoScriptFrontendController.php:3550
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\INTincScript
‪INTincScript(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:2694
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:171
‪TYPO3\CMS\Core\PageTitle\PageTitleProviderManager
Definition: PageTitleProviderManager.php:31
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getWebsiteTitle
‪string getWebsiteTitle()
Definition: TypoScriptFrontendController.php:2673
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\LANGUAGE_NOT_AVAILABLE
‪const LANGUAGE_NOT_AVAILABLE
Definition: PageAccessFailureReasons.php:41
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\PAGE_NOT_FOUND
‪const PAGE_NOT_FOUND
Definition: PageAccessFailureReasons.php:28
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pageNotFound
‪int $pageNotFound
Definition: TypoScriptFrontendController.php:186
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$ATagParams
‪string $ATagParams
Definition: TypoScriptFrontendController.php:350
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isGeneratePage
‪bool isGeneratePage()
Definition: TypoScriptFrontendController.php:2283
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:115
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\RENDERING_INSTRUCTIONS_NOT_CONFIGURED
‪const RENDERING_INSTRUCTIONS_NOT_CONFIGURED
Definition: PageAccessFailureReasons.php:33
‪TYPO3\CMS\Core\Http\ServerRequestFactory
Definition: ServerRequestFactory.php:34
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\initializeContext
‪initializeContext(Context $context)
Definition: TypoScriptFrontendController.php:571
‪TYPO3\CMS\Core\TimeTracker\TimeTracker\pull
‪pull($content='')
Definition: TimeTracker.php:206
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$loginAllowedInBranch
‪bool $loginAllowedInBranch
Definition: TypoScriptFrontendController.php:207
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$contentPid
‪int $contentPid
Definition: TypoScriptFrontendController.php:157
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$absRefPrefix
‪string $absRefPrefix
Definition: TypoScriptFrontendController.php:344
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_BE_USER_SECTION
‪const DOKTYPE_BE_USER_SECTION
Definition: PageRepository.php:113
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$spamProtectEmailAddresses
‪string int $spamProtectEmailAddresses
Definition: TypoScriptFrontendController.php:339
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\preparePageContentGeneration
‪preparePageContentGeneration(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2475
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\ACCESS_DENIED_SUBSECTION_NOT_RESOLVED
‪const ACCESS_DENIED_SUBSECTION_NOT_RESOLVED
Definition: PageAccessFailureReasons.php:49
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$sWordList
‪string $sWordList
Definition: TypoScriptFrontendController.php:365
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser
Definition: PageTsConfigParser.php:33
‪TYPO3\CMS\Core\Core\Environment\getBackendPath
‪static string getBackendPath()
Definition: Environment.php:276
‪TYPO3\CMS\Core\Charset\UnknownCharsetException
Definition: UnknownCharsetException.php:23
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\checkPageGroupAccess
‪bool checkPageGroupAccess($row)
Definition: TypoScriptFrontendController.php:1336
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\get_cache_timeout
‪int get_cache_timeout()
Definition: TypoScriptFrontendController.php:3172
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SYSFOLDER
‪const DOKTYPE_SYSFOLDER
Definition: PageRepository.php:116
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\headerNoCache
‪bool headerNoCache(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:1665
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$context
‪Context $context
Definition: TypoScriptFrontendController.php:534
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getPageAndRootline
‪getPageAndRootline(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:1013
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$debugInformationHeader
‪string $debugInformationHeader
Definition: TypoScriptFrontendController.php:540
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:57
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$newHash
‪string $newHash
Definition: TypoScriptFrontendController.php:285
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$all
‪array $all
Definition: TypoScriptFrontendController.php:265
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getConfigArray
‪getConfigArray(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:1765
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\printTitle
‪string printTitle(string $pageTitle, bool $noTitle=false, bool $showTitleFirst=false, string $pageTitleSeparator='')
Definition: TypoScriptFrontendController.php:2651
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\releaseLocks
‪releaseLocks()
Definition: TypoScriptFrontendController.php:2404
‪TYPO3\CMS\Core\Http\PropagateResponseException
Definition: PropagateResponseException.php:47
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$isClientCachable
‪bool $isClientCachable
Definition: TypoScriptFrontendController.php:257
‪TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher
Definition: ConditionMatcher.php:30
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getFromCache
‪getFromCache(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:1512
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\LANGUAGE_NOT_AVAILABLE_STRICT_MODE
‪const LANGUAGE_NOT_AVAILABLE_STRICT_MODE
Definition: PageAccessFailureReasons.php:42
‪$output
‪$output
Definition: annotationChecker.php:121
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$id
‪string int $id
Definition: TypoScriptFrontendController.php:117
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\whichWorkspace
‪int whichWorkspace()
Definition: TypoScriptFrontendController.php:3060
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setPageCacheContent
‪setPageCacheContent($content, $data, $expirationTstamp)
Definition: TypoScriptFrontendController.php:2321
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:38
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\logDeprecatedTyposcript
‪logDeprecatedTyposcript($typoScriptProperty, $explanation='')
Definition: TypoScriptFrontendController.php:3034
‪TYPO3\CMS\Core\TypoScript\TemplateService
Definition: TemplateService.php:46
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$displayEditIcons
‪string $displayEditIcons
Definition: TypoScriptFrontendController.php:379
‪TYPO3\CMS\Core\Error\Http\ShortcutTargetPageNotFoundException
Definition: ShortcutTargetPageNotFoundException.php:23
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isAllowedLinkVarValue
‪bool isAllowedLinkVarValue(string $haystack, string $needle)
Definition: TypoScriptFrontendController.php:2162
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\logPageAccessFailure
‪logPageAccessFailure(string $message, ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:3536
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\addCacheTags
‪addCacheTags(array $tags)
Definition: TypoScriptFrontendController.php:2416
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:104
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$recordRegister
‪array $recordRegister
Definition: TypoScriptFrontendController.php:416
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$uniqueString
‪string $uniqueString
Definition: TypoScriptFrontendController.php:442
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Error\Http\AbstractServerErrorException
Definition: AbstractServerErrorException.php:21
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getUriToCurrentPageForRedirect
‪string getUriToCurrentPageForRedirect(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2257
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:43
‪if
‪if(PHP_SAPI !=='cli')
Definition: checkNamespaceIntegrity.php:25
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\fetch_the_id
‪fetch_the_id(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:898
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\initializeSearchWordData
‪initializeSearchWordData($searchWords)
Definition: TypoScriptFrontendController.php:2545
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$cacheTimeOutDefault
‪int $cacheTimeOutDefault
Definition: TypoScriptFrontendController.php:238
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$sPre
‪string $sPre
Definition: TypoScriptFrontendController.php:271
‪TYPO3\CMS\Frontend\Page\CacheHashCalculator
Definition: CacheHashCalculator.php:25
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\INTincScript_loadJSCode
‪INTincScript_loadJSCode()
Definition: TypoScriptFrontendController.php:2812
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Core\Locking\LockFactory
Definition: LockFactory.php:25
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setSysLastChanged
‪setSysLastChanged()
Definition: TypoScriptFrontendController.php:2365
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\set_cache_timeout_default
‪set_cache_timeout_default($seconds)
Definition: TypoScriptFrontendController.php:3159
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getRequestedId
‪int getRequestedId()
Definition: TypoScriptFrontendController.php:3394
‪TYPO3\CMS\Frontend\Controller
Definition: ErrorController.php:18
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getPagesTSconfig
‪array getPagesTSconfig()
Definition: TypoScriptFrontendController.php:3076
‪TYPO3\CMS\Core\Exception\Page\RootLineException
Definition: RootLineException.php:24
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$sWordRegEx
‪string $sWordRegEx
Definition: TypoScriptFrontendController.php:358
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:22
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\updateRootLinesWithTranslations
‪updateRootLinesWithTranslations()
Definition: TypoScriptFrontendController.php:2020
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$cObj
‪ContentObjectRenderer $cObj
Definition: TypoScriptFrontendController.php:460
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:32
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$cObjectDepthCounter
‪int $cObjectDepthCounter
Definition: TypoScriptFrontendController.php:410
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\newCObj
‪newCObj(ServerRequestInterface $request=null)
Definition: TypoScriptFrontendController.php:2962
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:67
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$originalShortcutPage
‪array null $originalShortcutPage
Definition: TypoScriptFrontendController.php:174
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\checkPagerecordForIncludeSection
‪bool checkPagerecordForIncludeSection(array $row)
Definition: TypoScriptFrontendController.php:1359
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$languageService
‪LanguageService $languageService
Definition: TypoScriptFrontendController.php:484
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getRelevantParametersForCachingFromPageArguments
‪array getRelevantParametersForCachingFromPageArguments(PageArguments $pageArguments)
Definition: TypoScriptFrontendController.php:1494
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\calculatePageCacheTimeout
‪int calculatePageCacheTimeout()
Definition: TypoScriptFrontendController.php:3262
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\generatePage_postProcessing
‪generatePage_postProcessing()
Definition: TypoScriptFrontendController.php:2566
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$config
‪array $config
Definition: TypoScriptFrontendController.php:225
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\checkTranslatedShortcut
‪checkTranslatedShortcut(int $languageId, ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2037
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$language
‪SiteLanguage $language
Definition: TypoScriptFrontendController.php:130
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\setPageArguments
‪setPageArguments(PageArguments $pageArguments)
Definition: TypoScriptFrontendController.php:1475
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getTimeTracker
‪TimeTracker getTimeTracker()
Definition: TypoScriptFrontendController.php:3558
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$originalMountPointPage
‪array null $originalMountPointPage
Definition: TypoScriptFrontendController.php:165
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$content
‪string $content
Definition: TypoScriptFrontendController.php:465
‪TYPO3\CMS\Core\Http\ImmediateResponseException
Definition: ImmediateResponseException.php:35
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\resolveContentPid
‪int resolveContentPid(ServerRequestInterface $request)
Definition: TypoScriptFrontendController.php:2457
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$rootLine
‪array $rootLine
Definition: TypoScriptFrontendController.php:146
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\set_no_cache
‪set_no_cache($reason='', $internalRequest=false)
Definition: TypoScriptFrontendController.php:3114
‪TYPO3\CMS\Frontend\Aspect\PreviewAspect
Definition: PreviewAspect.php:30
‪TYPO3\CMS\Core\TimeTracker\TimeTracker
Definition: TimeTracker.php:31
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isBackendUserLoggedIn
‪bool isBackendUserLoggedIn()
Definition: TypoScriptFrontendController.php:661
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\releaseLock
‪releaseLock($type)
Definition: TypoScriptFrontendController.php:3478
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\initCaches
‪initCaches()
Definition: TypoScriptFrontendController.php:613
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:16
‪TYPO3\CMS\Core\Routing\PageArguments\getPageId
‪int getPageId()
Definition: PageArguments.php:111
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_RECYCLER
‪const DOKTYPE_RECYCLER
Definition: PageRepository.php:117
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:35
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\prepareDebugInformationForCachedPage
‪prepareDebugInformationForCachedPage(array $cachedData)
Definition: TypoScriptFrontendController.php:1650
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons
Definition: PageAccessFailureReasons.php:25
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\ROOTLINE_BROKEN
‪const ROOTLINE_BROKEN
Definition: PageAccessFailureReasons.php:29
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$sys_page
‪PageRepository string $sys_page
Definition: TypoScriptFrontendController.php:180
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:37
‪TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend
Definition: AbstractFrontend.php:26
‪TYPO3\CMS\Core\Http\NormalizedParams
Definition: NormalizedParams.php:35
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pageCacheTags
‪array $pageCacheTags
Definition: TypoScriptFrontendController.php:503
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\resolveTranslatedPageId
‪resolveTranslatedPageId()
Definition: TypoScriptFrontendController.php:1205
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$baseUrl
‪string $baseUrl
Definition: TypoScriptFrontendController.php:454
‪TYPO3\CMS\Core\Http\ServerRequestFactory\fromGlobals
‪static ServerRequest fromGlobals()
Definition: ServerRequestFactory.php:59
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\$pSetup
‪array string $pSetup
Definition: TypoScriptFrontendController.php:278
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\acquireLock
‪acquireLock($type, $key)
Definition: TypoScriptFrontendController.php:3433
‪TYPO3\CMS\Core\Core\Environment\getExtensionsPath
‪static string getExtensionsPath()
Definition: Environment.php:297
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\RENDERING_INSTRUCTIONS_NOT_FOUND
‪const RENDERING_INSTRUCTIONS_NOT_FOUND
Definition: PageAccessFailureReasons.php:32
‪TYPO3\CMS\Core\TimeTracker\TimeTracker\push
‪push($tslabel, $value='')
Definition: TimeTracker.php:179