‪TYPO3CMS  9.5
PageLayoutController.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
48 
53 {
56 
60  private ‪$deprecatedPublicMethods = [
61  'init' => 'Using PageLayoutController::init() is deprecated and will not be possible anymore in TYPO3 v10.0.',
62  'main' => 'Using PageLayoutController::main() is deprecated and will not be possible anymore in TYPO3 v10.0.',
63  'menuConfig' => 'Using PageLayoutController::menuConfig() is deprecated and will not be possible anymore in TYPO3 v10.0.',
64  'renderContent' => 'Using PageLayoutController::renderContent() is deprecated and will not be possible anymore in TYPO3 v10.0.',
65  'clearCache' => 'Using PageLayoutController::clearCache() is deprecated and will not be possible anymore in TYPO3 v10.0.',
66  'getModuleTemplate' => 'Using PageLayoutController::getModuleTemplate() is deprecated and will not be possible anymore in TYPO3 v10.0.',
67  'getLocalizedPageTitle' => 'Using PageLayoutController::getLocalizedPageTitle() is deprecated and will not be possible anymore in TYPO3 v10.0.',
68  'getNumberOfHiddenElements' => 'Using PageLayoutController::getNumberOfHiddenElements() is deprecated and will not be possible anymore in TYPO3 v10.0.',
69  'local_linkThisScript' => 'Using PageLayoutController::local_linkThisScript() is deprecated and will not be possible anymore in TYPO3 v10.0.',
70  'pageIsNotLockedForEditors' => 'Using PageLayoutController::pageIsNotLockedForEditors() is deprecated and will not be possible anymore in TYPO3 v10.0.',
71  'contentIsNotLockedForEditors' => 'Using PageLayoutController::contentIsNotLockedForEditors() is deprecated and will not be possible anymore in TYPO3 v10.0.',
72  ];
73 
78  'pointer' => 'Using PageLayoutController::$pointer is deprecated and will not be possible anymore in TYPO3 v10.0.',
79  'imagemode' => 'Using PageLayoutController::$imagemode is deprecated and will not be possible anymore in TYPO3 v10.0.',
80  'search_field' => 'Using PageLayoutController::$search_field is deprecated and will not be possible anymore in TYPO3 v10.0.',
81  'search_levels' => 'Using PageLayoutController::$search_levels is deprecated and will not be possible anymore in TYPO3 v10.0.',
82  'showLimit' => 'Using PageLayoutController::$showLimit is deprecated and will not be possible anymore in TYPO3 v10.0.',
83  'returnUrl' => 'Using PageLayoutController::$returnUrl is deprecated and will not be possible anymore in TYPO3 v10.0.',
84  'clear_cache' => 'Using PageLayoutController::$clear_cache is deprecated and will not be possible anymore in TYPO3 v10.0.',
85  'popView' => 'Using PageLayoutController::$popView is deprecated and will not be possible anymore in TYPO3 v10.0.',
86  'perms_clause' => 'Using PageLayoutController::$perms_clause is deprecated and will not be possible anymore in TYPO3 v10.0.',
87  'modTSconfig' => 'Using PageLayoutController::$modTSconfig is deprecated and will not be possible anymore in TYPO3 v10.0.',
88  'modSharedTSconfig' => 'Using PageLayoutController::$modSharedTSconfig is deprecated and will not be possible anymore in TYPO3 v10.0.',
89  'descrTable' => 'Using PageLayoutController::$descrTable is deprecated and will not be possible anymore in TYPO3 v10.0.',
90  'colPosList' => 'Using PageLayoutController::$colPosList is deprecated and will not be possible anymore in TYPO3 v10.0.',
91  'EDIT_CONTENT' => 'Using PageLayoutController::$EDIT_CONTENT is deprecated and will not be possible anymore in TYPO3 v10.0.',
92  'CALC_PERMS' => 'Using PageLayoutController::$CALC_PERMS is deprecated and will not be possible anymore in TYPO3 v10.0.',
93  'current_sys_language' => 'Using PageLayoutController::$current_sys_language is deprecated and will not be possible anymore in TYPO3 v10.0.',
94  'MCONF' => 'Using PageLayoutController::$MCONF is deprecated and will not be possible anymore in TYPO3 v10.0.',
95  'MOD_MENU' => 'Using PageLayoutController::$MOD_MENU is deprecated and will not be possible anymore in TYPO3 v10.0.',
96  'content' => 'Using PageLayoutController::$content is deprecated and will not be possible anymore in TYPO3 v10.0.',
97  'activeColPosList' => 'Using PageLayoutController::$activeColPosList is deprecated and will not be possible anymore in TYPO3 v10.0.',
98  ];
99 
106  public ‪$id;
107 
113  protected ‪$pointer;
114 
120  protected ‪$imagemode;
121 
127  protected ‪$search_field;
128 
134  protected ‪$search_levels;
135 
141  protected ‪$showLimit;
142 
148  protected ‪$returnUrl;
149 
155  protected ‪$clear_cache;
156 
162  protected ‪$popView;
163 
169  protected ‪$perms_clause;
170 
176  protected ‪$modTSconfig = [];
177 
183  protected ‪$modSharedTSconfig = [];
184 
191  public ‪$pageinfo;
192 
198  protected ‪$descrTable;
199 
205  protected ‪$colPosList;
206 
212  protected ‪$EDIT_CONTENT;
213 
219  protected ‪$CALC_PERMS;
220 
226  protected ‪$current_sys_language;
227 
233  protected ‪$MCONF = [];
234 
240  protected ‪$MOD_MENU = [];
241 
248  public ‪$MOD_SETTINGS = [];
249 
255  protected ‪$content;
256 
263  protected ‪$activeColPosList;
264 
268  protected ‪$editSelect;
269 
275  protected ‪$languagesInColumnCache = [];
276 
280  protected ‪$iconFactory;
281 
287  protected ‪$moduleName = 'web_layout';
288 
292  protected ‪$moduleTemplate;
293 
297  protected ‪$buttonBar;
298 
302  protected ‪$searchContent;
303 
311  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
312  {
313  ‪$GLOBALS['SOBE'] = $this;
314  $this->‪init($request);
315  $this->‪clearCache();
316  $this->‪main($request);
317  return new ‪HtmlResponse($this->moduleTemplate->renderContent());
318  }
319 
324  protected function ‪init(ServerRequestInterface $request = null): void
325  {
326  $request = $request ?: ‪$GLOBALS['TYPO3_REQUEST'];
327  // Set the GPvars from outside
328  $parsedBody = $request->getParsedBody();
329  $queryParams = $request->getQueryParams();
330 
331  $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
332  $this->iconFactory = $this->moduleTemplate->getIconFactory();
333  $this->buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
334  $this->‪getLanguageService()->‪includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
335  // Setting module configuration / page select clause
336  $this->MCONF['name'] = ‪$this->moduleName;
337  $this->perms_clause = $this->‪getBackendUser()->‪getPagePermsClause(‪Permission::PAGE_SHOW);
338  // Get session data
339  $sessionData = $this->‪getBackendUser()->‪getSessionData(__CLASS__);
340  $this->search_field = !empty($sessionData['search_field']) ? $sessionData['search_field'] : '';
341 
342  $this->id = (int)($parsedBody['id'] ?? $queryParams['id'] ?? 0);
343  $this->pointer = $parsedBody['pointer'] ?? $queryParams['pointer'] ?? null;
344  $this->imagemode = $parsedBody['imagemode'] ?? $queryParams['imagemode'] ?? null;
345  $this->clear_cache = $parsedBody['clear_cache'] ?? $queryParams['clear_cache'] ?? null;
346  $this->popView = $parsedBody['popView'] ?? $queryParams['popView'] ?? null;
347  $this->search_field = $parsedBody['search_field'] ?? $queryParams['search_field'] ?? null;
348  $this->search_levels = $parsedBody['search_levels'] ?? $queryParams['search_levels'] ?? null;
349  $this->showLimit = $parsedBody['showLimit'] ?? $queryParams['showLimit'] ?? null;
350  ‪$returnUrl = $parsedBody['returnUrl'] ?? $queryParams['returnUrl'] ?? null;
351  $this->returnUrl = GeneralUtility::sanitizeLocalUrl(‪$returnUrl);
352 
353  $sessionData['search_field'] = ‪$this->search_field;
354  // Store session data
355  $this->‪getBackendUser()->‪setAndSaveSessionData(__CLASS__, $sessionData);
356  // Load page info array:
357  $this->pageinfo = ‪BackendUtility::readPageAccess($this->id, $this->perms_clause);
358  // Initialize menu
359  $this->‪menuConfig($request);
360  // Setting sys language from session var:
361  $this->current_sys_language = (int)$this->MOD_SETTINGS['language'];
362  // CSH / Descriptions:
363  $this->descrTable = '_MOD_' . ‪$this->moduleName;
364  }
365 
370  protected function ‪menuConfig(ServerRequestInterface $request = null): void
371  {
372  $request = $request ?: ‪$GLOBALS['TYPO3_REQUEST'];
373  // Set the GPvars from outside
374  $parsedBody = $request->getParsedBody();
375  $queryParams = $request->getQueryParams();
376 
378  $currentSite = $request->getAttribute('site');
379  $availableLanguages = $currentSite->getAvailableLanguages($this->‪getBackendUser(), false, $this->id);
380 
381  $lang = $this->‪getLanguageService();
382  // MENU-ITEMS:
383  $this->MOD_MENU = [
384  'tt_content_showHidden' => '',
385  'function' => [
386  1 => $lang->getLL('m_function_1'),
387  2 => $lang->getLL('m_function_2')
388  ],
389  'language' => [
390  0 => $lang->getLL('m_default')
391  ]
392  ];
393  // initialize page/be_user TSconfig settings
394  $pageTsConfig = ‪BackendUtility::getPagesTSconfig($this->id);
395  $this->modSharedTSconfig['properties'] = $pageTsConfig['mod.']['SHARED.'] ?? [];
396  $this->modTSconfig['properties'] = $pageTsConfig['mod.']['web_layout.'] ?? [];
397 
398  // First, select all localized page records on the current page.
399  // Each represents a possibility for a language on the page. Add these to language selector.
400  if ($this->id) {
401  // Compile language data for pid != 0 only. The language drop-down is not shown on pid 0
402  // since pid 0 can't be localized.
403  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
404  $queryBuilder->getRestrictions()->removeAll()
405  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
406  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
407  $statement = $queryBuilder->select('uid', ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'])
408  ->from('pages')
409  ->where(
410  $queryBuilder->expr()->eq(
411  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
412  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
413  )
414  )->execute();
415  while ($pageTranslation = $statement->fetch()) {
416  $languageId = $pageTranslation[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']];
417  if (isset($availableLanguages[$languageId])) {
418  $this->MOD_MENU['language'][$languageId] = $availableLanguages[$languageId]->getTitle();
419  }
420  }
421  // Override the label
422  if (isset($availableLanguages[0])) {
423  $this->MOD_MENU['language'][0] = $availableLanguages[0]->getTitle();
424  }
425  }
426  // Initialize the available actions
427  $actions = $this->‪initActions();
428  // Clean up settings
429  $this->MOD_SETTINGS = ‪BackendUtility::getModuleData($this->MOD_MENU, $parsedBody['SET'] ?? $queryParams['SET'] ?? [], $this->moduleName);
430  // For all elements to be shown in draft workspaces & to also show hidden elements by default if user hasn't disabled the option
431  if ($this->‪getBackendUser()->workspace != 0
432  || !isset($this->MOD_SETTINGS['tt_content_showHidden'])
433  || $this->MOD_SETTINGS['tt_content_showHidden'] !== '0'
434  ) {
435  $this->MOD_SETTINGS['tt_content_showHidden'] = 1;
436  }
437  // Make action menu from available actions
438  $this->‪makeActionMenu($actions);
439  }
440 
446  protected function ‪initActions(): array
447  {
448  $actions = [
449  1 => $this->‪getLanguageService()->‪getLL('m_function_1'),
450  2 => $this->‪getLanguageService()->‪getLL('m_function_2')
451  ];
452  // Find if there are ANY languages at all (and if not, remove the language option from function menu).
453  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language');
454  if ($this->‪getBackendUser()->isAdmin()) {
455  $queryBuilder->getRestrictions()->removeAll();
456  }
457 
458  $count = $queryBuilder
459  ->count('uid')
460  ->from('sys_language')
461  ->execute()
462  ->fetchColumn(0);
463 
464  if (!$count) {
465  unset($actions['2']);
466  }
467  // Page / user TSconfig blinding of menu-items
468  $blindActions = $this->modTSconfig['properties']['menu.']['functions.'] ?? [];
469  foreach ($blindActions as $key => $value) {
470  if (!$value && array_key_exists($key, $actions)) {
471  unset($actions[$key]);
472  }
473  }
474 
475  return $actions;
476  }
477 
484  protected function ‪makeActionMenu(array $actions): void
485  {
486  $actionMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
487  $actionMenu->setIdentifier('actionMenu');
488  $actionMenu->setLabel('');
489 
490  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
491 
492  $defaultKey = null;
493  $foundDefaultKey = false;
494  foreach ($actions as $key => $action) {
495  $menuItem = $actionMenu
496  ->makeMenuItem()
497  ->setTitle($action)
498  ->setHref((string)$uriBuilder->buildUriFromRoute($this->moduleName) . '&id=' . $this->id . '&SET[function]=' . $key);
499 
500  if (!$foundDefaultKey) {
501  $defaultKey = $key;
502  $foundDefaultKey = true;
503  }
504  if ((int)$this->MOD_SETTINGS['function'] === $key) {
505  $menuItem->setActive(true);
506  $defaultKey = null;
507  }
508  $actionMenu->addMenuItem($menuItem);
509  }
510  if (isset($defaultKey)) {
511  $this->MOD_SETTINGS['function'] = $defaultKey;
512  }
513  $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($actionMenu);
514  }
515 
519  protected function ‪clearCache(): void
520  {
521  if ($this->clear_cache && !empty($this->pageinfo)) {
522  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
523  $dataHandler->start([], []);
524  $dataHandler->clear_cacheCmd($this->id);
525  }
526  }
527 
533  protected function ‪getHeaderFlashMessagesForCurrentPid(): string
534  {
535  ‪$content = '';
536  $lang = $this->‪getLanguageService();
537 
538  $view = GeneralUtility::makeInstance(StandaloneView::class);
539  $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/InfoBox.html'));
540 
541  // If page is a folder
542  if ($this->pageinfo['doktype'] == ‪PageRepository::DOKTYPE_SYSFOLDER) {
543  $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
544  $moduleLoader->load(‪$GLOBALS['TBE_MODULES']);
545  $modules = $moduleLoader->modules;
546  if (is_array($modules['web']['sub']['list'])) {
547  $title = $lang->getLL('goToListModule');
548  $message = '<p>' . $lang->getLL('goToListModuleMessage') . '</p>';
549  $message .= '<a class="btn btn-info" href="javascript:top.goToModule(\'web_list\',1);">' . $lang->getLL('goToListModule') . '</a>';
550  $view->assignMultiple([
551  'title' => $title,
552  'message' => $message,
554  ]);
555  ‪$content .= $view->render();
556  }
557  } elseif ($this->pageinfo['doktype'] === ‪PageRepository::DOKTYPE_SHORTCUT) {
558  $shortcutMode = (int)$this->pageinfo['shortcut_mode'];
559  $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
560  $targetPage = [];
561  $message = '';
563 
564  if ($shortcutMode || $this->pageinfo['shortcut']) {
565  switch ($shortcutMode) {
567  $targetPage = $this->‪getTargetPageIfVisible($pageRepository->getPage($this->pageinfo['shortcut']));
568  $message .= $targetPage === [] ? $lang->getLL('pageIsMisconfiguredOrNotAccessibleInternalLinkMessage') : '';
569  break;
571  $menuOfPages = $pageRepository->getMenu($this->pageinfo['uid'], '*', 'sorting', 'AND hidden = 0');
572  $targetPage = reset($menuOfPages) ?: [];
573  $message .= $targetPage === [] ? $lang->getLL('pageIsMisconfiguredFirstSubpageMessage') : '';
574  break;
576  $targetPage = $this->‪getTargetPageIfVisible($pageRepository->getPage($this->pageinfo['pid']));
577  $message .= $targetPage === [] ? $lang->getLL('pageIsMisconfiguredParentPageMessage') : '';
578  break;
580  $possibleTargetPages = $pageRepository->getMenu($this->pageinfo['uid'], '*', 'sorting', 'AND hidden = 0');
581  if ($possibleTargetPages === []) {
582  $message .= $lang->getLL('pageIsMisconfiguredOrNotAccessibleRandomInternalLinkMessage');
583  break;
584  }
585  $message = $lang->getLL('pageIsRandomInternalLinkMessage');
587  break;
588  }
589  $message = htmlspecialchars($message);
590  if ($targetPage !== [] && $shortcutMode !== ‪PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE) {
591  $linkToPid = $this->‪local_linkThisScript(['id' => $targetPage['uid']]);
592  $path = ‪BackendUtility::getRecordPath($targetPage['uid'], $this->‪getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW), 1000);
593  $linkedPath = '<a href="' . htmlspecialchars($linkToPid) . '">' . htmlspecialchars($path) . '</a>';
594  $message .= sprintf(htmlspecialchars($lang->getLL('pageIsInternalLinkMessage')), $linkedPath);
595  $message .= ' (' . htmlspecialchars($lang->sL(‪BackendUtility::getLabelFromItemlist('pages', 'shortcut_mode', $shortcutMode))) . ')';
597  }
598  } else {
599  $message = htmlspecialchars($lang->getLL('pageIsMisconfiguredInternalLinkMessage'));
601  }
602 
603  $view->assignMultiple([
604  'title' => $this->pageinfo['title'],
605  'message' => $message,
606  'state' => $state
607  ]);
608  ‪$content .= $view->render();
609  } elseif ($this->pageinfo['doktype'] === ‪PageRepository::DOKTYPE_LINK) {
610  if (empty($this->pageinfo['url'])) {
611  $view->assignMultiple([
612  'title' => $this->pageinfo['title'],
613  'message' => $lang->getLL('pageIsMisconfiguredExternalLinkMessage'),
615  ]);
616  ‪$content .= $view->render();
617  } else {
618  $externalUrl = htmlspecialchars(GeneralUtility::makeInstance(PageRepository::class)->getExtURL($this->pageinfo));
619  if ($externalUrl !== false) {
620  $externalUrlHtml = '<a href="' . $externalUrl . '" target="_blank" rel="noopener noreferrer">' . $externalUrl . '</a>';
621  $view->assignMultiple([
622  'title' => $this->pageinfo['title'],
623  'message' => sprintf($lang->getLL('pageIsExternalLinkMessage'), $externalUrlHtml),
625  ]);
626  ‪$content .= $view->render();
627  }
628  }
629  }
630  // If content from different pid is displayed
631  if ($this->pageinfo['content_from_pid']) {
632  $contentPage = ‪BackendUtility::getRecord('pages', (int)$this->pageinfo['content_from_pid']);
633  $linkToPid = $this->‪local_linkThisScript(['id' => $this->pageinfo['content_from_pid']]);
634  $title = ‪BackendUtility::getRecordTitle('pages', $contentPage);
635  $link = '<a href="' . htmlspecialchars($linkToPid) . '">' . htmlspecialchars($title) . ' (PID ' . (int)$this->pageinfo['content_from_pid'] . ')</a>';
636  $message = sprintf($lang->getLL('content_from_pid_title'), $link);
637  $view->assignMultiple([
638  'title' => $title,
639  'message' => $message,
641  ]);
642  ‪$content .= $view->render();
643  } else {
644  $links = $this->‪getPageLinksWhereContentIsAlsoShownOn($this->pageinfo['uid']);
645  if (!empty($links)) {
646  $message = sprintf($lang->getLL('content_on_pid_title'), $links);
647  $view->assignMultiple([
648  'title' => '',
649  'message' => $message,
651  ]);
652  ‪$content .= $view->render();
653  }
654  }
655  return ‪$content;
656  }
657 
664  protected function ‪getPageLinksWhereContentIsAlsoShownOn($pageId): string
665  {
666  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
667  $queryBuilder->getRestrictions()->removeAll();
668  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
669  $queryBuilder
670  ->select('*')
671  ->from('pages')
672  ->where($queryBuilder->expr()->eq('content_from_pid', $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)));
673 
674  $links = [];
675  $rows = $queryBuilder->execute()->fetchAll();
676  if (!empty($rows)) {
677  foreach ($rows as $row) {
678  $linkToPid = $this->‪local_linkThisScript(['id' => $row['uid']]);
679  $title = ‪BackendUtility::getRecordTitle('pages', $row);
680  $link = '<a href="' . htmlspecialchars($linkToPid) . '">' . htmlspecialchars($title) . ' (PID ' . (int)$row['uid'] . ')</a>';
681  $links[] = $link;
682  }
683  }
684  return implode(', ', $links);
685  }
686 
690  protected function ‪getLocalizedPageTitle(): string
691  {
692  if ($this->current_sys_language > 0) {
693  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
694  ->getQueryBuilderForTable('pages');
695  $queryBuilder->getRestrictions()
696  ->removeAll()
697  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
698  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
699  $localizedPage = $queryBuilder
700  ->select('*')
701  ->from('pages')
702  ->where(
703  $queryBuilder->expr()->eq(
704  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
705  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
706  ),
707  $queryBuilder->expr()->eq(
708  ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'],
709  $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)
710  )
711  )
712  ->setMaxResults(1)
713  ->execute()
714  ->fetch();
715  ‪BackendUtility::workspaceOL('pages', $localizedPage);
716  return $localizedPage['title'];
717  }
718  return $this->pageinfo['title'];
719  }
720 
727  protected function ‪main(ServerRequestInterface $request = null): void
728  {
729  $request = $request ?: ‪$GLOBALS['TYPO3_REQUEST'];
730  $lang = $this->‪getLanguageService();
731  // Access check...
732  // The page will show only if there is a valid page and if this page may be viewed by the user
733  $access = is_array($this->pageinfo);
734  // Content
735  ‪$content = '';
736  if ($this->id && $access) {
737  // Initialize permission settings:
738  $this->CALC_PERMS = $this->‪getBackendUser()->‪calcPerms($this->pageinfo);
739  $this->EDIT_CONTENT = $this->‪isContentEditable($this->current_sys_language);
740 
741  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
742 
743  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
744 
745  $this->moduleTemplate->addJavaScriptCode('mainJsFunctions', '
746  if (top.fsMod) {
747  top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
748  top.fsMod.navFrameHighlightedID["web"] = top.fsMod.currentBank + "_" + ' . (int)$this->id . ';
749  }
750  ' . ($this->popView ? ‪BackendUtility::viewOnClick($this->id, '', ‪BackendUtility::BEgetRootLine($this->id)) : '') . '
751  function deleteRecord(table,id,url) { //
752  window.location.href = ' . GeneralUtility::quoteJSvalue((string)$uriBuilder->buildUriFromRoute('tce_db') . '&cmd[')
753  . ' + table + "][" + id + "][delete]=1&redirect=" + encodeURIComponent(url);
754  return false;
755  }
756  ');
757 
758  // Find backend layout / columns
759  $backendLayout = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getSelectedBackendLayout', $this->id, $this);
760  if (!empty($backendLayout['__colPosList'])) {
761  $this->colPosList = implode(',', $backendLayout['__colPosList']);
762  }
763  // Removing duplicates, if any
764  $this->colPosList = array_unique(GeneralUtility::intExplode(',', $this->colPosList));
765  // Accessible columns
766  if (isset($this->modSharedTSconfig['properties']['colPos_list']) && trim($this->modSharedTSconfig['properties']['colPos_list']) !== '') {
767  $this->activeColPosList = array_unique(GeneralUtility::intExplode(',', trim($this->modSharedTSconfig['properties']['colPos_list'])));
768  // Match with the list which is present in the colPosList for the current page
769  if (!empty($this->colPosList) && !empty($this->activeColPosList)) {
770  $this->activeColPosList = array_unique(array_intersect(
771  $this->activeColPosList,
772  $this->colPosList
773  ));
774  }
775  } else {
776  $this->activeColPosList = ‪$this->colPosList;
777  }
778  $this->activeColPosList = implode(',', $this->activeColPosList);
779  $this->colPosList = implode(',', $this->colPosList);
780 
782 
783  // Render the primary module content:
784  if ($this->MOD_SETTINGS['function'] == 1 || $this->MOD_SETTINGS['function'] == 2) {
785  ‪$content .= '<form action="' . htmlspecialchars((string)$uriBuilder->buildUriFromRoute($this->moduleName, ['id' => $this->id, 'imagemode' => $this->imagemode])) . '" id="PageLayoutController" method="post">';
786  // Page title
787  ‪$content .= '<h1 class="' . ($this->‪isPageEditable($this->current_sys_language) ? 't3js-title-inlineedit' : '') . '">' . htmlspecialchars($this->‪getLocalizedPageTitle()) . '</h1>';
788  // All other listings
789  $content .= $this->‪renderContent();
790  }
791  $content .= '</form>';
793  // Setting up the buttons for the docheader
794  $this->‪makeButtons($request);
795 
796  // Create LanguageMenu
797  $this->‪makeLanguageMenu();
798  } else {
799  $this->moduleTemplate->addJavaScriptCode(
800  'mainJsFunctions',
801  'if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';'
802  );
803  $content .= '<h1>' . htmlspecialchars(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) . '</h1>';
804  $view = GeneralUtility::makeInstance(StandaloneView::class);
805  $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/InfoBox.html'));
806  $view->assignMultiple([
807  'title' => $lang->getLL('clickAPage_header'),
808  'message' => $lang->getLL('clickAPage_content'),
810  ]);
811  ‪$content .= $view->render();
812  }
813  // Set content
814  $this->moduleTemplate->setContent(‪$content);
815  }
816 
822  protected function ‪renderContent(): string
823  {
824  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
825 
826  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
827  $dbList = GeneralUtility::makeInstance(PageLayoutView::class);
828  $dbList->thumbs = ‪$this->imagemode;
829  $dbList->no_noWrap = 1;
830  $dbList->descrTable = ‪$this->descrTable;
831  $this->pointer = ‪MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
832  $dbList->script = (string)$uriBuilder->buildUriFromRoute($this->moduleName);
833  $dbList->showIcon = 0;
834  $dbList->setLMargin = 0;
835  $dbList->doEdit = ‪$this->EDIT_CONTENT;
836  $dbList->ext_CALC_PERMS = ‪$this->CALC_PERMS;
837  $dbList->agePrefixes = $this->‪getLanguageService()->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears');
838  $dbList->id = ‪$this->id;
839  $dbList->nextThree = ‪MathUtility::forceIntegerInRange($this->modTSconfig['properties']['editFieldsAtATime'], 0, 10);
840  $dbList->option_newWizard = empty($this->modTSconfig['properties']['disableNewContentElementWizard']);
841  $dbList->defLangBinding = !empty($this->modTSconfig['properties']['defLangBinding']);
842  if (!$dbList->nextThree) {
843  $dbList->nextThree = 1;
844  }
845  // Create menu for selecting a table to jump to (this is, if more than just pages/tt_content elements are found on the page!)
846  // also fills $dbList->activeTables
847  $dbList->getTableMenu($this->id);
848  // Initialize other variables:
849  $tableOutput = [];
850  $tableJSOutput = [];
851  $CMcounter = 0;
852  // Traverse the list of table names which has records on this page (that array is populated
853  // by the $dblist object during the function getTableMenu()):
854  foreach ($dbList->activeTables as $table => $value) {
855  $h_func = '';
856  $h_func_b = '';
857  if (!isset($dbList->externalTables[$table])) {
858  // Boolean: Display up/down arrows and edit icons for tt_content records
859  $dbList->tt_contentConfig['showCommands'] = 1;
860  // Boolean: Display info-marks or not
861  $dbList->tt_contentConfig['showInfo'] = 1;
862  // Setting up the tt_content columns to show:
863  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']['colPos']['config']['items'])) {
864  $colList = [];
865  $tcaItems = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getColPosListItemsParsed', $this->id, $this);
866  foreach ($tcaItems as $temp) {
867  $colList[] = $temp[1];
868  }
869  } else {
870  // ... should be impossible that colPos has no array. But this is the fallback should it make any sense:
871  $colList = ['1', '0', '2', '3'];
872  }
873  if ($this->colPosList !== '') {
874  $colList = array_intersect(GeneralUtility::intExplode(',', $this->colPosList), $colList);
875  }
876  // The order of the rows: Default is left(1), Normal(0), right(2), margin(3)
877  $dbList->tt_contentConfig['cols'] = implode(',', $colList);
878  $dbList->tt_contentConfig['activeCols'] = ‪$this->activeColPosList;
879  $dbList->tt_contentConfig['showHidden'] = $this->MOD_SETTINGS['tt_content_showHidden'];
880  $dbList->tt_contentConfig['sys_language_uid'] = (int)$this->current_sys_language;
881  // If the function menu is set to "Language":
882  if ($this->MOD_SETTINGS['function'] == 2) {
883  $dbList->tt_contentConfig['languageMode'] = 1;
884  $dbList->tt_contentConfig['languageCols'] = $this->MOD_MENU['language'];
885  $dbList->tt_contentConfig['languageColsPointer'] = ‪$this->current_sys_language;
886  }
887  // Toggle hidden ContentElements
888  $numberOfHiddenElements = $this->‪getNumberOfHiddenElements($dbList->tt_contentConfig);
889  if ($numberOfHiddenElements > 0) {
890  $h_func_b = '
891  <div class="checkbox">
892  <label for="checkTt_content_showHidden">
893  <input type="checkbox" id="checkTt_content_showHidden" class="checkbox" name="SET[tt_content_showHidden]" value="1" ' . ($this->MOD_SETTINGS['tt_content_showHidden'] ? 'checked="checked"' : '') . ' />
894  ' . htmlspecialchars($this->‪getLanguageService()->‪getLL('hiddenCE')) . ' (<span class="t3js-hidden-counter">' . $numberOfHiddenElements . '</span>)
895  </label>
896  </div>';
897  }
898  } else {
899  if (isset($this->MOD_SETTINGS) && isset($this->MOD_MENU)) {
900  $h_func = ‪BackendUtility::getFuncMenu($this->id, 'SET[' . $table . ']', $this->MOD_SETTINGS[$table], $this->MOD_MENU[$table], '', '');
901  }
902  }
903  // Start the dblist object:
904  $dbList->itemsLimitSingleTable = 1000;
905  $dbList->start($this->id, $table, $this->pointer, $this->search_field, $this->search_levels, $this->showLimit);
906  $dbList->counter = $CMcounter;
907  $dbList->ext_function = $this->MOD_SETTINGS['function'];
908  // Generate the list of elements here:
909  $dbList->generateList();
910  // Adding the list content to the tableOutput variable:
911  $tableOutput[$table] = $h_func . $dbList->HTMLcode . $h_func_b;
912  // ... and any accumulated JavaScript goes the same way!
913  $tableJSOutput[$table] = $dbList->JScode;
914  // Increase global counter:
915  $CMcounter += $dbList->counter;
916  // Reset variables after operation:
917  $dbList->HTMLcode = '';
918  $dbList->JScode = '';
919  }
920  // END: traverse tables
921  // For Context Sensitive Menus:
922  // Init the content
923  ‪$content = '';
924  // Additional header content
925  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'] ?? [] as $hook) {
926  $params = [];
927  ‪$content .= GeneralUtility::callUserFunction($hook, $params, $this);
928  }
929  // Add the content for each table we have rendered (traversing $tableOutput variable)
930  foreach ($tableOutput as $table => ‪$output) {
932  }
933  // Making search form:
934  if (!$this->modTSconfig['properties']['disableSearchBox'] && ($dbList->counter > 0 || $this->currentPageHasSubPages())) {
935  $this->‪getPageRenderer()->‪loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
936  $toggleSearchFormButton = $this->buttonBar->makeLinkButton()
937  ->setClasses('t3js-toggle-search-toolbox')
938  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))
939  ->setIcon($this->iconFactory->getIcon('actions-search', ‪Icon::SIZE_SMALL))
940  ->setHref('#');
941  $this->buttonBar->addButton($toggleSearchFormButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 4);
942  $this->searchContent = $dbList->getSearchBox();
943  }
944  // Additional footer content
945  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook'] ?? [] as $hook) {
946  $params = [];
947  ‪$content .= GeneralUtility::callUserFunction($hook, $params, $this);
948  }
949  return ‪$content;
950  }
951 
955  protected function ‪getModuleTemplate(): ModuleTemplate
956  {
958  }
959 
960  /***************************
961  *
962  * Sub-content functions, rendering specific parts of the module content.
963  *
964  ***************************/
969  protected function ‪makeButtons(ServerRequestInterface $request): void
970  {
971  if ($this->MOD_SETTINGS['function'] == 1 || $this->MOD_SETTINGS['function'] == 2) {
972  // Add CSH (Context Sensitive Help) icon to tool bar
973  $contextSensitiveHelpButton = $this->buttonBar->makeHelpButton()
974  ->setModuleName($this->descrTable)
975  ->setFieldName('columns_' . $this->MOD_SETTINGS['function']);
976  $this->buttonBar->addButton($contextSensitiveHelpButton);
977  }
978  $lang = $this->‪getLanguageService();
979  // View page
980  $pageTsConfig = ‪BackendUtility::getPagesTSconfig($this->id);
981  // Exclude sysfolders, spacers and recycler by default
982  $excludeDokTypes = [
986  ];
987  // Custom override of values
988  if (isset($pageTsConfig['TCEMAIN.']['preview.']['disableButtonForDokType'])) {
989  $excludeDokTypes = GeneralUtility::intExplode(
990  ',',
991  $pageTsConfig['TCEMAIN.']['preview.']['disableButtonForDokType'],
992  true
993  );
994  }
995 
996  if (
997  !in_array((int)$this->pageinfo['doktype'], $excludeDokTypes, true)
998  && !‪VersionState::cast($this->pageinfo['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)
999  ) {
1000  $languageParameter = $this->current_sys_language ? ('&L=' . ‪$this->current_sys_language) : '';
1001  $onClick = ‪BackendUtility::viewOnClick(
1002  $this->pageinfo['uid'],
1003  '',
1004  ‪BackendUtility::BEgetRootLine($this->pageinfo['uid']),
1005  '',
1006  '',
1007  $languageParameter
1008  );
1009  $viewButton = $this->buttonBar->makeLinkButton()
1010  ->setOnClick($onClick)
1011  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
1012  ->setIcon($this->iconFactory->getIcon('actions-view-page', ‪Icon::SIZE_SMALL))
1013  ->setHref('#');
1014 
1015  $this->buttonBar->addButton($viewButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 3);
1016  }
1017  // Shortcut
1018  $shortcutButton = $this->buttonBar->makeShortcutButton()
1019  ->setModuleName($this->moduleName)
1020  ->setGetVariables([
1021  'id',
1022  'route',
1023  'edit_record',
1024  'pointer',
1025  'new_unique_uid',
1026  'search_field',
1027  'search_levels',
1028  'showLimit'
1029  ])
1030  ->setSetVariables(array_keys($this->MOD_MENU));
1031  $this->buttonBar->addButton($shortcutButton);
1032 
1033  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1034  // Cache
1035  if (empty($this->modTSconfig['properties']['disableAdvanced'])) {
1036  $clearCacheButton = $this->buttonBar->makeLinkButton()
1037  ->setHref((string)$uriBuilder->buildUriFromRoute($this->moduleName, ['id' => $this->pageinfo['uid'], 'clear_cache' => '1']))
1038  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.clear_cache'))
1039  ->setIcon($this->iconFactory->getIcon('actions-system-cache-clear', ‪Icon::SIZE_SMALL));
1040  $this->buttonBar->addButton($clearCacheButton, ‪ButtonBar::BUTTON_POSITION_RIGHT, 1);
1041  }
1042  if (empty($this->modTSconfig['properties']['disableIconToolbar'])) {
1043  // Edit page properties and page language overlay icons
1044  if ($this->‪isPageEditable(0)) {
1046  $normalizedParams = $request->getAttribute('normalizedParams');
1047  // Edit localized pages only when one specific language is selected
1048  if ($this->MOD_SETTINGS['function'] == 1 && $this->current_sys_language > 0) {
1049  $localizationParentField = ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'];
1050  $languageField = ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'];
1051  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1052  ->getQueryBuilderForTable('pages');
1053  $queryBuilder->getRestrictions()
1054  ->removeAll()
1055  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1056  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
1057  $overlayRecord = $queryBuilder
1058  ->select('uid')
1059  ->from('pages')
1060  ->where(
1061  $queryBuilder->expr()->eq(
1062  $localizationParentField,
1063  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
1064  ),
1065  $queryBuilder->expr()->eq(
1066  $languageField,
1067  $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)
1068  )
1069  )
1070  ->setMaxResults(1)
1071  ->execute()
1072  ->fetch();
1073  // Edit button
1074  $urlParameters = [
1075  'edit' => [
1076  'pages' => [
1077  $overlayRecord['uid'] => 'edit'
1078  ]
1079  ],
1080  'returnUrl' => $normalizedParams->getRequestUri(),
1081  ];
1082 
1083  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1084  $editLanguageButton = $this->buttonBar->makeLinkButton()
1085  ->setHref($url)
1086  ->setTitle($lang->getLL('editPageLanguageOverlayProperties'))
1087  ->setIcon($this->iconFactory->getIcon('mimetypes-x-content-page-language-overlay', ‪Icon::SIZE_SMALL));
1088  $this->buttonBar->addButton($editLanguageButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 3);
1089  }
1090  $urlParameters = [
1091  'edit' => [
1092  'pages' => [
1093  $this->id => 'edit'
1094  ]
1095  ],
1096  'returnUrl' => $normalizedParams->getRequestUri(),
1097  ];
1098  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1099  $editPageButton = $this->buttonBar->makeLinkButton()
1100  ->setHref($url)
1101  ->setTitle($lang->getLL('editPageProperties'))
1102  ->setIcon($this->iconFactory->getIcon('actions-page-open', ‪Icon::SIZE_SMALL));
1103  $this->buttonBar->addButton($editPageButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 3);
1104  }
1105  }
1106  }
1107 
1108  /*******************************
1109  *
1110  * Other functions
1111  *
1112  ******************************/
1120  protected function ‪getNumberOfHiddenElements(array $contentConfig = []): int
1121  {
1122  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
1123  $queryBuilder->getRestrictions()
1124  ->removeAll()
1125  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1126  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
1127 
1128  $queryBuilder
1129  ->count('uid')
1130  ->from('tt_content')
1131  ->where(
1132  $queryBuilder->expr()->eq(
1133  'pid',
1134  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
1135  )
1136  );
1137 
1138  if (!empty($contentConfig['languageCols']) && is_array($contentConfig['languageCols'])) {
1139  // Multi-language view is active
1140  if ($this->current_sys_language > 0) {
1141  $queryBuilder->andWhere(
1142  $queryBuilder->expr()->in(
1143  'sys_language_uid',
1144  [0, $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)]
1145  )
1146  );
1147  }
1148  } else {
1149  $queryBuilder->andWhere(
1150  $queryBuilder->expr()->eq(
1151  'sys_language_uid',
1152  $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)
1153  )
1154  );
1155  }
1156 
1157  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'])) {
1158  $andWhere[] = $queryBuilder->expr()->neq(
1159  'hidden',
1160  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1161  );
1162  }
1163 
1164  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['starttime'])) {
1165  $andWhere[] = $queryBuilder->expr()->andX(
1166  $queryBuilder->expr()->neq(
1167  'starttime',
1168  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1169  ),
1170  $queryBuilder->expr()->gt(
1171  'starttime',
1172  $queryBuilder->createNamedParameter(‪$GLOBALS['SIM_ACCESS_TIME'], \PDO::PARAM_INT)
1173  )
1174  );
1175  }
1177  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['endtime'])) {
1178  $andWhere[] = $queryBuilder->expr()->andX(
1179  $queryBuilder->expr()->neq(
1180  'endtime',
1181  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1182  ),
1183  $queryBuilder->expr()->lte(
1184  'endtime',
1185  $queryBuilder->createNamedParameter(‪$GLOBALS['SIM_ACCESS_TIME'], \PDO::PARAM_INT)
1186  )
1187  );
1188  }
1190  if (!empty($andWhere)) {
1191  $queryBuilder->andWhere(
1192  $queryBuilder->expr()->orX(...$andWhere)
1193  );
1194  }
1195 
1196  $count = $queryBuilder
1197  ->execute()
1198  ->fetchColumn(0);
1199 
1200  return (int)$count;
1201  }
1202 
1210  protected function ‪local_linkThisScript($params): string
1211  {
1212  $params['popView'] = '';
1213  $params['new_unique_uid'] = '';
1214  return GeneralUtility::linkThisScript($params);
1215  }
1216 
1223  protected function ‪isPageEditable(int $languageId): bool
1224  {
1225  if ($this->‪getBackendUser()->isAdmin()) {
1226  return true;
1227  }
1228 
1229  return !$this->pageinfo['editlock']
1231  && $this->‪getBackendUser()->‪checkLanguageAccess($languageId);
1232  }
1233 
1239  protected function ‪pageIsNotLockedForEditors(): bool
1240  {
1241  if ($this->‪getBackendUser()->isAdmin()) {
1242  return true;
1243  }
1244  return !$this->pageinfo['editlock'] && $this->‪getBackendUser()->‪doesUserHaveAccess($this->pageinfo, ‪Permission::PAGE_EDIT);
1245  }
1246 
1253  protected function ‪isContentEditable(int $languageId): bool
1254  {
1255  if ($this->‪getBackendUser()->isAdmin()) {
1256  return true;
1257  }
1259  return !$this->pageinfo['editlock']
1261  && $this->‪getBackendUser()->‪checkLanguageAccess($languageId);
1262  }
1263 
1269  protected function ‪contentIsNotLockedForEditors(): bool
1270  {
1271  if ($this->‪getBackendUser()->isAdmin()) {
1272  return true;
1273  }
1274  return !$this->pageinfo['editlock'] && $this->‪getBackendUser()->‪doesUserHaveAccess($this->pageinfo, ‪Permission::CONTENT_EDIT);
1275  }
1282  protected function ‪getLanguageService(): ‪LanguageService
1283  {
1284  return ‪$GLOBALS['LANG'];
1285  }
1286 
1292  protected function ‪getBackendUser(): ‪BackendUserAuthentication
1293  {
1294  return ‪$GLOBALS['BE_USER'];
1295  }
1296 
1302  protected function ‪getPageRenderer(): PageRenderer
1303  {
1304  return GeneralUtility::makeInstance(PageRenderer::class);
1305  }
1306 
1310  protected function ‪makeLanguageMenu(): void
1311  {
1312  if (count($this->MOD_MENU['language']) > 1) {
1313  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1314  $languageMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
1315  $languageMenu->setIdentifier('languageMenu');
1316  foreach ($this->MOD_MENU['language'] as $key => $language) {
1317  $menuItem = $languageMenu
1318  ->makeMenuItem()
1319  ->setTitle($language)
1320  ->setHref((string)$uriBuilder->buildUriFromRoute($this->moduleName) . '&id=' . $this->id . '&SET[language]=' . $key);
1321  if ((int)$this->current_sys_language === $key) {
1322  $menuItem->setActive(true);
1323  }
1324  $languageMenu->addMenuItem($menuItem);
1325  }
1326  $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($languageMenu);
1327  }
1328  }
1329 
1335  protected function ‪currentPageHasSubPages(): bool
1336  {
1338  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1339  $queryBuilder->getRestrictions()
1340  ->removeAll()
1341  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1342  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
1343 
1344  // get workspace id
1345  $workspaceId = (int)$this->‪getBackendUser()->workspace;
1346  $comparisonExpression = $workspaceId === 0 ? 'neq' : 'eq';
1347 
1348  $count = $queryBuilder
1349  ->count('uid')
1350  ->from('pages')
1351  ->where(
1352  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)),
1353  $queryBuilder->expr()->eq(
1354  't3ver_wsid',
1355  $queryBuilder->createNamedParameter($workspaceId, \PDO::PARAM_INT)
1356  ),
1357  $queryBuilder->expr()->{$comparisonExpression}(
1358  'pid',
1359  $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
1360  )
1361  )
1362  ->execute()
1363  ->fetchColumn(0);
1364 
1365  return (bool)$count;
1366  }
1367 
1375  protected function getTargetPageIfVisible(array $targetPage): array
1376  {
1377  return !(bool)($targetPage['hidden'] ?? false) ? $targetPage : [];
1378  }
1379 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:81
‪TYPO3\CMS\Backend\Controller\PageLayoutController\renderContent
‪string renderContent()
Definition: PageLayoutController.php:788
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:25
‪TYPO3\CMS\Backend\Controller\PageLayoutController\main
‪main(ServerRequestInterface $request=null)
Definition: PageLayoutController.php:693
‪TYPO3\CMS\Core\Localization\LanguageService\includeLLFile
‪mixed includeLLFile($fileRef, $setGlobal=true, $mergeLocalOntoDefault=false)
Definition: LanguageService.php:260
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$searchContent
‪string $searchContent
Definition: PageLayoutController.php:268
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$buttonBar
‪ButtonBar $buttonBar
Definition: PageLayoutController.php:264
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$current_sys_language
‪int $current_sys_language
Definition: PageLayoutController.php:204
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeButtons
‪makeButtons(ServerRequestInterface $request)
Definition: PageLayoutController.php:935
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:35
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:31
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getTargetPageIfVisible
‪array getTargetPageIfVisible(array $targetPage)
Definition: PageLayoutController.php:1341
‪TYPO3\CMS\Backend\Controller\PageLayoutController\pageIsNotLockedForEditors
‪bool pageIsNotLockedForEditors()
Definition: PageLayoutController.php:1205
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$popView
‪bool $popView
Definition: PageLayoutController.php:149
‪TYPO3\CMS\Backend\Controller\PageLayoutController\isPageEditable
‪bool isPageEditable(int $languageId)
Definition: PageLayoutController.php:1189
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$perms_clause
‪string $perms_clause
Definition: PageLayoutController.php:155
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getPagePermsClause
‪string getPagePermsClause($perms)
Definition: BackendUserAuthentication.php:523
‪TYPO3\CMS\Backend\Controller\PageLayoutController\isContentEditable
‪bool isContentEditable(int $languageId)
Definition: PageLayoutController.php:1219
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:170
‪TYPO3\CMS\Backend\Controller\PageLayoutController\clearCache
‪clearCache()
Definition: PageLayoutController.php:485
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\calcPerms
‪int calcPerms($row)
Definition: BackendUserAuthentication.php:592
‪TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper\STATE_INFO
‪const STATE_INFO
Definition: InfoboxViewHelper.php:61
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeLanguageMenu
‪makeLanguageMenu()
Definition: PageLayoutController.php:1276
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$moduleName
‪string $moduleName
Definition: PageLayoutController.php:256
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$pageinfo
‪array $pageinfo
Definition: PageLayoutController.php:174
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$search_levels
‪int $search_levels
Definition: PageLayoutController.php:125
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$search_field
‪string $search_field
Definition: PageLayoutController.php:119
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:173
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getLanguageService
‪TYPO3 CMS Core Localization LanguageService getLanguageService()
Definition: PageLayoutController.php:1248
‪TYPO3\CMS\Backend\Controller\PageLayoutController\local_linkThisScript
‪string local_linkThisScript($params)
Definition: PageLayoutController.php:1176
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$colPosList
‪string $colPosList
Definition: PageLayoutController.php:186
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$MOD_SETTINGS
‪array $MOD_SETTINGS
Definition: PageLayoutController.php:223
‪TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction
Definition: BackendWorkspaceRestriction.php:28
‪TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper\STATE_ERROR
‪const STATE_ERROR
Definition: InfoboxViewHelper.php:64
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:31
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getPageRenderer
‪PageRenderer getPageRenderer()
Definition: PageLayoutController.php:1268
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:54
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:158
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$modSharedTSconfig
‪array $modSharedTSconfig
Definition: PageLayoutController.php:167
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$moduleTemplate
‪ModuleTemplate $moduleTemplate
Definition: PageLayoutController.php:260
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:374
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$imagemode
‪string $imagemode
Definition: PageLayoutController.php:113
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$clear_cache
‪bool $clear_cache
Definition: PageLayoutController.php:143
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncMenu
‪static string getFuncMenu( $mainParams, $elementName, $currentValue, $menuItems, $script='', $addParams='')
Definition: BackendUtility.php:2955
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:40
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Core\Page\PageRenderer\loadRequireJsModule
‪loadRequireJsModule($mainModuleName, $callBackFunction=null)
Definition: PageRenderer.php:1593
‪TYPO3\CMS\Frontend\Page\PageRepository\SHORTCUT_MODE_RANDOM_SUBPAGE
‪const SHORTCUT_MODE_RANDOM_SUBPAGE
Definition: PageRepository.php:182
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getModuleTemplate
‪ModuleTemplate getModuleTemplate()
Definition: PageLayoutController.php:921
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Backend\Controller\PageLayoutController\mainAction
‪ResponseInterface mainAction(ServerRequestInterface $request)
Definition: PageLayoutController.php:277
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:182
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:35
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$deprecatedPublicProperties
‪array $deprecatedPublicProperties
Definition: PageLayoutController.php:73
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_LINK
‪const DOKTYPE_LINK
Definition: PageRepository.php:169
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$CALC_PERMS
‪int $CALC_PERMS
Definition: PageLayoutController.php:198
‪TYPO3\CMS\Backend\Controller\PageLayoutController\contentIsNotLockedForEditors
‪bool contentIsNotLockedForEditors()
Definition: PageLayoutController.php:1235
‪TYPO3\CMS\Backend\Controller\PageLayoutController
Definition: PageLayoutController.php:53
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_SYSFOLDER
‪const DOKTYPE_SYSFOLDER
Definition: PageRepository.php:174
‪TYPO3\CMS\Frontend\Page\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$deprecatedPublicMethods
‪array $deprecatedPublicMethods
Definition: PageLayoutController.php:57
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getPageLinksWhereContentIsAlsoShownOn
‪string getPageLinksWhereContentIsAlsoShownOn($pageId)
Definition: PageLayoutController.php:630
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getHeaderFlashMessagesForCurrentPid
‪string getHeaderFlashMessagesForCurrentPid()
Definition: PageLayoutController.php:499
‪TYPO3\CMS\Backend\Module\ModuleLoader
Definition: ModuleLoader.php:32
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$iconFactory
‪IconFactory $iconFactory
Definition: PageLayoutController.php:250
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:331
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1811
‪TYPO3\CMS\Backend\Utility\BackendUtility\getModuleData
‪static array getModuleData( $MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='')
Definition: BackendUtility.php:3259
‪TYPO3\CMS\Backend\Controller\PageLayoutController\menuConfig
‪menuConfig(ServerRequestInterface $request=null)
Definition: PageLayoutController.php:336
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$pointer
‪int $pointer
Definition: PageLayoutController.php:107
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getSessionData
‪mixed getSessionData($key)
Definition: AbstractUserAuthentication.php:1258
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:733
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$languagesInColumnCache
‪array $languagesInColumnCache
Definition: PageLayoutController.php:246
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$returnUrl
‪string $returnUrl
Definition: PageLayoutController.php:137
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$showLimit
‪int $showLimit
Definition: PageLayoutController.php:131
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\setAndSaveSessionData
‪setAndSaveSessionData($key, $data)
Definition: AbstractUserAuthentication.php:1285
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getNumberOfHiddenElements
‪int getNumberOfHiddenElements(array $contentConfig=[])
Definition: PageLayoutController.php:1086
‪TYPO3\CMS\Backend\Controller\PageLayoutController\init
‪init(ServerRequestInterface $request=null)
Definition: PageLayoutController.php:290
‪TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait
Definition: PublicMethodDeprecationTrait.php:68
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$MCONF
‪array $MCONF
Definition: PageLayoutController.php:210
‪TYPO3\CMS\Frontend\Page\PageRepository\SHORTCUT_MODE_FIRST_SUBPAGE
‪const SHORTCUT_MODE_FIRST_SUBPAGE
Definition: PageRepository.php:181
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$modTSconfig
‪array $modTSconfig
Definition: PageLayoutController.php:161
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Backend\Controller\PageLayoutController\initActions
‪array initActions()
Definition: PageLayoutController.php:412
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:23
‪$output
‪$output
Definition: annotationChecker.php:113
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2616
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$MOD_MENU
‪array $MOD_MENU
Definition: PageLayoutController.php:216
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:32
‪TYPO3\CMS\Core\Type\Bitmask\Permission\CONTENT_EDIT
‪const CONTENT_EDIT
Definition: Permission.php:52
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
Definition: BackendUtility.php:864
‪TYPO3\CMS\Backend\View\BackendLayoutView
Definition: BackendLayoutView.php:28
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$editSelect
‪string $editSelect
Definition: PageLayoutController.php:240
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Utility\BackendUtility\workspaceOL
‪static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
Definition: BackendUtility.php:4048
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Backend\View\PageLayoutView
Definition: PageLayoutView.php:61
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_EDIT
‪const PAGE_EDIT
Definition: Permission.php:37
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemlist
‪static string getLabelFromItemlist($table, $col, $key)
Definition: BackendUtility.php:1680
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$descrTable
‪string $descrTable
Definition: PageLayoutController.php:180
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_RECYCLER
‪const DOKTYPE_RECYCLER
Definition: PageRepository.php:175
‪TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper
Definition: InfoboxViewHelper.php:58
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$id
‪int $id
Definition: PageLayoutController.php:101
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:66
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:118
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordPath
‪static mixed getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
Definition: BackendUtility.php:572
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_RIGHT
‪const BUTTON_POSITION_RIGHT
Definition: ButtonBar.php:40
‪TYPO3\CMS\Frontend\Page\PageRepository\SHORTCUT_MODE_NONE
‪const SHORTCUT_MODE_NONE
Definition: PageRepository.php:180
‪TYPO3\CMS\Backend\Controller
Definition: AbstractFormEngineAjaxController.php:3
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$activeColPosList
‪string $activeColPosList
Definition: PageLayoutController.php:236
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getLocalizedPageTitle
‪string getLocalizedPageTitle()
Definition: PageLayoutController.php:656
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$EDIT_CONTENT
‪bool $EDIT_CONTENT
Definition: PageLayoutController.php:192
‪TYPO3\CMS\Frontend\Page\PageRepository\SHORTCUT_MODE_PARENT_PAGE
‪const SHORTCUT_MODE_PARENT_PAGE
Definition: PageRepository.php:183
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getBackendUser
‪TYPO3 CMS Core Authentication BackendUserAuthentication getBackendUser()
Definition: PageLayoutController.php:1258
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:25
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array bool readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:635
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeActionMenu
‪makeActionMenu(array $actions)
Definition: PageLayoutController.php:450
‪TYPO3\CMS\Backend\Controller\PageLayoutController\currentPageHasSubPages
‪bool currentPageHasSubPages()
Definition: PageLayoutController.php:1301
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$content
‪string $content
Definition: PageLayoutController.php:229