‪TYPO3CMS  10.4
PageLayoutView.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Doctrine\DBAL\Driver\Statement;
19 use Doctrine\DBAL\ForwardCompatibility\Result;
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Log\LoggerAwareInterface;
22 use Psr\Log\LoggerAwareTrait;
54 
60 class ‪PageLayoutView implements LoggerAwareInterface
61 {
62  use LoggerAwareTrait;
63 
69  public ‪$option_newWizard = true;
70 
76  public ‪$doEdit = true;
77 
84  public ‪$defLangBinding = false;
85 
91  public ‪$tt_contentConfig = [
92  'languageCols' => 0,
93  'languageMode' => 0,
94  'languageColsPointer' => 0,
95  // Displays hidden records as well
96  'showHidden' => 1,
97  // Which language
98  'sys_language_uid' => 0,
99  'cols' => '1,0,2,3',
100  // Which columns can be accessed by current BE user
101  'activeCols' => '1,0,2,3'
102  ];
103 
108  public ‪$tt_contentData = [
109  'prev' => [],
110  'next' => []
111  ];
112 
118  public ‪$CType_labels = [];
119 
125  public ‪$itemLabels = [];
126 
132  public ‪$id;
133 
139  public ‪$pageRecord = [];
140 
146  protected ‪$siteLanguages = [];
147 
151  protected ‪$clipboard;
152 
158  protected ‪$pageinfo;
159 
166  protected ‪$contentElementCache = [];
167 
171  protected ‪$iconFactory;
172 
178  protected ‪$languageHasTranslationsCache = [];
179 
184 
190  protected ‪$referenceCount = [];
191 
195  protected ‪$eventDispatcher;
196 
200  protected ‪$uriBuilder;
201 
202  public function ‪__construct(EventDispatcherInterface ‪$eventDispatcher)
203  {
204  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
205  $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
206  $this->localizationController = GeneralUtility::makeInstance(LocalizationController::class);
207  $this->eventDispatcher = ‪$eventDispatcher;
208  }
209 
216  {
217  $drawingConfiguration = $context->‪getDrawingConfiguration();
218  $languageId = $drawingConfiguration->getSelectedLanguageId();
220  $pageLayoutView = GeneralUtility::makeInstance(self::class);
221  $pageLayoutView->id = $context->‪getPageId();
222  $pageLayoutView->pageinfo = ‪BackendUtility::readPageAccess($pageLayoutView->id, '');
223  $pageLayoutView->pageRecord = $context->‪getPageRecord();
224  $pageLayoutView->option_newWizard = $drawingConfiguration->getShowNewContentWizard();
225  $pageLayoutView->defLangBinding = $drawingConfiguration->getDefaultLanguageBinding();
226  $pageLayoutView->tt_contentConfig['cols'] = implode(',', $drawingConfiguration->getActiveColumns());
227  $pageLayoutView->tt_contentConfig['activeCols'] = implode(',', $drawingConfiguration->getActiveColumns());
228  $pageLayoutView->tt_contentConfig['showHidden'] = $drawingConfiguration->getShowHidden();
229  $pageLayoutView->tt_contentConfig['sys_language_uid'] = $languageId;
230  if ($drawingConfiguration->getLanguageMode()) {
231  $pageLayoutView->tt_contentConfig['languageMode'] = 1;
232  $pageLayoutView->tt_contentConfig['languageCols'] = $drawingConfiguration->getLanguageColumns();
233  $pageLayoutView->tt_contentConfig['languageColsPointer'] = $languageId;
234  }
235  $pageLayoutView->doEdit = $pageLayoutView->isContentEditable($languageId);
236  $pageLayoutView->CType_labels = $context->‪getContentTypeLabels();
237  $pageLayoutView->itemLabels = $context->‪getItemLabels();
238  return $pageLayoutView;
239  }
240 
241  protected function ‪initialize()
242  {
243  $this->‪resolveSiteLanguages($this->id);
244  $this->pageRecord = ‪BackendUtility::getRecordWSOL('pages', $this->id);
245  $this->‪initializeClipboard();
246  $this->pageinfo = ‪BackendUtility::readPageAccess($this->id, '');
247  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
248  $pageActionsCallback = null;
249  if ($this->‪isPageEditable()) {
250  $languageOverlayId = 0;
251  $pageLocalizationRecord = ‪BackendUtility::getRecordLocalization('pages', $this->id, (int)$this->tt_contentConfig['sys_language_uid']);
252  if (is_array($pageLocalizationRecord)) {
253  $pageLocalizationRecord = reset($pageLocalizationRecord);
254  }
255  if (!empty($pageLocalizationRecord['uid'])) {
256  $languageOverlayId = $pageLocalizationRecord['uid'];
257  }
258  $pageActionsCallback = 'function(PageActions) {
259  PageActions.setPageId(' . (int)$this->id . ');
260  PageActions.setLanguageOverlayId(' . $languageOverlayId . ');
261  }';
262  }
263  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', $pageActionsCallback);
264  // Get labels for CTypes and tt_content element fields in general:
265  $this->CType_labels = [];
266  foreach (‪$GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) {
267  $this->CType_labels[$val[1]] = $this->‪getLanguageService()->‪sL($val[0]);
268  }
269 
270  $this->itemLabels = [];
271  foreach (‪$GLOBALS['TCA']['tt_content']['columns'] as $name => $val) {
272  $this->itemLabels[$name] = $this->‪getLanguageService()->‪sL($val['label']);
273  }
274  }
275 
280  protected function ‪getSelectedLanguages(): array
281  {
282  $langList = $this->tt_contentConfig['sys_language_uid'];
283  if ($this->tt_contentConfig['languageMode']) {
284  if ($this->tt_contentConfig['languageColsPointer']) {
285  $langList = '0,' . $this->tt_contentConfig['languageColsPointer'];
286  } else {
287  $langList = implode(',', array_keys($this->tt_contentConfig['languageCols']));
288  }
289  }
290  return ‪GeneralUtility::intExplode(',', $langList);
291  }
292 
299  public function ‪getTable_tt_content(‪$id)
300  {
301  $this->id = (int)‪$id;
302  $this->‪initialize();
303  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
304  ->getConnectionForTable('tt_content')
305  ->getExpressionBuilder();
306 
307  $languageColumn = [];
308  $out = '';
309  $tcaItems = GeneralUtility::makeInstance(BackendLayoutView::class)->getColPosListItemsParsed($this->id);
310  $languageIds = $this->‪getSelectedLanguages();
311  $defaultLanguageElementsByColumn = [];
312  ‪$defLangBinding = [];
313  // For each languages...
314  // If not languageMode, then we'll only be through this once.
315  foreach ($languageIds as $lP) {
316  if (!isset($this->contentElementCache[$lP])) {
317  $this->contentElementCache[$lP] = [];
318  }
319 
320  if (count($languageIds) === 1 || $lP === 0) {
321  $showLanguage = $expressionBuilder->in('sys_language_uid', [$lP, -1]);
322  } else {
323  $showLanguage = $expressionBuilder->eq('sys_language_uid', $lP);
324  }
325  $content = [];
326  $head = [];
327 
328  $backendLayout = $this->‪getBackendLayoutView()->‪getSelectedBackendLayout($this->id);
329  $columns = $backendLayout['__colPosList'];
330  // Select content records per column
331  $contentRecordsPerColumn = $this->‪getContentRecordsPerColumn('tt_content', ‪$id, $columns, $showLanguage);
332  $cList = array_keys($contentRecordsPerColumn);
333  // For each column, render the content into a variable:
334  foreach ($cList as $columnId) {
335  if (!isset($this->contentElementCache[$lP])) {
336  $this->contentElementCache[$lP] = [];
337  }
338 
339  if (!$lP) {
340  $defaultLanguageElementsByColumn[$columnId] = [];
341  }
342 
343  // Start wrapping div
344  $content[$columnId] .= '<div data-colpos="' . $columnId . '" data-language-uid="' . $lP . '" class="t3js-sortable t3js-sortable-lang t3js-sortable-lang-' . $lP . ' t3-page-ce-wrapper';
345  if (empty($contentRecordsPerColumn[$columnId])) {
346  $content[$columnId] .= ' t3-page-ce-empty';
347  }
348  $content[$columnId] .= '">';
349  // Add new content at the top most position
350  $link = '';
351  if ($this->‪isContentEditable()
352  && (!$this->‪checkIfTranslationsExistInLanguage($contentRecordsPerColumn, $lP))
353  ) {
354  if ($this->option_newWizard) {
355  $urlParameters = [
356  'id' => ‪$id,
357  'sys_language_uid' => $lP,
358  'colPos' => $columnId,
359  'uid_pid' => ‪$id,
360  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
361  ];
362  $routeName = ‪BackendUtility::getPagesTSconfig(‪$id)['mod.']['newContentElementWizard.']['override']
363  ?? 'new_content_element_wizard';
364  $url = (string)$this->uriBuilder->buildUriFromRoute($routeName, $urlParameters);
365  } else {
366  $urlParameters = [
367  'edit' => [
368  'tt_content' => [
369  ‪$id => 'new'
370  ]
371  ],
372  'defVals' => [
373  'tt_content' => [
374  'colPos' => $columnId,
375  'sys_language_uid' => $lP
376  ]
377  ],
378  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
379  ];
380  $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
381  }
382  $title = htmlspecialchars($this->‪getLanguageService()->getLL('newContentElement'));
383  $link = '<a href="' . htmlspecialchars($url) . '" '
384  . 'title="' . $title . '"'
385  . 'data-title="' . $title . '"'
386  . 'class="btn btn-default btn-sm ' . ($this->option_newWizard ? 't3js-toggle-new-content-element-wizard disabled' : '') . '">'
387  . $this->iconFactory->getIcon('actions-add', ‪Icon::SIZE_SMALL)->render()
388  . ' '
389  . htmlspecialchars($this->‪getLanguageService()->getLL('content')) . '</a>';
390  }
391  if ($this->‪getBackendUser()->checkLanguageAccess($lP) && $columnId !== 'unused') {
392  $content[$columnId] .= '
393  <div class="t3-page-ce t3js-page-ce" data-page="' . (int)‪$id . '" id="' . ‪StringUtility::getUniqueId() . '">
394  <div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $columnId . '-page-' . ‪$id . '-' . ‪StringUtility::getUniqueId() . '">'
395  . $link
396  . '</div>
397  <div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div>
398  </div>
399  ';
400  }
401  $editUidList = '';
402  if (!isset($contentRecordsPerColumn[$columnId]) || !is_array($contentRecordsPerColumn[$columnId])) {
403  $message = GeneralUtility::makeInstance(
404  FlashMessage::class,
405  $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:error.invalidBackendLayout'),
406  '',
408  );
409  $service = GeneralUtility::makeInstance(FlashMessageService::class);
410  $queue = $service->getMessageQueueByIdentifier();
411  $queue->addMessage($message);
412  } else {
413  $rowArr = $contentRecordsPerColumn[$columnId];
414  $this->‪generateTtContentDataArray($rowArr);
415 
416  foreach ((array)$rowArr as $rKey => $row) {
417  $this->contentElementCache[$lP][$columnId][$row['uid']] = $row;
418  if ($this->tt_contentConfig['languageMode']) {
419  $languageColumn[$columnId][$lP] = $head[$columnId] . $content[$columnId];
420  }
421  if (is_array($row) && !‪VersionState::cast($row['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)) {
422  $singleElementHTML = '<div class="t3-page-ce-dragitem" id="' . ‪StringUtility::getUniqueId() . '">';
423  if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) {
424  $defaultLanguageElementsByColumn[$columnId][] = $row['uid'];
425  }
426  $editUidList .= $row['uid'] . ',';
427  $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0 && $this->‪checkIfTranslationsExistInLanguage($contentRecordsPerColumn, $lP);
428  $singleElementHTML .= $this->‪tt_content_drawHeader(
429  $row,
430  0,
431  $disableMoveAndNewButtons,
432  true,
434  );
435  $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>'
436  . $this->‪tt_content_drawItem($row) . '</div>';
437  $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div></div>'
438  . $this->‪tt_content_drawFooter($row);
439  $isDisabled = $this->‪isDisabled('tt_content', $row);
440  $statusHidden = $isDisabled ? ' t3-page-ce-hidden t3js-hidden-record' : '';
441  $displayNone = !$this->tt_contentConfig['showHidden'] && $isDisabled ? ' style="display: none;"' : '';
442  $highlightHeader = '';
443  if ($this->‪checkIfTranslationsExistInLanguage([], (int)$row['sys_language_uid']) && (int)$row['l18n_parent'] === 0) {
444  $highlightHeader = ' t3-page-ce-danger';
445  } elseif ($columnId === 'unused') {
446  $highlightHeader = ' t3-page-ce-warning';
447  }
448  $singleElementHTML = '<div class="t3-page-ce' . $highlightHeader . ' t3js-page-ce t3js-page-ce-sortable ' . $statusHidden . '" id="element-tt_content-'
449  . $row['uid'] . '" data-table="tt_content" data-uid="' . $row['uid'] . '" data-language-uid="'
450  . $row['sys_language_uid'] . '"' . $displayNone . '>' . $singleElementHTML . '</div>';
451 
452  $singleElementHTML .= '<div class="t3-page-ce" data-colpos="' . $columnId . '">';
453  $singleElementHTML .= '<div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $columnId . '-page-' . ‪$id .
454  '-' . ‪StringUtility::getUniqueId() . '">';
455  // Add icon "new content element below"
456  if (!$disableMoveAndNewButtons
457  && $this->‪isContentEditable($lP)
458  && (!$this->‪checkIfTranslationsExistInLanguage($contentRecordsPerColumn, $lP))
459  && $columnId !== 'unused'
460  ) {
461  // New content element:
462  if ($this->option_newWizard) {
463  $urlParameters = [
464  'id' => $row['pid'],
465  'sys_language_uid' => $row['sys_language_uid'],
466  'colPos' => $row['colPos'],
467  'uid_pid' => -$row['uid'],
468  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
469  ];
470  $routeName = ‪BackendUtility::getPagesTSconfig($row['pid'])['mod.']['newContentElementWizard.']['override']
471  ?? 'new_content_element_wizard';
472  $url = (string)$this->uriBuilder->buildUriFromRoute($routeName, $urlParameters);
473  } else {
474  $urlParameters = [
475  'edit' => [
476  'tt_content' => [
477  -$row['uid'] => 'new'
478  ]
479  ],
480  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
481  ];
482  $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
483  }
484  $title = htmlspecialchars($this->‪getLanguageService()->getLL('newContentElement'));
485  $singleElementHTML .= '<a href="' . htmlspecialchars($url) . '" '
486  . 'title="' . $title . '"'
487  . 'data-title="' . $title . '"'
488  . 'class="btn btn-default btn-sm ' . ($this->option_newWizard ? 't3js-toggle-new-content-element-wizard disabled' : '') . '">'
489  . $this->iconFactory->getIcon('actions-add', ‪Icon::SIZE_SMALL)->render()
490  . ' '
491  . htmlspecialchars($this->‪getLanguageService()->getLL('content')) . '</a>';
492  }
493  $singleElementHTML .= '</div></div><div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div></div>';
494  if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) {
495  ‪$defLangBinding[$columnId][$lP][$row[$lP ? 'l18n_parent' : 'uid'] ?: $row['uid']] = $singleElementHTML;
496  } else {
497  $content[$columnId] .= $singleElementHTML;
498  }
499  } else {
500  unset($rowArr[$rKey]);
501  }
502  }
503  $content[$columnId] .= '</div>';
504  if ($columnId === 'unused') {
505  if (empty($unusedElementsMessage)) {
506  $unusedElementsMessage = GeneralUtility::makeInstance(
507  FlashMessage::class,
508  $this->‪getLanguageService()->getLL('staleUnusedElementsWarning'),
509  $this->‪getLanguageService()->getLL('staleUnusedElementsWarningTitle'),
511  );
512  $service = GeneralUtility::makeInstance(FlashMessageService::class);
513  $queue = $service->getMessageQueueByIdentifier();
514  $queue->addMessage($unusedElementsMessage);
515  }
516  $colTitle = $this->‪getLanguageService()->‪sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.unused');
517  $editParam = '';
518  } else {
519  $colTitle = '';
520  foreach ($tcaItems as $item) {
521  if ($item[1] == $columnId) {
522  $colTitle = $this->‪getLanguageService()->‪sL($item[0]);
523  }
524  }
525  if (empty($colTitle)) {
526  $colTitle = ‪BackendUtility::getProcessedValue('tt_content', 'colPos', (string)$columnId) ?? '';
527  }
528  $editParam = $this->doEdit && !empty($rowArr)
529  ? '&edit[tt_content][' . $editUidList . ']=edit&recTitle=' . rawurlencode(‪BackendUtility::getRecordTitle('pages', $this->pageRecord, true))
530  : '';
531  }
532  $head[$columnId] .= $this->‪tt_content_drawColHeader($colTitle, $editParam);
533  }
534  }
535  // For each column, fit the rendered content into a table cell:
536  $out = '';
537  if ($this->tt_contentConfig['languageMode']) {
538  // in language mode process the content elements, but only fill $languageColumn. output will be generated later
539  $sortedLanguageColumn = [];
540  foreach ($cList as $columnId) {
541  if (GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnId) || $columnId === 'unused') {
542  $languageColumn[$columnId][$lP] = $head[$columnId] . $content[$columnId];
543 
544  // We sort $languageColumn again according to $cList as it may contain data already from above.
545  $sortedLanguageColumn[$columnId] = $languageColumn[$columnId];
546  }
547  }
548  if (!empty($languageColumn['unused'])) {
549  $sortedLanguageColumn['unused'] = $languageColumn['unused'];
550  }
551  $languageColumn = $sortedLanguageColumn;
552  } else {
553  // GRID VIEW:
554  $grid = '<div class="t3-grid-container"><table border="0" cellspacing="0" cellpadding="0" width="100%" class="t3-page-columns t3-grid-table t3js-page-columns">';
555  // Add colgroups
556  $colCount = (int)$backendLayout['__config']['backend_layout.']['colCount'];
557  $rowCount = (int)$backendLayout['__config']['backend_layout.']['rowCount'];
558  $colSpan = 0;
559  $rowSpan = 0;
560  $grid .= '<colgroup>';
561  for ($i = 0; $i < $colCount; $i++) {
562  $grid .= '<col />';
563  }
564  $grid .= '</colgroup>';
565 
566  // Check how to handle restricted columns
567  $hideRestrictedCols = (bool)(‪BackendUtility::getPagesTSconfig(‪$id)['mod.']['web_layout.']['hideRestrictedCols'] ?? false);
568 
569  // Cycle through rows
570  for ($row = 1; $row <= $rowCount; $row++) {
571  $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'];
572  if (!isset($rowConfig)) {
573  continue;
574  }
575  $grid .= '<tr>';
576  for ($col = 1; $col <= $colCount; $col++) {
577  $columnConfig = $rowConfig['columns.'][$col . '.'];
578  if (!isset($columnConfig)) {
579  continue;
580  }
581  // Which tt_content colPos should be displayed inside this cell
582  $columnKey = (int)$columnConfig['colPos'];
583  // Render the grid cell
584  $colSpan = (int)$columnConfig['colspan'];
585  $rowSpan = (int)$columnConfig['rowspan'];
586  $grid .= '<td valign="top"' .
587  ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') .
588  ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') .
589  ' data-colpos="' . (int)$columnConfig['colPos'] . '" data-language-uid="' . $lP . '" class="t3js-page-lang-column-' . $lP . ' t3js-page-column t3-grid-cell t3-page-column t3-page-column-' . $columnKey .
590  ((!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '') ? ' t3-grid-cell-unassigned' : '') .
591  ((isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !$head[$columnKey]) || !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos']) ? ($hideRestrictedCols ? ' t3-grid-cell-restricted t3-grid-cell-hidden' : ' t3-grid-cell-restricted') : '') .
592  ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') .
593  ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">';
594 
595  // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
596  // If not, a new header without any buttons will be generated.
597  if (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey]
598  && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
599  ) {
600  $grid .= $head[$columnKey];
601  $grid .= $this->‪dispatchSectionMarkupGeneratedEvent('before', $lP, $columnConfig);
602  $grid .= $content[$columnKey];
603  } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
604  && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
605  ) {
606  if (!$hideRestrictedCols) {
607  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->getLL('noAccess'));
608  $grid .= $this->‪dispatchSectionMarkupGeneratedEvent('before', $lP, $columnConfig);
609  }
610  } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
611  && !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
612  ) {
613  if (!$hideRestrictedCols) {
614  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->sL($columnConfig['name']) .
615  ' (' . $this->‪getLanguageService()->getLL('noAccess') . ')');
616  $grid .= $this->‪dispatchSectionMarkupGeneratedEvent('before', $lP, $columnConfig);
617  }
618  } elseif (isset($columnConfig['name']) && $columnConfig['name'] !== '') {
619  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->sL($columnConfig['name'])
620  . ' (' . $this->‪getLanguageService()->getLL('notAssigned') . ')');
621  $grid .= $this->‪dispatchSectionMarkupGeneratedEvent('before', $lP, $columnConfig);
622  } else {
623  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->getLL('notAssigned'));
624  $grid .= $this->‪dispatchSectionMarkupGeneratedEvent('before', $lP, $columnConfig);
625  }
626 
627  $grid .= $this->‪dispatchSectionMarkupGeneratedEvent('after', $lP, $columnConfig);
628 
629  $grid .= '</td>';
630  }
631  $grid .= '</tr>';
632  }
633  if (!empty($content['unused'])) {
634  $grid .= '<tr>';
635  // Which tt_content colPos should be displayed inside this cell
636  $columnKey = 'unused';
637  // Render the grid cell
638  $colSpan = (int)$backendLayout['__config']['backend_layout.']['colCount'];
639  $grid .= '<td valign="top"' .
640  ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') .
641  ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') .
642  ' data-colpos="unused" data-language-uid="' . $lP . '" class="t3js-page-lang-column-' . $lP . ' t3js-page-column t3-grid-cell t3-page-column t3-page-column-' . $columnKey .
643  ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') . '">';
644 
645  // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
646  // If not, a new header without any buttons will be generated.
647  $grid .= $head[$columnKey] . $content[$columnKey];
648  $grid .= '</td></tr>';
649  }
650  $out .= $grid . '</table></div>';
651  }
652  }
653  $elFromTable = $this->clipboard->elFromTable('tt_content');
654  if (!empty($elFromTable) && $this->‪isContentEditable()) {
655  $pasteItem = (int)substr((string)key($elFromTable), 11);
656  $pasteRecord = ‪BackendUtility::getRecord('tt_content', $pasteItem);
657  $pasteTitle = $pasteRecord['header'] ?: (string)$pasteItem;
658  $copyMode = $this->clipboard->clipData['normal']['mode'] ? '-' . $this->clipboard->clipData['normal']['mode'] : '';
659  $inlineJavaScript = '
660  top.pasteIntoLinkTemplate = '
661  . $this->‪tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-into', 'pasteIntoColumn')
662  . ';
663  top.pasteAfterLinkTemplate = '
664  . $this->‪tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-after', 'pasteAfterRecord')
665  . ';';
666  } else {
667  $inlineJavaScript = '
668  top.pasteIntoLinkTemplate = \'\';
669  top.pasteAfterLinkTemplate = \'\';';
670  }
671  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
672  $pageRenderer->addJsInlineCode('pasteLinkTemplates', $inlineJavaScript);
673  // If language mode, then make another presentation:
674  // Notice that THIS presentation will override the value of $out!
675  // But it needs the code above to execute since $languageColumn is filled with content we need!
676  if ($this->tt_contentConfig['languageMode']) {
677  return $this->‪generateLanguageView($languageIds, $defaultLanguageElementsByColumn, $languageColumn, ‪$defLangBinding);
678  }
679  return $out;
680  }
681 
690  protected function ‪generateLanguageView(
691  array $languageIds,
692  array $defaultLanguageElementsByColumn,
693  array $languageColumn,
694  array ‪$defLangBinding
695  ): string {
696  // Get language selector:
697  $languageSelector = $this->‪languageSelector($this->id);
698  // Reset out - we will make new content here:
699  $out = '';
700  // Traverse languages found on the page and build up the table displaying them side by side:
701  $cCont = [];
702  $sCont = [];
703  foreach ($languageIds as $languageId) {
704  $languageMode = '';
705  $labelClass = 'info';
706  // Header:
707  $languageId = (int)$languageId;
708  // Determine language mode
709  if ($languageId > 0 && isset($this->languageHasTranslationsCache[$languageId]['mode'])) {
710  switch ($this->languageHasTranslationsCache[$languageId]['mode']) {
711  case 'mixed':
712  $languageMode = $this->‪getLanguageService()->‪getLL('languageModeMixed');
713  $labelClass = 'danger';
714  break;
715  case 'connected':
716  $languageMode = $this->‪getLanguageService()->‪getLL('languageModeConnected');
717  break;
718  case 'free':
719  $languageMode = $this->‪getLanguageService()->‪getLL('languageModeFree');
720  break;
721  default:
722  // we'll let opcode optimize this intentionally empty case
723  }
724  }
725  $columnAttributes = [
726  'valign' => 'top',
727  'class' => 't3-page-column t3-page-column-lang-name',
728  'data-language-uid' => (string)$languageId,
729  ];
730 
731  if (isset($this->siteLanguages[$languageId])) {
732  $columnAttributes['data-language-title'] = $this->siteLanguages[$languageId]->getTitle();
733  $columnAttributes['data-flag-identifier'] = $this->siteLanguages[$languageId]->getFlagIdentifier();
734  }
735 
736  $cCont[$languageId] = '
737  <td ' . GeneralUtility::implodeAttributes($columnAttributes, true) . '>
738  <h2>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$languageId]) . '</h2>
739  ' . ($languageMode !== '' ? '<span class="label label-' . $labelClass . '">' . $languageMode . '</span>' : '') . '
740  </td>';
741 
742  $editLink = '';
743  $recordIcon = '';
744  $viewLink = '';
745  // "View page" icon is added:
746  if (!‪VersionState::cast($this->pageinfo['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)) {
748  $this->id,
749  '',
751  '',
752  '',
753  '&L=' . $languageId
754  );
755  $viewLink = '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars($onClick) . '" title="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')) . '">' . $this->iconFactory->getIcon('actions-view', ‪Icon::SIZE_SMALL)->render() . '</a>';
756  }
757  // Language overlay page header:
758  if ($languageId) {
759  $pageLocalizationRecord = ‪BackendUtility::getRecordLocalization('pages', $this->id, $languageId);
760  if (is_array($pageLocalizationRecord)) {
761  $pageLocalizationRecord = reset($pageLocalizationRecord);
762  }
763  ‪BackendUtility::workspaceOL('pages', $pageLocalizationRecord);
765  $this->iconFactory->getIconForRecord('pages', $pageLocalizationRecord, ‪Icon::SIZE_SMALL)->render(),
766  'pages',
767  $pageLocalizationRecord['uid']
768  );
769  $urlParameters = [
770  'edit' => [
771  'pages' => [
772  $pageLocalizationRecord['uid'] => 'edit'
773  ]
774  ],
775  // Disallow manual adjustment of the language field for pages
776  'overrideVals' => [
777  'pages' => [
778  'sys_language_uid' => $languageId
779  ]
780  ],
781  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
782  ];
783  $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
784  if ($this->‪getBackendUser()->‪check('tables_modify', 'pages')) {
785  $editLink = '<a href="' . htmlspecialchars($url) . '" class="btn btn-default btn-sm"'
786  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">'
787  . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
788  }
789 
790  $defaultLanguageElements = [];
791  array_walk($defaultLanguageElementsByColumn, function (array $columnContent) use (&$defaultLanguageElements) {
792  $defaultLanguageElements = array_merge($defaultLanguageElements, $columnContent);
793  });
794 
795  $localizationButtons = [];
796  $localizationButtons[] = $this->‪newLanguageButton(
797  $this->‪getNonTranslatedTTcontentUids($defaultLanguageElements, $this->id, $languageId),
798  $languageId
799  );
800 
801  $languageLabel =
802  '<div class="btn-group">'
803  . $viewLink
804  . $editLink
805  . (!empty($localizationButtons) ? implode(LF, $localizationButtons) : '')
806  . '</div>'
807  . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageLocalizationRecord['title'], 20))
808  ;
809  } else {
810  if ($this->‪getBackendUser()->checkLanguageAccess(0)) {
812  $this->iconFactory->getIconForRecord('pages', $this->pageRecord, ‪Icon::SIZE_SMALL)->render(),
813  'pages',
814  $this->id
815  );
816  $urlParameters = [
817  'edit' => [
818  'pages' => [
819  $this->id => 'edit'
820  ]
821  ],
822  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
823  ];
824  $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
825  if ($this->‪getBackendUser()->‪check('tables_modify', 'pages')) {
826  $editLink = '<a href="' . htmlspecialchars($url) . '" class="btn btn-default btn-sm"'
827  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">'
828  . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
829  }
830  }
831 
832  $languageLabel =
833  '<div class="btn-group">'
834  . $viewLink
835  . $editLink
836  . '</div>'
837  . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->pageRecord['title'], 20));
838  }
839  $sCont[$languageId] = '
840  <td class="t3-page-column t3-page-lang-label nowrap">' . $languageLabel . '</td>';
841  }
842  // Add headers:
843  $out .= '<tr>' . implode('', $cCont) . '</tr>';
844  $out .= '<tr>' . implode('', $sCont) . '</tr>';
845  unset($cCont, $sCont);
846 
847  // Traverse previously built content for the columns:
848  foreach ($languageColumn as $cKey => $cCont) {
849  $out .= '<tr>';
850  foreach ($cCont as $languageId => $columnContent) {
851  $out .= '<td valign="top" data-colpos="' . $cKey . '" class="t3-grid-cell t3-page-column t3js-page-column t3js-page-lang-column t3js-page-lang-column-' . $languageId . '">' . $columnContent . '</td>';
852  }
853  $out .= '</tr>';
854  if ($this->defLangBinding && !empty(‪$defLangBinding[$cKey])) {
855  $maxItemsCount = max(array_map('count', ‪$defLangBinding[$cKey]));
856  for ($i = 0; $i < $maxItemsCount; $i++) {
857  $defUid = $defaultLanguageElementsByColumn[$cKey][$i] ?? 0;
858  $cCont = [];
859  foreach ($languageIds as $languageId) {
860  if ($languageId > 0
861  && is_array(‪$defLangBinding[$cKey][$languageId])
862  && !$this->‪checkIfTranslationsExistInLanguage($defaultLanguageElementsByColumn[$cKey], $languageId)
863  && count(‪$defLangBinding[$cKey][$languageId]) > $i
864  ) {
865  $slice = array_slice(‪$defLangBinding[$cKey][$languageId], $i, 1);
866  $element = $slice[0] ?? '';
867  } else {
868  $element = ‪$defLangBinding[$cKey][$languageId][$defUid] ?? '';
869  }
870  $cCont[] = $element;
871  }
872  $out .= '
873  <tr>
874  <td valign="top" class="t3-grid-cell" data-colpos="' . $cKey . '">' . implode('</td>
875  <td valign="top" class="t3-grid-cell" data-colpos="' . $cKey . '">', $cCont) . '</td>
876  </tr>';
877  }
878  }
879  }
880  // Finally, wrap it all in a table and add the language selector on top of it:
881  return $languageSelector . '
882  <div class="t3-grid-container">
883  <table cellpadding="0" cellspacing="0" class="t3-page-columns t3-grid-table t3js-page-columns">
884  ' . $out . '
885  </table>
886  </div>';
887  }
888 
899  protected function ‪getContentRecordsPerColumn($table, ‪$id, array $columns, $additionalWhereClause = '')
900  {
901  $contentRecordsPerColumn = array_fill_keys($columns, []);
902  $columns = array_flip($columns);
903  $queryBuilder = $this->‪getQueryBuilder(
904  $table,
905  ‪$id,
906  [
907  $additionalWhereClause
908  ]
909  );
910 
911  // Traverse any selected elements and render their display code:
913  $result = $queryBuilder->execute();
914  $results = $this->‪getResult($result);
915  $unused = [];
916  $hookArray = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['record_is_used'] ?? [];
917  foreach ($results as $record) {
918  $used = isset($columns[$record['colPos']]);
919  foreach ($hookArray as $_funcRef) {
920  $_params = ['columns' => $columns, 'record' => $record, 'used' => $used];
921  $used = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
922  }
923  if ($used) {
924  $columnValue = (string)$record['colPos'];
925  $contentRecordsPerColumn[$columnValue][] = $record;
926  } else {
927  $unused[] = $record;
928  }
929  }
930  if (!empty($unused)) {
931  $contentRecordsPerColumn['unused'] = $unused;
932  }
933  return $contentRecordsPerColumn;
934  }
935 
943  public function ‪tt_content_drawColHeader($colName, $editParams = '')
944  {
945  ‪$icons = '';
946  // Edit whole of column:
947  if ($editParams && $this->‪hasContentModificationAndAccessPermissions() && $this->‪getBackendUser()->checkLanguageAccess(0)) {
948  $link = $this->uriBuilder->buildUriFromRoute('record_edit') . $editParams . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'));
949  ‪$icons = '<a href="' . htmlspecialchars($link) . '" title="'
950  . htmlspecialchars($this->‪getLanguageService()->getLL('editColumn')) . '">'
951  . $this->iconFactory->getIcon('actions-document-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
952  ‪$icons = '<div class="t3-page-column-header-icons">' . ‪$icons . '</div>';
953  }
954  return '<div class="t3-page-column-header">
955  ' . ‪$icons . '
956  <div class="t3-page-column-header-label">' . htmlspecialchars($colName) . '</div>
957  </div>';
958  }
959 
971  protected function ‪tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, $cssClass, $title)
972  {
973  $pasteIcon = json_encode(
974  ' <button type="button"'
975  . ' data-content="' . htmlspecialchars((string)$pasteItem) . '"'
976  . ' data-title="' . htmlspecialchars($pasteTitle) . '"'
977  . ' data-severity="warning"'
978  . ' class="t3js-paste t3js-paste' . htmlspecialchars($copyMode) . ' ' . htmlspecialchars($cssClass) . ' btn btn-default btn-sm"'
979  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL($title)) . '">'
980  . $this->iconFactory->getIcon('actions-document-paste-into', ‪Icon::SIZE_SMALL)->render()
981  . '</button>'
982  );
983  return $pasteIcon;
984  }
985 
993  protected function ‪tt_content_drawFooter(array $row)
994  {
995  $content = '';
996  // Get processed values:
997  $info = [];
998  $this->‪getProcessedValue('tt_content', 'starttime,endtime,fe_group,space_before_class,space_after_class', $row, $info);
999 
1000  // Content element annotation
1001  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']) && !empty($row[‪$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']])) {
1002  $info[] = htmlspecialchars($row[‪$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']]);
1003  }
1004 
1005  // Call drawFooter hooks
1006  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawFooter'] ?? [] as $className) {
1007  $hookObject = GeneralUtility::makeInstance($className);
1008  if (!$hookObject instanceof PageLayoutViewDrawFooterHookInterface) {
1009  throw new \UnexpectedValueException($className . ' must implement interface ' . PageLayoutViewDrawFooterHookInterface::class, 1404378171);
1010  }
1011  $hookObject->preProcess($this, $info, $row);
1012  }
1013 
1014  // Display info from records fields:
1015  if (!empty($info)) {
1016  $content = '<div class="t3-page-ce-info">
1017  ' . implode('<br>', $info) . '
1018  </div>';
1019  }
1020  if (!empty($content)) {
1021  $content = '<div class="t3-page-ce-footer">' . $content . '</div>';
1022  }
1023  return $content;
1024  }
1025 
1036  public function ‪tt_content_drawHeader($row, $space = 0, $disableMoveAndNewButtons = false, $langMode = false, $dragDropEnabled = false)
1037  {
1038  $backendUser = $this->‪getBackendUser();
1039  $out = '';
1040  // Render control panel for the element
1041  if ($backendUser->recordEditAccessInternals('tt_content', $row) && $this->isContentEditable($row['sys_language_uid'])) {
1042  // Edit content element:
1043  $urlParameters = [
1044  'edit' => [
1045  'tt_content' => [
1046  $row['uid'] => 'edit'
1047  ]
1048  ],
1049  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid'],
1050  ];
1051  $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters) . '#element-tt_content-' . $row['uid'];
1052 
1053  $out .= '<a class="btn btn-default" href="' . htmlspecialchars($url)
1054  . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit'))
1055  . '">' . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
1056  // Hide element:
1057  $hiddenField = ‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
1058  if ($hiddenField && ‪$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]
1059  && (!‪$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]['exclude']
1060  || $backendUser->check('non_exclude_fields', 'tt_content:' . $hiddenField))
1061  ) {
1062  if ($row[$hiddenField]) {
1063  $value = 0;
1064  $label = 'unHide';
1065  } else {
1066  $value = 1;
1067  $label = 'hide';
1068  }
1069  $params = '&data[tt_content][' . ($row['_ORIG_uid'] ?: $row['uid'])
1070  . '][' . $hiddenField . ']=' . $value;
1071  $out .= '<a class="btn btn-default" href="' . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params))
1072  . '#element-tt_content-' . $row['uid'] . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL($label)) . '">'
1073  . $this->iconFactory->getIcon('actions-edit-' . strtolower($label), ‪Icon::SIZE_SMALL)->render() . '</a>';
1074  }
1075  // Delete
1076  $disableDelete = (bool)\trim(
1077  $backendUser->getTSConfig()['options.']['disableDelete.']['tt_content']
1078  ?? $backendUser->getTSConfig()['options.']['disableDelete']
1079  ?? '0'
1080  );
1081  if (!$disableDelete) {
1082  $params = '&cmd[tt_content][' . $row['uid'] . '][delete]=1';
1083  $refCountMsg = ‪BackendUtility::referenceCount(
1084  'tt_content',
1085  $row['uid'],
1086  ' ' . $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord'),
1087  (string)$this->‪getReferenceCount('tt_content', $row['uid'])
1089  'tt_content',
1090  $row['uid'],
1091  ' ' . $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord')
1092  );
1093  $confirm = $this->‪getLanguageService()->‪getLL('deleteWarning')
1094  . $refCountMsg;
1095  $out .= '<a class="btn btn-default t3js-modal-trigger" href="' . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params)) . '"'
1096  . ' data-severity="warning"'
1097  . ' data-title="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:label.confirm.delete_record.title')) . '"'
1098  . ' data-content="' . htmlspecialchars($confirm) . '" '
1099  . ' data-button-close-text="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel')) . '"'
1100  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('deleteItem')) . '">'
1101  . $this->iconFactory->getIcon('actions-edit-delete', ‪Icon::SIZE_SMALL)->render() . '</a>';
1102  if ($out && $this->‪hasContentModificationAndAccessPermissions()) {
1103  $out = '<div class="btn-group btn-group-sm" role="group">' . $out . '</div>';
1104  } else {
1105  $out = '';
1106  }
1107  }
1108  if (!$disableMoveAndNewButtons) {
1109  $moveButtonContent = '';
1110  $displayMoveButtons = false;
1111  // Move element up:
1112  if ($this->tt_contentData['prev'][$row['uid']]) {
1113  $params = '&cmd[tt_content][' . $row['uid'] . '][move]=' . $this->tt_contentData['prev'][$row['uid']];
1114  $moveButtonContent .= '<a class="btn btn-default" href="'
1115  . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params))
1116  . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('moveUp')) . '">'
1117  . $this->iconFactory->getIcon('actions-move-up', ‪Icon::SIZE_SMALL)->render() . '</a>';
1118  if (!$dragDropEnabled) {
1119  $displayMoveButtons = true;
1120  }
1121  } else {
1122  $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', ‪Icon::SIZE_SMALL)->render() . '</span>';
1123  }
1124  // Move element down:
1125  if ($this->tt_contentData['next'][$row['uid']]) {
1126  $params = '&cmd[tt_content][' . $row['uid'] . '][move]= ' . $this->tt_contentData['next'][$row['uid']];
1127  $moveButtonContent .= '<a class="btn btn-default" href="'
1128  . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params))
1129  . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('moveDown')) . '">'
1130  . $this->iconFactory->getIcon('actions-move-down', ‪Icon::SIZE_SMALL)->render() . '</a>';
1131  if (!$dragDropEnabled) {
1132  $displayMoveButtons = true;
1133  }
1134  } else {
1135  $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', ‪Icon::SIZE_SMALL)->render() . '</span>';
1136  }
1137  if ($displayMoveButtons) {
1138  $out .= '<div class="btn-group btn-group-sm" role="group">' . $moveButtonContent . '</div>';
1139  }
1140  }
1141  }
1142  $allowDragAndDrop = $this->‪isDragAndDropAllowed($row);
1143  $additionalIcons = [];
1144  $additionalIcons[] = $this->‪getIcon('tt_content', $row) . ' ';
1145  if ($langMode && isset($this->siteLanguages[(int)$row['sys_language_uid']])) {
1146  $additionalIcons[] = $this->‪renderLanguageFlag($this->siteLanguages[(int)$row['sys_language_uid']]);
1147  }
1148  // Get record locking status:
1149  if ($lockInfo = ‪BackendUtility::isRecordLocked('tt_content', $row['uid'])) {
1150  $additionalIcons[] = '<a href="#" data-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">'
1151  . $this->iconFactory->getIcon('warning-in-use', ‪Icon::SIZE_SMALL)->render() . '</a>';
1152  }
1153  // Call stats information hook
1154  $_params = ['tt_content', $row['uid'], &$row];
1155  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] ?? [] as $_funcRef) {
1156  $additionalIcons[] = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1157  }
1158 
1159  // Wrap the whole header
1160  // NOTE: end-tag for <div class="t3-page-ce-body"> is in getTable_tt_content()
1161  return '<div class="t3-page-ce-header ' . ($allowDragAndDrop ? 't3-page-ce-header-draggable t3js-page-ce-draghandle' : '') . '">
1162  <div class="t3-page-ce-header-icons-left">' . implode('', $additionalIcons) . '</div>
1163  <div class="t3-page-ce-header-icons-right">' . ($out ? '<div class="btn-toolbar">' . $out . '</div>' : '') . '</div>
1164  </div>
1165  <div class="t3-page-ce-body">';
1166  }
1167 
1176  protected function ‪getReferenceCount(string $tableName, int $uid): int
1177  {
1178  if (!isset($this->referenceCount[$tableName][$uid])) {
1179  $referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
1180  $numberOfReferences = $referenceIndex->getNumberOfReferencedRecords($tableName, $uid);
1181  $this->referenceCount[$tableName][$uid] = $numberOfReferences;
1182  }
1183  return $this->referenceCount[$tableName][$uid];
1184  }
1185 
1192  protected function ‪isDragAndDropAllowed(array $row)
1193  {
1194  if ((int)$row['l18n_parent'] === 0 &&
1195  (
1196  $this->‪getBackendUser()->isAdmin()
1197  || ((int)$row['editlock'] === 0 && (int)$this->pageinfo['editlock'] === 0)
1199  && $this->‪getBackendUser()->checkAuthMode('tt_content', 'CType', $row['CType'], ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
1200  )
1201  ) {
1202  return true;
1203  }
1204  return false;
1205  }
1206 
1214  public function ‪tt_content_drawItem($row)
1215  {
1216  $out = '';
1217  $outHeader = $this->‪renderContentElementHeader($row);
1218  $drawItem = true;
1219  // Hook: Render an own preview of a record
1220  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem'] ?? [] as $className) {
1221  $hookObject = GeneralUtility::makeInstance($className);
1222  if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) {
1223  throw new \UnexpectedValueException($className . ' must implement interface ' . PageLayoutViewDrawItemHookInterface::class, 1218547409);
1224  }
1225  $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row);
1226  }
1227 
1228  // If the previous hook did not render something,
1229  // then check if a Fluid-based preview template was defined for this CType
1230  // and render it via Fluid. Possible option:
1231  // mod.web_layout.tt_content.preview.media = EXT:site_mysite/Resources/Private/Templates/Preview/Media.html
1232  if ($drawItem) {
1233  $fluidPreview = $this->‪renderContentElementPreviewFromFluidTemplate($row);
1234  if ($fluidPreview !== null) {
1235  $out .= $fluidPreview;
1236  $drawItem = false;
1237  }
1238  }
1239 
1240  // Draw preview of the item depending on its CType (if not disabled by previous hook)
1241  if ($drawItem) {
1242  $out .= $this->‪renderContentElementPreview($row);
1243  }
1244  $out = $outHeader . '<span class="exampleContent">' . $out . '</span>';
1245  if ($this->‪isDisabled('tt_content', $row)) {
1246  return '<span class="text-muted">' . $out . '</span>';
1247  }
1248  return $out;
1249  }
1250 
1251  public function ‪renderContentElementHeader(array $row): string
1252  {
1253  $outHeader = '';
1254  // Make header:
1255  if ($row['header']) {
1256  $hiddenHeaderNote = '';
1257  // If header layout is set to 'hidden', display an accordant note:
1258  if ($row['header_layout'] == 100) {
1259  $hiddenHeaderNote = ' <em>[' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.hidden')) . ']</em>';
1260  }
1261  $outHeader = $row['date']
1262  ? htmlspecialchars($this->itemLabels['date'] . ' ' . ‪BackendUtility::date($row['date'])) . '<br />'
1263  : '';
1264  $outHeader .= '<strong>' . $this->‪linkEditContent($this->‪renderText($row['header']), $row)
1265  . $hiddenHeaderNote . '</strong><br />';
1266  }
1267  return $outHeader;
1268  }
1269 
1270  public function ‪renderContentElementPreviewFromFluidTemplate(array $row): ?string
1271  {
1272  $tsConfig = ‪BackendUtility::getPagesTSconfig($row['pid'])['mod.']['web_layout.']['tt_content.']['preview.'] ?? [];
1273  $fluidTemplateFile = '';
1274 
1275  if ($row['CType'] === 'list' && !empty($row['list_type'])
1276  && !empty($tsConfig['list.'][$row['list_type']])
1277  ) {
1278  $fluidTemplateFile = $tsConfig['list.'][$row['list_type']];
1279  } elseif (!empty($tsConfig[$row['CType']])) {
1280  $fluidTemplateFile = $tsConfig[$row['CType']];
1281  }
1282 
1283  if ($fluidTemplateFile) {
1284  $fluidTemplateFile = GeneralUtility::getFileAbsFileName($fluidTemplateFile);
1285  if ($fluidTemplateFile) {
1286  try {
1287  $view = GeneralUtility::makeInstance(StandaloneView::class);
1288  $view->setTemplatePathAndFilename($fluidTemplateFile);
1289  $view->assignMultiple($row);
1290  if (!empty($row['pi_flexform'])) {
1291  $flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
1292  $view->assign('pi_flexform_transformed', $flexFormService->convertFlexFormContentToArray($row['pi_flexform']));
1293  }
1294  return $view->render();
1295  } catch (\Exception $e) {
1296  $this->logger->warning(sprintf(
1297  'The backend preview for content element %d can not be rendered using the Fluid template file "%s": %s',
1298  $row['uid'],
1299  $fluidTemplateFile,
1300  $e->getMessage()
1301  ));
1302 
1303  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] && $this->‪getBackendUser()->isAdmin()) {
1304  $view = GeneralUtility::makeInstance(StandaloneView::class);
1305  $view->assign('error', [
1306  'message' => str_replace(‪Environment::getProjectPath(), '', $e->getMessage()),
1307  'title' => 'Error while rendering FluidTemplate preview using ' . str_replace(‪Environment::getProjectPath(), '', $fluidTemplateFile),
1308  ]);
1309  $view->setTemplateSource('<f:be.infobox title="{error.title}" state="2">{error.message}</f:be.infobox>');
1310  return $view->render();
1311  }
1312  }
1313  }
1314  }
1315  return null;
1316  }
1317 
1323  public function ‪renderContentElementPreview(array $row): string
1324  {
1325  $previewHtml = '';
1326  switch ($row['CType']) {
1327  case 'header':
1328  if ($row['subheader']) {
1329  $previewHtml = $this->‪linkEditContent($this->‪renderText($row['subheader']), $row) . '<br />';
1330  }
1331  break;
1332  case 'bullets':
1333  case 'table':
1334  if ($row['bodytext']) {
1335  $previewHtml = $this->‪linkEditContent($this->‪renderText($row['bodytext']), $row) . '<br />';
1336  }
1337  break;
1338  case 'uploads':
1339  if ($row['media']) {
1340  $previewHtml = $this->‪linkEditContent($this->‪getThumbCodeUnlinked($row, 'tt_content', 'media'), $row) . '<br />';
1341  }
1342  break;
1343  case 'shortcut':
1344  if (!empty($row['records'])) {
1345  $shortcutContent = [];
1346  $recordList = explode(',', $row['records']);
1347  foreach ($recordList as $recordIdentifier) {
1348  $split = ‪BackendUtility::splitTable_Uid($recordIdentifier);
1349  $tableName = empty($split[0]) ? 'tt_content' : $split[0];
1350  $shortcutRecord = ‪BackendUtility::getRecord($tableName, $split[1]);
1351  if (is_array($shortcutRecord)) {
1352  $icon = $this->iconFactory->getIconForRecord($tableName, $shortcutRecord, ‪Icon::SIZE_SMALL)->render();
1354  $icon,
1355  $tableName,
1356  $shortcutRecord['uid']
1357  );
1358  $shortcutContent[] = $icon
1359  . htmlspecialchars(‪BackendUtility::getRecordTitle($tableName, $shortcutRecord));
1360  }
1361  }
1362  $previewHtml = implode('<br />', $shortcutContent) . '<br />';
1363  }
1364  break;
1365  case 'list':
1366  $hookOut = '';
1367  $_params = ['pObj' => &$this, 'row' => $row];
1368  foreach (
1369  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']] ??
1370  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'] ??
1371  [] as $_funcRef
1372  ) {
1373  $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1374  }
1375  if ((string)$hookOut !== '') {
1376  $previewHtml = $hookOut;
1377  } elseif (!empty($row['list_type'])) {
1378  $label = ‪BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'list_type', $row['list_type']);
1379  if (!empty($label)) {
1380  $previewHtml = $this->‪linkEditContent('<strong>' . htmlspecialchars($this->‪getLanguageService()->sL($label)) . '</strong>', $row) . '<br />';
1381  } else {
1382  $message = sprintf($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'), $row['list_type']);
1383  $previewHtml = '<span class="label label-warning">' . htmlspecialchars($message) . '</span>';
1384  }
1385  } else {
1386  $previewHtml = '<strong>' . $this->‪getLanguageService()->‪getLL('noPluginSelected') . '</strong>';
1387  }
1388  $previewHtml .= htmlspecialchars($this->‪getLanguageService()->sL(
1389  ‪BackendUtility::getLabelFromItemlist('tt_content', 'pages', $row['pages'])
1390  )) . '<br />';
1391  break;
1392  default:
1393  $contentType = $this->CType_labels[$row['CType']];
1394  if (!isset($contentType)) {
1395  $contentType = ‪BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'CType', $row['CType']);
1396  }
1397 
1398  if ($contentType) {
1399  $previewHtml = $this->‪linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />';
1400  if ($row['bodytext']) {
1401  $previewHtml .= $this->‪linkEditContent($this->‪renderText($row['bodytext']), $row) . '<br />';
1402  }
1403  if ($row['image']) {
1404  $previewHtml .= $this->‪linkEditContent($this->‪getThumbCodeUnlinked($row, 'tt_content', 'image'), $row) . '<br />';
1405  }
1406  } else {
1407  $message = sprintf(
1408  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'),
1409  $row['CType']
1410  );
1411  $previewHtml = '<span class="label label-warning">' . htmlspecialchars($message) . '</span>';
1412  }
1413  }
1414  return $previewHtml;
1415  }
1416 
1427  public function ‪getNonTranslatedTTcontentUids($defaultLanguageUids, ‪$id, $lP)
1428  {
1429  if ($lP && !empty($defaultLanguageUids)) {
1430  // Select all translations here:
1431  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1432  ->getQueryBuilderForTable('tt_content');
1433  $queryBuilder->getRestrictions()
1434  ->removeAll()
1435  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1436  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
1437  $queryBuilder
1438  ->select('*')
1439  ->from('tt_content')
1440  ->where(
1441  $queryBuilder->expr()->eq(
1442  'sys_language_uid',
1443  $queryBuilder->createNamedParameter($lP, \PDO::PARAM_INT)
1444  ),
1445  $queryBuilder->expr()->in(
1446  'l18n_parent',
1447  $queryBuilder->createNamedParameter($defaultLanguageUids, Connection::PARAM_INT_ARRAY)
1448  )
1449  );
1450 
1451  $result = $queryBuilder->execute();
1452 
1453  // Flip uids:
1454  $defaultLanguageUids = array_flip($defaultLanguageUids);
1455  // Traverse any selected elements and unset original UID if any:
1456  while ($row = $result->fetch()) {
1457  ‪BackendUtility::workspaceOL('tt_content', $row);
1458  unset($defaultLanguageUids[$row['l18n_parent']]);
1459  }
1460  // Flip again:
1461  $defaultLanguageUids = array_keys($defaultLanguageUids);
1462  }
1463  return $defaultLanguageUids;
1464  }
1465 
1473  public function ‪newLanguageButton($defaultLanguageUids, $lP)
1474  {
1475  $lP = (int)$lP;
1476  if (!$this->doEdit || !$lP || !$this->‪hasContentModificationAndAccessPermissions()) {
1477  return '';
1478  }
1479  $theNewButton = '';
1480 
1481  $localizationTsConfig = ‪BackendUtility::getPagesTSconfig($this->id)['mod.']['web_layout.']['localization.'] ?? [];
1482  $allowCopy = (bool)($localizationTsConfig['enableCopy'] ?? true);
1483  $allowTranslate = (bool)($localizationTsConfig['enableTranslate'] ?? true);
1484  if (!empty($this->languageHasTranslationsCache[$lP])) {
1485  if (isset($this->languageHasTranslationsCache[$lP]['hasStandAloneContent'])) {
1486  $allowTranslate = false;
1487  }
1488  if (isset($this->languageHasTranslationsCache[$lP]['hasTranslations'])) {
1489  $allowCopy = $allowCopy && !$this->languageHasTranslationsCache[$lP]['hasTranslations'];
1490  }
1491  }
1492 
1493  if (isset($this->contentElementCache[$lP]) && is_array($this->contentElementCache[$lP])) {
1494  foreach ($this->contentElementCache[$lP] as $column => $records) {
1495  foreach ($records as $record) {
1496  $key = array_search($record['l10n_source'], $defaultLanguageUids);
1497  if ($key !== false) {
1498  unset($defaultLanguageUids[$key]);
1499  }
1500  }
1501  }
1502  }
1503 
1504  if (!empty($defaultLanguageUids)) {
1505  $theNewButton =
1506  '<a'
1507  . ' href="#"'
1508  . ' class="btn btn-default btn-sm t3js-localize disabled"'
1509  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('newPageContent_translate')) . '"'
1510  . ' data-page="' . htmlspecialchars($this->‪getLocalizedPageTitle()) . '"'
1511  . ' data-has-elements="' . (int)!empty($this->contentElementCache[$lP]) . '"'
1512  . ' data-allow-copy="' . (int)$allowCopy . '"'
1513  . ' data-allow-translate="' . (int)$allowTranslate . '"'
1514  . ' data-table="tt_content"'
1515  . ' data-page-id="' . (int)GeneralUtility::_GP('id') . '"'
1516  . ' data-language-id="' . $lP . '"'
1517  . ' data-language-name="' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '"'
1518  . '>'
1519  . $this->iconFactory->getIcon('actions-localize', ‪Icon::SIZE_SMALL)->render()
1520  . ' ' . htmlspecialchars($this->‪getLanguageService()->getLL('newPageContent_translate'))
1521  . '</a>';
1522  }
1523 
1524  return $theNewButton;
1525  }
1526 
1536  public function ‪linkEditContent($str, $row)
1537  {
1538  if ($this->doEdit
1540  && $this->‪getBackendUser()->recordEditAccessInternals('tt_content', $row)
1541  ) {
1542  $urlParameters = [
1543  'edit' => [
1544  'tt_content' => [
1545  $row['uid'] => 'edit'
1546  ]
1547  ],
1548  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid']
1549  ];
1550  $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1551  return '<a href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">' . $str . '</a>';
1552  }
1553  return $str;
1554  }
1555 
1565  public function ‪languageSelector(‪$id)
1566  {
1567  if (!$this->‪getBackendUser()->check('tables_modify', 'pages')) {
1568  return '';
1569  }
1570  ‪$id = (int)‪$id;
1571 
1572  // First, select all languages that are available for the current user
1573  $availableTranslations = [];
1574  foreach ($this->siteLanguages as $language) {
1575  if ($language->getLanguageId() <= 0) {
1576  continue;
1577  }
1578  $availableTranslations[$language->getLanguageId()] = $language->getTitle();
1579  }
1580 
1581  // Then, subtract the languages which are already on the page:
1582  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1583  $queryBuilder->getRestrictions()->removeAll()
1584  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1585  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->‪getBackendUser()->workspace));
1586  $queryBuilder->select('uid', ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'])
1587  ->from('pages')
1588  ->where(
1589  $queryBuilder->expr()->eq(
1590  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
1591  $queryBuilder->createNamedParameter(‪$id, \PDO::PARAM_INT)
1592  )
1593  );
1594  $statement = $queryBuilder->execute();
1595  while ($row = $statement->fetch()) {
1596  unset($availableTranslations[(int)$row[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']]]);
1597  }
1598  // If any languages are left, make selector:
1599  if (!empty($availableTranslations)) {
1600  ‪$output = '<option value="">' . htmlspecialchars($this->‪getLanguageService()->getLL('new_language')) . '</option>';
1601  foreach ($availableTranslations as $languageUid => $languageTitle) {
1602  // Build localize command URL to DataHandler (tce_db)
1603  // which redirects to FormEngine (record_edit)
1604  // which, when finished editing should return back to the current page (returnUrl)
1605  $parameters = [
1606  'justLocalized' => 'pages:' . ‪$id . ':' . $languageUid,
1607  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1608  ];
1609  $redirectUrl = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $parameters);
1611  '&cmd[pages][' . ‪$id . '][localize]=' . $languageUid,
1612  $redirectUrl
1613  );
1615  ‪$output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>';
1616  }
1617 
1618  return '<div class="form-inline form-inline-spaced">'
1619  . '<div class="form-group">'
1620  . '<select class="form-control input-sm" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">'
1621  . ‪$output
1622  . '</select></div></div>';
1623  }
1624  return '';
1625  }
1626 
1633  public function ‪getResult($result): array
1634  {
1635  ‪$output = [];
1636  // Traverse the result:
1637  while ($row = $result->fetch()) {
1638  ‪BackendUtility::workspaceOL('tt_content', $row, -99, true);
1639  if ($row) {
1640  // Add the row to the array:
1641  ‪$output[] = $row;
1642  }
1643  }
1645  // Return selected records
1646  return ‪$output;
1647  }
1648 
1649  /********************************
1650  *
1651  * Various helper functions
1652  *
1653  ********************************/
1654 
1662  protected function ‪initializeClipboard()
1663  {
1664  // Start clipboard
1665  $this->clipboard = GeneralUtility::makeInstance(Clipboard::class);
1667  // Initialize - reads the clipboard content from the user session
1668  $this->clipboard->initializeClipboard();
1669 
1670  // This locks the clipboard to the Normal for this request.
1671  $this->clipboard->lockToNormal();
1672 
1673  // Clean up pad
1674  $this->clipboard->cleanCurrent();
1675 
1676  // Save the clipboard content
1677  $this->clipboard->endClipboard();
1678  }
1679 
1685  protected function ‪generateTtContentDataArray(array $rowArray)
1686  {
1687  if (empty($this->tt_contentData)) {
1688  $this->tt_contentData = [
1689  'next' => [],
1690  'prev' => [],
1691  ];
1692  }
1693  foreach ($rowArray as $key => $value) {
1694  // Create information for next and previous content elements
1695  if (isset($rowArray[$key - 1])) {
1696  if (isset($rowArray[$key - 2])) {
1697  $this->tt_contentData['prev'][$value['uid']] = -$rowArray[$key - 2]['uid'];
1698  } else {
1699  $this->tt_contentData['prev'][$value['uid']] = $value['pid'];
1700  }
1701  $this->tt_contentData['next'][$rowArray[$key - 1]['uid']] = -$value['uid'];
1702  }
1703  }
1704  }
1705 
1712  public function ‪renderText($input)
1713  {
1714  $input = strip_tags($input);
1715  $input = GeneralUtility::fixed_lgd_cs($input, 1500);
1716  return nl2br(htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8', false));
1717  }
1718 
1726  public function ‪getIcon($table, $row)
1727  {
1728  // Initialization
1729  $toolTip = ‪BackendUtility::getRecordToolTip($row, $table);
1730  $icon = '<span ' . $toolTip . '>' . $this->iconFactory->getIconForRecord($table, $row, ‪Icon::SIZE_SMALL)->render() . '</span>';
1731  // The icon with link
1732  if ($this->‪getBackendUser()->recordEditAccessInternals($table, $row)) {
1733  $icon = ‪BackendUtility::wrapClickMenuOnIcon($icon, $table, $row['uid']);
1734  }
1735  return $icon;
1736  }
1737 
1747  public function ‪getProcessedValue($table, $fieldList, array $row, array &$info)
1748  {
1749  // Splitting values from $fieldList
1750  $fieldArr = explode(',', $fieldList);
1751  // Traverse fields from $fieldList
1752  foreach ($fieldArr as $field) {
1753  if ($row[$field]) {
1754  $info[] = '<strong>' . htmlspecialchars($this->itemLabels[$field]) . '</strong> '
1755  . htmlspecialchars(‪BackendUtility::getProcessedValue($table, $field, $row[$field]) ?? '');
1756  }
1757  }
1758  }
1759 
1767  public function ‪isDisabled($table, $row)
1768  {
1769  $enableCols = ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
1770  return $enableCols['disabled'] && $row[$enableCols['disabled']]
1771  || $enableCols['starttime'] && $row[$enableCols['starttime']] > ‪$GLOBALS['EXEC_TIME']
1772  || $enableCols['endtime'] && $row[$enableCols['endtime']] && $row[$enableCols['endtime']] < ‪$GLOBALS['EXEC_TIME'];
1773  }
1774 
1775  /*****************************************
1776  *
1777  * External renderings
1778  *
1779  *****************************************/
1780 
1789  public function ‪getThumbCodeUnlinked($row, $table, $field)
1790  {
1791  return ‪BackendUtility::thumbCode($row, $table, $field, '', '', null, 0, '', '', false);
1792  }
1793 
1802  protected function ‪checkIfTranslationsExistInLanguage(array $contentElements, int $language)
1803  {
1804  // If in default language, you may always create new entries
1805  // Also, you may override this strict behavior via user TS Config
1806  // If you do so, you're on your own and cannot rely on any support by the TYPO3 core
1807  // We jump out here since we don't need to do the expensive loop operations
1808  $allowInconsistentLanguageHandling = (bool)(‪BackendUtility::getPagesTSconfig($this->id)['mod.']['web_layout.']['allowInconsistentLanguageHandling'] ?? false);
1809  if ($language === 0 || $allowInconsistentLanguageHandling) {
1810  return false;
1811  }
1815  if (!isset($this->languageHasTranslationsCache[$language])) {
1816  foreach ($contentElements as $columns) {
1817  foreach ($columns as $contentElement) {
1818  if ((int)$contentElement['l18n_parent'] === 0) {
1819  $this->languageHasTranslationsCache[$language]['hasStandAloneContent'] = true;
1820  $this->languageHasTranslationsCache[$language]['mode'] = 'free';
1821  }
1822  if ((int)$contentElement['l18n_parent'] > 0) {
1823  $this->languageHasTranslationsCache[$language]['hasTranslations'] = true;
1824  $this->languageHasTranslationsCache[$language]['mode'] = 'connected';
1825  }
1826  }
1827  }
1828  if (!isset($this->languageHasTranslationsCache[$language])) {
1829  $this->languageHasTranslationsCache[$language]['hasTranslations'] = false;
1830  }
1831  // Check whether we have a mix of both
1832  if (isset($this->languageHasTranslationsCache[$language]['hasStandAloneContent'])
1833  && $this->languageHasTranslationsCache[$language]['hasTranslations']
1834  ) {
1835  $this->languageHasTranslationsCache[$language]['mode'] = 'mixed';
1836  $siteLanguage = $this->siteLanguages[$language];
1837  $message = GeneralUtility::makeInstance(
1838  FlashMessage::class,
1839  $this->‪getLanguageService()->getLL('staleTranslationWarning'),
1840  sprintf($this->‪getLanguageService()->getLL('staleTranslationWarningTitle'), $siteLanguage->getTitle()),
1842  );
1843  $service = GeneralUtility::makeInstance(FlashMessageService::class);
1844  $queue = $service->getMessageQueueByIdentifier();
1845  $queue->addMessage($message);
1846  }
1847  }
1848 
1849  return $this->languageHasTranslationsCache[$language]['hasTranslations'];
1850  }
1851 
1855  protected function ‪getBackendLayoutView()
1856  {
1857  return GeneralUtility::makeInstance(BackendLayoutView::class);
1858  }
1859 
1863  protected function ‪getBackendUser()
1864  {
1865  return ‪$GLOBALS['BE_USER'];
1866  }
1867 
1876  public function ‪thumbCode($row, $table, $field)
1877  {
1878  return ‪BackendUtility::thumbCode($row, $table, $field);
1879  }
1880 
1890  public function ‪getQueryBuilder(
1891  string $table,
1892  int $pageId,
1893  array $additionalConstraints = [],
1894  array ‪$fields = ['*']
1895  ): QueryBuilder {
1896  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1897  ->getQueryBuilderForTable($table);
1898  $queryBuilder->getRestrictions()
1899  ->removeAll()
1900  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1901  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->‪getBackendUser()->workspace));
1902  $queryBuilder
1903  ->select(...‪$fields)
1904  ->from($table);
1905 
1906  if (!empty($additionalConstraints)) {
1907  $queryBuilder->andWhere(...$additionalConstraints);
1908  }
1909 
1910  $queryBuilder = $this->‪prepareQueryBuilder($table, $pageId, ‪$fields, $additionalConstraints, $queryBuilder);
1911 
1912  return $queryBuilder;
1913  }
1914 
1926  protected function ‪prepareQueryBuilder(
1927  string $table,
1928  int $pageId,
1929  array $fieldList,
1930  array $additionalConstraints,
1931  QueryBuilder $queryBuilder
1932  ): QueryBuilder {
1933  $parameters = [
1934  'table' => $table,
1935  'fields' => $fieldList,
1936  'groupBy' => null,
1937  'orderBy' => null
1938  ];
1939 
1940  $sortBy = (string)(‪$GLOBALS['TCA'][$table]['ctrl']['sortby'] ?: ‪$GLOBALS['TCA'][$table]['ctrl']['default_sortby']);
1941  foreach (‪QueryHelper::parseOrderBy($sortBy) as $orderBy) {
1942  $queryBuilder->addOrderBy($orderBy[0], $orderBy[1]);
1943  }
1944 
1945  // Build the query constraints
1946  $queryBuilder->andWhere(
1947  $queryBuilder->expr()->eq(
1948  $table . '.pid',
1949  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
1950  )
1951  );
1952 
1953  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][PageLayoutView::class]['modifyQuery'] ?? [] as $className) {
1954  $hookObject = GeneralUtility::makeInstance($className);
1955  if (method_exists($hookObject, 'modifyQuery')) {
1956  $hookObject->modifyQuery(
1957  $parameters,
1958  $table,
1959  $pageId,
1960  $additionalConstraints,
1961  $fieldList,
1962  $queryBuilder
1963  );
1964  }
1965  }
1966 
1967  return $queryBuilder;
1968  }
1969 
1976  protected function ‪renderLanguageFlag(‪SiteLanguage $language)
1977  {
1978  $title = htmlspecialchars($language->‪getTitle());
1979  if ($language->‪getFlagIdentifier()) {
1980  $icon = $this->iconFactory->getIcon(
1981  $language->‪getFlagIdentifier(),
1983  )->render();
1984  return '<span title="' . $title . '" class="t3js-flag">' . $icon . '</span>&nbsp;<span class="t3js-language-title">' . $title . '</span>';
1985  }
1986  return $title;
1987  }
1988 
1995  protected function ‪resolveSiteLanguages(int $pageId)
1996  {
1997  try {
1998  $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageId);
1999  } catch (SiteNotFoundException $e) {
2000  $site = new NullSite();
2001  }
2002  $this->siteLanguages = $site->getAvailableLanguages($this->‪getBackendUser(), true, $pageId);
2003  }
2004 
2008  protected function ‪getLocalizedPageTitle(): string
2009  {
2010  if (($this->tt_contentConfig['sys_language_uid'] ?? 0) > 0) {
2011  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2012  ->getQueryBuilderForTable('pages');
2013  $queryBuilder->getRestrictions()
2014  ->removeAll()
2015  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2016  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->‪getBackendUser()->workspace));
2017  $localizedPage = $queryBuilder
2018  ->select('*')
2019  ->from('pages')
2020  ->where(
2021  $queryBuilder->expr()->eq(
2022  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
2023  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
2024  ),
2025  $queryBuilder->expr()->eq(
2026  ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'],
2027  $queryBuilder->createNamedParameter($this->tt_contentConfig['sys_language_uid'], \PDO::PARAM_INT)
2028  )
2029  )
2030  ->setMaxResults(1)
2031  ->execute()
2032  ->fetch();
2033  ‪BackendUtility::workspaceOL('pages', $localizedPage);
2034  return $localizedPage['title'];
2035  }
2036  return $this->pageinfo['title'];
2037  }
2038 
2044  protected function ‪isPageEditable()
2045  {
2046  if ($this->‪getBackendUser()->isAdmin()) {
2047  return true;
2048  }
2049  return !$this->pageinfo['editlock'] && $this->‪getBackendUser()->‪doesUserHaveAccess($this->pageinfo, ‪Permission::PAGE_EDIT);
2050  }
2051 
2058  protected function ‪isContentEditable(?int $languageId = null)
2059  {
2060  if ($this->‪getBackendUser()->isAdmin()) {
2061  return true;
2062  }
2063  return !$this->pageinfo['editlock']
2065  && ($languageId === null || $this->‪getBackendUser()->‪checkLanguageAccess($languageId));
2066  }
2067 
2073  protected function ‪hasContentModificationAndAccessPermissions(): bool
2074  {
2075  return $this->‪getBackendUser()->‪check('tables_modify', 'tt_content')
2077  }
2078 
2083  protected function ‪getLanguageService()
2084  {
2085  return ‪$GLOBALS['LANG'];
2086  }
2087 
2094  protected function ‪dispatchSectionMarkupGeneratedEvent(string $position, int $lP, array $columnConfig): string
2095  {
2096  if ($position === 'before') {
2097  $event = new BeforeSectionMarkupGeneratedEvent($this, $lP, $columnConfig);
2098  } else {
2099  $event = new AfterSectionMarkupGeneratedEvent($this, $lP, $columnConfig);
2100  }
2101 
2102  $this->eventDispatcher->dispatch($event);
2103  return $event->getContent();
2104  }
2105 }
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:30
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Backend\View\PageLayoutView\dispatchSectionMarkupGeneratedEvent
‪string dispatchSectionMarkupGeneratedEvent(string $position, int $lP, array $columnConfig)
Definition: PageLayoutView.php:2075
‪TYPO3\CMS\Backend\View\PageLayoutView\getIcon
‪string getIcon($table, $row)
Definition: PageLayoutView.php:1707
‪TYPO3\CMS\Backend\View\BackendLayoutView\getSelectedBackendLayout
‪array null getSelectedBackendLayout($pageId)
Definition: BackendLayoutView.php:334
‪TYPO3\CMS\Backend\View\PageLayoutView\$iconFactory
‪IconFactory $iconFactory
Definition: PageLayoutView.php:157
‪TYPO3\CMS\Backend\View\PageLayoutView\createFromPageLayoutContext
‪static PageLayoutView createFromPageLayoutContext(PageLayoutContext $context)
Definition: PageLayoutView.php:196
‪TYPO3\CMS\Backend\View\PageLayoutView\$localizationController
‪LocalizationController $localizationController
Definition: PageLayoutView.php:167
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordLocalization
‪static mixed getRecordLocalization($table, $uid, $language, $andWhereClause='')
Definition: BackendUtility.php:285
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLinkToDataHandlerAction
‪static string getLinkToDataHandlerAction($parameters, $redirectUrl='')
Definition: BackendUtility.php:2539
‪TYPO3\CMS\Backend\View\PageLayoutView\$id
‪int $id
Definition: PageLayoutView.php:124
‪TYPO3\CMS\Backend\View\PageLayoutView\$tt_contentData
‪array $tt_contentData
Definition: PageLayoutView.php:103
‪TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface
Definition: PageLayoutViewDrawItemHookInterface.php:23
‪TYPO3\CMS\Backend\View\PageLayoutView\$languageHasTranslationsCache
‪array $languageHasTranslationsCache
Definition: PageLayoutView.php:163
‪TYPO3\CMS\Backend\View\PageLayoutView\hasContentModificationAndAccessPermissions
‪bool hasContentModificationAndAccessPermissions()
Definition: PageLayoutView.php:2054
‪TYPO3\CMS\Backend\View\PageLayoutView\isDragAndDropAllowed
‪bool isDragAndDropAllowed(array $row)
Definition: PageLayoutView.php:1173
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:43
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪string eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:109
‪TYPO3\CMS\Backend\View\PageLayoutView\$defLangBinding
‪bool $defLangBinding
Definition: PageLayoutView.php:81
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:26
‪TYPO3\CMS\Backend\View\PageLayoutView\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: PageLayoutView.php:1844
‪TYPO3\CMS\Backend\View
Definition: ArrayBrowser.php:18
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:48
‪TYPO3\CMS\Backend\View\PageLayoutView\getQueryBuilder
‪TYPO3 CMS Core Database Query QueryBuilder getQueryBuilder(string $table, int $pageId, array $additionalConstraints=[], array $fields=[' *'])
Definition: PageLayoutView.php:1871
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getTitle
‪string getTitle()
Definition: SiteLanguage.php:222
‪TYPO3\CMS\Backend\Exception
Definition: Exception.php:24
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\createNamedParameter
‪string createNamedParameter($value, int $type=\PDO::PARAM_STR, string $placeHolder=null)
Definition: QueryBuilder.php:941
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface\removeAll
‪QueryRestrictionContainerInterface removeAll()
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:624
‪TYPO3\CMS\Core\Site\Entity\NullSite
Definition: NullSite.php:32
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:26
‪TYPO3\CMS\Backend\View\PageLayoutView\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: PageLayoutView.php:177
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawPasteIcon
‪string tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, $cssClass, $title)
Definition: PageLayoutView.php:952
‪TYPO3\CMS\Backend\View\PageLayoutView\initializeClipboard
‪initializeClipboard()
Definition: PageLayoutView.php:1643
‪TYPO3\CMS\Backend\View\PageLayoutView\renderLanguageFlag
‪string renderLanguageFlag(SiteLanguage $language)
Definition: PageLayoutView.php:1957
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\getRestrictions
‪QueryRestrictionContainerInterface getRestrictions()
Definition: QueryBuilder.php:104
‪TYPO3\CMS\Backend\Utility\BackendUtility\thumbCode
‪static string thumbCode( $row, $table, $field, $backPath='', $thumbScript='', $uploaddir=null, $abs=0, $tparams='', $size='', $linkInfoPopup=true)
Definition: BackendUtility.php:1137
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:33
‪TYPO3\CMS\Backend\View\PageLayoutView\getLanguageService
‪LanguageService getLanguageService()
Definition: PageLayoutView.php:2064
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:55
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:194
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:343
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Backend\View\PageLayoutView\$itemLabels
‪array $itemLabels
Definition: PageLayoutView.php:118
‪TYPO3\CMS\Backend\View\PageLayoutView\prepareQueryBuilder
‪QueryBuilder prepareQueryBuilder(string $table, int $pageId, array $fieldList, array $additionalConstraints, QueryBuilder $queryBuilder)
Definition: PageLayoutView.php:1907
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:24
‪TYPO3\CMS\Backend\View\PageLayoutView\renderContentElementHeader
‪renderContentElementHeader(array $row)
Definition: PageLayoutView.php:1232
‪TYPO3\CMS\Backend\View\PageLayoutView\getReferenceCount
‪int getReferenceCount(string $tableName, int $uid)
Definition: PageLayoutView.php:1157
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Core\Service\FlexFormService
Definition: FlexFormService.php:25
‪TYPO3\CMS\Backend\View\PageLayoutView\resolveSiteLanguages
‪resolveSiteLanguages(int $pageId)
Definition: PageLayoutView.php:1976
‪TYPO3\CMS\Backend\Utility\BackendUtility\translationCount
‪static string translationCount($table, $ref, $msg='')
Definition: BackendUtility.php:3361
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Backend\View\PageLayoutContext\getItemLabels
‪getItemLabels()
Definition: PageLayoutContext.php:250
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapClickMenuOnIcon
‪static string wrapClickMenuOnIcon( $content, $table, $uid=0, $context='', $_addParams='', $_enDisItems='', $returnTagParameters=false)
Definition: BackendUtility.php:2510
‪TYPO3\CMS\Backend\View\PageLayoutView\$uriBuilder
‪UriBuilder $uriBuilder
Definition: PageLayoutView.php:181
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Backend\View\PageLayoutView\languageSelector
‪string languageSelector($id)
Definition: PageLayoutView.php:1546
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:42
‪TYPO3\CMS\Core\Messaging\AbstractMessage\WARNING
‪const WARNING
Definition: AbstractMessage.php:30
‪TYPO3\CMS\Core\Core\Environment\getProjectPath
‪static string getProjectPath()
Definition: Environment.php:169
‪TYPO3\CMS\Backend\View\PageLayoutView\$clipboard
‪Clipboard $clipboard
Definition: PageLayoutView.php:140
‪TYPO3\CMS\Backend\View\PageLayoutView\isContentEditable
‪bool isContentEditable(?int $languageId=null)
Definition: PageLayoutView.php:2039
‪TYPO3\CMS\Backend\View\Event\AfterSectionMarkupGeneratedEvent
Definition: AfterSectionMarkupGeneratedEvent.php:25
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\andWhere
‪QueryBuilder andWhere(... $where)
Definition: QueryBuilder.php:694
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getFlagIdentifier
‪string getFlagIdentifier()
Definition: SiteLanguage.php:246
‪TYPO3\CMS\Backend\View\PageLayoutContext\getContentTypeLabels
‪getContentTypeLabels()
Definition: PageLayoutContext.php:240
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawFooter
‪string tt_content_drawFooter(array $row)
Definition: PageLayoutView.php:974
‪TYPO3\CMS\Backend\View\PageLayoutView\getBackendLayoutView
‪BackendLayoutView getBackendLayoutView()
Definition: PageLayoutView.php:1836
‪TYPO3\CMS\Backend\View\PageLayoutView\$CType_labels
‪array $CType_labels
Definition: PageLayoutView.php:112
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawHeader
‪string tt_content_drawHeader($row, $space=0, $disableMoveAndNewButtons=false, $langMode=false, $dragDropEnabled=false)
Definition: PageLayoutView.php:1017
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:38
‪TYPO3\CMS\Backend\View\PageLayoutView\isPageEditable
‪bool isPageEditable()
Definition: PageLayoutView.php:2025
‪TYPO3\CMS\Backend\View\PageLayoutContext\getPageRecord
‪getPageRecord()
Definition: PageLayoutContext.php:169
‪TYPO3\CMS\Backend\View\PageLayoutView\initialize
‪initialize()
Definition: PageLayoutView.php:222
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController
Definition: LocalizationController.php:42
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:330
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemListMerged
‪static string getLabelFromItemListMerged($pageId, $table, $column, $key)
Definition: BackendUtility.php:1434
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id)
Definition: BackendUtility.php:698
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordToolTip
‪static string getRecordToolTip(array $row, $table='pages')
Definition: BackendUtility.php:1339
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1541
‪TYPO3\CMS\Backend\View\PageLayoutView\generateLanguageView
‪string generateLanguageView(array $languageIds, array $defaultLanguageElementsByColumn, array $languageColumn, array $defLangBinding)
Definition: PageLayoutView.php:671
‪TYPO3\CMS\Backend\View\PageLayoutView\getTable_tt_content
‪string getTable_tt_content($id)
Definition: PageLayoutView.php:280
‪TYPO3\CMS\Backend\View\PageLayoutView\$option_newWizard
‪bool $option_newWizard
Definition: PageLayoutView.php:68
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:709
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\View\PageLayoutView\generateTtContentDataArray
‪generateTtContentDataArray(array $rowArray)
Definition: PageLayoutView.php:1666
‪TYPO3\CMS\Backend\View\PageLayoutView\getSelectedLanguages
‪int[] getSelectedLanguages()
Definition: PageLayoutView.php:261
‪TYPO3\CMS\Backend\View\PageLayoutView\renderContentElementPreviewFromFluidTemplate
‪renderContentElementPreviewFromFluidTemplate(array $row)
Definition: PageLayoutView.php:1251
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordWSOL
‪static array getRecordWSOL( $table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
Definition: BackendUtility.php:139
‪TYPO3\CMS\Backend\View\PageLayoutView\renderText
‪string renderText($input)
Definition: PageLayoutView.php:1693
‪TYPO3\CMS\Backend\View\PageLayoutView\getNonTranslatedTTcontentUids
‪array getNonTranslatedTTcontentUids($defaultLanguageUids, $id, $lP)
Definition: PageLayoutView.php:1408
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:24
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array false readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:597
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Backend\View\PageLayoutView\newLanguageButton
‪string newLanguageButton($defaultLanguageUids, $lP)
Definition: PageLayoutView.php:1454
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2359
‪TYPO3\CMS\Backend\Utility\BackendUtility\getProcessedValue
‪static string null getProcessedValue( $table, $col, $value, $fixed_lgd_chars=0, $defaultPassthrough=false, $noRecordLookup=false, $uid=0, $forceResult=true, $pid=0)
Definition: BackendUtility.php:1664
‪TYPO3\CMS\Backend\View\PageLayoutView\getLocalizedPageTitle
‪string getLocalizedPageTitle()
Definition: PageLayoutView.php:1989
‪TYPO3\CMS\Backend\View\PageLayoutView\__construct
‪__construct(EventDispatcherInterface $eventDispatcher)
Definition: PageLayoutView.php:183
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:92
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:24
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:34
‪TYPO3\CMS\Backend\View\PageLayoutView\getResult
‪array getResult($result)
Definition: PageLayoutView.php:1614
‪TYPO3\CMS\Core\Type\Bitmask\Permission\CONTENT_EDIT
‪const CONTENT_EDIT
Definition: Permission.php:53
‪TYPO3\CMS\Backend\View\PageLayoutView\$pageRecord
‪string[] $pageRecord
Definition: PageLayoutView.php:130
‪TYPO3\CMS\Backend\View\PageLayoutView\getProcessedValue
‪getProcessedValue($table, $fieldList, array $row, array &$info)
Definition: PageLayoutView.php:1728
‪TYPO3\CMS\Backend\View\BackendLayoutView
Definition: BackendLayoutView.php:36
‪TYPO3\CMS\Backend\View\PageLayoutView\renderContentElementPreview
‪string renderContentElementPreview(array $row)
Definition: PageLayoutView.php:1304
‪$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:3586
‪TYPO3\CMS\Backend\View\PageLayoutContext
Definition: PageLayoutContext.php:43
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Backend\View\PageLayoutContext\getPageId
‪getPageId()
Definition: PageLayoutContext.php:174
‪TYPO3\CMS\Backend\View\PageLayoutView
Definition: PageLayoutView.php:61
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Backend\View\PageLayoutView\linkEditContent
‪string linkEditContent($str, $row)
Definition: PageLayoutView.php:1517
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_EDIT
‪const PAGE_EDIT
Definition: Permission.php:38
‪TYPO3\CMS\Backend\View\PageLayoutView\$siteLanguages
‪SiteLanguage[] $siteLanguages
Definition: PageLayoutView.php:136
‪TYPO3\CMS\Backend\View\PageLayoutView\$tt_contentConfig
‪array $tt_contentConfig
Definition: PageLayoutView.php:87
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemlist
‪static string getLabelFromItemlist($table, $col, $key)
Definition: BackendUtility.php:1410
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:988
‪TYPO3\CMS\Backend\View\PageLayoutView\getThumbCodeUnlinked
‪string getThumbCodeUnlinked($row, $table, $field)
Definition: PageLayoutView.php:1770
‪TYPO3\CMS\Backend\View\Event\BeforeSectionMarkupGeneratedEvent
Definition: BeforeSectionMarkupGeneratedEvent.php:25
‪TYPO3\CMS\Backend\View\PageLayoutView\$referenceCount
‪array $referenceCount
Definition: PageLayoutView.php:173
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Backend\View\PageLayoutView\checkIfTranslationsExistInLanguage
‪bool checkIfTranslationsExistInLanguage(array $contentElements, int $language)
Definition: PageLayoutView.php:1783
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\addOrderBy
‪QueryBuilder addOrderBy(string $fieldName, string $order=null)
Definition: QueryBuilder.php:856
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface\add
‪QueryRestrictionContainerInterface add(QueryRestrictionInterface $restriction)
‪TYPO3\CMS\Backend\View\PageLayoutContext\getDrawingConfiguration
‪getDrawingConfiguration()
Definition: PageLayoutContext.php:154
‪TYPO3\CMS\Backend\View\PageLayoutView\thumbCode
‪string thumbCode($row, $table, $field)
Definition: PageLayoutView.php:1857
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:154
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Backend\Utility\BackendUtility\date
‪static string date($tstamp)
Definition: BackendUtility.php:978
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawItem
‪string tt_content_drawItem($row)
Definition: PageLayoutView.php:1195
‪TYPO3\CMS\Backend\View\PageLayoutView\$contentElementCache
‪array $contentElementCache
Definition: PageLayoutView.php:153
‪TYPO3\CMS\Backend\View\PageLayoutView\$doEdit
‪bool $doEdit
Definition: PageLayoutView.php:74
‪$icons
‪$icons
Definition: ext_localconf.php:54
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\expr
‪ExpressionBuilder expr()
Definition: QueryBuilder.php:151
‪TYPO3\CMS\Backend\Utility\BackendUtility\splitTable_Uid
‪static array splitTable_Uid($str)
Definition: BackendUtility.php:208
‪TYPO3\CMS\Backend\View\PageLayoutView\getContentRecordsPerColumn
‪array getContentRecordsPerColumn($table, $id, array $columns, $additionalWhereClause='')
Definition: PageLayoutView.php:880
‪TYPO3\CMS\Backend\Utility\BackendUtility\referenceCount
‪static string int referenceCount($table, $ref, $msg='', $count=null)
Definition: BackendUtility.php:3311
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRecordLocked
‪static array bool isRecordLocked($table, $uid)
Definition: BackendUtility.php:3011
‪TYPO3\CMS\Backend\View\PageLayoutView\$pageinfo
‪array $pageinfo
Definition: PageLayoutView.php:146
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawColHeader
‪string tt_content_drawColHeader($colName, $editParams='')
Definition: PageLayoutView.php:924
‪TYPO3\CMS\Backend\View\PageLayoutView\isDisabled
‪bool isDisabled($table, $row)
Definition: PageLayoutView.php:1748
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39