‪TYPO3CMS  ‪main
PageLayoutController.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
36 use TYPO3\CMS\Backend\Utility\BackendUtility;
47 use TYPO3\CMS\Core\Imaging\IconSize;
56 
60 #[AsController]
62 {
66  protected int ‪$id = 0;
67 
71  protected array|bool ‪$pageinfo = false;
72 
74  protected array ‪$MOD_MENU;
75 
79  protected array ‪$availableLanguages = [];
80 
81  protected ?‪ModuleData ‪$moduleData = null;
82 
83  public function ‪__construct(
84  protected readonly ‪IconFactory $iconFactory,
85  protected readonly ‪PageRenderer $pageRenderer,
86  protected readonly ‪UriBuilder $uriBuilder,
87  protected readonly ‪PageRepository $pageRepository,
88  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory,
89  protected readonly EventDispatcherInterface $eventDispatcher,
90  protected readonly ‪ModuleProvider $moduleProvider,
91  protected readonly ‪BackendLayoutRenderer $backendLayoutRenderer,
92  protected readonly ‪BackendLayoutView $backendLayoutView,
93  ) {}
94 
95  protected function ‪initialize(ServerRequestInterface $request): void
96  {
97  $backendUser = $this->‪getBackendUser();
98  $this->id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0);
99  $this->moduleData = $request->getAttribute('moduleData');
100  $this->pageinfo = BackendUtility::readPageAccess($this->id, $backendUser->getPagePermsClause(‪Permission::PAGE_SHOW));
101  $this->availableLanguages = $request->getAttribute('site')->getAvailableLanguages($backendUser, false, $this->id);
102  $this->pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
103  }
104 
109  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
110  {
111  $this->‪initialize($request);
112  $languageService = $this->‪getLanguageService();
113 
114  $view = $this->moduleTemplateFactory->create($request);
115  if ($this->id === 0 || $this->pageinfo === false) {
116  // Page uid 0 or no access.
117  $view->setTitle($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'));
118  $view->assignMultiple([
119  'pageId' => $this->id,
120  'siteName' => ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ?? '',
121  ]);
122  return $view->renderResponse('PageLayout/PageModuleNoAccess');
123  }
124 
125  $tsConfig = BackendUtility::getPagesTSconfig($this->id);
126  $this->‪menuConfig($request);
127  $this->currentSelectedLanguage = (int)$this->moduleData->get('language');
129  $this->‪makeActionMenu($view, $tsConfig);
130  $this->‪makeButtons($view, $request, $tsConfig);
131  $this->‪initializeClipboard($request);
132  $event = $this->eventDispatcher->dispatch(new ‪ModifyPageLayoutContentEvent($request, $view));
133 
134  $pageLayoutContext = $this->‪createPageLayoutContext();
135  $mainLayoutHtml = $this->backendLayoutRenderer->drawContent($request, $pageLayoutContext);
136  $numberOfHiddenElements = $this->‪getNumberOfHiddenElements(
137  $pageLayoutContext->getDrawingConfiguration()->getLanguageMode()
138  );
139 
140  $pageLocalizationRecord = $this->‪getLocalizedPageRecord($this->currentSelectedLanguage);
141 
142  $view->setTitle($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'), $this->pageinfo['title']);
143  $view->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
144  $view->assignMultiple([
145  'pageId' => $this->id,
146  'localizedPageId' => $pageLocalizationRecord['uid'] ?? 0,
147  'infoBoxes' => $this->‪generateMessagesForCurrentPage($request),
148  'isPageEditable' => $this->‪isPageEditable($this->currentSelectedLanguage),
149  'localizedPageTitle' => $this->‪getLocalizedPageTitle($this->currentSelectedLanguage, $this->pageinfo),
150  'eventContentHtmlTop' => $event->getHeaderContent(),
151  'mainContentHtml' => $mainLayoutHtml,
152  'hiddenElementsShowToggle' => ($this->getBackendUser()->check('tables_select', 'tt_content') && ($numberOfHiddenElements > 0)),
153  'hiddenElementsState' => (bool)$this->moduleData->get('showHidden'),
154  'hiddenElementsCount' => $numberOfHiddenElements,
155  'eventContentHtmlBottom' => $event->getFooterContent(),
156  ]);
157  return $view->renderResponse('PageLayout/PageModule');
158  }
159 
161  {
162  $tsConfig = BackendUtility::getPagesTSconfig($this->id);
163  $pageLayoutContext = GeneralUtility::makeInstance(PageLayoutContext::class, $this->pageinfo, $this->backendLayoutView->getBackendLayoutForPage($this->id));
164  $configuration = $pageLayoutContext->getDrawingConfiguration();
165  $configuration->setDefaultLanguageBinding(!empty($tsConfig['mod.']['web_layout.']['defLangBinding']));
166  $configuration->setActiveColumns($this->‪getActiveColumnsArray($pageLayoutContext, $tsConfig));
167  $configuration->setShowHidden((bool)$this->moduleData->get('showHidden'));
168  $configuration->setLanguageColumns($this->MOD_MENU['language']);
169  $configuration->setSelectedLanguageId($this->currentSelectedLanguage);
170  $configuration->setAllowInconsistentLanguageHandling((bool)($tsConfig['mod.']['web_layout.']['allowInconsistentLanguageHandling'] ?? false));
171  if ((int)$this->moduleData->get('function') === 2) {
172  $configuration->setLanguageMode(true);
173  }
174  return $pageLayoutContext;
175  }
176 
180  protected function ‪menuConfig(ServerRequestInterface $request): void
181  {
182  $backendUser = $this->‪getBackendUser();
183  $languageService = $this->‪getLanguageService();
184 
185  // MENU-ITEMS:
186  $this->MOD_MENU = [
187  'function' => [
188  1 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.layout'),
189  2 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.language_comparison'),
190  ],
191  'language' => [
192  0 => isset($this->availableLanguages[0]) ? $this->availableLanguages[0]->getTitle() : $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:m_default'),
193  ],
194  ];
195 
196  // First, select all localized page records on the current page.
197  // Each represents a possibility for a language on the page. Add these to language selector.
198  if ($this->id) {
199  // Compile language data for pid != 0 only. The language drop-down is not shown on pid 0
200  // since pid 0 can't be localized.
201  $pageTranslations = $this->‪getExistingPageTranslations();
202  foreach ($pageTranslations as $pageTranslation) {
203  $languageId = $pageTranslation[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']];
204  if (isset($this->availableLanguages[$languageId])) {
205  $this->MOD_MENU['language'][$languageId] = $this->availableLanguages[$languageId]->getTitle();
206  }
207  }
208 
209  // Add special "-1" in case translations of the current page exist
210  if (count($this->MOD_MENU['language']) > 1) {
211  // We need to add -1 (all) here so a possible -1 value will be allowed when calling
212  // moduleData->cleanUp(). Actually, this is only relevant if we are dealing with the
213  // "languages" mode, which however can only be safely determined, after the moduleData
214  // have been cleaned up => chicken and egg problem. We therefore remove the -1 item from
215  // the menu again, as soon as we are able to determine the requested mode.
216  // @todo Replace the whole "mode" handling with some more robust solution
217  $this->MOD_MENU['language'][-1] = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages');
218  }
219  }
220  // Clean up settings
221  if ($this->moduleData->cleanUp($this->MOD_MENU)) {
222  $backendUser->pushModuleData($this->moduleData->getModuleIdentifier(), $this->moduleData->toArray());
223  }
224  if ($backendUser->workspace !== 0) {
225  // Show all elements in draft workspaces
226  $this->moduleData->set('showHidden', true);
227  }
228  if ((int)$this->moduleData->get('function') !== 2) {
229  // Remove -1 (all) from the module menu if not "languages" mode
230  unset($this->MOD_MENU['language'][-1]);
231  // In case -1 (all) is still set as language, but we are no longer in
232  // "languages" mode, we fall back to the default, preventing an empty grid.
233  if ((int)$this->moduleData->get('language') === -1) {
234  $this->moduleData->set('language', 0);
235  }
236  }
237  }
238 
243  protected function ‪getExistingPageTranslations(): array
244  {
245  if ($this->id === 0) {
246  return [];
247  }
248  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
249  $queryBuilder->getRestrictions()->removeAll()
250  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
251  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
252  $result = $queryBuilder
253  ->select('*')
254  ->from('pages')
255  ->where(
256  $queryBuilder->expr()->eq(
257  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
258  $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT)
259  )
260  )
261  ->executeQuery();
262 
263  $rows = [];
264  while ($row = $result->fetchAssociative()) {
265  BackendUtility::workspaceOL('pages', $row, $this->‪getBackendUser()->workspace);
266  if ($row && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
267  $rows[] = $row;
268  }
269  }
270  return $rows;
271  }
272 
273  protected function ‪getLocalizedPageRecord(int $languageId): ?array
274  {
275  if ($languageId === 0) {
276  return null;
277  }
278  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
279  $queryBuilder->getRestrictions()
280  ->removeAll()
281  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
282  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
283  $overlayRecord = $queryBuilder
284  ->select('*')
285  ->from('pages')
286  ->where(
287  $queryBuilder->expr()->eq(
288  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
289  $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT)
290  ),
291  $queryBuilder->expr()->eq(
292  ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'],
293  $queryBuilder->createNamedParameter($languageId, ‪Connection::PARAM_INT)
294  )
295  )
296  ->setMaxResults(1)
297  ->executeQuery()
298  ->fetchAssociative();
299  if ($overlayRecord) {
300  BackendUtility::workspaceOL('pages', $overlayRecord, $this->‪getBackendUser()->workspace);
301  }
302  return is_array($overlayRecord) ? $overlayRecord : null;
303  }
304 
309  protected function ‪makeActionMenu(‪ModuleTemplate $view, array $tsConfig): void
310  {
311  $languageService = $this->‪getLanguageService();
312  $actions = [
313  1 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.layout'),
314  ];
315  // Find if there are ANY languages at all (and if not, do not show the language option from function menu).
316  // The second check is for an edge case: Only two languages in the site and the default is not allowed.
317  if (count($this->availableLanguages) > 1 || (int)array_key_first($this->availableLanguages) > 0) {
318  $actions[2] = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.language_comparison');
319  }
320  // Page / user TSconfig blinding of menu-items
321  $blindActions = $tsConfig['mod.']['web_layout.']['menu.']['functions.'] ?? [];
322  foreach ($blindActions as $key => $value) {
323  if (!$value && array_key_exists($key, $actions)) {
324  unset($actions[$key]);
325  }
326  }
327 
328  $actionMenu = $view->‪getDocHeaderComponent()->getMenuRegistry()->makeMenu();
329  $actionMenu->setIdentifier('actionMenu');
330  $actionMenu->setLabel('');
331  $defaultKey = null;
332  $foundDefaultKey = false;
333  foreach ($actions as $key => $action) {
334  $menuItem = $actionMenu
335  ->makeMenuItem()
336  ->setTitle($action)
337  ->setHref((string)$this->uriBuilder->buildUriFromRoute('web_layout', ['id' => $this->id, 'function' => $key]));
338  if (!$foundDefaultKey) {
339  $defaultKey = $key;
340  $foundDefaultKey = true;
341  }
342  if ((int)$this->moduleData->get('function') === $key) {
343  $menuItem->setActive(true);
344  $defaultKey = null;
345  }
346  $actionMenu->addMenuItem($menuItem);
347  }
348  if (isset($defaultKey)) {
349  $this->moduleData->set('function', $defaultKey);
350  }
351  $view->‪getDocHeaderComponent()->getMenuRegistry()->addMenu($actionMenu);
352  }
353 
358  protected function ‪generateMessagesForCurrentPage(ServerRequestInterface $request): array
359  {
360  $languageService = $this->‪getLanguageService();
361  $backendUser = $this->‪getBackendUser();
362 
363  $infoBoxes = [];
364  $currentDocumentType = (int)$this->pageinfo['doktype'];
365  if ($currentDocumentType === ‪PageRepository::DOKTYPE_SYSFOLDER && $this->moduleProvider->accessGranted('web_list', $backendUser)) {
366  $infoBoxes[] = [
367  'title' => $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:goToListModule'),
368  'message' => '<p>' . $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:goToListModuleMessage') . '</p>'
369  . '<a class="btn btn-primary" data-dispatch-action="TYPO3.ModuleMenu.showModule" data-dispatch-args-list="web_list">'
370  . $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:goToListModule')
371  . '</a>',
373  ];
374  }
375  if ($currentDocumentType === ‪PageRepository::DOKTYPE_SHORTCUT) {
376  $shortcutMode = (int)$this->pageinfo['shortcut_mode'];
377  $targetPage = [];
378  $message = '';
380  if ($shortcutMode || $this->pageinfo['shortcut']) {
381  switch ($shortcutMode) {
383  $targetPage = $this->‪getTargetPageIfVisible($this->pageRepository->getPage((int)$this->pageinfo['shortcut'], true));
384  $message = $targetPage === [] ? $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsMisconfiguredOrNotAccessibleInternalLinkMessage') : '';
385  break;
387  $menuOfPages = $this->pageRepository->getMenu($this->pageinfo['uid'], '*', 'sorting', 'AND hidden = 0', true, true);
388  $targetPage = reset($menuOfPages) ?: [];
389  $message = $targetPage === [] ? $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsMisconfiguredFirstSubpageMessage') : '';
390  break;
392  $targetPage = $this->‪getTargetPageIfVisible($this->pageRepository->getPage((int)$this->pageinfo['pid'], true));
393  $message = $targetPage === [] ? $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsMisconfiguredParentPageMessage') : '';
394  break;
396  $possibleTargetPages = $this->pageRepository->getMenu($this->pageinfo['uid'], '*', 'sorting', 'AND hidden = 0', true, true);
397  if ($possibleTargetPages === []) {
398  $message = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsMisconfiguredOrNotAccessibleRandomInternalLinkMessage');
399  } else {
400  $message = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsRandomInternalLinkMessage');
402  }
403  break;
404  }
405  $message = htmlspecialchars($message);
406  if ($targetPage !== [] && $shortcutMode !== ‪PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE) {
407  $linkToPid = $this->uriBuilder->buildUriFromRoute('web_layout', ['id' => $targetPage['uid']]);
408  $path = BackendUtility::getRecordPath($targetPage['uid'], $backendUser->getPagePermsClause(‪Permission::PAGE_SHOW), 1000);
409  $linkedPath = '<a href="' . htmlspecialchars((string)$linkToPid) . '">' . htmlspecialchars($path) . '</a>';
410  $message .= sprintf(htmlspecialchars($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsInternalLinkMessage')), $linkedPath);
411  $message .= ' (' . htmlspecialchars($languageService->sL(BackendUtility::getLabelFromItemlist('pages', 'shortcut_mode', (string)$shortcutMode, $this->pageinfo))) . ')';
413  }
414  } else {
415  $message = htmlspecialchars($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsMisconfiguredInternalLinkMessage'));
417  }
418  $infoBoxes[] = [
419  'message' => $message,
420  'state' => $state,
421  ];
422  }
423  if ($currentDocumentType === ‪PageRepository::DOKTYPE_LINK) {
424  if (empty($this->pageinfo['url'])) {
425  $infoBoxes[] = [
426  'message' => $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsMisconfiguredExternalLinkMessage'),
428  ];
429  } else {
430  $externalUrl = $this->‪resolveExternalUrl($this->pageinfo, $request);
431  if ($externalUrl !== '') {
432  $externalUrl = htmlspecialchars($externalUrl);
433  $externalUrlHtml = '<a href="' . $externalUrl . '" target="_blank" rel="noreferrer">' . $externalUrl . '</a>';
434  $infoBoxes[] = [
435  'message' => sprintf($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:pageIsExternalLinkMessage'), $externalUrlHtml),
437  ];
438  }
439  }
440  }
441  if ($this->pageinfo['content_from_pid']) {
442  // If content from different pid is displayed
443  $contentPage = BackendUtility::getRecord('pages', (int)$this->pageinfo['content_from_pid']);
444  if ($contentPage === null) {
445  $infoBoxes[] = [
446  'message' => sprintf($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:content_from_pid_invalid_title'), $this->pageinfo['content_from_pid']),
448  ];
449  } else {
450  $linkToPid = $this->uriBuilder->buildUriFromRoute('web_layout', ['id' => $this->pageinfo['content_from_pid']]);
451  $title = BackendUtility::getRecordTitle('pages', $contentPage);
452  $link = '<a href="' . htmlspecialchars((string)$linkToPid) . '">' . htmlspecialchars($title) . ' (PID ' . (int)$this->pageinfo['content_from_pid'] . ')</a>';
453  $infoBoxes[] = [
454  'message' => sprintf($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:content_from_pid_title'), $link),
456  ];
457  }
458  } else {
459  $links = $this->‪getPageLinksWhereContentIsAlsoShownOn((int)$this->pageinfo['uid']);
460  if (!empty($links)) {
461  $infoBoxes[] = [
462  'message' => sprintf($languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:content_on_pid_title'), $links),
464  ];
465  }
466  }
467  return $infoBoxes;
468  }
469 
470  protected function ‪addJavaScriptModuleInstructions(): void
471  {
472  $this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(
473  ‪JavaScriptModuleInstruction::create('@typo3/backend/page-actions.js')
474  );
475  }
476 
480  protected function ‪getPageLinksWhereContentIsAlsoShownOn(int $pageId): string
481  {
482  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
483  $queryBuilder->getRestrictions()->removeAll();
484  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
485  $queryBuilder->select('*')
486  ->from('pages')
487  ->where($queryBuilder->expr()->eq('content_from_pid', $queryBuilder->createNamedParameter($pageId, ‪Connection::PARAM_INT)));
488  $links = [];
489  $rows = $queryBuilder->executeQuery()->fetchAllAssociative();
490  if (!empty($rows)) {
491  foreach ($rows as $row) {
492  $linkToPid = $this->uriBuilder->buildUriFromRoute('web_layout', ['id' => $row['uid']]);
493  $title = BackendUtility::getRecordTitle('pages', $row);
494  $link = '<a href="' . htmlspecialchars((string)$linkToPid) . '">' . htmlspecialchars($title) . ' (PID ' . (int)$row['uid'] . ')</a>';
495  $links[] = $link;
496  }
497  }
498  return implode(', ', $links);
499  }
500 
501  protected function ‪getLocalizedPageTitle(int ‪$currentSelectedLanguage, array $pageInfo): string
502  {
503  if (‪$currentSelectedLanguage <= 0) {
504  return $pageInfo['title'];
505  }
506  $pageLocalizationRecord = $this->‪getLocalizedPageRecord($currentSelectedLanguage);
507  if (!is_array($pageLocalizationRecord)) {
508  return $pageInfo['title'];
509  }
510  return $pageLocalizationRecord['title'] ?? '';
511  }
512 
516  protected function ‪initializeClipboard(ServerRequestInterface $request): void
517  {
518  $clipboard = GeneralUtility::makeInstance(Clipboard::class);
519  $clipboard->initializeClipboard($request);
520  $clipboard->lockToNormal();
521  $clipboard->cleanCurrent();
522  $clipboard->endClipboard();
523  $elFromTable = $clipboard->elFromTable('tt_content');
524  if (!empty($elFromTable) && $this->‪isContentEditable($this->currentSelectedLanguage)) {
525  $pasteItem = (int)substr((string)key($elFromTable), 11);
526  $pasteRecord = BackendUtility::getRecordWSOL('tt_content', $pasteItem);
527  $pasteTitle = BackendUtility::getRecordTitle('tt_content', $pasteRecord);
528  $this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(
529  ‪JavaScriptModuleInstruction::create('@typo3/backend/layout-module/paste.js')
530  ->instance([
531  'itemOnClipboardUid' => $pasteItem,
532  'itemOnClipboardTitle' => $pasteTitle,
533  'copyMode' => $clipboard->clipData['normal']['mode'] ?? '',
534  ])
535  );
536  }
537  }
538 
539  protected function ‪getActiveColumnsArray(‪PageLayoutContext $pageLayoutContext, array $tsConfig): array
540  {
541  $availableColumnPositionsFromBackendLayout = array_unique($pageLayoutContext->‪getBackendLayout()->getColumnPositionNumbers());
542  $allowedColumnPositionsByTsConfig = array_unique(‪GeneralUtility::intExplode(',', (string)($tsConfig['mod.']['SHARED.']['colPos_list'] ?? ''), true));
543  $activeColumns = $availableColumnPositionsFromBackendLayout;
544  if (!empty($allowedColumnPositionsByTsConfig)) {
545  // If there is no tsConfig colPos_list, no restriction. Else create intersection of available and allowed.
546  $activeColumns = array_intersect($availableColumnPositionsFromBackendLayout, $allowedColumnPositionsByTsConfig);
547  }
548  return $activeColumns;
549  }
550 
554  protected function ‪makeButtons(‪ModuleTemplate $view, ServerRequestInterface $request, array $tsConfig): void
555  {
556  $languageService = $this->‪getLanguageService();
557  $buttonBar = $view->‪getDocHeaderComponent()->getButtonBar();
558 
559  // Language
560  if ($languageButton = $this->‪makeLanguageSwitchButton($buttonBar)) {
561  $buttonBar->addButton($languageButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 0);
562  }
563 
564  // View
565  if ($viewButton = $this->‪makeViewButton($buttonBar, $tsConfig)) {
566  $buttonBar->addButton($viewButton);
567  }
568 
569  // Edit
570  if ($editButton = $this->‪makeEditButton($buttonBar, $request)) {
571  $buttonBar->addButton($editButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 2);
572  }
573 
574  // Shortcut
575  $shortcutButton = $buttonBar->makeShortcutButton()
576  ->setRouteIdentifier('web_layout')
577  ->setDisplayName($this->‪getShortcutTitle())
578  ->setArguments([
579  'id' => $this->id,
580  'showHidden' => (bool)$this->moduleData->get('showHidden'),
581  'function' => (int)$this->moduleData->get('function'),
582  'language' => $this->currentSelectedLanguage,
583  ]);
584  $buttonBar->addButton($shortcutButton);
585 
586  // Cache
587  $clearCacheButton = $buttonBar->makeLinkButton()
588  ->setHref('#')
589  ->setDataAttributes(['id' => $this->pageinfo['uid']])
590  ->setClasses('t3js-clear-page-cache')
591  ->setTitle($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.clear_cache'))
592  ->setIcon($this->iconFactory->getIcon('actions-system-cache-clear', IconSize::SMALL));
593  $buttonBar->addButton($clearCacheButton, ‪ButtonBar::BUTTON_POSITION_RIGHT, 1);
594 
595  // Reload
596  $reloadButton = $buttonBar->makeLinkButton()
597  ->setHref($request->getAttribute('normalizedParams')->getRequestUri())
598  ->setTitle($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
599  ->setIcon($this->iconFactory->getIcon('actions-refresh', IconSize::SMALL));
600  $buttonBar->addButton($reloadButton, ‪ButtonBar::BUTTON_POSITION_RIGHT);
601  }
602 
606  protected function ‪makeViewButton(‪ButtonBar $buttonBar, array $tsConfig): ?‪ButtonInterface
607  {
608  // Do not create a "View webpage" button if
609  // * "All languages" is selected
610  // * not in "Columns" view,
611  // * record is a placeholder
612  if (
613  $this->currentSelectedLanguage === -1
614  || (int)$this->moduleData->get('function') !== 1
615  || VersionState::tryFrom($this->pageinfo['t3ver_state'] ?? 0) === VersionState::DELETE_PLACEHOLDER
616  ) {
617  return null;
618  }
619 
620  if (isset($tsConfig['TCEMAIN.']['preview.']['disableButtonForDokType'])) {
621  // Exclude doktypes, set via tsConfig
622  $excludeDokTypes = ‪GeneralUtility::intExplode(',', (string)($tsConfig['TCEMAIN.']['preview.']['disableButtonForDokType'] ?? ''), true);
623  } else {
624  // Exclude default doktypes: sysfolders and spacers
625  $excludeDokTypes = [
628  ];
629  }
630 
631  if (in_array((int)$this->pageinfo['doktype'], $excludeDokTypes, true)) {
632  return null;
633  }
634 
635  $previewDataAttributes = ‪PreviewUriBuilder::create((int)$this->pageinfo['uid'])
636  ->withRootLine(BackendUtility::BEgetRootLine($this->pageinfo['uid']))
637  ->withLanguage($this->currentSelectedLanguage)
638  ->buildDispatcherDataAttributes();
639 
640  return $buttonBar->‪makeLinkButton()
641  ->‪setHref('#')
642  ->‪setDataAttributes($previewDataAttributes ?? [])
643  ->setDisabled(!$previewDataAttributes)
644  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
645  ->setIcon($this->iconFactory->getIcon('actions-view-page', IconSize::SMALL))
646  ->setShowLabelText(true);
647  }
648 
652  protected function ‪makeEditButton(‪ButtonBar $buttonBar, ServerRequestInterface $request): ?‪ButtonInterface
653  {
654  if ((int)$this->moduleData->get('function') !== 1
655  || !$this->isPageEditable($this->currentSelectedLanguage)
656  ) {
657  return null;
658  }
659 
660  $pageUid = ‪$this->id;
661  if ($this->currentSelectedLanguage > 0) {
662  $overlayRecord = $this->‪getLocalizedPageRecord($this->currentSelectedLanguage);
663  $pageUid = $overlayRecord['uid'];
664  }
665  $params = [
666  'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(),
667  'edit' => [
668  'pages' => [
669  $pageUid => 'edit',
670  ],
671  ],
672  ];
673 
674  return $buttonBar->‪makeLinkButton()
675  ->‪setHref((string)$this->uriBuilder->buildUriFromRoute('record_edit', $params))
676  ->‪setTitle($this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:editPageProperties'))
677  ->setShowLabelText(true)
678  ->setIcon($this->iconFactory->getIcon('actions-page-open', IconSize::SMALL));
679  }
680 
685  {
686  // Early return if less than 2 languages are available
687  if (count($this->MOD_MENU['language']) < 2) {
688  return null;
689  }
690 
691  $languageService = $this->‪getLanguageService();
692 
693  $languageDropDownButton = $buttonbar->‪makeDropDownButton()
694  ->‪setLabel($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.language'))
695  ->setShowLabelText(true);
696 
697  foreach ($this->MOD_MENU['language'] as $key => $language) {
698  $siteLanguage = $this->availableLanguages[$key] ?? null;
699  if (!$siteLanguage instanceof ‪SiteLanguage) {
700  // Skip invalid language keys, e.g. "-1" for "all languages"
701  continue;
702  }
704  $languageItem = GeneralUtility::makeInstance(DropDownRadio::class)
705  ->setActive($this->currentSelectedLanguage === $siteLanguage->getLanguageId())
706  ->setIcon($this->iconFactory->getIcon($siteLanguage->getFlagIdentifier()))
707  ->setHref((string)$this->uriBuilder->buildUriFromRoute('web_layout', [
708  'id' => $this->id,
709  'function' => (int)$this->moduleData->get('function'),
710  'language' => $siteLanguage->getLanguageId(),
711  ]))
712  ->setLabel($siteLanguage->getTitle());
713  $languageDropDownButton->addItem($languageItem);
714  }
715 
716  if ((int)$this->moduleData->get('function') !== 1) {
718  $allLanguagesItem = GeneralUtility::makeInstance(DropDownRadio::class)
719  ->setActive($this->currentSelectedLanguage === -1)
720  ->setIcon($this->iconFactory->getIcon('flags-multiple'))
721  ->setHref((string)$this->uriBuilder->buildUriFromRoute('web_layout', [
722  'id' => $this->id,
723  'function' => (int)$this->moduleData->get('function'),
724  'language' => -1,
725  ]))
726  ->setLabel($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages'));
727  $languageDropDownButton->addItem($allLanguagesItem);
728  }
729 
730  return $languageDropDownButton;
731  }
732 
737  protected function ‪getNumberOfHiddenElements(bool $isLanguageModeActive): int
738  {
739  $andWhere = [];
740  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
741  $queryBuilder->getRestrictions()
742  ->removeAll()
743  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
744  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
745  $queryBuilder
746  ->count('uid')
747  ->from('tt_content')
748  ->where(
749  $queryBuilder->expr()->eq(
750  'pid',
751  $queryBuilder->createNamedParameter($this->id, ‪Connection::PARAM_INT)
752  )
753  );
754 
755  if ($this->currentSelectedLanguage === 0) {
756  // Default language is active (in columns or language mode) - consider "all languages" and the default
757  $queryBuilder->andWhere(
758  $queryBuilder->expr()->in(
759  ‪$GLOBALS['TCA']['tt_content']['ctrl']['languageField'],
760  [-1, 0]
761  )
762  );
763  } elseif ($isLanguageModeActive && $this->currentSelectedLanguage !== -1) {
764  // Multi-language view with any translation is active -
765  // consider "all languages", the default and the translation
766  $queryBuilder->andWhere(
767  $queryBuilder->expr()->in(
768  ‪$GLOBALS['TCA']['tt_content']['ctrl']['languageField'],
769  [-1, 0, $queryBuilder->createNamedParameter($this->currentSelectedLanguage, ‪Connection::PARAM_INT)]
770  )
771  );
772  } elseif ($this->currentSelectedLanguage > 0) {
773  // Columns mode with any translation is active - consider "all languages" and the translation
774  $queryBuilder->andWhere(
775  $queryBuilder->expr()->in(
776  ‪$GLOBALS['TCA']['tt_content']['ctrl']['languageField'],
777  [-1, $queryBuilder->createNamedParameter($this->currentSelectedLanguage, ‪Connection::PARAM_INT)]
778  )
779  );
780  }
781 
782  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'])) {
783  $andWhere[] = $queryBuilder->expr()->neq(
784  ‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'],
785  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
786  );
787  }
788  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['starttime'])) {
789  $starttimeField = ‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['starttime'];
790  $andWhere[] = $queryBuilder->expr()->and(
791  $queryBuilder->expr()->neq(
792  $starttimeField,
793  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
794  ),
795  $queryBuilder->expr()->gt(
796  $starttimeField,
797  $queryBuilder->createNamedParameter(‪$GLOBALS['SIM_ACCESS_TIME'], ‪Connection::PARAM_INT)
798  )
799  );
800  }
801  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['endtime'])) {
802  $endtimeField = ‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['endtime'];
803  $andWhere[] = $queryBuilder->expr()->and(
804  $queryBuilder->expr()->neq(
805  $endtimeField,
806  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
807  ),
808  $queryBuilder->expr()->lte(
809  $endtimeField,
810  $queryBuilder->createNamedParameter(‪$GLOBALS['SIM_ACCESS_TIME'], ‪Connection::PARAM_INT)
811  )
812  );
813  }
814  if (!empty($andWhere)) {
815  $queryBuilder->andWhere(
816  $queryBuilder->expr()->or(...$andWhere)
817  );
818  }
819  $count = $queryBuilder
820  ->executeQuery()
821  ->fetchOne();
822  return (int)$count;
823  }
824 
828  protected function ‪isPageEditable(int $languageId): bool
829  {
830  if (‪$GLOBALS['TCA']['pages']['ctrl']['readOnly'] ?? false) {
831  return false;
832  }
833  $backendUser = $this->‪getBackendUser();
834  if ($backendUser->isAdmin()) {
835  return true;
836  }
837  if (‪$GLOBALS['TCA']['pages']['ctrl']['adminOnly'] ?? false) {
838  return false;
839  }
840  return is_array($this->pageinfo)
841  && $this->pageinfo !== []
842  && !(bool)($this->pageinfo[‪$GLOBALS['TCA']['pages']['ctrl']['editlock'] ?? null] ?? false)
843  && $backendUser->doesUserHaveAccess($this->pageinfo, ‪Permission::PAGE_EDIT)
844  && $backendUser->checkLanguageAccess($languageId)
845  && $backendUser->check('tables_modify', 'pages');
846  }
847 
851  protected function ‪isContentEditable(int $languageId): bool
852  {
853  if ($this->‪getBackendUser()->isAdmin()) {
854  return true;
855  }
856  return !($this->pageinfo['editlock'] ?? false)
857  && $this->‪getBackendUser()->doesUserHaveAccess($this->pageinfo, ‪Permission::CONTENT_EDIT)
858  && $this->‪getBackendUser()->check('tables_modify', 'tt_content')
859  && $this->‪getBackendUser()->checkLanguageAccess($languageId);
860  }
861 
865  protected function ‪getTargetPageIfVisible(array $targetPage): array
866  {
867  return !(bool)($targetPage['hidden'] ?? false) ? $targetPage : [];
868  }
869 
873  protected function ‪getShortcutTitle(): string
874  {
875  return sprintf(
876  '%s: %s [%d]',
877  $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_mod.xlf:mlang_labels_tablabel'),
878  BackendUtility::getRecordTitle('pages', (array)$this->pageinfo),
879  $this->id
880  );
881  }
882 
886  protected function ‪resolveExternalUrl(array $pagerow, ServerRequestInterface $request): string
887  {
888  $redirectTo = (string)($pagerow['url'] ?? '');
889  if ($redirectTo === '') {
890  return '';
891  }
892  $urlInformation = parse_url($redirectTo);
893  // If relative path, prefix Site URL
894  // If it's a valid email without protocol, add "mailto:"
895  if (!($urlInformation['scheme'] ?? false)) {
896  if (GeneralUtility::validEmail($redirectTo)) {
897  $redirectTo = 'mailto:' . $redirectTo;
898  } elseif ($redirectTo[0] !== '/') {
899  $redirectTo = $request->getAttribute('normalizedParams')->getSiteUrl() . $redirectTo;
900  }
901  }
902  return $redirectTo;
903  }
904 
906  {
907  return ‪$GLOBALS['LANG'];
908  }
909 
911  {
912  return ‪$GLOBALS['BE_USER'];
913  }
914 }
‪TYPO3\CMS\Backend\Controller\PageLayoutController\isPageEditable
‪isPageEditable(int $languageId)
Definition: PageLayoutController.php:828
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:37
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:33
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:48
‪TYPO3\CMS\Backend\Controller\PageLayoutController\createPageLayoutContext
‪createPageLayoutContext()
Definition: PageLayoutController.php:160
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\makeDropDownButton
‪DropDownButton makeDropDownButton()
Definition: ButtonBar.php:122
‪TYPO3\CMS\Backend\Controller\PageLayoutController\initializeClipboard
‪initializeClipboard(ServerRequestInterface $request)
Definition: PageLayoutController.php:516
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:33
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$availableLanguages
‪array $availableLanguages
Definition: PageLayoutController.php:79
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getLocalizedPageRecord
‪getLocalizedPageRecord(int $languageId)
Definition: PageLayoutController.php:273
‪TYPO3\CMS\Core\Versioning\VersionState
‪VersionState
Definition: VersionState.php:22
‪TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper\STATE_INFO
‪const STATE_INFO
Definition: InfoboxViewHelper.php:68
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getLanguageService
‪getLanguageService()
Definition: PageLayoutController.php:905
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getLocalizedPageTitle
‪getLocalizedPageTitle(int $currentSelectedLanguage, array $pageInfo)
Definition: PageLayoutController.php:501
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\create
‪static create(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:47
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:100
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getExistingPageTranslations
‪getExistingPageTranslations()
Definition: PageLayoutController.php:243
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_LINK
‪const DOKTYPE_LINK
Definition: PageRepository.php:99
‪TYPO3\CMS\Backend\View\PageLayoutContext\getBackendLayout
‪getBackendLayout()
Definition: PageLayoutContext.php:142
‪TYPO3\CMS\Backend\Module\ModuleData
Definition: ModuleData.php:30
‪TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper\STATE_ERROR
‪const STATE_ERROR
Definition: InfoboxViewHelper.php:71
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getActiveColumnsArray
‪getActiveColumnsArray(PageLayoutContext $pageLayoutContext, array $tsConfig)
Definition: PageLayoutController.php:539
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getTargetPageIfVisible
‪getTargetPageIfVisible(array $targetPage)
Definition: PageLayoutController.php:865
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent
Definition: ModifyPageLayoutContentEvent.php:27
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeButtons
‪makeButtons(ModuleTemplate $view, ServerRequestInterface $request, array $tsConfig)
Definition: PageLayoutController.php:554
‪TYPO3\CMS\Backend\Module\ModuleProvider
Definition: ModuleProvider.php:29
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\SHORTCUT_MODE_RANDOM_SUBPAGE
‪const SHORTCUT_MODE_RANDOM_SUBPAGE
Definition: PageRepository.php:111
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:46
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\SHORTCUT_MODE_FIRST_SUBPAGE
‪const SHORTCUT_MODE_FIRST_SUBPAGE
Definition: PageRepository.php:110
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Backend\Controller\PageLayoutController\mainAction
‪mainAction(ServerRequestInterface $request)
Definition: PageLayoutController.php:109
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:27
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getShortcutTitle
‪getShortcutTitle()
Definition: PageLayoutController.php:873
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$currentSelectedLanguage
‪int $currentSelectedLanguage
Definition: PageLayoutController.php:73
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeViewButton
‪makeViewButton(ButtonBar $buttonBar, array $tsConfig)
Definition: PageLayoutController.php:606
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:44
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownRadio
Definition: DropDownRadio.php:54
‪TYPO3\CMS\Backend\Controller\PageLayoutController
Definition: PageLayoutController.php:62
‪TYPO3\CMS\Backend\Controller\PageLayoutController\__construct
‪__construct(protected readonly IconFactory $iconFactory, protected readonly PageRenderer $pageRenderer, protected readonly UriBuilder $uriBuilder, protected readonly PageRepository $pageRepository, protected readonly ModuleTemplateFactory $moduleTemplateFactory, protected readonly EventDispatcherInterface $eventDispatcher, protected readonly ModuleProvider $moduleProvider, protected readonly BackendLayoutRenderer $backendLayoutRenderer, protected readonly BackendLayoutView $backendLayoutView,)
Definition: PageLayoutController.php:83
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownItemInterface
Definition: DropDownItemInterface.php:19
‪TYPO3\CMS\Backend\Controller\PageLayoutController\menuConfig
‪menuConfig(ServerRequestInterface $request)
Definition: PageLayoutController.php:180
‪TYPO3\CMS\Backend\Controller\PageLayoutController\initialize
‪initialize(ServerRequestInterface $request)
Definition: PageLayoutController.php:95
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$moduleData
‪ModuleData $moduleData
Definition: PageLayoutController.php:81
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder\create
‪static static create(int $pageId)
Definition: PreviewUriBuilder.php:65
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$pageinfo
‪array bool $pageinfo
Definition: PageLayoutController.php:71
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:103
‪TYPO3\CMS\Backend\Controller\PageLayoutController\resolveExternalUrl
‪resolveExternalUrl(array $pagerow, ServerRequestInterface $request)
Definition: PageLayoutController.php:886
‪TYPO3\CMS\Backend\View\Drawing\BackendLayoutRenderer
Definition: BackendLayoutRenderer.php:48
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:61
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SYSFOLDER
‪const DOKTYPE_SYSFOLDER
Definition: PageRepository.php:104
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDownButton\setLabel
‪setLabel(string $label)
Definition: DropDownButton.php:72
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\makeLinkButton
‪LinkButton makeLinkButton()
Definition: ButtonBar.php:132
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\SHORTCUT_MODE_PARENT_PAGE
‪const SHORTCUT_MODE_PARENT_PAGE
Definition: PageRepository.php:112
‪TYPO3\CMS\Backend\Controller\PageLayoutController\generateMessagesForCurrentPage
‪generateMessagesForCurrentPage(ServerRequestInterface $request)
Definition: PageLayoutController.php:358
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeActionMenu
‪makeActionMenu(ModuleTemplate $view, array $tsConfig)
Definition: PageLayoutController.php:309
‪TYPO3\CMS\Backend\Template\ModuleTemplate\getDocHeaderComponent
‪getDocHeaderComponent()
Definition: ModuleTemplate.php:181
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$MOD_MENU
‪array $MOD_MENU
Definition: PageLayoutController.php:74
‪TYPO3\CMS\Core\Type\Bitmask\Permission\CONTENT_EDIT
‪const CONTENT_EDIT
Definition: Permission.php:55
‪TYPO3\CMS\Backend\View\BackendLayoutView
Definition: BackendLayoutView.php:38
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\SHORTCUT_MODE_NONE
‪const SHORTCUT_MODE_NONE
Definition: PageRepository.php:109
‪TYPO3\CMS\Backend\View\PageLayoutContext
Definition: PageLayoutContext.php:44
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder
Definition: PreviewUriBuilder.php:44
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_EDIT
‪const PAGE_EDIT
Definition: Permission.php:40
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper
Definition: InfoboxViewHelper.php:65
‪TYPO3\CMS\Backend\Controller\PageLayoutController\$id
‪int $id
Definition: PageLayoutController.php:66
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getNumberOfHiddenElements
‪getNumberOfHiddenElements(bool $isLanguageModeActive)
Definition: PageLayoutController.php:737
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getPageLinksWhereContentIsAlsoShownOn
‪getPageLinksWhereContentIsAlsoShownOn(int $pageId)
Definition: PageLayoutController.php:480
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeEditButton
‪makeEditButton(ButtonBar $buttonBar, ServerRequestInterface $request)
Definition: PageLayoutController.php:652
‪TYPO3\CMS\Backend\Template\Components\AbstractControl\setDataAttributes
‪$this setDataAttributes(array $dataAttributes)
Definition: AbstractControl.php:105
‪TYPO3\CMS\Backend\Template\Components\AbstractControl\setTitle
‪$this setTitle($title)
Definition: AbstractControl.php:92
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_RIGHT
‪const BUTTON_POSITION_RIGHT
Definition: ButtonBar.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:751
‪TYPO3\CMS\Backend\Controller
Definition: AboutController.php:18
‪TYPO3\CMS\Backend\Controller\PageLayoutController\makeLanguageSwitchButton
‪makeLanguageSwitchButton(ButtonBar $buttonbar)
Definition: PageLayoutController.php:684
‪TYPO3\CMS\Backend\Controller\PageLayoutController\addJavaScriptModuleInstructions
‪addJavaScriptModuleInstructions()
Definition: PageLayoutController.php:470
‪TYPO3\CMS\Backend\Controller\PageLayoutController\isContentEditable
‪isContentEditable(int $languageId)
Definition: PageLayoutController.php:851
‪TYPO3\CMS\Backend\Template\Components\Buttons\ButtonInterface
Definition: ButtonInterface.php:22
‪TYPO3\CMS\Backend\Controller\PageLayoutController\getBackendUser
‪getBackendUser()
Definition: PageLayoutController.php:910
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39