‪TYPO3CMS  9.5
PageLayoutView.php
Go to the documentation of this file.
1 <?php
2 
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Doctrine\DBAL\Driver\Statement;
19 use Psr\Log\LoggerAwareInterface;
20 use Psr\Log\LoggerAwareTrait;
55 
60 class ‪PageLayoutView implements LoggerAwareInterface
61 {
62  use LoggerAwareTrait;
63 
69  public ‪$pI_showUser = false;
70 
76  public ‪$nextThree = 3;
77 
83  public ‪$pages_noEditColumns = false;
84 
90  public ‪$option_newWizard = true;
91 
97  public ‪$ext_function = 0;
98 
104  public ‪$doEdit = true;
105 
111  public ‪$agePrefixes = ' min| hrs| days| yrs| min| hour| day| year';
112 
118  public ‪$externalTables = [];
119 
125  public ‪$descrTable;
126 
133  public ‪$defLangBinding = false;
134 
140  public ‪$tt_contentConfig = [
141  // Boolean: Display info-marks or not
142  'showInfo' => 1,
143  // Boolean: Display up/down arrows and edit icons for tt_content records
144  'showCommands' => 1,
145  'languageCols' => 0,
146  'languageMode' => 0,
147  'languageColsPointer' => 0,
148  'showHidden' => 1,
149  // Displays hidden records as well
150  'sys_language_uid' => 0,
151  // Which language
152  'cols' => '1,0,2,3',
153  'activeCols' => '1,0,2,3'
154  // Which columns can be accessed by current BE user
155  ];
156 
162  public ‪$activeTables = [];
163 
167  public ‪$tt_contentData = [
168  'nextThree' => [],
169  'prev' => [],
170  'next' => []
171  ];
172 
178  public ‪$CType_labels = [];
179 
185  public ‪$itemLabels = [];
186 
192  public ‪$allFields = 0;
193 
199  public ‪$showLimit = 0;
200 
207 
213  public ‪$hideTables = '';
214 
220  public ‪$displayFields;
221 
227  public ‪$hideTranslations = '';
228 
234  public ‪$csvOutput = false;
235 
241  public ‪$recPath_cache = [];
242 
249 
255  public ‪$itemsLimitPerTable = 20;
256 
262  public ‪$perms_clause = '';
263 
269  public ‪$id;
270 
276  public ‪$returnUrl = '';
277 
283  public ‪$table = '';
284 
290  public ‪$calcPerms = 0;
291 
297  public ‪$clickTitleMode = '';
298 
304  public ‪$searchLevels = '';
305 
311  public ‪$iLimit = 0;
312 
318  public ‪$totalItems = '';
319 
325  public ‪$tableTSconfigOverTCA = [];
326 
332  public ‪$pageRecord = [];
333 
339  public ‪$duplicateStack = [];
340 
346  public ‪$setFields = [];
347 
353  public ‪$script = 'index.php';
354 
360  public ‪$listOnlyInSingleTableMode = false;
361 
367  public ‪$JScode = '';
368 
375 
381  public ‪$eCounter = 0;
382 
388  public ‪$searchString = '';
389 
395  public ‪$itemsLimitSingleTable = 100;
396 
402  public ‪$sortRev;
403 
409  public ‪$duplicateField;
410 
416  public ‪$tableList = '';
417 
423  public ‪$tablesCollapsed = [];
424 
428  public ‪$modTSconfig;
429 
435  public ‪$HTMLcode = '';
436 
442  public ‪$thumbs = 0;
443 
449  public ‪$currentTable = [];
450 
456  public ‪$leftMargin = 0;
457 
463  public ‪$fieldArray = [];
464 
470  public ‪$setLMargin = 1;
471 
477  public ‪$pageOverlays = [];
478 
484  public ‪$counter = 0;
485 
492  public ‪$languageIconTitles = [];
493 
499  protected ‪$siteLanguages = [];
500 
506  public ‪$thisScript = '';
507 
513  public ‪$oddColumnsCssClass = '';
514 
521  public ‪$fixedL = 30;
522 
527  public ‪$translateTools;
528 
534  public ‪$addElement_tdParams = [];
535 
539  public ‪$no_noWrap = 0;
540 
544  public ‪$showIcon = 1;
545 
551  public ‪$addElement_tdCssClass = [];
552 
556  protected ‪$clipboard;
557 
563  public ‪$ext_CALC_PERMS;
564 
570  protected ‪$pageinfo;
571 
577  protected ‪$languagesInColumnCache = [];
578 
585  protected ‪$contentElementCache = [];
586 
590  protected ‪$iconFactory;
591 
597  protected ‪$languageHasTranslationsCache = [];
598 
602  protected ‪$localizationController;
603 
609  protected ‪$overridePageIdList = [];
610 
616  protected ‪$overrideUrlParameters = [];
617 
627  protected ‪$tableDisplayOrder = [];
628 
634  protected ‪$referenceCount = [];
635 
639  public function ‪__construct()
640  {
641  if (isset(‪$GLOBALS['BE_USER']->uc['titleLen']) && ‪$GLOBALS['BE_USER']->uc['titleLen'] > 0) {
642  $this->fixedL = ‪$GLOBALS['BE_USER']->uc['titleLen'];
643  }
644  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
645  // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Remove this instance along with the property.
646  $this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
647  $this->‪determineScriptUrl();
648  $this->localizationController = GeneralUtility::makeInstance(LocalizationController::class);
649  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
650  $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
651  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
652  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Localization');
653  }
654 
655  /*****************************************
656  *
657  * Renderings
658  *
659  *****************************************/
668  public function ‪getTable(‪$table, ‪$id, ‪$fields = '')
669  {
670  if (isset($this->externalTables[‪$table])) {
671  return $this->‪getExternalTables($id, ‪$table);
672  }
673  // Branch out based on table name:
674  switch (‪$table) {
675  case 'pages':
676  return $this->‪getTable_pages($id);
677  case 'tt_content':
678  return $this->‪getTable_tt_content($id);
679  default:
680  return '';
681  }
682  }
683 
691  public function ‪getExternalTables(‪$id, ‪$table)
692  {
693  $this->pageinfo = ‪BackendUtility::readPageAccess(‪$id, '');
694  $type = $this->‪getPageLayoutController()->MOD_SETTINGS[‪$table];
695  if (!isset($type)) {
696  $type = 0;
697  }
698  // eg. "name;title;email;company,image"
699  $fList = $this->externalTables[‪$table][$type]['fList'];
700  // The columns are separeted by comma ','.
701  // Values separated by semicolon ';' are shown in the same column.
702  $icon = $this->externalTables[‪$table][$type]['icon'];
703  $addWhere = $this->externalTables[‪$table][$type]['addWhere'];
704  // Create listing
705  $out = $this->‪makeOrdinaryList($table, ‪$id, $fList, $icon, $addWhere);
706  return $out;
707  }
708 
716  public function ‪getTable_pages(‪$id)
717  {
718  // Initializing:
719  $out = '';
720  $lang = $this->‪getLanguageService();
721  // Select current page:
722  if (!$id) {
723  // The root has a pseudo record in pageinfo...
724  $row = $this->‪getPageLayoutController()->pageinfo;
725  } else {
726  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
727  ->getQueryBuilderForTable('pages');
728  $queryBuilder->getRestrictions()
729  ->removeAll()
730  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
731  $row = $queryBuilder
732  ->select('*')
733  ->from('pages')
734  ->where(
735  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(‪$id, \PDO::PARAM_INT)),
736  $this->getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW)
737  )
738  ->execute()
739  ->fetch();
740  ‪BackendUtility::workspaceOL('pages', $row);
741  }
742  // If there was found a page:
743  if (is_array($row)) {
744  // Getting select-depth:
745  $depth = (int)$this->‪getPageLayoutController()->MOD_SETTINGS['pages_levels'];
746  // Overriding a few things:
747  $this->no_noWrap = 0;
748  // Items
749  $this->eCounter = ‪$this->firstElementNumber;
750  // Creating elements:
751  list($flag, $code) = $this->‪fwd_rwd_nav();
752  $out .= $code;
753  $editUids = [];
754  if ($flag) {
755  // Getting children:
756  $theRows = $this->‪getPageRecordsRecursive($row['uid'], $depth);
757  if ($this->‪getBackendUser()->doesUserHaveAccess($row, 2) && $row['uid'] > 0) {
758  $editUids[] = $row['uid'];
759  }
760  $out .= $this->‪pages_drawItem($row, $this->fieldArray);
761  // Traverse all pages selected:
762  foreach ($theRows as $sRow) {
763  if ($this->‪getBackendUser()->doesUserHaveAccess($sRow, 2)) {
764  $editUids[] = $sRow['uid'];
765  }
766  $out .= $this->‪pages_drawItem($sRow, $this->fieldArray);
767  }
768  $this->eCounter++;
769  }
770  // Header line is drawn
771  $theData = [];
772  $editIdList = implode(',', $editUids);
773  // Traverse fields (as set above) in order to create header values:
774  foreach ($this->fieldArray as $field) {
775  if ($editIdList
776  && isset(‪$GLOBALS['TCA']['pages']['columns'][$field])
777  && $field !== 'uid'
778  && !$this->pages_noEditColumns
779  ) {
780  $iTitle = sprintf(
781  $lang->getLL('editThisColumn'),
782  rtrim(trim($lang->sL(‪BackendUtility::getItemLabel('pages', $field))), ':')
783  );
784  $urlParameters = [
785  'edit' => [
786  'pages' => [
787  $editIdList => 'edit'
788  ]
789  ],
790  'columnsOnly' => $field,
791  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
792  ];
793  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
794  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
795  $eI = '<a class="btn btn-default" href="' . htmlspecialchars($url)
796  . '" title="' . htmlspecialchars($iTitle) . '">'
797  . $this->iconFactory->getIcon('actions-document-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
798  } else {
799  $eI = '';
800  }
801  switch ($field) {
802  case 'title':
803  $theData[$field] = $eI . '&nbsp;<strong>'
804  . $lang->sL(‪$GLOBALS['TCA']['pages']['columns'][$field]['label'])
805  . '</strong>';
806  break;
807  case 'uid':
808  $theData[$field] = '';
809  break;
810  default:
811  if (strpos($field, 'table_') === 0) {
812  $f2 = substr($field, 6);
813  if (‪$GLOBALS['TCA'][$f2]) {
814  $theData[$field] = '&nbsp;' .
815  '<span title="' .
816  htmlspecialchars($lang->sL(‪$GLOBALS['TCA'][$f2]['ctrl']['title'])) .
817  '">' .
818  $this->iconFactory->getIconForRecord($f2, [], ‪Icon::SIZE_SMALL)->render() .
819  '</span>';
820  }
821  } else {
822  $theData[$field] = $eI . '&nbsp;<strong>'
823  . htmlspecialchars($lang->sL(‪$GLOBALS['TCA']['pages']['columns'][$field]['label']))
824  . '</strong>';
825  }
826  }
827  }
828  $out = '<div class="table-fit">'
829  . '<table class="table table-striped table-hover typo3-page-pages">'
830  . '<thead>'
831  . $this->‪addElement(1, '', $theData)
832  . '</thead>'
833  . '<tbody>'
834  . $out
835  . '</tbody>'
836  . '</table>'
837  . '</div>';
838  }
839  return $out;
840  }
841 
848  public function ‪getTable_tt_content(‪$id)
849  {
850  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
851  ->getConnectionForTable('tt_content')
852  ->getExpressionBuilder();
853  $this->pageinfo = ‪BackendUtility::readPageAccess($this->id, '');
854  $this->‪initializeLanguages();
855  $this->‪initializeClipboard();
856  $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode(‪BackendUtility::getRecordTitle('pages', ‪BackendUtility::getRecordWSOL('pages', ‪$id), true));
858  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
859  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/DragDrop');
860  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
861  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/Paste');
862  $pageActionsCallback = null;
863  if ($this->‪isPageEditable()) {
864  $languageOverlayId = 0;
865  $pageLocalizationRecord = ‪BackendUtility::getRecordLocalization('pages', $this->id, (int)$this->tt_contentConfig['sys_language_uid']);
866  if (is_array($pageLocalizationRecord)) {
867  $pageLocalizationRecord = reset($pageLocalizationRecord);
868  }
869  if (!empty($pageLocalizationRecord['uid'])) {
870  $languageOverlayId = $pageLocalizationRecord['uid'];
871  }
872  $pageActionsCallback = 'function(PageActions) {
873  PageActions.setPageId(' . (int)$this->id . ');
874  PageActions.setLanguageOverlayId(' . $languageOverlayId . ');
875  }';
876  }
877  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', $pageActionsCallback);
878  // Get labels for CTypes and tt_content element fields in general:
879  $this->CType_labels = [];
880  foreach (‪$GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) {
881  $this->CType_labels[$val[1]] = $this->‪getLanguageService()->‪sL($val[0]);
882  }
883 
884  $this->itemLabels = [];
885  foreach (‪$GLOBALS['TCA']['tt_content']['columns'] as $name => $val) {
886  $this->itemLabels[$name] = $this->‪getLanguageService()->‪sL($val['label']);
887  }
888  $languageColumn = [];
889  $out = '';
890 
891  // Setting language list:
892  $langList = $this->tt_contentConfig['sys_language_uid'];
893  if ($this->tt_contentConfig['languageMode']) {
894  if ($this->tt_contentConfig['languageColsPointer']) {
895  $langList = '0,' . $this->tt_contentConfig['languageColsPointer'];
896  } else {
897  $langList = implode(',', array_keys($this->tt_contentConfig['languageCols']));
898  }
899  $languageColumn = [];
900  }
901  $langListArr = GeneralUtility::intExplode(',', $langList);
902  $defaultLanguageElementsByColumn = [];
903  ‪$defLangBinding = [];
904  // For each languages... :
905  // If not languageMode, then we'll only be through this once.
906  foreach ($langListArr as $lP) {
907  $lP = (int)$lP;
908 
909  if (!isset($this->contentElementCache[$lP])) {
910  $this->contentElementCache[$lP] = [];
911  }
912 
913  if (count($langListArr) === 1 || $lP === 0) {
914  $showLanguage = $expressionBuilder->in('sys_language_uid', [$lP, -1]);
915  } else {
916  $showLanguage = $expressionBuilder->eq('sys_language_uid', $lP);
917  }
918  $content = [];
919  $head = [];
920 
921  $backendLayout = $this->‪getBackendLayoutView()->‪getSelectedBackendLayout($this->id);
922  $columns = $backendLayout['__colPosList'];
923  // Select content records per column
924  $contentRecordsPerColumn = $this->‪getContentRecordsPerColumn('table', $id, $columns, $showLanguage);
925  $cList = array_keys($contentRecordsPerColumn);
926  // For each column, render the content into a variable:
927  foreach ($cList as $columnId) {
928  if (!isset($this->contentElementCache[$lP])) {
929  $this->contentElementCache[$lP] = [];
930  }
931 
932  if (!$lP) {
933  $defaultLanguageElementsByColumn[$columnId] = [];
934  }
935 
936  // Start wrapping div
937  $content[$columnId] .= '<div data-colpos="' . $columnId . '" data-language-uid="' . $lP . '" class="t3js-sortable t3js-sortable-lang t3js-sortable-lang-' . $lP . ' t3-page-ce-wrapper';
938  if (empty($contentRecordsPerColumn[$columnId])) {
939  $content[$columnId] .= ' t3-page-ce-empty';
940  }
941  $content[$columnId] .= '">';
942  // Add new content at the top most position
943  $link = '';
944  if ($this->‪isContentEditable()
945  && (!$this->‪checkIfTranslationsExistInLanguage($contentRecordsPerColumn, $lP))
946  ) {
947  if ($this->option_newWizard) {
948  $urlParameters = [
949  'id' => ‪$id,
950  'sys_language_uid' => $lP,
951  'colPos' => $columnId,
952  'uid_pid' => ‪$id,
953  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
954  ];
955  $routeName = ‪BackendUtility::getPagesTSconfig(‪$id)['mod.']['newContentElementWizard.']['override']
956  ?? 'new_content_element_wizard';
957  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
958  $url = (string)$uriBuilder->buildUriFromRoute($routeName, $urlParameters);
959  } else {
960  $urlParameters = [
961  'edit' => [
962  'tt_content' => [
963  ‪$id => 'new'
964  ]
965  ],
966  'defVals' => [
967  'tt_content' => [
968  'colPos' => $columnId,
969  'sys_language_uid' => $lP
970  ]
971  ],
972  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
973  ];
974  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
975  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
976  }
977  $title = htmlspecialchars($this->‪getLanguageService()->getLL('newContentElement'));
978  $link = '<a href="' . htmlspecialchars($url) . '" '
979  . 'title="' . $title . '"'
980  . 'data-title="' . $title . '"'
981  . 'class="btn btn-default btn-sm ' . ($this->option_newWizard ? 't3js-toggle-new-content-element-wizard disabled' : '') . '">'
982  . $this->iconFactory->getIcon('actions-add', ‪Icon::SIZE_SMALL)->render()
983  . ' '
984  . htmlspecialchars($this->‪getLanguageService()->getLL('content')) . '</a>';
985  }
986  if ($this->‪getBackendUser()->checkLanguageAccess($lP) && $columnId !== 'unused') {
987  $content[$columnId] .= '
988  <div class="t3-page-ce t3js-page-ce" data-page="' . (int)‪$id . '" id="' . ‪StringUtility::getUniqueId() . '">
989  <div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $columnId . '-' . 'page-' . ‪$id . '-' . ‪StringUtility::getUniqueId() . '">'
990  . $link
991  . '</div>
992  <div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div>
993  </div>
994  ';
995  }
996  $editUidList = '';
997  if (!isset($contentRecordsPerColumn[$columnId]) || !is_array($contentRecordsPerColumn[$columnId])) {
998  $message = GeneralUtility::makeInstance(
999  FlashMessage::class,
1000  $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:error.invalidBackendLayout'),
1001  '',
1003  );
1004  $service = GeneralUtility::makeInstance(FlashMessageService::class);
1005  $queue = $service->getMessageQueueByIdentifier();
1006  $queue->addMessage($message);
1007  } else {
1008  $rowArr = $contentRecordsPerColumn[$columnId];
1009  $this->‪generateTtContentDataArray($rowArr);
1010 
1011  foreach ((array)$rowArr as $rKey => $row) {
1012  $this->contentElementCache[$lP][$columnId][$row['uid']] = $row;
1013  if ($this->tt_contentConfig['languageMode']) {
1014  $languageColumn[$columnId][$lP] = $head[$columnId] . $content[$columnId];
1015  }
1016  if (is_array($row) && !‪VersionState::cast($row['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)) {
1017  $singleElementHTML = '<div class="t3-page-ce-dragitem" id="' . ‪StringUtility::getUniqueId() . '">';
1018  if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) {
1019  $defaultLanguageElementsByColumn[$columnId][] = ($row['_ORIG_uid'] ?? $row['uid']);
1020  }
1021  $editUidList .= $row['uid'] . ',';
1022  $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0 && $this->‪checkIfTranslationsExistInLanguage($contentRecordsPerColumn, $lP);
1023  $singleElementHTML .= $this->‪tt_content_drawHeader(
1024  $row,
1025  $this->tt_contentConfig['showInfo'] ? 15 : 5,
1026  $disableMoveAndNewButtons,
1027  true,
1028  $this->‪getBackendUser()->doesUserHaveAccess($this->pageinfo, ‪Permission::CONTENT_EDIT)
1029  );
1030  $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>'
1031  . $this->‪tt_content_drawItem($row) . '</div>';
1032  $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div></div>'
1033  . $this->‪tt_content_drawFooter($row);
1034  $isDisabled = $this->‪isDisabled('tt_content', $row);
1035  $statusHidden = $isDisabled ? ' t3-page-ce-hidden t3js-hidden-record' : '';
1036  $displayNone = !$this->tt_contentConfig['showHidden'] && $isDisabled ? ' style="display: none;"' : '';
1037  $highlightHeader = '';
1038  if ($this->‪checkIfTranslationsExistInLanguage([], (int)$row['sys_language_uid']) && (int)$row['l18n_parent'] === 0) {
1039  $highlightHeader = ' t3-page-ce-danger';
1040  } elseif ($columnId === 'unused') {
1041  $highlightHeader = ' t3-page-ce-warning';
1042  }
1043  $singleElementHTML = '<div class="t3-page-ce' . $highlightHeader . ' t3js-page-ce t3js-page-ce-sortable ' . $statusHidden . '" id="element-tt_content-'
1044  . $row['uid'] . '" data-table="tt_content" data-uid="' . $row['uid'] . '"' . $displayNone . '>' . $singleElementHTML . '</div>';
1045 
1046  $singleElementHTML .= '<div class="t3-page-ce" data-colpos="' . $columnId . '">';
1047  $singleElementHTML .= '<div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $columnId . '-' . 'page-' . ‪$id .
1048  '-' . ‪StringUtility::getUniqueId() . '">';
1049  // Add icon "new content element below"
1050  if (!$disableMoveAndNewButtons
1051  && $this->‪isContentEditable($lP)
1052  && (!$this->‪checkIfTranslationsExistInLanguage($contentRecordsPerColumn, $lP))
1053  && $columnId !== 'unused'
1054  ) {
1055  // New content element:
1056  if ($this->option_newWizard) {
1057  $urlParameters = [
1058  'id' => $row['pid'],
1059  'sys_language_uid' => $row['sys_language_uid'],
1060  'colPos' => $row['colPos'],
1061  'uid_pid' => -$row['uid'],
1062  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1063  ];
1064  $routeName = ‪BackendUtility::getPagesTSconfig($row['pid'])['mod.']['newContentElementWizard.']['override']
1065  ?? 'new_content_element_wizard';
1066  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1067  $url = (string)$uriBuilder->buildUriFromRoute($routeName, $urlParameters);
1068  } else {
1069  $urlParameters = [
1070  'edit' => [
1071  'tt_content' => [
1072  -$row['uid'] => 'new'
1073  ]
1074  ],
1075  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1076  ];
1077  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1078  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1079  }
1080  $title = htmlspecialchars($this->‪getLanguageService()->getLL('newContentElement'));
1081  $singleElementHTML .= '<a href="' . htmlspecialchars($url) . '" '
1082  . 'title="' . $title . '"'
1083  . 'data-title="' . $title . '"'
1084  . 'class="btn btn-default btn-sm ' . ($this->option_newWizard ? 't3js-toggle-new-content-element-wizard disabled' : '') . '">'
1085  . $this->iconFactory->getIcon('actions-add', ‪Icon::SIZE_SMALL)->render()
1086  . ' '
1087  . htmlspecialchars($this->‪getLanguageService()->getLL('content')) . '</a>';
1088  }
1089  $singleElementHTML .= '</div></div><div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div></div>';
1090  if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) {
1091  ‪$defLangBinding[$columnId][$lP][$row[$lP ? 'l18n_parent' : 'uid'] ?: $row['uid']] = $singleElementHTML;
1092  } else {
1093  $content[$columnId] .= $singleElementHTML;
1094  }
1095  } else {
1096  unset($rowArr[$rKey]);
1097  }
1098  }
1099  $content[$columnId] .= '</div>';
1100  $colTitle = ‪BackendUtility::getProcessedValue('tt_content', 'colPos', $columnId);
1101  $tcaItems = GeneralUtility::callUserFunction(\‪TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getColPosListItemsParsed', ‪$id, $this);
1102  foreach ($tcaItems as $item) {
1103  if ($item[1] == $columnId) {
1104  $colTitle = $this->‪getLanguageService()->‪sL($item[0]);
1105  }
1106  }
1107  if ($columnId === 'unused') {
1108  if (empty($unusedElementsMessage)) {
1109  $unusedElementsMessage = GeneralUtility::makeInstance(
1110  FlashMessage::class,
1111  $this->‪getLanguageService()->getLL('staleUnusedElementsWarning'),
1112  $this->‪getLanguageService()->getLL('staleUnusedElementsWarningTitle'),
1114  );
1115  $service = GeneralUtility::makeInstance(FlashMessageService::class);
1116  $queue = $service->getMessageQueueByIdentifier();
1117  $queue->addMessage($unusedElementsMessage);
1118  }
1119  $colTitle = $this->‪getLanguageService()->‪sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.unused');
1120  $editParam = '';
1121  } else {
1122  $editParam = $this->doEdit && !empty($rowArr)
1123  ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc
1124  : '';
1125  }
1126  $head[$columnId] .= $this->‪tt_content_drawColHeader($colTitle, $editParam);
1127  }
1128  }
1129  // For each column, fit the rendered content into a table cell:
1130  $out = '';
1131  if ($this->tt_contentConfig['languageMode']) {
1132  // in language mode process the content elements, but only fill $languageColumn. output will be generated later
1133  $sortedLanguageColumn = [];
1134  foreach ($cList as $columnId) {
1135  if (GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnId) || $columnId === 'unused') {
1136  $languageColumn[$columnId][$lP] = $head[$columnId] . $content[$columnId];
1137 
1138  // We sort $languageColumn again according to $cList as it may contain data already from above.
1139  $sortedLanguageColumn[$columnId] = $languageColumn[$columnId];
1140  }
1141  }
1142  if (!empty($languageColumn['unused'])) {
1143  $sortedLanguageColumn['unused'] = $languageColumn['unused'];
1144  }
1145  $languageColumn = $sortedLanguageColumn;
1146  } else {
1147  // GRID VIEW:
1148  $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">';
1149  // Add colgroups
1150  $colCount = (int)$backendLayout['__config']['backend_layout.']['colCount'];
1151  $rowCount = (int)$backendLayout['__config']['backend_layout.']['rowCount'];
1152  $grid .= '<colgroup>';
1153  for ($i = 0; $i < $colCount; $i++) {
1154  $grid .= '<col />';
1155  }
1156  $grid .= '</colgroup>';
1157 
1158  // Check how to handle restricted columns
1159  $hideRestrictedCols = (bool)(‪BackendUtility::getPagesTSconfig(‪$id)['mod.']['web_layout.']['hideRestrictedCols'] ?? false);
1160 
1161  // Cycle through rows
1162  for ($row = 1; $row <= $rowCount; $row++) {
1163  $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'];
1164  if (!isset($rowConfig)) {
1165  continue;
1166  }
1167  $grid .= '<tr>';
1168  for ($col = 1; $col <= $colCount; $col++) {
1169  $columnConfig = $rowConfig['columns.'][$col . '.'];
1170  if (!isset($columnConfig)) {
1171  continue;
1172  }
1173  // Which tt_content colPos should be displayed inside this cell
1174  $columnKey = (int)$columnConfig['colPos'];
1175  // Render the grid cell
1176  $colSpan = (int)$columnConfig['colspan'];
1177  $rowSpan = (int)$columnConfig['rowspan'];
1178  $grid .= '<td valign="top"' .
1179  ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') .
1180  ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') .
1181  ' 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 .
1182  ((!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '') ? ' t3-grid-cell-unassigned' : '') .
1183  ((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') : '') .
1184  ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') .
1185  ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">';
1186 
1187  // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
1188  // If not, a new header without any buttons will be generated.
1189  if (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey]
1190  && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
1191  ) {
1192  $grid .= $head[$columnKey] . $content[$columnKey];
1193  } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
1194  && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
1195  ) {
1196  if (!$hideRestrictedCols) {
1197  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->getLL('noAccess'));
1198  }
1199  } elseif (isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
1200  && !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
1201  ) {
1202  if (!$hideRestrictedCols) {
1203  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->sL($columnConfig['name']) .
1204  ' (' . $this->‪getLanguageService()->getLL('noAccess') . ')');
1205  }
1206  } elseif (isset($columnConfig['name']) && $columnConfig['name'] !== '') {
1207  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->sL($columnConfig['name'])
1208  . ' (' . $this->‪getLanguageService()->getLL('notAssigned') . ')');
1209  } else {
1210  $grid .= $this->‪tt_content_drawColHeader($this->‪getLanguageService()->getLL('notAssigned'));
1211  }
1212 
1213  $grid .= '</td>';
1214  }
1215  $grid .= '</tr>';
1216  }
1217  if (!empty($content['unused'])) {
1218  $grid .= '<tr>';
1219  // Which tt_content colPos should be displayed inside this cell
1220  $columnKey = 'unused';
1221  // Render the grid cell
1222  $colSpan = (int)$backendLayout['__config']['backend_layout.']['colCount'];
1223  $grid .= '<td valign="top"' .
1224  ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') .
1225  ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') .
1226  ' 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 .
1227  ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') . '">';
1228 
1229  // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
1230  // If not, a new header without any buttons will be generated.
1231  $grid .= $head[$columnKey] . $content[$columnKey];
1232  $grid .= '</td></tr>';
1233  }
1234  $out .= $grid . '</table></div>';
1235  }
1236  }
1237  $elFromTable = $this->clipboard->elFromTable('tt_content');
1238  if (!empty($elFromTable) && $this->‪isContentEditable()) {
1239  $pasteItem = substr(key($elFromTable), 11);
1240  $pasteRecord = ‪BackendUtility::getRecord('tt_content', (int)$pasteItem);
1241  $pasteTitle = $pasteRecord['header'] ? $pasteRecord['header'] : $pasteItem;
1242  $copyMode = $this->clipboard->clipData['normal']['mode'] ? '-' . $this->clipboard->clipData['normal']['mode'] : '';
1243  $addExtOnReadyCode = '
1244  top.pasteIntoLinkTemplate = '
1245  . $this->‪tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-into', 'pasteIntoColumn')
1246  . ';
1247  top.pasteAfterLinkTemplate = '
1248  . $this->‪tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-after', 'pasteAfterRecord')
1249  . ';';
1250  } else {
1251  $addExtOnReadyCode = '
1252  top.pasteIntoLinkTemplate = \'\';
1253  top.pasteAfterLinkTemplate = \'\';';
1254  }
1255  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
1256  $pageRenderer->addJsInlineCode('pasteLinkTemplates', $addExtOnReadyCode);
1257  // If language mode, then make another presentation:
1258  // Notice that THIS presentation will override the value of $out!
1259  // But it needs the code above to execute since $languageColumn is filled with content we need!
1260  if ($this->tt_contentConfig['languageMode']) {
1261  // Get language selector:
1262  $languageSelector = $this->‪languageSelector($id);
1263  // Reset out - we will make new content here:
1264  $out = '';
1265  // Traverse languages found on the page and build up the table displaying them side by side:
1266  $cCont = [];
1267  $sCont = [];
1268  foreach ($langListArr as $lP) {
1269  $languageMode = '';
1270  $labelClass = 'info';
1271  // Header:
1272  $lP = (int)$lP;
1273  // Determine language mode
1274  if ($lP > 0 && isset($this->languageHasTranslationsCache[$lP]['mode'])) {
1275  switch ($this->languageHasTranslationsCache[$lP]['mode']) {
1276  case 'mixed':
1277  $languageMode = $this->‪getLanguageService()->‪getLL('languageModeMixed');
1278  $labelClass = 'danger';
1279  break;
1280  case 'connected':
1281  $languageMode = $this->‪getLanguageService()->‪getLL('languageModeConnected');
1282  break;
1283  case 'free':
1284  $languageMode = $this->‪getLanguageService()->‪getLL('languageModeFree');
1285  break;
1286  default:
1287  // we'll let opcode optimize this intentionally empty case
1288  }
1289  }
1290  $cCont[$lP] = '
1291  <td valign="top" class="t3-page-column t3-page-column-lang-name" data-language-uid="' . $lP . '">
1292  <h2>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '</h2>
1293  ' . ($languageMode !== '' ? '<span class="label label-' . $labelClass . '">' . $languageMode . '</span>' : '') . '
1294  </td>';
1295 
1296  // "View page" icon is added:
1297  $viewLink = '';
1298  if (!‪VersionState::cast($this->‪getPageLayoutController()->pageinfo['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)) {
1299  $onClick = ‪BackendUtility::viewOnClick(
1300  $this->id,
1301  '',
1303  '',
1304  '',
1305  '&L=' . $lP
1306  );
1307  $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>';
1308  }
1309  // Language overlay page header:
1310  if ($lP) {
1311  $pageLocalizationRecord = ‪BackendUtility::getRecordLocalization('pages', ‪$id, $lP);
1312  if (is_array($pageLocalizationRecord)) {
1313  $pageLocalizationRecord = reset($pageLocalizationRecord);
1314  }
1315  ‪BackendUtility::workspaceOL('pages', $pageLocalizationRecord);
1317  $this->iconFactory->getIconForRecord('pages', $pageLocalizationRecord, ‪Icon::SIZE_SMALL)->render(),
1318  'pages',
1319  $pageLocalizationRecord['uid']
1320  );
1321  $urlParameters = [
1322  'edit' => [
1323  'pages' => [
1324  $pageLocalizationRecord['uid'] => 'edit'
1325  ]
1326  ],
1327  // Disallow manual adjustment of the language field for pages
1328  'overrideVals' => [
1329  'pages' => [
1330  'sys_language_uid' => $lP
1331  ]
1332  ],
1333  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1334  ];
1335  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1336  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1337  $editLink = (
1338  $this->‪getBackendUser()->‪check('tables_modify', 'pages')
1339  ? '<a href="' . htmlspecialchars($url) . '" class="btn btn-default btn-sm"'
1340  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">'
1341  . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>'
1342  : ''
1343  );
1344 
1345  $defaultLanguageElements = [];
1346  array_walk($defaultLanguageElementsByColumn, function (array $columnContent) use (&$defaultLanguageElements) {
1347  $defaultLanguageElements = array_merge($defaultLanguageElements, $columnContent);
1348  });
1349 
1350  $localizationButtons = [];
1351  $localizationButtons[] = $this->‪newLanguageButton(
1352  $this->‪getNonTranslatedTTcontentUids($defaultLanguageElements, ‪$id, $lP),
1353  $lP
1354  );
1355 
1356  $lPLabel =
1357  '<div class="btn-group">'
1358  . $viewLink
1359  . $editLink
1360  . (!empty($localizationButtons) ? implode(LF, $localizationButtons) : '')
1361  . '</div>'
1362  . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageLocalizationRecord['title'], 20))
1363  ;
1364  } else {
1365  $editLink = '';
1366  $recordIcon = '';
1367  if ($this->‪getBackendUser()->checkLanguageAccess(0)) {
1369  $this->iconFactory->getIconForRecord('pages', $this->pageRecord, ‪Icon::SIZE_SMALL)->render(),
1370  'pages',
1371  $this->id
1372  );
1373  $urlParameters = [
1374  'edit' => [
1375  'pages' => [
1376  $this->id => 'edit'
1377  ]
1378  ],
1379  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1380  ];
1381  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1382  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1383  $editLink = (
1384  $this->‪getBackendUser()->‪check('tables_modify', 'pages')
1385  ? '<a href="' . htmlspecialchars($url) . '" class="btn btn-default btn-sm"'
1386  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">'
1387  . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>'
1388  : ''
1389  );
1390  }
1391 
1392  $lPLabel =
1393  '<div class="btn-group">'
1394  . $viewLink
1395  . $editLink
1396  . '</div>'
1397  . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->pageRecord['title'], 20));
1398  }
1399  $sCont[$lP] = '
1400  <td class="t3-page-column t3-page-lang-label nowrap">' . $lPLabel . '</td>';
1401  }
1402  // Add headers:
1403  $out .= '<tr>' . implode('', $cCont) . '</tr>';
1404  $out .= '<tr>' . implode('', $sCont) . '</tr>';
1405  unset($cCont, $sCont);
1406 
1407  // Traverse previously built content for the columns:
1408  foreach ($languageColumn as $cKey => $cCont) {
1409  $out .= '<tr>';
1410  foreach ($cCont as $languageId => $columnContent) {
1411  $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>';
1412  }
1413  $out .= '</tr>';
1414  if ($this->defLangBinding && !empty(‪$defLangBinding[$cKey])) {
1415  $maxItemsCount = max(array_map('count', ‪$defLangBinding[$cKey]));
1416  for ($i = 0; $i < $maxItemsCount; $i++) {
1417  $defUid = $defaultLanguageElementsByColumn[$cKey][$i] ?? 0;
1418  $cCont = [];
1419  foreach ($langListArr as $lP) {
1420  if ($lP > 0
1421  && is_array(‪$defLangBinding[$cKey][$lP])
1422  && !$this->‪checkIfTranslationsExistInLanguage($defaultLanguageElementsByColumn[$cKey], $lP)
1423  && count(‪$defLangBinding[$cKey][$lP]) > $i
1424  ) {
1425  $slice = array_slice(‪$defLangBinding[$cKey][$lP], $i, 1);
1426  $element = $slice[0] ?? '';
1427  } else {
1428  $element = ‪$defLangBinding[$cKey][$lP][$defUid] ?? '';
1429  }
1430  $cCont[] = $element;
1431  }
1432  $out .= '
1433  <tr>
1434  <td valign="top" class="t3-grid-cell" data-colpos="' . $cKey . '">' . implode('</td>
1435  <td valign="top" class="t3-grid-cell" data-colpos="' . $cKey . '">', $cCont) . '</td>
1436  </tr>';
1437  }
1438  }
1439  }
1440  // Finally, wrap it all in a table and add the language selector on top of it:
1441  $out = $languageSelector . '
1442  <div class="t3-grid-container">
1443  <table cellpadding="0" cellspacing="0" class="t3-page-columns t3-grid-table t3js-page-columns">
1444  ' . $out . '
1445  </table>
1446  </div>';
1447  }
1448 
1449  return $out;
1450  }
1451 
1452  /**********************************
1453  *
1454  * Generic listing of items
1455  *
1456  **********************************/
1467  public function ‪makeOrdinaryList(‪$table, ‪$id, $fList, $icon = false, $addWhere = '')
1468  {
1469  // Initialize
1470  $addWhere = empty($addWhere) ? [] : [‪QueryHelper::stripLogicalOperatorPrefix($addWhere)];
1471  $queryBuilder = $this->‪getQueryBuilder($table, ‪$id, $addWhere);
1472  $this->‪setTotalItems($table, ‪$id, $addWhere);
1473  $dbCount = 0;
1474  $result = false;
1475  // Make query for records if there were any records found in the count operation
1476  if ($this->totalItems) {
1477  $result = $queryBuilder->execute();
1478  // Will return FALSE, if $result is invalid
1479  $dbCount = $queryBuilder->count('uid')->execute()->fetchColumn(0);
1480  }
1481  // If records were found, render the list
1482  if (!$dbCount) {
1483  return '';
1484  }
1485  // Set fields
1486  $out = '';
1487  $this->fieldArray = GeneralUtility::trimExplode(',', '__cmds__,' . $fList . ',__editIconLink__', true);
1488  $theData = [];
1489  $theData = $this->‪headerFields($this->fieldArray, ‪$table, $theData);
1490  // Title row
1491  $localizedTableTitle = htmlspecialchars($this->‪getLanguageService()->sL(‪$GLOBALS['TCA'][‪$table]['ctrl']['title']));
1492  $out .= '<tr><th class="col-icon"></th>'
1493  . '<th colspan="' . (count($theData) - 2) . '"><span class="c-table">'
1494  . $localizedTableTitle . '</span> (' . $dbCount . ')</td>' . '<td class="col-icon"></td>'
1495  . '</tr>';
1496  // Column's titles
1497  if ($this->doEdit) {
1498  $urlParameters = [
1499  'edit' => [
1500  ‪$table => [
1501  $this->id => 'new'
1502  ]
1503  ],
1504  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1505  ];
1506  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1507  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1508  $title = htmlspecialchars($this->‪getLanguageService()->getLL('new'));
1509  $theData['__cmds__'] = '<a href="' . htmlspecialchars($url) . '" class="' . ($this->option_newWizard ? 't3js-toggle-new-content-element-wizard disabled' : '') . '" '
1510  . 'title="' . $title . '"'
1511  . 'data-title="' . $title . '">'
1512  . $this->iconFactory->getIcon('actions-add', ‪Icon::SIZE_SMALL)->render() . '</a>';
1513  }
1514  $out .= $this->‪addElement(1, '', $theData, ' class="c-headLine"', 15, '', 'th');
1515  // Render Items
1516  $this->eCounter = ‪$this->firstElementNumber;
1517  while ($row = $result->fetch()) {
1519  if (is_array($row)) {
1520  list($flag, $code) = $this->‪fwd_rwd_nav();
1521  $out .= $code;
1522  if ($flag) {
1523  $Nrow = [];
1524  // Setting icons links
1525  if ($icon) {
1526  $Nrow['__cmds__'] = $this->‪getIcon($table, $row);
1527  }
1528  // Get values:
1529  $Nrow = $this->‪dataFields($this->fieldArray, ‪$table, $row, $Nrow);
1530  // Attach edit icon
1531  if ($this->doEdit) {
1532  $urlParameters = [
1533  'edit' => [
1534  ‪$table => [
1535  $row['uid'] => 'edit'
1536  ]
1537  ],
1538  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1539  ];
1540  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1541  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1542  $Nrow['__editIconLink__'] = '<a class="btn btn-default" href="' . htmlspecialchars($url)
1543  . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">'
1544  . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
1545  } else {
1546  $Nrow['__editIconLink__'] = $this->‪noEditIcon();
1547  }
1548  $out .= $this->‪addElement(1, '', $Nrow);
1549  }
1550  $this->eCounter++;
1551  }
1552  }
1553  // Wrap it all in a table:
1554  $out = '
1555  <!--
1556  Standard list of table "' . ‪$table . '"
1557  -->
1558  <div class="table-fit"><table class="table table-hover table-striped">
1559  ' . $out . '
1560  </table></div>';
1561  return $out;
1562  }
1563 
1578  public function ‪dataFields($fieldArr, ‪$table, $row, $out = [])
1579  {
1580  // Check table validity
1581  if (!isset(‪$GLOBALS['TCA'][‪$table])) {
1582  return $out;
1583  }
1584 
1585  $thumbsCol = ‪$GLOBALS['TCA'][‪$table]['ctrl']['thumbnail'];
1586  // Traverse fields
1587  foreach ($fieldArr as $fieldName) {
1588  if (‪$GLOBALS['TCA'][‪$table]['columns'][$fieldName]) {
1589  // Each field has its own cell (if configured in TCA)
1590  // If the column is a thumbnail column:
1591  if ($fieldName == $thumbsCol) {
1592  $out[$fieldName] = $this->‪thumbCode($row, ‪$table, $fieldName);
1593  } else {
1594  // ... otherwise just render the output:
1595  $out[$fieldName] = nl2br(htmlspecialchars(trim(GeneralUtility::fixed_lgd_cs(
1596  ‪BackendUtility::getProcessedValue(‪$table, $fieldName, $row[$fieldName], 0, 0, 0, $row['uid']),
1597  250
1598  ))));
1599  }
1600  } else {
1601  // Each field is separated by <br /> and shown in the same cell (If not a TCA field, then explode
1602  // the field name with ";" and check each value there as a TCA configured field)
1603  $theFields = explode(';', $fieldName);
1604  // Traverse fields, separated by ";" (displayed in a single cell).
1605  foreach ($theFields as $fName2) {
1606  if (‪$GLOBALS['TCA'][‪$table]['columns'][$fName2]) {
1607  $out[$fieldName] .= '<strong>' . htmlspecialchars($this->‪getLanguageService()->sL(
1608  ‪$GLOBALS['TCA'][‪$table]['columns'][$fName2]['label']
1609  )) . '</strong>' . '&nbsp;&nbsp;' . htmlspecialchars(GeneralUtility::fixed_lgd_cs(
1610  ‪BackendUtility::getProcessedValue(‪$table, $fName2, $row[$fName2], 0, 0, 0, $row['uid']),
1611  25
1612  )) . '<br />';
1613  }
1614  }
1615  }
1616  // If no value, add a nbsp.
1617  if (!$out[$fieldName]) {
1618  $out[$fieldName] = '&nbsp;';
1619  }
1620  // Wrap in dimmed-span tags if record is "disabled"
1621  if ($this->‪isDisabled($table, $row)) {
1622  $out[$fieldName] = '<span class="text-muted">' . $out[$fieldName] . '</span>';
1623  }
1624  }
1625  return $out;
1626  }
1627 
1637  public function ‪headerFields($fieldArr, ‪$table, $out = [])
1638  {
1639  foreach ($fieldArr as $fieldName) {
1640  $ll = htmlspecialchars($this->‪getLanguageService()->sL(‪$GLOBALS['TCA'][‪$table]['columns'][$fieldName]['label']));
1641  $out[$fieldName] = $ll ? $ll : '&nbsp;';
1642  }
1643  return $out;
1644  }
1645 
1656  protected function ‪getContentRecordsPerColumn(‪$table, ‪$id, array $columns, $additionalWhereClause = '')
1657  {
1658  $contentRecordsPerColumn = array_fill_keys($columns, []);
1659  $columns = array_flip($columns);
1660  $queryBuilder = $this->‪getQueryBuilder(
1661  'tt_content',
1662  $id,
1663  [
1664  $additionalWhereClause
1665  ]
1666  );
1667 
1668  // Traverse any selected elements and render their display code:
1669  $results = $this->‪getResult($queryBuilder->execute());
1670  $unused = [];
1671  $hookArray = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['record_is_used'] ?? [];
1672  foreach ($results as $record) {
1673  $used = isset($columns[$record['colPos']]);
1674  foreach ($hookArray as $_funcRef) {
1675  $_params = ['columns' => $columns, 'record' => $record, 'used' => $used];
1676  $used = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1677  }
1678  if ($used) {
1679  $columnValue = (string)$record['colPos'];
1680  $contentRecordsPerColumn[$columnValue][] = $record;
1681  } else {
1682  $unused[] = $record;
1683  }
1684  }
1685  if (!empty($unused)) {
1686  $contentRecordsPerColumn['unused'] = $unused;
1687  }
1688  return $contentRecordsPerColumn;
1689  }
1690 
1691  /**********************************
1692  *
1693  * Additional functions; Pages
1694  *
1695  **********************************/
1696 
1706  protected function ‪getPageRecordsRecursive(int $pid, int $depth, string $iconPrefix = '', array $rows = []): array
1707  {
1708  $depth--;
1709  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1710  $queryBuilder->getRestrictions()
1711  ->removeAll()
1712  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1713  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
1714 
1715  $queryBuilder
1716  ->select('*')
1717  ->from('pages')
1718  ->where(
1719  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)),
1720  $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
1721  $this->getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW)
1722  );
1723 
1724  if (!empty(‪$GLOBALS['TCA']['pages']['ctrl']['sortby'])) {
1725  $queryBuilder->orderBy(‪$GLOBALS['TCA']['pages']['ctrl']['sortby']);
1726  }
1727 
1728  if ($depth >= 0) {
1729  $result = $queryBuilder->execute();
1730  $rowCount = $queryBuilder->count('uid')->execute()->fetchColumn(0);
1731  $count = 0;
1732  while ($row = $result->fetch()) {
1733  ‪BackendUtility::workspaceOL('pages', $row);
1734  if (is_array($row)) {
1735  $count++;
1736  $row['treeIcons'] = $iconPrefix
1737  . '<span class="treeline-icon treeline-icon-join'
1738  . ($rowCount === $count ? 'bottom' : '')
1739  . '"></span>';
1740  $rows[] = $row;
1741  // Get the branch
1742  $spaceOutIcons = '<span class="treeline-icon treeline-icon-'
1743  . ($rowCount === $count ? 'clear' : 'line')
1744  . '"></span>';
1745  $rows = $this->‪getPageRecordsRecursive(
1746  $row['uid'],
1747  $row['php_tree_stop'] ? 0 : $depth,
1748  $iconPrefix . $spaceOutIcons,
1749  $rows
1750  );
1751  }
1752  }
1753  }
1754 
1755  return $rows;
1756  }
1757 
1765  public function ‪pages_drawItem($row, $fieldArr)
1766  {
1767  $userTsConfig = $this->‪getBackendUser()->‪getTSConfig();
1768 
1769  // Initialization
1770  $theIcon = $this->‪getIcon('pages', $row);
1771  // Preparing and getting the data-array
1772  $theData = [];
1773  foreach ($fieldArr as $field) {
1774  switch ($field) {
1775  case 'title':
1776  $showPageId = !empty($userTsConfig['options.']['pageTree.']['showPageIdWithTitle']);
1777  $pTitle = htmlspecialchars(‪BackendUtility::getProcessedValue('pages', $field, $row[$field], 20));
1778  $theData[$field] = $row['treeIcons'] . $theIcon . ($showPageId ? '[' . $row['uid'] . '] ' : '') . $pTitle;
1779  break;
1780  case 'php_tree_stop':
1781  // Intended fall through
1782  case 'TSconfig':
1783  $theData[$field] = $row[$field] ? '<strong>x</strong>' : '&nbsp;';
1784  break;
1785  case 'uid':
1786  if ($this->‪getBackendUser()->‪doesUserHaveAccess($row, 2) && $row['uid'] > 0) {
1787  $urlParameters = [
1788  'edit' => [
1789  'pages' => [
1790  $row['uid'] => 'edit'
1791  ]
1792  ],
1793  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
1794  ];
1795  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1796  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
1797  $onClick = ‪BackendUtility::viewOnClick($row['uid'], '', ‪BackendUtility::BEgetRootLine($row['uid']));
1798 
1799  $eI =
1800  '<a href="#" onclick="' . htmlspecialchars($onClick) . '" class="btn btn-default" title="' .
1801  $this->‪getLanguageService()->‪sL('LLL:EXT:frontend/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_viewPage') . '">' .
1802  $this->iconFactory->getIcon('actions-view-page', ‪Icon::SIZE_SMALL)->render() .
1803  '</a>';
1804  $eI .=
1805  '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" title="' .
1806  htmlspecialchars($this->‪getLanguageService()->getLL('editThisPage')) . '">' .
1807  $this->iconFactory->getIcon('actions-page-open', ‪Icon::SIZE_SMALL)->render() .
1808  '</a>';
1809  } else {
1810  $eI = '';
1811  }
1812  $theData[$field] = '<div class="btn-group" role="group">' . $eI . '</div>';
1813  break;
1814  case 'shortcut':
1815  case 'shortcut_mode':
1816  if ((int)$row['doktype'] === \‪TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_SHORTCUT) {
1817  $theData[$field] = $this->‪getPagesTableFieldValue($field, $row);
1818  }
1819  break;
1820  default:
1821  if (strpos($field, 'table_') === 0) {
1822  $f2 = substr($field, 6);
1823  if (‪$GLOBALS['TCA'][$f2]) {
1824  $c = $this->‪numberOfRecords($f2, $row['uid']);
1825  $theData[$field] = ($c ? $c : '');
1826  }
1827  } else {
1828  $theData[$field] = $this->‪getPagesTableFieldValue($field, $row);
1829  }
1830  }
1831  }
1832  $this->addElement_tdParams['title'] = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : '';
1833  return $this->‪addElement(1, '', $theData);
1834  }
1835 
1844  protected function ‪getPagesTableFieldValue($field, array $row)
1845  {
1846  return htmlspecialchars(‪BackendUtility::getProcessedValue('pages', $field, $row[$field]));
1847  }
1848 
1849  /**********************************
1850  *
1851  * Additional functions; Content Elements
1852  *
1853  **********************************/
1861  public function ‪tt_content_drawColHeader($colName, $editParams = '')
1862  {
1863  $iconsArr = [];
1864  // Create command links:
1865  if ($this->tt_contentConfig['showCommands']) {
1866  // Edit whole of column:
1867  if ($editParams && $this->‪getBackendUser()->doesUserHaveAccess($this->pageinfo, ‪Permission::CONTENT_EDIT) && $this->‪getBackendUser()->checkLanguageAccess(0)) {
1868  $iconsArr['edit'] = '<a href="#" onclick="'
1869  . htmlspecialchars(‪BackendUtility::editOnClick($editParams)) . '" title="'
1870  . htmlspecialchars($this->‪getLanguageService()->getLL('editColumn')) . '">'
1871  . $this->iconFactory->getIcon('actions-document-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
1872  }
1873  }
1874  ‪$icons = '';
1875  if (!empty($iconsArr)) {
1876  ‪$icons = '<div class="t3-page-column-header-icons">' . implode('', $iconsArr) . '</div>';
1877  }
1878  // Create header row:
1879  $out = '<div class="t3-page-column-header">
1880  ' . ‪$icons . '
1881  <div class="t3-page-column-header-label">' . htmlspecialchars($colName) . '</div>
1882  </div>';
1883  return $out;
1884  }
1885 
1897  protected function ‪tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, $cssClass, $title)
1898  {
1899  $pasteIcon = json_encode(
1900  ' <a data-content="' . htmlspecialchars($pasteItem) . '"'
1901  . ' data-title="' . htmlspecialchars($pasteTitle) . '"'
1902  . ' data-severity="warning"'
1903  . ' class="t3js-paste t3js-paste' . htmlspecialchars($copyMode) . ' ' . htmlspecialchars($cssClass) . ' btn btn-default btn-sm"'
1904  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL($title)) . '">'
1905  . $this->iconFactory->getIcon('actions-document-paste-into', ‪Icon::SIZE_SMALL)->render()
1906  . '</a>'
1907  );
1908  return $pasteIcon;
1909  }
1910 
1918  protected function ‪tt_content_drawFooter(array $row)
1919  {
1920  $content = '';
1921  // Get processed values:
1922  $info = [];
1923  $this->‪getProcessedValue('tt_content', 'starttime,endtime,fe_group,space_before_class,space_after_class', $row, $info);
1924 
1925  // Content element annotation
1926  if (!empty(‪$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']) && !empty($row[‪$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']])) {
1927  $info[] = htmlspecialchars($row[‪$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']]);
1928  }
1929 
1930  // Call drawFooter hooks
1931  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawFooter'] ?? [] as $className) {
1932  $hookObject = GeneralUtility::makeInstance($className);
1933  if (!$hookObject instanceof PageLayoutViewDrawFooterHookInterface) {
1934  throw new \UnexpectedValueException($className . ' must implement interface ' . PageLayoutViewDrawFooterHookInterface::class, 1404378171);
1935  }
1936  $hookObject->preProcess($this, $info, $row);
1937  }
1938 
1939  // Display info from records fields:
1940  if (!empty($info)) {
1941  $content = '<div class="t3-page-ce-info">
1942  ' . implode('<br>', $info) . '
1943  </div>';
1944  }
1945  // Wrap it
1946  if (!empty($content)) {
1947  $content = '<div class="t3-page-ce-footer">' . $content . '</div>';
1948  }
1949  return $content;
1950  }
1951 
1962  public function ‪tt_content_drawHeader($row, $space = 0, $disableMoveAndNewButtons = false, $langMode = false, $dragDropEnabled = false)
1963  {
1964  $backendUser = $this->‪getBackendUser();
1965  $out = '';
1966  // If show info is set...;
1967  if ($this->tt_contentConfig['showInfo'] && $backendUser->recordEditAccessInternals('tt_content', $row)) {
1968  // Render control panel for the element:
1969  if ($this->tt_contentConfig['showCommands'] && $this->‪isContentEditable($row['sys_language_uid'])) {
1970  // Edit content element:
1971  $urlParameters = [
1972  'edit' => [
1973  'tt_content' => [
1974  $this->tt_contentData['nextThree'][$row['uid']] => 'edit'
1975  ]
1976  ],
1977  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid'],
1978  ];
1979  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1980  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters) . '#element-tt_content-' . $row['uid'];
1981 
1982  $out .= '<a class="btn btn-default" href="' . htmlspecialchars($url)
1983  . '" title="' . htmlspecialchars($this->nextThree > 1
1984  ? sprintf($this->‪getLanguageService()->getLL('nextThree'), $this->nextThree)
1985  : $this->‪getLanguageService()->getLL('edit'))
1986  . '">' . $this->iconFactory->getIcon('actions-open', ‪Icon::SIZE_SMALL)->render() . '</a>';
1987  // Hide element:
1988  $hiddenField = ‪$GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
1989  if ($hiddenField && ‪$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]
1990  && (!‪$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]['exclude']
1991  || $backendUser->check('non_exclude_fields', 'tt_content:' . $hiddenField))
1992  ) {
1993  if ($row[$hiddenField]) {
1994  $value = 0;
1995  $label = 'unHide';
1996  } else {
1997  $value = 1;
1998  $label = 'hide';
1999  }
2000  $params = '&data[tt_content][' . ($row['_ORIG_uid'] ? $row['_ORIG_uid'] : $row['uid'])
2001  . '][' . $hiddenField . ']=' . $value;
2002  $out .= '<a class="btn btn-default" href="' . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params))
2003  . '#element-tt_content-' . $row['uid'] . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL($label)) . '">'
2004  . $this->iconFactory->getIcon('actions-edit-' . strtolower($label), ‪Icon::SIZE_SMALL)->render() . '</a>';
2005  }
2006  // Delete
2007  $disableDelete = (bool)\trim(
2008  $backendUser->getTSConfig()['options.']['disableDelete.']['tt_content']
2009  ?? $backendUser->getTSConfig()['options.']['disableDelete']
2010  ?? '0'
2011  );
2012  if (!$disableDelete) {
2013  $params = '&cmd[tt_content][' . $row['uid'] . '][delete]=1';
2014  $refCountMsg = ‪BackendUtility::referenceCount(
2015  'tt_content',
2016  $row['uid'],
2017  ' ' . $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord'),
2018  $this->‪getReferenceCount('tt_content', $row['uid'])
2020  'tt_content',
2021  $row['uid'],
2022  ' ' . $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord')
2023  );
2024  $confirm = $this->‪getLanguageService()->‪getLL('deleteWarning')
2025  . $refCountMsg;
2026  $out .= '<a class="btn btn-default t3js-modal-trigger" href="' . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params)) . '"'
2027  . ' data-severity="warning"'
2028  . ' data-title="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:label.confirm.delete_record.title')) . '"'
2029  . ' data-content="' . htmlspecialchars($confirm) . '" '
2030  . ' data-button-close-text="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel')) . '"'
2031  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('deleteItem')) . '">'
2032  . $this->iconFactory->getIcon('actions-edit-delete', ‪Icon::SIZE_SMALL)->render() . '</a>';
2033  if ($out && $backendUser->doesUserHaveAccess($this->pageinfo, ‪Permission::CONTENT_EDIT)) {
2034  $out = '<div class="btn-group btn-group-sm" role="group">' . $out . '</div>';
2035  } else {
2036  $out = '';
2037  }
2038  }
2039  if (!$disableMoveAndNewButtons) {
2040  $moveButtonContent = '';
2041  $displayMoveButtons = false;
2042  // Move element up:
2043  if ($this->tt_contentData['prev'][$row['uid']]) {
2044  $params = '&cmd[tt_content][' . $row['uid'] . '][move]=' . $this->tt_contentData['prev'][$row['uid']];
2045  $moveButtonContent .= '<a class="btn btn-default" href="'
2046  . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params))
2047  . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('moveUp')) . '">'
2048  . $this->iconFactory->getIcon('actions-move-up', ‪Icon::SIZE_SMALL)->render() . '</a>';
2049  if (!$dragDropEnabled) {
2050  $displayMoveButtons = true;
2051  }
2052  } else {
2053  $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', ‪Icon::SIZE_SMALL)->render() . '</span>';
2054  }
2055  // Move element down:
2056  if ($this->tt_contentData['next'][$row['uid']]) {
2057  $params = '&cmd[tt_content][' . $row['uid'] . '][move]= ' . $this->tt_contentData['next'][$row['uid']];
2058  $moveButtonContent .= '<a class="btn btn-default" href="'
2059  . htmlspecialchars(‪BackendUtility::getLinkToDataHandlerAction($params))
2060  . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('moveDown')) . '">'
2061  . $this->iconFactory->getIcon('actions-move-down', ‪Icon::SIZE_SMALL)->render() . '</a>';
2062  if (!$dragDropEnabled) {
2063  $displayMoveButtons = true;
2064  }
2065  } else {
2066  $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', ‪Icon::SIZE_SMALL)->render() . '</span>';
2067  }
2068  if ($displayMoveButtons) {
2069  $out .= '<div class="btn-group btn-group-sm" role="group">' . $moveButtonContent . '</div>';
2070  }
2071  }
2072  }
2073  }
2074  $allowDragAndDrop = $this->‪isDragAndDropAllowed($row);
2075  $additionalIcons = [];
2076  $additionalIcons[] = $this->‪getIcon('tt_content', $row) . ' ';
2077  if ($langMode && isset($this->siteLanguages[(int)$row['sys_language_uid']])) {
2078  $additionalIcons[] = $this->‪renderLanguageFlag($this->siteLanguages[(int)$row['sys_language_uid']]);
2079  }
2080  // Get record locking status:
2081  if ($lockInfo = ‪BackendUtility::isRecordLocked('tt_content', $row['uid'])) {
2082  $additionalIcons[] = '<a href="#" data-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">'
2083  . $this->iconFactory->getIcon('warning-in-use', ‪Icon::SIZE_SMALL)->render() . '</a>';
2084  }
2085  // Call stats information hook
2086  $_params = ['tt_content', $row['uid'], &$row];
2087  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] ?? [] as $_funcRef) {
2088  $additionalIcons[] = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2089  }
2090 
2091  // Wrap the whole header
2092  // NOTE: end-tag for <div class="t3-page-ce-body"> is in getTable_tt_content()
2093  return '<div class="t3-page-ce-header ' . ($allowDragAndDrop ? 't3-page-ce-header-draggable t3js-page-ce-draghandle' : '') . '">
2094  <div class="t3-page-ce-header-icons-left">' . implode('', $additionalIcons) . '</div>
2095  <div class="t3-page-ce-header-icons-right">' . ($out ? '<div class="btn-toolbar">' . $out . '</div>' : '') . '</div>
2096  </div>
2097  <div class="t3-page-ce-body">';
2098  }
2099 
2108  protected function ‪getReferenceCount(string $tableName, int $uid): int
2109  {
2110  if (!isset($this->referenceCount[$tableName][$uid])) {
2111  $referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
2112  $numberOfReferences = $referenceIndex->getNumberOfReferencedRecords($tableName, $uid);
2113  $this->referenceCount[$tableName][$uid] = $numberOfReferences;
2114  }
2115  return $this->referenceCount[$tableName][$uid];
2116  }
2117 
2124  protected function ‪isDragAndDropAllowed(array $row)
2125  {
2126  if ((int)$row['l18n_parent'] === 0 &&
2127  (
2128  $this->‪getBackendUser()->isAdmin()
2129  || ((int)$row['editlock'] === 0 && (int)$this->pageinfo['editlock'] === 0)
2130  && $this->‪getBackendUser()->doesUserHaveAccess($this->pageinfo, ‪Permission::CONTENT_EDIT)
2131  && $this->‪getBackendUser()->checkAuthMode('tt_content', 'CType', $row['CType'], ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
2132  )
2133  ) {
2134  return true;
2135  }
2136  return false;
2137  }
2138 
2146  public function ‪tt_content_drawItem($row)
2147  {
2148  $out = '';
2149  $outHeader = '';
2150  // Make header:
2151 
2152  if ($row['header']) {
2153  $hiddenHeaderNote = '';
2154  // If header layout is set to 'hidden', display an accordant note:
2155  if ($row['header_layout'] == 100) {
2156  $hiddenHeaderNote = ' <em>[' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.hidden')) . ']</em>';
2157  }
2158  $outHeader = $row['date']
2159  ? htmlspecialchars($this->itemLabels['date'] . ' ' . ‪BackendUtility::date($row['date'])) . '<br />'
2160  : '';
2161  $outHeader .= '<strong>' . $this->‪linkEditContent($this->‪renderText($row['header']), $row)
2162  . $hiddenHeaderNote . '</strong><br />';
2163  }
2164  // Make content:
2165  $drawItem = true;
2166  // Hook: Render an own preview of a record
2167  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem'] ?? [] as $className) {
2168  $hookObject = GeneralUtility::makeInstance($className);
2169  if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) {
2170  throw new \UnexpectedValueException($className . ' must implement interface ' . PageLayoutViewDrawItemHookInterface::class, 1218547409);
2171  }
2172  $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row);
2173  }
2174 
2175  // If the previous hook did not render something,
2176  // then check if a Fluid-based preview template was defined for this CType
2177  // and render it via Fluid. Possible option:
2178  // mod.web_layout.tt_content.preview.media = EXT:site_mysite/Resources/Private/Templates/Preview/Media.html
2179  if ($drawItem) {
2180  $tsConfig = ‪BackendUtility::getPagesTSconfig($row['pid'])['mod.']['web_layout.']['tt_content.']['preview.'] ?? [];
2181  $fluidTemplateFile = '';
2182 
2183  if ($row['CType'] === 'list' && !empty($row['list_type'])
2184  && !empty($tsConfig['list.'][$row['list_type']])
2185  ) {
2186  $fluidTemplateFile = $tsConfig['list.'][$row['list_type']];
2187  } elseif (!empty($tsConfig[$row['CType']])) {
2188  $fluidTemplateFile = $tsConfig[$row['CType']];
2189  }
2190 
2191  if ($fluidTemplateFile) {
2192  $fluidTemplateFile = GeneralUtility::getFileAbsFileName($fluidTemplateFile);
2193  if ($fluidTemplateFile) {
2194  try {
2195  $view = GeneralUtility::makeInstance(StandaloneView::class);
2196  $view->setTemplatePathAndFilename($fluidTemplateFile);
2197  $view->assignMultiple($row);
2198  if (!empty($row['pi_flexform'])) {
2199  $flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
2200  $view->assign('pi_flexform_transformed', $flexFormService->convertFlexFormContentToArray($row['pi_flexform']));
2201  }
2202  $out = $view->render();
2203  $drawItem = false;
2204  } catch (\Exception $e) {
2205  $this->logger->warning(sprintf(
2206  'The backend preview for content element %d can not be rendered using the Fluid template file "%s": %s',
2207  $row['uid'],
2208  $fluidTemplateFile,
2209  $e->getMessage()
2210  ));
2211  }
2212  }
2213  }
2214  }
2215 
2216  // Draw preview of the item depending on its CType (if not disabled by previous hook):
2217  if ($drawItem) {
2218  switch ($row['CType']) {
2219  case 'header':
2220  if ($row['subheader']) {
2221  $out .= $this->‪linkEditContent($this->‪renderText($row['subheader']), $row) . '<br />';
2222  }
2223  break;
2224  case 'bullets':
2225  case 'table':
2226  if ($row['bodytext']) {
2227  $out .= $this->‪linkEditContent($this->‪renderText($row['bodytext']), $row) . '<br />';
2228  }
2229  break;
2230  case 'uploads':
2231  if ($row['media']) {
2232  $out .= $this->‪linkEditContent($this->‪getThumbCodeUnlinked($row, 'tt_content', 'media'), $row) . '<br />';
2233  }
2234  break;
2235  case 'menu':
2236  $contentType = $this->CType_labels[$row['CType']];
2237  $out .= $this->‪linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />';
2238  // Add Menu Type
2239  $menuTypeLabel = $this->‪getLanguageService()->‪sL(
2240  ‪BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'menu_type', $row['menu_type'])
2241  );
2242  $menuTypeLabel = $menuTypeLabel ?: 'invalid menu type';
2243  $out .= $this->‪linkEditContent(htmlspecialchars($menuTypeLabel), $row);
2244  if ($row['menu_type'] !== '2' && ($row['pages'] || $row['selected_categories'])) {
2245  // Show pages if menu type is not "Sitemap"
2246  $out .= ':' . $this->‪linkEditContent($this->‪generateListForCTypeMenu($row), $row) . '<br />';
2247  }
2248  break;
2249  case 'shortcut':
2250  if (!empty($row['records'])) {
2251  $shortcutContent = [];
2252  $recordList = explode(',', $row['records']);
2253  foreach ($recordList as $recordIdentifier) {
2254  $split = ‪BackendUtility::splitTable_Uid($recordIdentifier);
2255  $tableName = empty($split[0]) ? 'tt_content' : $split[0];
2256  $shortcutRecord = ‪BackendUtility::getRecord($tableName, $split[1]);
2257  if (is_array($shortcutRecord)) {
2258  $icon = $this->iconFactory->getIconForRecord($tableName, $shortcutRecord, ‪Icon::SIZE_SMALL)->render();
2260  $icon,
2261  $tableName,
2262  $shortcutRecord['uid']
2263  );
2264  $shortcutContent[] = $icon
2265  . htmlspecialchars(‪BackendUtility::getRecordTitle($tableName, $shortcutRecord));
2266  }
2267  }
2268  $out .= implode('<br />', $shortcutContent) . '<br />';
2269  }
2270  break;
2271  case 'list':
2272  $hookOut = '';
2273  $_params = ['pObj' => &$this, 'row' => $row, 'infoArr' => []];
2274  foreach (
2275  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$row['list_type']] ??
2276  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'] ??
2277  [] as $_funcRef
2278  ) {
2279  $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2280  }
2281  if ((string)$hookOut !== '') {
2282  $out .= $hookOut;
2283  } elseif (!empty($row['list_type'])) {
2284  $label = ‪BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'list_type', $row['list_type']);
2285  if (!empty($label)) {
2286  $out .= $this->‪linkEditContent('<strong>' . htmlspecialchars($this->‪getLanguageService()->sL($label)) . '</strong>', $row) . '<br />';
2287  } else {
2288  $message = sprintf($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'), $row['list_type']);
2289  $out .= '<span class="label label-warning">' . htmlspecialchars($message) . '</span>';
2290  }
2291  } else {
2292  $out .= '<strong>' . $this->‪getLanguageService()->‪getLL('noPluginSelected') . '</strong>';
2293  }
2294  $out .= htmlspecialchars($this->‪getLanguageService()->sL(
2295  ‪BackendUtility::getLabelFromItemlist('tt_content', 'pages', $row['pages'])
2296  )) . '<br />';
2297  break;
2298  default:
2299  $contentType = $this->CType_labels[$row['CType']];
2300  if (!isset($contentType)) {
2301  $contentType = ‪BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'CType', $row['CType']);
2302  }
2303 
2304  if ($contentType) {
2305  $out .= $this->‪linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />';
2306  if ($row['bodytext']) {
2307  $out .= $this->‪linkEditContent($this->‪renderText($row['bodytext']), $row) . '<br />';
2308  }
2309  if ($row['image']) {
2310  $out .= $this->‪linkEditContent($this->‪getThumbCodeUnlinked($row, 'tt_content', 'image'), $row) . '<br />';
2311  }
2312  } else {
2313  $message = sprintf(
2314  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'),
2315  $row['CType']
2316  );
2317  $out .= '<span class="label label-warning">' . htmlspecialchars($message) . '</span>';
2318  }
2319  }
2320  }
2321  // Wrap span-tags:
2322  $out = '
2323  <span class="exampleContent">' . $out . '</span>';
2324  // Add header:
2325  $out = $outHeader . $out;
2326  // Return values:
2327  if ($this->‪isDisabled('tt_content', $row)) {
2328  return '<span class="text-muted">' . $out . '</span>';
2329  }
2330  return $out;
2331  }
2332 
2339  protected function ‪generateListForCTypeMenu(array $row)
2340  {
2341  ‪$table = 'pages';
2342  $field = 'pages';
2343  // get categories instead of pages
2344  if (strpos($row['menu_type'], 'categorized_') !== false) {
2345  ‪$table = 'sys_category';
2346  $field = 'selected_categories';
2347  }
2348  if (trim($row[$field]) === '') {
2349  return '';
2350  }
2351  $content = '';
2352  $uidList = explode(',', $row[$field]);
2353  foreach ($uidList as $uid) {
2354  $uid = (int)$uid;
2355  $record = ‪BackendUtility::getRecord(‪$table, $uid, 'title');
2356  $content .= '<br>' . htmlspecialchars($record['title']) . ' (' . $uid . ')';
2357  }
2358  return $content;
2359  }
2360 
2371  public function ‪getNonTranslatedTTcontentUids($defaultLanguageUids, ‪$id, $lP)
2372  {
2373  if ($lP && !empty($defaultLanguageUids)) {
2374  // Select all translations here:
2375  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2376  ->getQueryBuilderForTable('tt_content');
2377  $queryBuilder->getRestrictions()
2378  ->removeAll()
2379  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2380  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, null, false));
2381  $queryBuilder
2382  ->select('*')
2383  ->from('tt_content')
2384  ->where(
2385  $queryBuilder->expr()->eq(
2386  'sys_language_uid',
2387  $queryBuilder->createNamedParameter($lP, \PDO::PARAM_INT)
2388  ),
2389  $queryBuilder->expr()->in(
2390  'l18n_parent',
2391  $queryBuilder->createNamedParameter($defaultLanguageUids, Connection::PARAM_INT_ARRAY)
2392  )
2393  );
2394 
2395  $result = $queryBuilder->execute();
2396 
2397  // Flip uids:
2398  $defaultLanguageUids = array_flip($defaultLanguageUids);
2399  // Traverse any selected elements and unset original UID if any:
2400  while ($row = $result->fetch()) {
2401  ‪BackendUtility::workspaceOL('tt_content', $row);
2402  unset($defaultLanguageUids[$row['l18n_parent']]);
2403  }
2404  // Flip again:
2405  $defaultLanguageUids = array_keys($defaultLanguageUids);
2406  }
2407  return $defaultLanguageUids;
2408  }
2409 
2417  public function ‪newLanguageButton($defaultLanguageUids, $lP)
2418  {
2419  $lP = (int)$lP;
2420  if (!$this->doEdit || !$lP) {
2421  return '';
2422  }
2423  $theNewButton = '';
2424 
2425  $localizationTsConfig = ‪BackendUtility::getPagesTSconfig($this->id)['mod.']['web_layout.']['localization.'] ?? [];
2426  $allowCopy = (bool)($localizationTsConfig['enableCopy'] ?? true);
2427  $allowTranslate = (bool)($localizationTsConfig['enableTranslate'] ?? true);
2428  if (!empty($this->languageHasTranslationsCache[$lP])) {
2429  if (isset($this->languageHasTranslationsCache[$lP]['hasStandAloneContent'])) {
2430  $allowTranslate = false;
2431  }
2432  if (isset($this->languageHasTranslationsCache[$lP]['hasTranslations'])) {
2433  $allowCopy = $allowCopy && !$this->languageHasTranslationsCache[$lP]['hasTranslations'];
2434  }
2435  }
2436 
2437  if (isset($this->contentElementCache[$lP]) && is_array($this->contentElementCache[$lP])) {
2438  foreach ($this->contentElementCache[$lP] as $column => $records) {
2439  foreach ($records as $record) {
2440  $key = array_search($record['l10n_source'], $defaultLanguageUids);
2441  if ($key !== false) {
2442  unset($defaultLanguageUids[$key]);
2443  }
2444  }
2445  }
2446  }
2447 
2448  if (!empty($defaultLanguageUids)) {
2449  $theNewButton =
2450  '<a'
2451  . ' href="#"'
2452  . ' class="btn btn-default btn-sm t3js-localize disabled"'
2453  . ' title="' . htmlspecialchars($this->‪getLanguageService()->getLL('newPageContent_translate')) . '"'
2454  . ' data-page="' . htmlspecialchars($this->‪getLocalizedPageTitle()) . '"'
2455  . ' data-has-elements="' . (int)!empty($this->contentElementCache[$lP]) . '"'
2456  . ' data-allow-copy="' . (int)$allowCopy . '"'
2457  . ' data-allow-translate="' . (int)$allowTranslate . '"'
2458  . ' data-table="tt_content"'
2459  . ' data-page-id="' . (int)GeneralUtility::_GP('id') . '"'
2460  . ' data-language-id="' . $lP . '"'
2461  . ' data-language-name="' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '"'
2462  . '>'
2463  . $this->iconFactory->getIcon('actions-localize', ‪Icon::SIZE_SMALL)->render()
2464  . ' ' . htmlspecialchars($this->‪getLanguageService()->getLL('newPageContent_translate'))
2465  . '</a>';
2466  }
2467 
2468  return $theNewButton;
2469  }
2470 
2480  public function ‪newContentElementOnClick(‪$id, $colPos, $sys_language)
2481  {
2482  if ($this->option_newWizard) {
2483  $routeName = ‪BackendUtility::getPagesTSconfig(‪$id)['mod.']['newContentElementWizard.']['override']
2484  ?? 'new_content_element_wizard';
2485  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2486  $url = $uriBuilder->buildUriFromRoute($routeName, [
2487  'id' => ‪$id,
2488  'colPos' => $colPos,
2489  'sys_language_uid' => $sys_language,
2490  'uid_pid' => ‪$id,
2491  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
2492  ]);
2493  $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue((string)$url) . ';';
2494  } else {
2495  $onClick = ‪BackendUtility::editOnClick('&edit[tt_content][' . ‪$id . ']=new&defVals[tt_content][colPos]='
2496  . $colPos . '&defVals[tt_content][sys_language_uid]=' . $sys_language);
2497  }
2498  return $onClick;
2499  }
2500 
2510  public function ‪linkEditContent($str, $row)
2511  {
2512  if ($this->doEdit && $this->‪getBackendUser()->recordEditAccessInternals('tt_content', $row)) {
2513  $urlParameters = [
2514  'edit' => [
2515  'tt_content' => [
2516  $row['uid'] => 'edit'
2517  ]
2518  ],
2519  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid']
2520  ];
2521  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2522  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
2523  // Return link
2524  return '<a href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($this->‪getLanguageService()->getLL('edit')) . '">' . $str . '</a>';
2525  }
2526  return $str;
2527  }
2538  public function ‪languageSelector(‪$id)
2539  {
2540  if (!$this->‪getBackendUser()->check('tables_modify', 'pages')) {
2541  return '';
2542  }
2543  ‪$id = (int)‪$id;
2544 
2545  // First, select all languages that are available for the current user
2546  $availableTranslations = [];
2547  foreach ($this->siteLanguages as $language) {
2548  if ($language->getLanguageId() <= 0) {
2549  continue;
2550  }
2551  $availableTranslations[$language->getLanguageId()] = $language->getTitle();
2552  }
2553 
2554  // Then, subtract the languages which are already on the page:
2555  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
2556  $queryBuilder->getRestrictions()->removeAll()
2557  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2558  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2559  $queryBuilder->select('uid', ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'])
2560  ->from('pages')
2561  ->where(
2562  $queryBuilder->expr()->eq(
2563  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
2564  $queryBuilder->createNamedParameter(‪$id, \PDO::PARAM_INT)
2565  )
2566  );
2567  $statement = $queryBuilder->execute();
2568  while ($row = $statement->fetch()) {
2569  unset($availableTranslations[(int)$row[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']]]);
2570  }
2571  // If any languages are left, make selector:
2572  if (!empty($availableTranslations)) {
2573  ‪$output = '<option value="">' . htmlspecialchars($this->‪getLanguageService()->getLL('new_language')) . '</option>';
2574  foreach ($availableTranslations as $languageUid => $languageTitle) {
2575  // Build localize command URL to DataHandler (tce_db)
2576  // which redirects to FormEngine (record_edit)
2577  // which, when finished editing should return back to the current page (returnUrl)
2578  $parameters = [
2579  'justLocalized' => 'pages:' . ‪$id . ':' . $languageUid,
2580  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
2581  ];
2582  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2583  $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', $parameters);
2585  '&cmd[pages][' . ‪$id . '][localize]=' . $languageUid,
2586  $redirectUrl
2587  );
2588 
2589  ‪$output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>';
2590  }
2591 
2592  return '<div class="form-inline form-inline-spaced">'
2593  . '<div class="form-group">'
2594  . '<select class="form-control input-sm" name="createNewLanguage" onchange="window.location.href=this.options[this.selectedIndex].value">'
2595  . ‪$output
2596  . '</select></div></div>';
2597  }
2598  return '';
2599  }
2600 
2608  public function ‪getResult(Statement $result, string ‪$table = 'tt_content'): array
2609  {
2610  ‪$output = [];
2611  // Traverse the result:
2612  while ($row = $result->fetch()) {
2613  ‪BackendUtility::workspaceOL(‪$table, $row, -99, true);
2614  if ($row) {
2615  // Add the row to the array:
2616  ‪$output[] = $row;
2617  }
2618  }
2620  // Return selected records
2621  return ‪$output;
2622  }
2623 
2624  /********************************
2625  *
2626  * Various helper functions
2627  *
2628  ********************************/
2629 
2637  protected function ‪initializeClipboard()
2638  {
2639  // Start clipboard
2640  $this->clipboard = GeneralUtility::makeInstance(\‪TYPO3\CMS\Backend\Clipboard\Clipboard::class);
2641 
2642  // Initialize - reads the clipboard content from the user session
2643  $this->clipboard->initializeClipboard();
2644 
2645  // This locks the clipboard to the Normal for this request.
2646  $this->clipboard->lockToNormal();
2647 
2648  // Clean up pad
2649  $this->clipboard->cleanCurrent();
2650 
2651  // Save the clipboard content
2652  $this->clipboard->endClipboard();
2653  }
2654 
2660  protected function ‪generateTtContentDataArray(array $rowArray)
2661  {
2662  if (empty($this->tt_contentData)) {
2663  $this->tt_contentData = [
2664  'nextThree' => [],
2665  'next' => [],
2666  'prev' => [],
2667  ];
2668  }
2669  foreach ($rowArray as $key => $value) {
2670  // Create the list of the next three ids (for editing links...)
2671  for ($i = 0; $i < ‪$this->nextThree; $i++) {
2672  if (isset($rowArray[$key - $i])
2673  && !GeneralUtility::inList($this->tt_contentData['nextThree'][$rowArray[$key - $i]['uid']], $value['uid'])
2674  ) {
2675  $this->tt_contentData['nextThree'][$rowArray[$key - $i]['uid']] .= $value['uid'] . ',';
2676  }
2677  }
2678 
2679  // Create information for next and previous content elements
2680  if (isset($rowArray[$key - 1])) {
2681  if (isset($rowArray[$key - 2])) {
2682  $this->tt_contentData['prev'][$value['uid']] = -$rowArray[$key - 2]['uid'];
2683  } else {
2684  $this->tt_contentData['prev'][$value['uid']] = $value['pid'];
2685  }
2686  $this->tt_contentData['next'][$rowArray[$key - 1]['uid']] = -$value['uid'];
2687  }
2688  }
2689  }
2690 
2698  public function ‪numberOfRecords(‪$table, $pid)
2699  {
2700  $count = 0;
2701  if (‪$GLOBALS['TCA'][‪$table]) {
2702  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2703  ->getQueryBuilderForTable(‪$table);
2704  $queryBuilder->getRestrictions()
2705  ->removeAll()
2706  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2707  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2708  $count = (int)$queryBuilder->count('uid')
2709  ->from(‪$table)
2710  ->where(
2711  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))
2712  )
2713  ->execute()
2714  ->fetchColumn();
2715  }
2716 
2717  return $count;
2718  }
2726  public function ‪renderText($input)
2727  {
2728  $input = strip_tags($input);
2729  $input = GeneralUtility::fixed_lgd_cs($input, 1500);
2730  return nl2br(htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8', false));
2731  }
2732 
2741  public function ‪getIcon(‪$table, $row, $enabledClickMenuItems = '')
2742  {
2743  // Initialization
2744  $toolTip = ‪BackendUtility::getRecordToolTip($row, 'tt_content');
2745  $icon = '<span ' . $toolTip . '>' . $this->iconFactory->getIconForRecord(‪$table, $row, ‪Icon::SIZE_SMALL)->render() . '</span>';
2746  $this->counter++;
2747  // The icon with link
2748  if ($this->‪getBackendUser()->recordEditAccessInternals(‪$table, $row)) {
2749  $icon = ‪BackendUtility::wrapClickMenuOnIcon($icon, ‪$table, $row['uid']);
2750  }
2751  return $icon;
2752  }
2753 
2763  public function ‪getProcessedValue(‪$table, $fieldList, array $row, array &$info)
2764  {
2765  // Splitting values from $fieldList
2766  $fieldArr = explode(',', $fieldList);
2767  // Traverse fields from $fieldList
2768  foreach ($fieldArr as $field) {
2769  if ($row[$field]) {
2770  $info[] = '<strong>' . htmlspecialchars($this->itemLabels[$field]) . '</strong> '
2771  . htmlspecialchars(‪BackendUtility::getProcessedValue(‪$table, $field, $row[$field]));
2772  }
2773  }
2774  }
2775 
2783  public function ‪isDisabled(‪$table, $row)
2784  {
2785  $enableCols = ‪$GLOBALS['TCA'][‪$table]['ctrl']['enablecolumns'];
2786  return $enableCols['disabled'] && $row[$enableCols['disabled']]
2787  || $enableCols['starttime'] && $row[$enableCols['starttime']] > ‪$GLOBALS['EXEC_TIME']
2788  || $enableCols['endtime'] && $row[$enableCols['endtime']] && $row[$enableCols['endtime']] < ‪$GLOBALS['EXEC_TIME'];
2789  }
2790 
2799  public function ‪noEditIcon($label = 'noEditItems')
2800  {
2801  $title = htmlspecialchars($this->‪getLanguageService()->getLL($label));
2802  return '<span title="' . $title . '">' . $this->iconFactory->getIcon('status-edit-read-only', ‪Icon::SIZE_SMALL)->render() . '</span>';
2803  }
2804 
2805  /*****************************************
2806  *
2807  * External renderings
2808  *
2809  *****************************************/
2810 
2819  public function ‪getTableMenu(‪$id)
2820  {
2821  // Initialize:
2822  $this->activeTables = [];
2823  $theTables = ['tt_content'];
2824  // External tables:
2825  if (is_array($this->externalTables)) {
2826  $theTables = array_unique(array_merge($theTables, array_keys($this->externalTables)));
2827  }
2828  $out = '';
2829  // Traverse tables to check:
2830  foreach ($theTables as $tName) {
2831  // Check access and whether the proper extensions are loaded:
2832  if ($this->‪getBackendUser()->check('tables_select', $tName)
2833  && (
2834  isset($this->externalTables[$tName])
2835  || $tName === 'fe_users' || $tName === 'tt_content'
2836  || \‪TYPO3\CMS\Core\Utility\‪ExtensionManagementUtility::isLoaded($tName)
2837  )
2838  ) {
2839  // Make query to count records from page:
2840  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2841  ->getQueryBuilderForTable($tName);
2842  $queryBuilder->getRestrictions()
2843  ->removeAll()
2844  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2845  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2846  $count = $queryBuilder->count('uid')
2847  ->from($tName)
2848  ->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter(‪$id, \PDO::PARAM_INT)))
2849  ->execute()
2850  ->fetchColumn();
2851  // If records were found (or if "tt_content" is the table...):
2852  if ($count || $tName === 'tt_content') {
2853  // Add row to menu:
2854  $out .= '
2855  <td><a href="#' . $tName . '" title="' . htmlspecialchars($this->‪getLanguageService()->sL(‪$GLOBALS['TCA'][$tName]['ctrl']['title'])) . '"></a>'
2856  . $this->iconFactory->getIconForRecord($tName, [], ‪Icon::SIZE_SMALL)->render()
2857  . '</td>';
2858  // ... and to the internal array, activeTables we also add table icon and title (for use elsewhere)
2859  $title = htmlspecialchars($this->‪getLanguageService()->sL(‪$GLOBALS['TCA'][$tName]['ctrl']['title']))
2860  . ': ' . $count . ' ' . htmlspecialchars($this->‪getLanguageService()->getLL('records'));
2861  $this->activeTables[$tName] = '<span title="' . $title . '">'
2862  . $this->iconFactory->getIconForRecord($tName, [], ‪Icon::SIZE_SMALL)->render()
2863  . '</span>'
2864  . '&nbsp;' . htmlspecialchars($this->‪getLanguageService()->sL(‪$GLOBALS['TCA'][$tName]['ctrl']['title']));
2865  }
2866  }
2867  }
2868  // Wrap cells in table tags:
2869  $out = '
2870  <!--
2871  Menu of tables on the page (table menu)
2872  -->
2873  <table border="0" cellpadding="0" cellspacing="0" id="typo3-page-tblMenu">
2874  <tr>' . $out . '
2875  </tr>
2876  </table>';
2877  // Return the content:
2878  return $out;
2879  }
2880 
2889  public function ‪getThumbCodeUnlinked($row, ‪$table, $field)
2890  {
2891  return ‪BackendUtility::thumbCode($row, ‪$table, $field, '', '', null, 0, '', '', false);
2892  }
2893 
2902  protected function ‪checkIfTranslationsExistInLanguage(array $contentElements, int $language)
2903  {
2904  // If in default language, you may always create new entries
2905  // Also, you may override this strict behavior via user TS Config
2906  // If you do so, you're on your own and cannot rely on any support by the TYPO3 core
2907  // We jump out here since we don't need to do the expensive loop operations
2908  $allowInconsistentLanguageHandling = (bool)(‪BackendUtility::getPagesTSconfig($this->id)['mod.']['web_layout.']['allowInconsistentLanguageHandling'] ?? false);
2909  if ($language === 0 || $allowInconsistentLanguageHandling) {
2910  return false;
2911  }
2915  if (!isset($this->languageHasTranslationsCache[$language])) {
2916  foreach ($contentElements as $columns) {
2917  foreach ($columns as $contentElement) {
2918  if ((int)$contentElement['l18n_parent'] === 0) {
2919  $this->languageHasTranslationsCache[$language]['hasStandAloneContent'] = true;
2920  $this->languageHasTranslationsCache[$language]['mode'] = 'free';
2921  }
2922  if ((int)$contentElement['l18n_parent'] > 0) {
2923  $this->languageHasTranslationsCache[$language]['hasTranslations'] = true;
2924  $this->languageHasTranslationsCache[$language]['mode'] = 'connected';
2925  }
2926  }
2927  }
2928  if (!isset($this->languageHasTranslationsCache[$language])) {
2929  $this->languageHasTranslationsCache[$language]['hasTranslations'] = false;
2930  }
2931  // Check whether we have a mix of both
2932  if (isset($this->languageHasTranslationsCache[$language]['hasStandAloneContent'])
2933  && $this->languageHasTranslationsCache[$language]['hasTranslations']
2934  ) {
2935  $this->languageHasTranslationsCache[$language]['mode'] = 'mixed';
2936  $siteLanguage = $this->siteLanguages[$language];
2937  $message = GeneralUtility::makeInstance(
2938  FlashMessage::class,
2939  sprintf($this->‪getLanguageService()->getLL('staleTranslationWarning'), $siteLanguage->getTitle()),
2940  sprintf($this->‪getLanguageService()->getLL('staleTranslationWarningTitle'), $siteLanguage->getTitle()),
2942  );
2943  $service = GeneralUtility::makeInstance(FlashMessageService::class);
2944  $queue = $service->getMessageQueueByIdentifier();
2945  $queue->addMessage($message);
2946  }
2947  }
2948 
2949  return $this->languageHasTranslationsCache[$language]['hasTranslations'];
2950  }
2951 
2955  protected function ‪getBackendLayoutView()
2956  {
2957  return GeneralUtility::makeInstance(BackendLayoutView::class);
2958  }
2959 
2963  protected function ‪getBackendUser()
2964  {
2965  return ‪$GLOBALS['BE_USER'];
2966  }
2967 
2971  protected function ‪getPageLayoutController()
2972  {
2973  return ‪$GLOBALS['SOBE'];
2974  }
2975 
2987  public function ‪start(‪$id, ‪$table, $pointer, $search = '', $levels = 0, ‪$showLimit = 0)
2988  {
2989  $this->‪resolveSiteLanguages((int)$id);
2990  $backendUser = $this->‪getBackendUser();
2991  // Setting internal variables:
2992  // sets the parent id
2993  $this->id = (int)‪$id;
2994  if (‪$GLOBALS['TCA'][‪$table]) {
2995  // Setting single table mode, if table exists:
2996  $this->table = ‪$table;
2997  }
2998  $this->firstElementNumber = $pointer;
2999  $this->searchString = trim($search);
3000  $this->searchLevels = (int)$levels;
3001  $this->showLimit = ‪MathUtility::forceIntegerInRange(‪$showLimit, 0, 10000);
3002  // Setting GPvars:
3003  $this->csvOutput = (bool)GeneralUtility::_GP('csv');
3004  $this->sortField = GeneralUtility::_GP('sortField');
3005  $this->sortRev = GeneralUtility::_GP('sortRev');
3006  $this->displayFields = GeneralUtility::_GP('displayFields');
3007  $this->duplicateField = GeneralUtility::_GP('duplicateField');
3008  if (GeneralUtility::_GP('justLocalized')) {
3009  $this->‪localizationRedirect(GeneralUtility::_GP('justLocalized'));
3010  }
3011  // Init dynamic vars:
3012  $this->counter = 0;
3013  $this->JScode = '';
3014  $this->HTMLcode = '';
3015  // Limits
3016  if (isset($this->modTSconfig['properties']['itemsLimitPerTable'])) {
3017  $this->itemsLimitPerTable = ‪MathUtility::forceIntegerInRange(
3018  (int)$this->modTSconfig['properties']['itemsLimitPerTable'],
3019  1,
3020  10000
3021  );
3022  }
3023  if (isset($this->modTSconfig['properties']['itemsLimitSingleTable'])) {
3024  $this->itemsLimitSingleTable = ‪MathUtility::forceIntegerInRange(
3025  (int)$this->modTSconfig['properties']['itemsLimitSingleTable'],
3026  1,
3027  10000
3028  );
3029  }
3030 
3031  // $table might be NULL at this point in the code. As the expressionBuilder
3032  // is used to limit returned records based on the page permissions and the
3033  // uid field of the pages it can hardcoded to work on the pages table.
3034  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3035  ->getQueryBuilderForTable('pages')
3036  ->expr();
3037  $permsClause = $expressionBuilder->andX($backendUser->getPagePermsClause(‪Permission::PAGE_SHOW));
3038  // This will hide records from display - it has nothing to do with user rights!!
3039  $pidList = GeneralUtility::intExplode(',', $backendUser->getTSConfig()['options.']['hideRecords.']['pages'] ?? '', true);
3040  if (!empty($pidList)) {
3041  $permsClause->add($expressionBuilder->notIn('pages.uid', $pidList));
3042  }
3043  $this->perms_clause = (string)$permsClause;
3044 
3045  // Get configuration of collapsed tables from user uc and merge with sanitized GP vars
3046  $this->tablesCollapsed = is_array($backendUser->uc['moduleData']['list'])
3047  ? $backendUser->uc['moduleData']['list']
3048  : [];
3049  $collapseOverride = GeneralUtility::_GP('collapse');
3050  if (is_array($collapseOverride)) {
3051  foreach ($collapseOverride as $collapseTable => $collapseValue) {
3052  if (is_array(‪$GLOBALS['TCA'][$collapseTable]) && ($collapseValue == 0 || $collapseValue == 1)) {
3053  $this->tablesCollapsed[$collapseTable] = $collapseValue;
3054  }
3055  }
3056  // Save modified user uc
3057  $backendUser->uc['moduleData']['list'] = ‪$this->tablesCollapsed;
3058  $backendUser->writeUC($backendUser->uc);
3059  ‪$returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
3060  if (‪$returnUrl !== '') {
3062  }
3063  }
3064  $this->‪initializeLanguages();
3065  }
3066 
3072  public function ‪generateList()
3073  {
3074  // Set page record in header
3075  $this->pageRecord = ‪BackendUtility::getRecordWSOL('pages', $this->id);
3076  $hideTablesArray = GeneralUtility::trimExplode(',', $this->hideTables);
3077 
3078  $backendUser = $this->‪getBackendUser();
3079 
3080  // pre-process tables and add sorting instructions
3081  $tableNames = array_flip(array_keys(‪$GLOBALS['TCA']));
3082  foreach ($tableNames as $tableName => &$config) {
3083  $hideTable = false;
3084 
3085  // Checking if the table should be rendered:
3086  // Checks that we see only permitted/requested tables:
3087  if ($this->table && $tableName !== $this->table
3088  || $this->tableList && !GeneralUtility::inList($this->tableList, $tableName)
3089  || !$backendUser->check('tables_select', $tableName)
3090  ) {
3091  $hideTable = true;
3092  }
3093 
3094  if (!$hideTable) {
3095  // Don't show table if hidden by TCA ctrl section
3096  // Don't show table if hidden by pageTSconfig mod.web_list.hideTables
3097  $hideTable = $hideTable
3098  || !empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['hideTable'])
3099  || in_array($tableName, $hideTablesArray, true)
3100  || in_array('*', $hideTablesArray, true);
3101  // Override previous selection if table is enabled or hidden by TSconfig TCA override mod.web_list.table
3102  if (isset($this->tableTSconfigOverTCA[$tableName . '.']['hideTable'])) {
3103  $hideTable = (bool)$this->tableTSconfigOverTCA[$tableName . '.']['hideTable'];
3104  }
3105  }
3106  if ($hideTable) {
3107  unset($tableNames[$tableName]);
3108  } else {
3109  if (isset($this->tableDisplayOrder[$tableName])) {
3110  // Copy display order information
3111  $tableNames[$tableName] = $this->tableDisplayOrder[$tableName];
3112  } else {
3113  $tableNames[$tableName] = [];
3114  }
3115  }
3116  }
3117  unset($config);
3118 
3119  $orderedTableNames = GeneralUtility::makeInstance(DependencyOrderingService::class)
3120  ->orderByDependencies($tableNames);
3121 
3122  foreach ($orderedTableNames as $tableName => $_) {
3123  // check if we are in single- or multi-table mode
3124  if ($this->table) {
3125  $this->iLimit = isset(‪$GLOBALS['TCA'][$tableName]['interface']['maxSingleDBListItems'])
3126  ? (int)‪$GLOBALS['TCA'][$tableName]['interface']['maxSingleDBListItems']
3127  : $this->itemsLimitSingleTable;
3128  } else {
3129  // if there are no records in table continue current foreach
3130  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3131  ->getQueryBuilderForTable($tableName);
3132  $queryBuilder->getRestrictions()
3133  ->removeAll()
3134  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3135  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3136  $queryBuilder = $this->‪addPageIdConstraint($tableName, $queryBuilder);
3137  $firstRow = $queryBuilder->select('uid')
3138  ->from($tableName)
3139  ->execute()
3140  ->fetch();
3141  if (!is_array($firstRow)) {
3142  continue;
3143  }
3144  $this->iLimit = isset(‪$GLOBALS['TCA'][$tableName]['interface']['maxDBListItems'])
3145  ? (int)‪$GLOBALS['TCA'][$tableName]['interface']['maxDBListItems']
3146  : $this->itemsLimitPerTable;
3147  }
3148  if ($this->showLimit) {
3149  $this->iLimit = ‪$this->showLimit;
3150  }
3151  // Setting fields to select:
3152  if ($this->allFields) {
3153  ‪$fields = $this->‪makeFieldList($tableName);
3154  ‪$fields[] = 'tstamp';
3155  ‪$fields[] = 'crdate';
3156  ‪$fields[] = '_PATH_';
3157  ‪$fields[] = '_CONTROL_';
3158  if (is_array($this->setFields[$tableName])) {
3159  ‪$fields = array_intersect(‪$fields, $this->setFields[$tableName]);
3160  } else {
3161  ‪$fields = [];
3162  }
3163  } else {
3164  ‪$fields = [];
3165  }
3166 
3167  // Finally, render the list:
3168  $this->HTMLcode .= $this->‪getTable($tableName, $this->id, implode(',', ‪$fields));
3169  }
3170  }
3171 
3178  public function ‪getSearchBox($formFields = true)
3179  {
3180  $lang = $this->‪getLanguageService();
3181  // Setting form-elements, if applicable:
3182  $formElements = ['', ''];
3183  if ($formFields) {
3184  $formElements = [
3185  '<form action="' . htmlspecialchars(
3186  $this->‪listURL('', '-1', 'firstElementNumber,search_field')
3187  ) . '" method="post">',
3188  '</form>'
3189  ];
3190  }
3191  // Make level selector:
3192  $opt = [];
3194  // "New" generation of search levels ... based on TS config
3195  $config = ‪BackendUtility::getPagesTSconfig($this->id);
3196  $searchLevelsFromTSconfig = $config['mod.']['web_list.']['searchLevel.']['items.'];
3197  $searchLevelItems = [];
3198 
3199  // get translated labels for search levels from pagets
3200  foreach ($searchLevelsFromTSconfig as $keySearchLevel => $labelConfigured) {
3201  $label = $lang->sL('LLL:' . $labelConfigured);
3202  if ($label === '') {
3203  $label = $labelConfigured;
3204  }
3205  $searchLevelItems[$keySearchLevel] = $label;
3206  }
3207 
3208  foreach ($searchLevelItems as $kv => $label) {
3209  $opt[] = '<option value="' . $kv . '"' . ($kv === $this->searchLevels ? ' selected="selected"' : '') . '>' . htmlspecialchars(
3210  $label
3211  ) . '</option>';
3212  }
3213  $lMenu = '<select class="form-control" name="search_levels" title="' . htmlspecialchars(
3214  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search_levels')
3215  ) . '" id="search_levels">' . implode('', $opt) . '</select>';
3216  // Table with the search box:
3217  $content = '<div class="db_list-searchbox-form db_list-searchbox-toolbar module-docheader-bar module-docheader-bar-search t3js-module-docheader-bar t3js-module-docheader-bar-search" id="db_list-searchbox-toolbar" style="display: ' . ($this->searchString == '' ? 'none' : 'block') . ';">
3218  ' . $formElements[0] . '
3219  <div id="typo3-dblist-search">
3220  <div class="panel panel-default">
3221  <div class="panel-body">
3222  <div class="row">
3223  <div class="form-group col-xs-12">
3224  <label for="search_field">' . htmlspecialchars(
3225  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.searchString')
3226  ) . ': </label>
3227  <input class="form-control" type="search" placeholder="' . htmlspecialchars(
3228  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')
3229  ) . '" title="' . htmlspecialchars(
3230  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchString')
3231  ) . '" name="search_field" id="search_field" value="' . htmlspecialchars($this->searchString) . '" />
3232  </div>
3233  <div class="form-group col-xs-12 col-sm-6">
3234  <label for="search_levels">' . htmlspecialchars(
3235  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.search_levels')
3236  ) . ': </label>
3237  ' . $lMenu . '
3238  </div>
3239  <div class="form-group col-xs-12 col-sm-6">
3240  <label for="showLimit">' . htmlspecialchars(
3241  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.limit')
3242  ) . ': </label>
3243  <input class="form-control" type="number" min="0" max="10000" placeholder="10" title="' . htmlspecialchars(
3244  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.limit')
3245  ) . '" name="showLimit" id="showLimit" value="' . htmlspecialchars(
3246  ($this->showLimit ? $this->showLimit : '')
3247  ) . '" />
3248  </div>
3249  <div class="form-group col-xs-12">
3250  <div class="form-control-wrap">
3251  <button type="submit" class="btn btn-default" name="search" title="' . htmlspecialchars(
3252  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')
3253  ) . '">
3254  ' . $this->iconFactory->getIcon('actions-search', ‪Icon::SIZE_SMALL)->render(
3255  ) . ' ' . htmlspecialchars(
3256  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search')
3257  ) . '
3258  </button>
3259  </div>
3260  </div>
3261  </div>
3262  </div>
3263  </div>
3264  </div>
3265  ' . $formElements[1] . '</div>';
3266  return $content;
3267  }
3268 
3273  public function ‪setDispFields()
3274  {
3275  $backendUser = $this->‪getBackendUser();
3276  // Getting from session:
3277  $dispFields = $backendUser->getModuleData('list/displayFields');
3278  // If fields has been inputted, then set those as the value and push it to session variable:
3279  if (is_array($this->displayFields)) {
3280  reset($this->displayFields);
3281  $tKey = key($this->displayFields);
3282  $dispFields[$tKey] = $this->displayFields[$tKey];
3283  $backendUser->pushModuleData('list/displayFields', $dispFields);
3284  }
3285  // Setting result:
3286  $this->setFields = $dispFields;
3287  }
3288 
3297  public function ‪thumbCode($row, ‪$table, $field)
3298  {
3299  return ‪BackendUtility::thumbCode($row, ‪$table, $field);
3300  }
3301 
3312  public function ‪getQueryBuilder(
3313  string ‪$table,
3314  int $pageId,
3315  array $additionalConstraints = [],
3316  array ‪$fields = ['*']
3317  ): QueryBuilder {
3318  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3319  ->getQueryBuilderForTable(‪$table);
3320  $queryBuilder->getRestrictions()
3321  ->removeAll()
3322  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3323  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3324  $queryBuilder
3325  ->select(...‪$fields)
3326  ->from(‪$table);
3327 
3328  if (!empty($additionalConstraints)) {
3329  $queryBuilder->andWhere(...$additionalConstraints);
3330  }
3331 
3332  $queryBuilder = $this->‪prepareQueryBuilder($table, $pageId, ‪$fields, $additionalConstraints, $queryBuilder);
3333 
3334  return $queryBuilder;
3335  }
3336 
3349  protected function ‪prepareQueryBuilder(
3350  string ‪$table,
3351  int $pageId,
3352  array $fieldList = ['*'],
3353  array $additionalConstraints = [],
3354  QueryBuilder $queryBuilder,
3355  bool $addSorting = true
3356  ): QueryBuilder {
3357  $parameters = [
3358  'table' => ‪$table,
3359  'fields' => $fieldList,
3360  'groupBy' => null,
3361  'orderBy' => null,
3362  'firstResult' => $this->firstElementNumber ?: null,
3363  'maxResults' => $this->iLimit ?: null
3364  ];
3365 
3366  if ($this->iLimit > 0) {
3367  $queryBuilder->setMaxResults($this->iLimit);
3368  }
3369 
3370  if ($addSorting) {
3371  if ($this->sortField && in_array($this->sortField, $this->‪makeFieldList($table, 1))) {
3372  $queryBuilder->orderBy($this->sortField, $this->sortRev ? 'DESC' : 'ASC');
3373  } else {
3374  $orderBy = ‪$GLOBALS['TCA'][‪$table]['ctrl']['sortby'] ?: ‪$GLOBALS['TCA'][‪$table]['ctrl']['default_sortby'];
3375  $orderBys = ‪QueryHelper::parseOrderBy((string)$orderBy);
3376  foreach ($orderBys as $orderBy) {
3377  $queryBuilder->addOrderBy($orderBy[0], $orderBy[1]);
3378  }
3379  }
3380  }
3381 
3382  // Build the query constraints
3383  $queryBuilder = $this->‪addPageIdConstraint($table, $queryBuilder);
3384  $searchWhere = $this->‪makeSearchString($table, $pageId);
3385  if (!empty($searchWhere)) {
3386  $queryBuilder->andWhere($searchWhere);
3387  }
3388 
3389  // Filtering on displayable pages (permissions):
3390  if (‪$table === 'pages' && $this->perms_clause) {
3391  $queryBuilder->andWhere($this->perms_clause);
3392  }
3393 
3394  // Filter out records that are translated, if TSconfig mod.web_list.hideTranslations is set
3395  if (!empty(‪$GLOBALS['TCA'][‪$table]['ctrl']['transOrigPointerField'])
3396  && (GeneralUtility::inList($this->hideTranslations, ‪$table) || $this->hideTranslations === '*')
3397  ) {
3398  $queryBuilder->andWhere(
3399  $queryBuilder->expr()->eq(
3400  ‪$GLOBALS['TCA'][‪$table]['ctrl']['transOrigPointerField'],
3401  0
3402  )
3403  );
3404  }
3405 
3406  $hookName = DatabaseRecordList::class;
3407  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookName]['buildQueryParameters'] ?? [] as $className) {
3408  // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0, the modifyQuery hook should be used instead.
3409  trigger_error('The hook ($GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][' . $hookName . '][\'buildQueryParameters\']) will be removed in TYPO3 v10.0, the modifyQuery hook should be used instead.', E_USER_DEPRECATED);
3410  $hookObject = GeneralUtility::makeInstance($className);
3411  if (method_exists($hookObject, 'buildQueryParametersPostProcess')) {
3412  $hookObject->buildQueryParametersPostProcess(
3413  $parameters,
3414  ‪$table,
3415  $pageId,
3416  $additionalConstraints,
3417  $fieldList,
3418  $this,
3419  $queryBuilder
3420  );
3421  }
3422  }
3423  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][PageLayoutView::class]['modifyQuery'] ?? [] as $className) {
3424  $hookObject = GeneralUtility::makeInstance($className);
3425  if (method_exists($hookObject, 'modifyQuery')) {
3426  $hookObject->modifyQuery(
3427  $parameters,
3428  ‪$table,
3429  $pageId,
3430  $additionalConstraints,
3431  $fieldList,
3432  $queryBuilder
3433  );
3434  }
3435  }
3436 
3437  // array_unique / array_filter used to eliminate empty and duplicate constraints
3438  // the array keys are eliminated by this as well to facilitate argument unpacking
3439  // when used with the querybuilder.
3440  // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0
3441  if (!empty($parameters['where'])) {
3442  $parameters['where'] = array_unique(array_filter(array_values($parameters['where'])));
3443  }
3444  if (!empty($parameters['where'])) {
3445  $this->‪logDeprecation('where');
3446  $queryBuilder->where(...$parameters['where']);
3447  }
3448  if (!empty($parameters['orderBy'])) {
3449  $this->‪logDeprecation('orderBy');
3450  foreach ($parameters['orderBy'] as $fieldNameAndSorting) {
3451  list($fieldName, $sorting) = $fieldNameAndSorting;
3452  $queryBuilder->addOrderBy($fieldName, $sorting);
3453  }
3454  }
3455  if (!empty($parameters['firstResult'])) {
3456  $this->‪logDeprecation('firstResult');
3457  $queryBuilder->setFirstResult((int)$parameters['firstResult']);
3458  }
3459  if (!empty($parameters['maxResults']) && $parameters['maxResults'] !== $this->iLimit) {
3460  $this->‪logDeprecation('maxResults');
3461  $queryBuilder->setMaxResults((int)$parameters['maxResults']);
3462  }
3463  if (!empty($parameters['groupBy'])) {
3464  $this->‪logDeprecation('groupBy');
3465  $queryBuilder->groupBy($parameters['groupBy']);
3466  }
3467 
3468  return $queryBuilder;
3469  }
3470 
3479  public function ‪setTotalItems(string ‪$table, int $pageId, array $constraints)
3480  {
3481  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3482  ->getQueryBuilderForTable(‪$table);
3483 
3484  $queryBuilder->getRestrictions()
3485  ->removeAll()
3486  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3487  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3488  $queryBuilder
3489  ->from(‪$table);
3490 
3491  if (!empty($constraints)) {
3492  $queryBuilder->andWhere(...$constraints);
3493  }
3494 
3495  $queryBuilder = $this->‪prepareQueryBuilder($table, $pageId, ['*'], $constraints, $queryBuilder, false);
3496  // Reset limit and offset for full count query
3497  $queryBuilder->setFirstResult(0);
3498  $queryBuilder->setMaxResults(1);
3499 
3500  $this->totalItems = (int)$queryBuilder->count('*')
3501  ->execute()
3502  ->fetchColumn();
3503  }
3504 
3513  public function ‪makeSearchString(‪$table, $currentPid = -1)
3514  {
3515  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(‪$table);
3516  $expressionBuilder = $queryBuilder->expr();
3517  $constraints = [];
3518  $currentPid = (int)$currentPid;
3519  $tablePidField = ‪$table === 'pages' ? 'uid' : 'pid';
3520  // Make query only if table is valid and a search string is actually defined
3521  if (empty($this->searchString)) {
3522  return '';
3523  }
3524 
3525  $searchableFields = $this->‪getSearchFields($table);
3526  if (‪MathUtility::canBeInterpretedAsInteger($this->searchString)) {
3527  $constraints[] = $expressionBuilder->eq('uid', (int)$this->searchString);
3528  foreach ($searchableFields as $fieldName) {
3529  if (!isset(‪$GLOBALS['TCA'][‪$table]['columns'][$fieldName])) {
3530  continue;
3531  }
3532  $fieldConfig = ‪$GLOBALS['TCA'][‪$table]['columns'][$fieldName]['config'];
3533  $fieldType = $fieldConfig['type'];
3534  $evalRules = $fieldConfig['eval'] ?: '';
3535  if ($fieldType === 'input' && $evalRules && GeneralUtility::inList($evalRules, 'int')) {
3536  if (!isset($fieldConfig['search']['pidonly'])
3537  || ($fieldConfig['search']['pidonly'] && $currentPid > 0)
3538  ) {
3539  $constraints[] = $expressionBuilder->andX(
3540  $expressionBuilder->eq($fieldName, (int)$this->searchString),
3541  $expressionBuilder->eq($tablePidField, (int)$currentPid)
3542  );
3543  }
3544  } elseif ($fieldType === 'text'
3545  || $fieldType === 'flex'
3546  || ($fieldType === 'input' && (!$evalRules || !preg_match('/\b(?:date|time|int)\b/', $evalRules)))
3547  ) {
3548  $constraints[] = $expressionBuilder->like(
3549  $fieldName,
3550  $queryBuilder->quote('%' . (int)$this->searchString . '%')
3551  );
3552  }
3553  }
3554  } elseif (!empty($searchableFields)) {
3555  $like = $queryBuilder->quote('%' . $queryBuilder->escapeLikeWildcards($this->searchString) . '%');
3556  foreach ($searchableFields as $fieldName) {
3557  if (!isset(‪$GLOBALS['TCA'][‪$table]['columns'][$fieldName])) {
3558  continue;
3559  }
3560  $fieldConfig = ‪$GLOBALS['TCA'][‪$table]['columns'][$fieldName]['config'];
3561  $fieldType = $fieldConfig['type'];
3562  $evalRules = $fieldConfig['eval'] ?: '';
3563  $searchConstraint = $expressionBuilder->andX(
3564  $expressionBuilder->comparison(
3565  'LOWER(' . $queryBuilder->quoteIdentifier($fieldName) . ')',
3566  'LIKE',
3567  'LOWER(' . $like . ')'
3568  )
3569  );
3570  if (is_array($fieldConfig['search'])) {
3571  $searchConfig = $fieldConfig['search'];
3572  if (in_array('case', $searchConfig)) {
3573  // Replace case insensitive default constraint
3574  $searchConstraint = $expressionBuilder->andX($expressionBuilder->like($fieldName, $like));
3575  }
3576  if (in_array('pidonly', $searchConfig) && $currentPid > 0) {
3577  $searchConstraint->add($expressionBuilder->eq($tablePidField, (int)$currentPid));
3578  }
3579  if ($searchConfig['andWhere']) {
3580  $searchConstraint->add(
3581  ‪QueryHelper::stripLogicalOperatorPrefix($fieldConfig['search']['andWhere'])
3582  );
3583  }
3584  }
3585  if ($fieldType === 'text'
3586  || $fieldType === 'flex'
3587  || $fieldType === 'input' && (!$evalRules || !preg_match('/\b(?:date|time|int)\b/', $evalRules))
3588  ) {
3589  if ($searchConstraint->count() !== 0) {
3590  $constraints[] = $searchConstraint;
3591  }
3592  }
3593  }
3594  }
3595  // If no search field conditions have been built ensure no results are returned
3596  if (empty($constraints)) {
3597  return '0=1';
3598  }
3599 
3600  return $expressionBuilder->orX(...$constraints);
3601  }
3602 
3609  protected function ‪getSearchFields($tableName)
3610  {
3611  ‪$fieldArray = [];
3612  $fieldListWasSet = false;
3613  // Get fields from ctrl section of TCA first
3614  if (isset(‪$GLOBALS['TCA'][$tableName]['ctrl']['searchFields'])) {
3615  ‪$fieldArray = GeneralUtility::trimExplode(',', ‪$GLOBALS['TCA'][$tableName]['ctrl']['searchFields'], true);
3616  $fieldListWasSet = true;
3617  }
3618  // Call hook to add or change the list
3619  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['mod_list']['getSearchFieldList'] ?? [] as $hookFunction) {
3620  $hookParameters = [
3621  'tableHasSearchConfiguration' => $fieldListWasSet,
3622  'tableName' => $tableName,
3623  'searchFields' => &‪$fieldArray,
3624  'searchString' => ‪$this->searchString
3625  ];
3626  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
3627  }
3628  return ‪$fieldArray;
3629  }
3630 
3639  public function ‪linkWrapTable(‪$table, $code)
3640  {
3641  if ($this->table !== ‪$table) {
3642  return '<a href="' . htmlspecialchars(
3643  $this->‪listURL('', $table, 'firstElementNumber')
3644  ) . '">' . $code . '</a>';
3645  }
3646  return '<a href="' . htmlspecialchars(
3647  $this->‪listURL('', '', 'sortField,sortRev,table,firstElementNumber')
3648  ) . '">' . $code . '</a>';
3649  }
3650 
3660  public function ‪linkWrapItems(‪$table, $uid, $code, $row)
3661  {
3662  $lang = $this->‪getLanguageService();
3663  $origCode = $code;
3664  // If the title is blank, make a "no title" label:
3665  if ((string)$code === '') {
3666  $code = '<i>[' . htmlspecialchars(
3667  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title')
3668  ) . ']</i> - '
3669  . htmlspecialchars(‪BackendUtility::getRecordTitle(‪$table, $row));
3670  } else {
3671  $code = htmlspecialchars($code, ENT_QUOTES, 'UTF-8', false);
3672  if ($code != htmlspecialchars($origCode)) {
3673  $code = '<span title="' . htmlspecialchars(
3674  $origCode,
3675  ENT_QUOTES,
3676  'UTF-8',
3677  false
3678  ) . '">' . $code . '</span>';
3679  }
3680  }
3681  switch ((string)$this->clickTitleMode) {
3682  case 'edit':
3683  // If the listed table is 'pages' we have to request the permission settings for each page:
3684  if (‪$table === 'pages') {
3685  $localCalcPerms = $this->‪getBackendUser()->‪calcPerms(
3686  ‪BackendUtility::getRecord('pages', $row['uid'])
3687  );
3688  $permsEdit = $localCalcPerms & ‪Permission::PAGE_EDIT;
3689  } else {
3690  $permsEdit = $this->calcPerms & ‪Permission::CONTENT_EDIT;
3691  }
3692  // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
3693  if ($permsEdit) {
3694  $params = '&edit[' . ‪$table . '][' . $row['uid'] . ']=edit';
3695  $code = '<a href="#" onclick="' . htmlspecialchars(
3696  ‪BackendUtility::editOnClick($params, '', -1)
3697  ) . '" title="' . htmlspecialchars($lang->getLL('edit')) . '">' . $code . '</a>';
3698  }
3699  break;
3700  case 'show':
3701  // "Show" link (only pages and tt_content elements)
3702  if (‪$table === 'pages' || ‪$table === 'tt_content') {
3703  $code = '<a href="#" onclick="' . htmlspecialchars(
3705  (‪$table === 'tt_content' ? $this->id . '#' . $row['uid'] : $row['uid'])
3706  )
3707  ) . '" title="' . htmlspecialchars(
3708  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')
3709  ) . '">' . $code . '</a>';
3710  }
3711  break;
3712  case 'info':
3713  // "Info": (All records)
3714  $code = '<a href="#" onclick="' . htmlspecialchars(
3715  'top.TYPO3.InfoWindow.showItem(\'' . ‪$table . '\', \'' . $row['uid'] . '\'); return false;'
3716  ) . '" title="' . htmlspecialchars($lang->getLL('showInfo')) . '">' . $code . '</a>';
3717  break;
3718  default:
3719  // Output the label now:
3720  if ($table === 'pages') {
3721  $code = '<a href="' . htmlspecialchars(
3722  $this->listURL($uid, '', 'firstElementNumber')
3723  ) . '" onclick="setHighlight(' . $uid . ')">' . $code . '</a>';
3724  } else {
3725  $code = $this->linkUrlMail($code, $origCode);
3726  }
3727  }
3728  return $code;
3729  }
3730 
3738  public function linkUrlMail($code, $testString)
3739  {
3740  // Check for URL:
3741  $scheme = parse_url($testString, PHP_URL_SCHEME);
3742  if ($scheme === 'http' || $scheme === 'https' || $scheme === 'ftp') {
3743  return '<a href="' . htmlspecialchars($testString) . '" target="_blank">' . $code . '</a>';
3744  }
3745  // Check for email:
3746  if (GeneralUtility::validEmail($testString)) {
3747  return '<a href="mailto:' . htmlspecialchars($testString) . '" target="_blank">' . $code . '</a>';
3748  }
3749  // Return if nothing else...
3750  return $code;
3751  }
3752 
3763  public function listURL($altId = '', $table = '-1', $exclList = '')
3764  {
3765  $urlParameters = [];
3766  if ((string)$altId !== '') {
3767  $urlParameters['id'] = $altId;
3768  } else {
3769  $urlParameters['id'] = $this->id;
3770  }
3771  if ($table === '-1') {
3772  $urlParameters['table'] = $this->table;
3773  } else {
3774  $urlParameters['table'] = $table;
3775  }
3776  if ($this->thumbs) {
3777  $urlParameters['imagemode'] = $this->thumbs;
3778  }
3779  if ($this->returnUrl) {
3780  $urlParameters['returnUrl'] = $this->returnUrl;
3781  }
3782  if ((!$exclList || !GeneralUtility::inList($exclList, 'search_field')) && $this->searchString) {
3783  $urlParameters['search_field'] = $this->searchString;
3784  }
3785  if ($this->searchLevels) {
3786  $urlParameters['search_levels'] = $this->searchLevels;
3787  }
3788  if ($this->showLimit) {
3789  $urlParameters['showLimit'] = $this->showLimit;
3790  }
3791  if ((!$exclList || !GeneralUtility::inList($exclList, 'firstElementNumber')) && $this->firstElementNumber) {
3792  $urlParameters['pointer'] = $this->firstElementNumber;
3793  }
3794  if ((!$exclList || !GeneralUtility::inList($exclList, 'sortField')) && $this->sortField) {
3795  $urlParameters['sortField'] = $this->sortField;
3796  }
3797  if ((!$exclList || !GeneralUtility::inList($exclList, 'sortRev')) && $this->sortRev) {
3798  $urlParameters['sortRev'] = $this->sortRev;
3799  }
3800 
3801  $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters);
3802 
3803  if ($routePath = GeneralUtility::_GP('route')) {
3804  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
3805  $url = (string)$uriBuilder->buildUriFromRoutePath($routePath, $urlParameters);
3806  } else {
3807  $url = GeneralUtility::getIndpEnv('SCRIPT_NAME') . HttpUtility::buildQueryString($urlParameters, '?');
3808  }
3809  return $url;
3810  }
3811 
3816  public function requestUri()
3817  {
3818  return $this->listURL();
3819  }
3820 
3829  public function makeFieldList($table, $dontCheckUser = false, $addDateFields = false)
3830  {
3831  $backendUser = $this->getBackendUser();
3832  // Init fieldlist array:
3833  $fieldListArr = [];
3834  // Check table:
3835  if (is_array($GLOBALS['TCA'][$table]) && isset($GLOBALS['TCA'][$table]['columns']) && is_array(
3836  $GLOBALS['TCA'][$table]['columns']
3837  )) {
3838  if (isset($GLOBALS['TCA'][$table]['columns']) && is_array($GLOBALS['TCA'][$table]['columns'])) {
3839  // Traverse configured columns and add them to field array, if available for user.
3840  foreach ($GLOBALS['TCA'][$table]['columns'] as $fN => $fieldValue) {
3841  if ($dontCheckUser || (!$fieldValue['exclude'] || $backendUser->check(
3842  'non_exclude_fields',
3843  $table . ':' . $fN
3844  )) && $fieldValue['config']['type'] !== 'passthrough') {
3845  $fieldListArr[] = $fN;
3846  }
3847  }
3848 
3849  $fieldListArr[] = 'uid';
3850  $fieldListArr[] = 'pid';
3851 
3852  // Add date fields
3853  if ($dontCheckUser || $backendUser->isAdmin() || $addDateFields) {
3854  if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
3855  $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
3856  }
3857  if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
3858  $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
3859  }
3860  }
3861  // Add more special fields:
3862  if ($dontCheckUser || $backendUser->isAdmin()) {
3863  if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
3864  $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['cruser_id'];
3865  }
3866  if ($GLOBALS['TCA'][$table]['ctrl']['sortby']) {
3867  $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
3868  }
3869  if (ExtensionManagementUtility::isLoaded('workspaces')
3870  && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
3871  $fieldListArr[] = 't3ver_id';
3872  $fieldListArr[] = 't3ver_state';
3873  $fieldListArr[] = 't3ver_wsid';
3874  }
3875  }
3876  } else {
3877  $this->logger->error('TCA is broken for the table "' . $table . '": no required "columns" entry in TCA.');
3878  }
3879  }
3880  return $fieldListArr;
3881  }
3882 
3888  public function localizationRedirect($justLocalized)
3889  {
3890  list($table, $orig_uid, $language) = explode(':', $justLocalized);
3891  if ($GLOBALS['TCA'][$table]
3892  && $GLOBALS['TCA'][$table]['ctrl']['languageField']
3893  && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
3894  ) {
3895  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
3896  $queryBuilder->getRestrictions()
3897  ->removeAll()
3898  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3899  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3900 
3901  $localizedRecordUid = $queryBuilder->select('uid')
3902  ->from($table)
3903  ->where(
3904  $queryBuilder->expr()->eq(
3905  $GLOBALS['TCA'][$table]['ctrl']['languageField'],
3906  $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
3907  ),
3908  $queryBuilder->expr()->eq(
3909  $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
3910  $queryBuilder->createNamedParameter($orig_uid, \PDO::PARAM_INT)
3911  )
3912  )
3913  ->setMaxResults(1)
3914  ->execute()
3915  ->fetchColumn();
3916 
3917  if ($localizedRecordUid !== false) {
3918  // Create parameters and finally run the classic page module for creating a new page translation
3919  $url = $this->listURL();
3920  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
3921  $editUserAccountUrl = (string)$uriBuilder->buildUriFromRoute(
3922  'record_edit',
3923  [
3924  'edit[' . $table . '][' . $localizedRecordUid . ']' => 'edit',
3925  'returnUrl' => $url
3926  ]
3927  );
3928  HttpUtility::redirect($editUserAccountUrl);
3929  }
3930  }
3931  }
3932 
3938  public function setOverrideUrlParameters(array $urlParameters)
3939  {
3940  $this->overrideUrlParameters = $urlParameters;
3941  }
3942 
3955  public function setTableDisplayOrder(array $orderInformation)
3956  {
3957  foreach ($orderInformation as $tableName => &$configuration) {
3958  if (isset($configuration['before'])) {
3959  if (is_string($configuration['before'])) {
3960  $configuration['before'] = GeneralUtility::trimExplode(',', $configuration['before'], true);
3961  } elseif (!is_array($configuration['before'])) {
3962  throw new \UnexpectedValueException(
3963  'The specified "before" order configuration for table "' . $tableName . '" is invalid.',
3964  1504870805
3965  );
3966  }
3967  }
3968  if (isset($configuration['after'])) {
3969  if (is_string($configuration['after'])) {
3970  $configuration['after'] = GeneralUtility::trimExplode(',', $configuration['after'], true);
3971  } elseif (!is_array($configuration['after'])) {
3972  throw new \UnexpectedValueException(
3973  'The specified "after" order configuration for table "' . $tableName . '" is invalid.',
3974  1504870806
3975  );
3976  }
3977  }
3978  }
3979  $this->tableDisplayOrder = $orderInformation;
3980  }
3981 
3985  public function getOverridePageIdList(): array
3986  {
3987  return $this->overridePageIdList;
3988  }
3989 
3993  public function setOverridePageIdList(array $overridePageIdList)
3994  {
3995  $this->overridePageIdList = array_map('intval', $overridePageIdList);
3996  }
3997 
4006  protected function getSearchableWebmounts($id, $depth, $perms_clause)
4007  {
4008  $backendUser = $this->getBackendUser();
4010  $tree = GeneralUtility::makeInstance(PageTreeView::class);
4011  $tree->init('AND ' . $perms_clause);
4012  $tree->makeHTML = 0;
4013  $tree->fieldArray = ['uid', 'php_tree_stop'];
4014  $idList = [];
4015 
4016  $allowedMounts = !$backendUser->isAdmin() && $id === 0
4017  ? $backendUser->returnWebmounts()
4018  : [$id];
4019 
4020  foreach ($allowedMounts as $allowedMount) {
4021  $idList[] = $allowedMount;
4022  if ($depth) {
4023  $tree->getTree($allowedMount, $depth, '');
4024  }
4025  $idList = array_merge($idList, $tree->ids);
4026  }
4027 
4028  return $idList;
4029  }
4030 
4039  protected function addPageIdConstraint(string $tableName, QueryBuilder $queryBuilder): QueryBuilder
4040  {
4041  // Set search levels:
4042  $searchLevels = $this->searchLevels;
4043 
4044  // Set search levels to 999 instead of -1 as the following methods
4045  // do not support -1 as valid value for infinite search.
4046  if ($searchLevels === -1) {
4047  $searchLevels = 999;
4048  }
4049 
4050  if ($searchLevels === 0) {
4051  $queryBuilder->andWhere(
4052  $queryBuilder->expr()->eq(
4053  $tableName . '.pid',
4054  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
4055  )
4056  );
4057  } elseif ($searchLevels > 0) {
4058  $allowedMounts = $this->getSearchableWebmounts($this->id, $searchLevels, $this->perms_clause);
4059  $queryBuilder->andWhere(
4060  $queryBuilder->expr()->in(
4061  $tableName . '.pid',
4062  $queryBuilder->createNamedParameter($allowedMounts, Connection::PARAM_INT_ARRAY)
4063  )
4064  );
4065  }
4066 
4067  if (!empty($this->getOverridePageIdList())) {
4068  $queryBuilder->andWhere(
4069  $queryBuilder->expr()->in(
4070  $tableName . '.pid',
4071  $queryBuilder->createNamedParameter($this->getOverridePageIdList(), Connection::PARAM_INT_ARRAY)
4072  )
4073  );
4074  }
4075 
4076  return $queryBuilder;
4077  }
4078 
4085  protected function logDeprecation(string $index)
4086  {
4087  trigger_error(
4088  '[index: ' . $index . '] $parameters in "buildQueryParameters"-Hook will be removed in TYPO3 v10.0, use $queryBuilder instead',
4089  E_USER_DEPRECATED
4090  );
4091  }
4092 
4096  protected function determineScriptUrl()
4097  {
4098  if ($routePath = GeneralUtility::_GP('route')) {
4099  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
4100  $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath);
4101  } else {
4102  $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME');
4103  }
4104  }
4105 
4120  public function addElement($h, $icon, $data, $rowParams = '', $_ = '', $_2 = '', $colType = 'td')
4121  {
4122  $colType = ($colType === 'th') ? 'th' : 'td';
4123  $noWrap = $this->no_noWrap ? '' : ' nowrap';
4124  // Start up:
4125  $l10nParent = isset($data['_l10nparent_']) ? (int)$data['_l10nparent_'] : 0;
4126  $out = '
4127  <!-- Element, begin: -->
4128  <tr ' . $rowParams . ' data-uid="' . (int)$data['uid'] . '" data-l10nparent="' . $l10nParent . '">';
4129  // Show icon and lines
4130  if ($this->showIcon) {
4131  $out .= '
4132  <' . $colType . ' class="col-icon nowrap">';
4133  if (!$h) {
4134  $out .= '&nbsp;';
4135  } else {
4136  for ($a = 0; $a < $h; $a++) {
4137  if (!$a) {
4138  if ($icon) {
4139  $out .= $icon;
4140  }
4141  }
4142  }
4143  }
4144  $out .= '</' . $colType . '>
4145  ';
4146  }
4147  // Init rendering.
4148  $colsp = '';
4149  $lastKey = '';
4150  $c = 0;
4151  $ccount = 0;
4152  // __label is used as the label key to circumvent problems with uid used as label (see #67756)
4153  // as it was introduced later on, check if it really exists before using it
4154  $fields = $this->fieldArray;
4155  if ($colType === 'td' && array_key_exists('__label', $data)) {
4156  $fields[0] = '__label';
4157  }
4158  // Traverse field array which contains the data to present:
4159  foreach ($fields as $vKey) {
4160  if (isset($data[$vKey])) {
4161  if ($lastKey) {
4162  $cssClass = $this->addElement_tdCssClass[$lastKey];
4163  if ($this->oddColumnsCssClass && $ccount % 2 == 0) {
4164  $cssClass = implode(' ', [$this->addElement_tdCssClass[$lastKey], $this->oddColumnsCssClass]);
4165  }
4166  $out .= '
4167  <' . $colType . ' class="' . $cssClass . $noWrap . '"' . $colsp . $this->addElement_tdParams[$lastKey] . '>' . $data[$lastKey] . '</' . $colType . '>';
4168  }
4169  $lastKey = $vKey;
4170  $c = 1;
4171  $ccount++;
4172  } else {
4173  if (!$lastKey) {
4174  $lastKey = $vKey;
4175  }
4176  $c++;
4177  }
4178  if ($c > 1) {
4179  $colsp = ' colspan="' . $c . '"';
4180  } else {
4181  $colsp = '';
4182  }
4183  }
4184  if ($lastKey) {
4185  $cssClass = $this->addElement_tdCssClass[$lastKey];
4186  if ($this->oddColumnsCssClass) {
4187  $cssClass = implode(' ', [$this->addElement_tdCssClass[$lastKey], $this->oddColumnsCssClass]);
4188  }
4189  $out .= '
4190  <' . $colType . ' class="' . $cssClass . $noWrap . '"' . $colsp . $this->addElement_tdParams[$lastKey] . '>' . $data[$lastKey] . '</' . $colType . '>';
4191  }
4192  // End row
4193  $out .= '
4194  </tr>';
4195  // Return row.
4196  return $out;
4197  }
4198 
4202  public function writeTop()
4203  {
4204  }
4205 
4212  public function fwd_rwd_nav($table = '')
4213  {
4214  $code = '';
4215  if ($this->eCounter >= $this->firstElementNumber && $this->eCounter < $this->firstElementNumber + $this->iLimit) {
4216  if ($this->firstElementNumber && $this->eCounter == $this->firstElementNumber) {
4217  // Reverse
4218  $theData = [];
4219  $titleCol = $this->fieldArray[0];
4220  $theData[$titleCol] = $this->fwd_rwd_HTML('fwd', $this->eCounter, $table);
4221  $code = $this->addElement(1, '', $theData, 'class="‪fwd_rwd_nav"');
4222  }
4223  return [1, $code];
4224  }
4225  if ($this->eCounter == $this->firstElementNumber + $this->iLimit) {
4226  // Forward
4227  $theData = [];
4228  $titleCol = $this->fieldArray[0];
4229  $theData[$titleCol] = $this->fwd_rwd_HTML('rwd', $this->eCounter, $table);
4230  $code = $this->addElement(1, '', $theData, 'class="‪fwd_rwd_nav"');
4231  }
4232  return [0, $code];
4233  }
4234 
4244  public function fwd_rwd_HTML($type, $pointer, $table = '')
4245  {
4246  $content = '';
4247  $tParam = $table ? '&table=' . rawurlencode($table) : '';
4248  switch ($type) {
4249  case 'fwd':
4250  $href = $this->listURL() . '&pointer=' . ($pointer - $this->iLimit) . $tParam;
4251  $content = '<a href="' . htmlspecialchars($href) . '">' . $this->iconFactory->getIcon(
4252  'actions-move-up',
4253  Icon::SIZE_SMALL
4254  )->render() . '</a> <i>[' . (max(0, $pointer - $this->iLimit) + 1) . ' - ' . $pointer . ']</i>';
4255  break;
4256  case 'rwd':
4257  $href = $this->listURL() . '&pointer=' . $pointer . $tParam;
4258  $content = '<a href="' . htmlspecialchars($href) . '">' . $this->iconFactory->getIcon(
4259  'actions-move-down',
4260  Icon::SIZE_SMALL
4261  )->render() . '</a> <i>[' . ($pointer + 1) . ' - ' . $this->totalItems . ']</i>';
4262  break;
4263  }
4264  return $content;
4265  }
4266 
4270  protected function getThisScript()
4271  {
4272  return strpos($this->thisScript, '?') === false ? $this->thisScript . '?' : $this->thisScript . '&';
4273  }
4274 
4280  public function CBfunctions()
4281  {
4282  return '
4283  // checkOffCB()
4284  function checkOffCB(listOfCBnames, link) { //
4285  var checkBoxes, flag, i;
4286  var checkBoxes = listOfCBnames.split(",");
4287  if (link.rel === "") {
4288  link.rel = "allChecked";
4289  flag = true;
4290  } else {
4291  link.rel = "";
4292  flag = false;
4293  }
4294  for (i = 0; i < checkBoxes.length; i++) {
4295  setcbValue(checkBoxes[i], flag);
4296  }
4297  }
4298  // cbValue()
4299  function cbValue(CBname) { //
4300  var CBfullName = "CBC["+CBname+"]";
4301  return (document.dblistForm[CBfullName] && document.dblistForm[CBfullName].checked ? 1 : 0);
4302  }
4303  // setcbValue()
4304  function setcbValue(CBname,flag) { //
4305  CBfullName = "CBC["+CBname+"]";
4306  if(document.dblistForm[CBfullName]) {
4307  document.dblistForm[CBfullName].checked = flag ? "on" : 0;
4308  }
4309  }
4310 
4311  ';
4312  }
4313 
4317  public function initializeLanguages()
4318  {
4319  // Look up page overlays:
4320  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4321  ->getQueryBuilderForTable('pages');
4322  $queryBuilder->getRestrictions()
4323  ->removeAll()
4324  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
4325  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
4326  $result = $queryBuilder
4327  ->select('*')
4328  ->from('pages')
4329  ->where(
4330  $queryBuilder->expr()->andX(
4331  $queryBuilder->expr()->eq(
4332  $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
4333  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
4334  ),
4335  $queryBuilder->expr()->gt(
4336  $GLOBALS['TCA']['pages']['ctrl']['languageField'],
4337  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
4338  )
4339  )
4340  )
4341  ->execute();
4343  $this->pageOverlays = [];
4344  while ($row = $result->fetch()) {
4345  $this->pageOverlays[$row[$GLOBALS['TCA']['pages']['ctrl']['languageField']]] = $row;
4346  }
4347  // @deprecated $this->languageIconTitles can be removed in TYPO3 v10.0.
4348  foreach ($this->siteLanguages as $language) {
4349  $this->languageIconTitles[$language->getLanguageId()] = [
4350  'title' => $language->getTitle(),
4351  'flagIcon' => $language->getFlagIdentifier()
4352  ];
4353  }
4354  }
4355 
4364  public function languageFlag($sys_language_uid, $addAsAdditionalText = true)
4365  {
4366  trigger_error('This method will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
4367  $out = '';
4368  $title = htmlspecialchars($this->languageIconTitles[$sys_language_uid]['title']);
4369  if ($this->languageIconTitles[$sys_language_uid]['flagIcon']) {
4370  $out .= '<span title="' . $title . '">' . $this->iconFactory->getIcon(
4371  $this->languageIconTitles[$sys_language_uid]['flagIcon'],
4372  Icon::SIZE_SMALL
4373  )->render() . '</span>';
4374  if (!$addAsAdditionalText) {
4375  return $out;
4376  }
4377  $out .= '&nbsp;';
4378  }
4379  $out .= $title;
4380  return $out;
4381  }
4382 
4389  protected function renderLanguageFlag(SiteLanguage $language)
4390  {
4391  $title = htmlspecialchars($language->getTitle());
4392  if ($language->getFlagIdentifier()) {
4393  $icon = $this->iconFactory->getIcon(
4394  $language->getFlagIdentifier(),
4395  Icon::SIZE_SMALL
4396  )->render();
4397  return '<span title="' . $title . '">' . $icon . '</span>&nbsp;' . $title;
4398  }
4399  return $title;
4400  }
4401 
4408  protected function resolveSiteLanguages(int $pageId)
4409  {
4410  $site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId);
4411  $this->siteLanguages = $site->getAvailableLanguages($this->getBackendUser(), true, $pageId);
4412  }
4413 
4422  protected function generateReferenceToolTip($references, $launchViewParameter = '')
4423  {
4424  if (!$references) {
4425  $htmlCode = '-';
4426  } else {
4427  $htmlCode = '<a href="#"';
4428  if ($launchViewParameter !== '') {
4429  $htmlCode .= ' onclick="' . htmlspecialchars(
4430  'top.TYPO3.InfoWindow.showItem(' . $launchViewParameter . '); return false;'
4431  ) . '"';
4432  }
4433  $htmlCode .= ' title="' . htmlspecialchars(
4434  $this->getLanguageService()->sL(
4435  'LLL:EXT:backend/Resources/Private/Language/locallang.xlf:show_references'
4436  ) . ' (' . $references . ')'
4437  ) . '">';
4438  $htmlCode .= $references;
4439  $htmlCode .= '</a>';
4440  }
4441  return $htmlCode;
4442  }
4443 
4447  protected function getLocalizedPageTitle(): string
4448  {
4449  if (($this->tt_contentConfig['sys_language_uid'] ?? 0) > 0) {
4450  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4451  ->getQueryBuilderForTable('pages');
4452  $queryBuilder->getRestrictions()
4453  ->removeAll()
4454  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
4455  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
4456  $localizedPage = $queryBuilder
4457  ->select('*')
4458  ->from('pages')
4459  ->where(
4460  $queryBuilder->expr()->eq(
4461  $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
4462  $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
4463  ),
4464  $queryBuilder->expr()->eq(
4465  $GLOBALS['TCA']['pages']['ctrl']['languageField'],
4466  $queryBuilder->createNamedParameter($this->tt_contentConfig['sys_language_uid'], \PDO::PARAM_INT)
4467  )
4468  )
4469  ->setMaxResults(1)
4470  ->execute()
4471  ->fetch();
4472  BackendUtility::workspaceOL('pages', $localizedPage);
4473  return $localizedPage['title'];
4474  }
4475  return $this->pageinfo['title'];
4476  }
4477 
4483  protected function isPageEditable()
4484  {
4485  if ($this->getBackendUser()->isAdmin()) {
4486  return true;
4487  }
4488  return !$this->pageinfo['editlock'] && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::PAGE_EDIT);
4489  }
4490 
4497  protected function isContentEditable(?int $languageId = null)
4498  {
4499  if ($this->getBackendUser()->isAdmin()) {
4500  return true;
4501  }
4502  return !$this->pageinfo['editlock']
4503  && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)
4504  && ($languageId === null || $this->getBackendUser()->checkLanguageAccess($languageId));
4505  }
4506 
4511  protected function getLanguageService()
4512  {
4513  return $GLOBALS['LANG'];
4514  }
4515 }
‪TYPO3\CMS\Backend\View\PageLayoutView\$activeTables
‪array $activeTables
Definition: PageLayoutView.php:150
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:42
‪TYPO3\CMS\Backend\View\BackendLayoutView\getSelectedBackendLayout
‪array null getSelectedBackendLayout($pageId)
Definition: BackendLayoutView.php:333
‪TYPO3\CMS\Backend\View\PageLayoutView\$iconFactory
‪IconFactory $iconFactory
Definition: PageLayoutView.php:516
‪TYPO3\CMS\Backend\View\PageLayoutView\fwd_rwd_nav
‪array fwd_rwd_nav($table='')
Definition: PageLayoutView.php:4132
‪TYPO3\CMS\Backend\View\PageLayoutView\generateList
‪generateList()
Definition: PageLayoutView.php:2992
‪TYPO3\CMS\Backend\View\PageLayoutView\$localizationController
‪LocalizationController $localizationController
Definition: PageLayoutView.php:526
‪TYPO3\CMS\Backend\View\PageLayoutView\$showLimit
‪int $showLimit
Definition: PageLayoutView.php:182
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\groupBy
‪QueryBuilder groupBy(... $groupBy)
Definition: QueryBuilder.php:679
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordLocalization
‪static mixed getRecordLocalization($table, $uid, $language, $andWhereClause='')
Definition: BackendUtility.php:316
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLinkToDataHandlerAction
‪static string getLinkToDataHandlerAction($parameters, $redirectUrl='')
Definition: BackendUtility.php:2788
‪TYPO3\CMS\Backend\View\PageLayoutView\$id
‪int $id
Definition: PageLayoutView.php:242
‪TYPO3\CMS\Backend\View\PageLayoutView\$tt_contentData
‪array $tt_contentData
Definition: PageLayoutView.php:154
‪TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface
Definition: PageLayoutViewDrawItemHookInterface.php:22
‪TYPO3\CMS\Backend\View\PageLayoutView\$languageHasTranslationsCache
‪array $languageHasTranslationsCache
Definition: PageLayoutView.php:522
‪TYPO3\CMS\Backend\View\PageLayoutView\isDragAndDropAllowed
‪bool isDragAndDropAllowed(array $row)
Definition: PageLayoutView.php:2044
‪TYPO3\CMS\Backend\View\PageLayoutView\$table
‪string $table
Definition: PageLayoutView.php:254
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪string eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:107
‪TYPO3\CMS\Backend\View\PageLayoutView\$defLangBinding
‪bool $defLangBinding
Definition: PageLayoutView.php:123
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Backend\View\PageLayoutView\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: PageLayoutView.php:2883
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\calcPerms
‪int calcPerms($row)
Definition: BackendUserAuthentication.php:592
‪TYPO3\CMS\Backend\View\PageLayoutView\determineScriptUrl
‪determineScriptUrl()
Definition: PageLayoutView.php:4016
‪TYPO3\CMS\Backend\View\PageLayoutView\$overridePageIdList
‪array $overridePageIdList
Definition: PageLayoutView.php:532
‪TYPO3\CMS\Backend\View\PageLayoutView\$ext_function
‪int $ext_function
Definition: PageLayoutView.php:92
‪TYPO3\CMS\Backend\View
‪TYPO3\CMS\Backend\View\PageLayoutView\$descrTable
‪string $descrTable
Definition: PageLayoutView.php:116
‪TYPO3\CMS\Backend\View\PageLayoutView\getPageRecordsRecursive
‪array getPageRecordsRecursive(int $pid, int $depth, string $iconPrefix='', array $rows=[])
Definition: PageLayoutView.php:1626
‪TYPO3\CMS\Backend\View\PageLayoutView\logDeprecation
‪logDeprecation(string $index)
Definition: PageLayoutView.php:4005
‪TYPO3\CMS\Backend\View\PageLayoutView\$fixedL
‪int $fixedL
Definition: PageLayoutView.php:458
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:50
‪TYPO3
‪TYPO3\CMS\Backend\View\PageLayoutView\getQueryBuilder
‪TYPO3 CMS Core Database Query QueryBuilder getQueryBuilder(string $table, int $pageId, array $additionalConstraints=[], array $fields=[' *'])
Definition: PageLayoutView.php:3232
‪TYPO3\CMS\Backend\Exception
Definition: Exception.php:23
‪TYPO3\CMS\Backend\View\PageLayoutView\$itemsLimitPerTable
‪int $itemsLimitPerTable
Definition: PageLayoutView.php:230
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface\removeAll
‪QueryRestrictionContainerInterface removeAll()
‪TYPO3\CMS\Backend\View\PageLayoutView\$tableDisplayOrder
‪array[] $tableDisplayOrder
Definition: PageLayoutView.php:548
‪TYPO3\CMS\Backend\View\PageLayoutView\headerFields
‪array headerFields($fieldArr, $table, $out=[])
Definition: PageLayoutView.php:1557
‪TYPO3\CMS\Backend\View\PageLayoutView\prepareQueryBuilder
‪QueryBuilder prepareQueryBuilder(string $table, int $pageId, array $fieldList=[' *'], array $additionalConstraints=[], QueryBuilder $queryBuilder, bool $addSorting=true)
Definition: PageLayoutView.php:3269
‪TYPO3\CMS\Backend\View\PageLayoutView\__construct
‪__construct()
Definition: PageLayoutView.php:559
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
‪TYPO3\CMS\Backend\View\PageLayoutView\$duplicateStack
‪string[] $duplicateStack
Definition: PageLayoutView.php:302
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\orderBy
‪QueryBuilder orderBy(string $fieldName, string $order=null)
Definition: QueryBuilder.php:794
‪TYPO3\CMS\Backend\View\PageLayoutView\$duplicateField
‪string $duplicateField
Definition: PageLayoutView.php:362
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:648
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig($objectString=null, $config=null)
Definition: BackendUserAuthentication.php:1232
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Backend\View\PageLayoutView\generateListForCTypeMenu
‪string generateListForCTypeMenu(array $row)
Definition: PageLayoutView.php:2259
‪TYPO3\CMS\Backend\View\PageLayoutView\$clickTitleMode
‪string $clickTitleMode
Definition: PageLayoutView.php:266
‪TYPO3\CMS\Backend\View\PageLayoutView\addPageIdConstraint
‪QueryBuilder addPageIdConstraint(string $tableName, QueryBuilder $queryBuilder)
Definition: PageLayoutView.php:3959
‪TYPO3\CMS\Backend\Utility\BackendUtility\getItemLabel
‪static string getItemLabel($table, $col)
Definition: BackendUtility.php:1791
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawPasteIcon
‪string tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, $cssClass, $title)
Definition: PageLayoutView.php:1817
‪TYPO3\CMS\Backend\View\PageLayoutView\initializeClipboard
‪initializeClipboard()
Definition: PageLayoutView.php:2557
‪TYPO3\CMS\Backend\View\PageLayoutView\renderLanguageFlag
‪string renderLanguageFlag(SiteLanguage $language)
Definition: PageLayoutView.php:4309
‪TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction
Definition: BackendWorkspaceRestriction.php:28
‪TYPO3\CMS\Backend\View\PageLayoutView\$perms_clause
‪string $perms_clause
Definition: PageLayoutView.php:236
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\getRestrictions
‪QueryRestrictionContainerInterface getRestrictions()
Definition: QueryBuilder.php:89
‪TYPO3\CMS\Backend\View\PageLayoutView\$languagesInColumnCache
‪array $languagesInColumnCache
Definition: PageLayoutView.php:505
‪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:1338
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:31
‪TYPO3\CMS\Backend\View\PageLayoutView\makeSearchString
‪string makeSearchString($table, $currentPid=-1)
Definition: PageLayoutView.php:3433
‪TYPO3\CMS\Backend\View\PageLayoutView\getTable_pages
‪string getTable_pages($id)
Definition: PageLayoutView.php:636
‪TYPO3\CMS\Backend\View\PageLayoutView\getLanguageService
‪LanguageService getLanguageService()
Definition: PageLayoutView.php:4431
‪TYPO3\CMS\Backend\View\PageLayoutView\$sortField
‪string $sortField
Definition: PageLayoutView.php:224
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:54
‪TYPO3\CMS\Backend\View\PageLayoutView\newContentElementOnClick
‪string newContentElementOnClick($id, $colPos, $sys_language)
Definition: PageLayoutView.php:2400
‪TYPO3\CMS\Backend\Utility\BackendUtility\referenceCount
‪static string referenceCount($table, $ref, $msg='', $count=null)
Definition: BackendUtility.php:3787
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:158
‪TYPO3\CMS\Backend\View\PageLayoutView\$tableTSconfigOverTCA
‪mixed[][] $tableTSconfigOverTCA
Definition: PageLayoutView.php:290
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:374
‪TYPO3\CMS\Backend\View\PageLayoutView\$eCounter
‪int $eCounter
Definition: PageLayoutView.php:338
‪TYPO3\CMS\Backend\Tree\View\PageTreeView
Definition: PageTreeView.php:23
‪TYPO3\CMS\Backend\View\PageLayoutView\$pageOverlays
‪array $pageOverlays
Definition: PageLayoutView.php:420
‪$fields
‪$fields
Definition: pages.php:4
‪TYPO3\CMS\Backend\View\PageLayoutView\$setFields
‪string[] $setFields
Definition: PageLayoutView.php:308
‪TYPO3\CMS\Backend\View\PageLayoutView\$returnUrl
‪string $returnUrl
Definition: PageLayoutView.php:248
‪TYPO3\CMS\Backend\View\PageLayoutView\$itemLabels
‪array $itemLabels
Definition: PageLayoutView.php:170
‪TYPO3\CMS\Backend\View\PageLayoutView\getTable
‪string getTable($table, $id, $fields='')
Definition: PageLayoutView.php:588
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Backend\View\PageLayoutView\getReferenceCount
‪int getReferenceCount(string $tableName, int $uid)
Definition: PageLayoutView.php:2028
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Core\Service\FlexFormService
Definition: FlexFormService.php:21
‪TYPO3\CMS\Backend\View\PageLayoutView\resolveSiteLanguages
‪resolveSiteLanguages(int $pageId)
Definition: PageLayoutView.php:4328
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Backend\Utility\BackendUtility\translationCount
‪static string translationCount($table, $ref, $msg='')
Definition: BackendUtility.php:3837
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:25
‪TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList
Definition: DatabaseRecordList.php:59
‪TYPO3\CMS\Backend\View\PageLayoutView\getPagesTableFieldValue
‪string getPagesTableFieldValue($field, array $row)
Definition: PageLayoutView.php:1764
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapClickMenuOnIcon
‪static string wrapClickMenuOnIcon( $content, $table, $uid=0, $context='', $_addParams='', $_enDisItems='', $returnTagParameters=false)
Definition: BackendUtility.php:2759
‪TYPO3\CMS\Backend\View\PageLayoutView\$showIcon
‪int $showIcon
Definition: PageLayoutView.php:477
‪TYPO3\CMS\Backend\View\PageLayoutView\$oddColumnsCssClass
‪string $oddColumnsCssClass
Definition: PageLayoutView.php:451
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:182
‪TYPO3\CMS\Backend\View\PageLayoutView\languageSelector
‪string languageSelector($id)
Definition: PageLayoutView.php:2458
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:35
‪TYPO3\CMS\Core\Messaging\AbstractMessage\WARNING
‪const WARNING
Definition: AbstractMessage.php:28
‪TYPO3\CMS\Backend\View\PageLayoutView\$sortRev
‪bool $sortRev
Definition: PageLayoutView.php:356
‪TYPO3\CMS\Backend\View\PageLayoutView\$externalTables
‪array $externalTables
Definition: PageLayoutView.php:110
‪TYPO3\CMS\Backend\View\PageLayoutView\isContentEditable
‪bool isContentEditable(?int $languageId=null)
Definition: PageLayoutView.php:4417
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\andWhere
‪QueryBuilder andWhere(... $where)
Definition: QueryBuilder.php:647
‪TYPO3\CMS\Backend\View\PageLayoutView\linkWrapItems
‪string linkWrapItems($table, $uid, $code, $row)
Definition: PageLayoutView.php:3580
‪TYPO3\CMS\Backend\View\PageLayoutView\linkWrapTable
‪string linkWrapTable($table, $code)
Definition: PageLayoutView.php:3559
‪TYPO3\CMS\Backend\View\PageLayoutView\$pI_showUser
‪bool $pI_showUser
Definition: PageLayoutView.php:68
‪TYPO3\CMS\Backend\Controller\PageLayoutController
Definition: PageLayoutController.php:53
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:30
‪TYPO3\CMS\Backend\View\PageLayoutView\$searchLevels
‪int $searchLevels
Definition: PageLayoutView.php:272
‪TYPO3\CMS\Backend\View\PageLayoutView\start
‪start($id, $table, $pointer, $search='', $levels=0, $showLimit=0)
Definition: PageLayoutView.php:2907
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawFooter
‪string tt_content_drawFooter(array $row)
Definition: PageLayoutView.php:1838
‪TYPO3\CMS\Backend\View\PageLayoutView\getBackendLayoutView
‪BackendLayoutView getBackendLayoutView()
Definition: PageLayoutView.php:2875
‪TYPO3\CMS\Backend\View\PageLayoutView\$CType_labels
‪array $CType_labels
Definition: PageLayoutView.php:164
‪TYPO3\CMS\Backend\View\PageLayoutView\numberOfRecords
‪int numberOfRecords($table, $pid)
Definition: PageLayoutView.php:2618
‪TYPO3\CMS\Backend\View\PageLayoutView\$leftMargin
‪int $leftMargin
Definition: PageLayoutView.php:402
‪TYPO3\CMS\Backend\View\PageLayoutView\$JScode
‪string $JScode
Definition: PageLayoutView.php:326
‪TYPO3\CMS\Backend\View\PageLayoutView\$nextThree
‪int $nextThree
Definition: PageLayoutView.php:74
‪TYPO3\CMS\Backend\View\PageLayoutView\$csvOutput
‪bool $csvOutput
Definition: PageLayoutView.php:212
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawHeader
‪string tt_content_drawHeader($row, $space=0, $disableMoveAndNewButtons=false, $langMode=false, $dragDropEnabled=false)
Definition: PageLayoutView.php:1882
‪TYPO3\CMS\Backend\View\PageLayoutView\initializeLanguages
‪initializeLanguages()
Definition: PageLayoutView.php:4237
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Backend\View\PageLayoutView\isPageEditable
‪bool isPageEditable()
Definition: PageLayoutView.php:4403
‪TYPO3\CMS\Backend\View\PageLayoutView\$translateTools
‪TranslationConfigurationProvider $translateTools
Definition: PageLayoutView.php:463
‪TYPO3\CMS\Backend\View\PageLayoutView\$thisScript
‪string $thisScript
Definition: PageLayoutView.php:445
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController
Definition: LocalizationController.php:39
‪TYPO3\CMS\Backend\View\PageLayoutView\getSearchFields
‪string[] getSearchFields($tableName)
Definition: PageLayoutView.php:3529
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:331
‪TYPO3\CMS\Backend\View\PageLayoutView\pages_drawItem
‪string pages_drawItem($row, $fieldArr)
Definition: PageLayoutView.php:1685
‪TYPO3\CMS\Backend\View\PageLayoutView\$tableList
‪string $tableList
Definition: PageLayoutView.php:368
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemListMerged
‪static string getLabelFromItemListMerged($pageId, $table, $column, $key)
Definition: BackendUtility.php:1704
‪TYPO3\CMS\Backend\View\PageLayoutView\$addElement_tdCssClass
‪array $addElement_tdCssClass
Definition: PageLayoutView.php:483
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordToolTip
‪static string getRecordToolTip(array $row, $table='pages')
Definition: BackendUtility.php:1603
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1811
‪TYPO3\CMS\Backend\View\PageLayoutView\setDispFields
‪setDispFields()
Definition: PageLayoutView.php:3193
‪TYPO3\CMS\Backend\View\PageLayoutView\getTable_tt_content
‪string getTable_tt_content($id)
Definition: PageLayoutView.php:768
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key, $exitOnError=null)
Definition: ExtensionManagementUtility.php:115
‪TYPO3\CMS\Backend\View\PageLayoutView\$searchString
‪string $searchString
Definition: PageLayoutView.php:344
‪TYPO3\CMS\Core\Service\DependencyOrderingService
Definition: DependencyOrderingService.php:31
‪TYPO3\CMS\Backend\View\PageLayoutView\getExternalTables
‪string getExternalTables($id, $table)
Definition: PageLayoutView.php:611
‪TYPO3\CMS\Backend\View\PageLayoutView\$option_newWizard
‪bool $option_newWizard
Definition: PageLayoutView.php:86
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:733
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Utility\BackendUtility\editOnClick
‪static string editOnClick($params, $_='', $requestUri='')
Definition: BackendUtility.php:2592
‪TYPO3\CMS\Backend\View\PageLayoutView\noEditIcon
‪string noEditIcon($label='noEditItems')
Definition: PageLayoutView.php:2719
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Backend\View\PageLayoutView\$fieldArray
‪array $fieldArray
Definition: PageLayoutView.php:408
‪TYPO3\CMS\Backend\View\PageLayoutView\generateTtContentDataArray
‪generateTtContentDataArray(array $rowArray)
Definition: PageLayoutView.php:2580
‪TYPO3\CMS\Backend\View\PageLayoutView\$counter
‪int $counter
Definition: PageLayoutView.php:426
‪TYPO3\CMS\Backend\View\PageLayoutView\makeOrdinaryList
‪string makeOrdinaryList($table, $id, $fList, $icon=false, $addWhere='')
Definition: PageLayoutView.php:1387
‪TYPO3\CMS\Backend\View\PageLayoutView\$tablesCollapsed
‪int[][] $tablesCollapsed
Definition: PageLayoutView.php:374
‪TYPO3\CMS\Backend\View\PageLayoutView\localizationRedirect
‪localizationRedirect($justLocalized)
Definition: PageLayoutView.php:3808
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\View\PageLayoutView\$thumbs
‪bool $thumbs
Definition: PageLayoutView.php:390
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordWSOL
‪static array getRecordWSOL( $table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
Definition: BackendUtility.php:174
‪TYPO3\CMS\Backend\View\PageLayoutView\renderText
‪string renderText($input)
Definition: PageLayoutView.php:2646
‪TYPO3\CMS\Backend\View\PageLayoutView\getNonTranslatedTTcontentUids
‪array getNonTranslatedTTcontentUids($defaultLanguageUids, $id, $lP)
Definition: PageLayoutView.php:2291
‪TYPO3\CMS\Backend\View\PageLayoutView\makeFieldList
‪string[] makeFieldList($table, $dontCheckUser=false, $addDateFields=false)
Definition: PageLayoutView.php:3749
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\setMaxResults
‪QueryBuilder setMaxResults(int $maxResults)
Definition: QueryBuilder.php:329
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:23
‪$output
‪$output
Definition: annotationChecker.php:113
‪TYPO3\CMS\Backend\View\PageLayoutView\setTotalItems
‪setTotalItems(string $table, int $pageId, array $constraints)
Definition: PageLayoutView.php:3399
‪TYPO3\CMS\Backend\View\PageLayoutView\$script
‪string $script
Definition: PageLayoutView.php:314
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:31
‪TYPO3\CMS\Backend\View\PageLayoutView\newLanguageButton
‪string newLanguageButton($defaultLanguageUids, $lP)
Definition: PageLayoutView.php:2337
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2616
‪TYPO3\CMS\Backend\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:1933
‪TYPO3\CMS\Backend\View\PageLayoutView\getLocalizedPageTitle
‪string getLocalizedPageTitle()
Definition: PageLayoutView.php:4367
‪TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider
Definition: TranslationConfigurationProvider.php:35
‪TYPO3\CMS\Backend\View\PageLayoutView\$hideTables
‪string $hideTables
Definition: PageLayoutView.php:194
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:91
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:22
‪TYPO3\CMS\Backend\View\PageLayoutView\getIcon
‪string getIcon($table, $row, $enabledClickMenuItems='')
Definition: PageLayoutView.php:2661
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:32
‪TYPO3\CMS\Backend\View\PageLayoutView\$setLMargin
‪int $setLMargin
Definition: PageLayoutView.php:414
‪TYPO3\CMS\Core\Type\Bitmask\Permission\CONTENT_EDIT
‪const CONTENT_EDIT
Definition: Permission.php:52
‪TYPO3\CMS\Backend\View\PageLayoutView\$pageRecord
‪string[] $pageRecord
Definition: PageLayoutView.php:296
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:163
‪TYPO3\CMS\Backend\View\PageLayoutView\$firstElementNumber
‪int $firstElementNumber
Definition: PageLayoutView.php:332
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
Definition: BackendUtility.php:864
‪TYPO3\CMS\Backend\View\PageLayoutView\getProcessedValue
‪getProcessedValue($table, $fieldList, array $row, array &$info)
Definition: PageLayoutView.php:2683
‪TYPO3\CMS\Backend\View\BackendLayoutView
Definition: BackendLayoutView.php:28
‪TYPO3\CMS\Backend\View\PageLayoutView\$no_noWrap
‪int $no_noWrap
Definition: PageLayoutView.php:473
‪TYPO3\CMS\Backend\View\PageLayoutView\$HTMLcode
‪string $HTMLcode
Definition: PageLayoutView.php:384
‪TYPO3\CMS\Backend\View\PageLayoutView\getSearchBox
‪string getSearchBox($formFields=true)
Definition: PageLayoutView.php:3098
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Utility\BackendUtility\workspaceOL
‪static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
Definition: BackendUtility.php:4048
‪TYPO3\CMS\Backend\View\PageLayoutView\listURL
‪string listURL($altId='', $table='-1', $exclList='')
Definition: PageLayoutView.php:3683
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\setFirstResult
‪QueryBuilder setFirstResult(int $firstResult)
Definition: QueryBuilder.php:304
‪TYPO3\CMS\Backend\View\PageLayoutView\$hideTranslations
‪string $hideTranslations
Definition: PageLayoutView.php:206
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Backend\View\PageLayoutView\$addElement_tdParams
‪array $addElement_tdParams
Definition: PageLayoutView.php:469
‪TYPO3\CMS\Backend\View\PageLayoutView
Definition: PageLayoutView.php:61
‪TYPO3\CMS\Backend\View\PageLayoutView\linkEditContent
‪string linkEditContent($str, $row)
Definition: PageLayoutView.php:2430
‪TYPO3\CMS\Backend\View\PageLayoutView\$languageIconTitles
‪array $languageIconTitles
Definition: PageLayoutView.php:433
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_EDIT
‪const PAGE_EDIT
Definition: Permission.php:37
‪TYPO3\CMS\Backend\View\PageLayoutView\$siteLanguages
‪SiteLanguage[] $siteLanguages
Definition: PageLayoutView.php:439
‪TYPO3\CMS\Backend\View\PageLayoutView\$tt_contentConfig
‪array $tt_contentConfig
Definition: PageLayoutView.php:129
‪TYPO3\CMS\Backend\View\PageLayoutView\dataFields
‪array dataFields($fieldArr, $table, $row, $out=[])
Definition: PageLayoutView.php:1498
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemlist
‪static string getLabelFromItemlist($table, $col, $key)
Definition: BackendUtility.php:1680
‪TYPO3\CMS\Backend\View\PageLayoutView\$totalItems
‪string $totalItems
Definition: PageLayoutView.php:284
‪TYPO3\CMS\Backend\View\PageLayoutView\getPageLayoutController
‪PageLayoutController getPageLayoutController()
Definition: PageLayoutView.php:2891
‪TYPO3\CMS\Backend\View\PageLayoutView\getThumbCodeUnlinked
‪string getThumbCodeUnlinked($row, $table, $field)
Definition: PageLayoutView.php:2809
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Backend\View\PageLayoutView\$ext_CALC_PERMS
‪int $ext_CALC_PERMS
Definition: PageLayoutView.php:493
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Backend\View\PageLayoutView\$referenceCount
‪array $referenceCount
Definition: PageLayoutView.php:554
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Backend\View\PageLayoutView\$allFields
‪int $allFields
Definition: PageLayoutView.php:176
‪TYPO3\CMS\Backend\View\PageLayoutView\checkIfTranslationsExistInLanguage
‪bool checkIfTranslationsExistInLanguage(array $contentElements, int $language)
Definition: PageLayoutView.php:2822
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\addOrderBy
‪QueryBuilder addOrderBy(string $fieldName, string $order=null)
Definition: QueryBuilder.php:809
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Backend\View\PageLayoutView\addElement
‪string addElement($h, $icon, $data, $rowParams='', $_='', $_2='', $colType='td')
Definition: PageLayoutView.php:4040
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface\add
‪QueryRestrictionContainerInterface add(QueryRestrictionInterface $restriction)
‪TYPO3\CMS\Backend\View\PageLayoutView\thumbCode
‪string thumbCode($row, $table, $field)
Definition: PageLayoutView.php:3217
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:118
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:21
‪TYPO3\CMS\Backend\Utility\BackendUtility\date
‪static string date($tstamp)
Definition: BackendUtility.php:1179
‪TYPO3\CMS\Core\Utility\HttpUtility\redirect
‪static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:103
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawItem
‪string tt_content_drawItem($row)
Definition: PageLayoutView.php:2066
‪TYPO3\CMS\Backend\View\PageLayoutView\$contentElementCache
‪array $contentElementCache
Definition: PageLayoutView.php:512
‪TYPO3\CMS\Backend\View\PageLayoutView\getTableMenu
‪string getTableMenu($id)
Definition: PageLayoutView.php:2739
‪TYPO3\CMS\Backend\View\PageLayoutView\$doEdit
‪bool $doEdit
Definition: PageLayoutView.php:98
‪TYPO3\CMS\Backend\View\PageLayoutView\$overrideUrlParameters
‪string[] $overrideUrlParameters
Definition: PageLayoutView.php:538
‪$icons
‪$icons
Definition: ext_localconf.php:77
‪TYPO3\CMS\Backend\View\PageLayoutView\$pages_noEditColumns
‪bool $pages_noEditColumns
Definition: PageLayoutView.php:80
‪TYPO3\CMS\Backend\View\PageLayoutView\$displayFields
‪string[] $displayFields
Definition: PageLayoutView.php:200
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\where
‪QueryBuilder where(... $predicates)
Definition: QueryBuilder.php:630
‪TYPO3\CMS\Backend\View\PageLayoutView\$currentTable
‪int[][] $currentTable
Definition: PageLayoutView.php:396
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:25
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\expr
‪ExpressionBuilder expr()
Definition: QueryBuilder.php:125
‪TYPO3\CMS\Backend\View\PageLayoutView\$recPath_cache
‪mixed[] $recPath_cache
Definition: PageLayoutView.php:218
‪TYPO3\CMS\Backend\Utility\BackendUtility\splitTable_Uid
‪static array splitTable_Uid($str)
Definition: BackendUtility.php:240
‪TYPO3\CMS\Backend\View\PageLayoutView\getContentRecordsPerColumn
‪array getContentRecordsPerColumn($table, $id, array $columns, $additionalWhereClause='')
Definition: PageLayoutView.php:1576
‪TYPO3\CMS\Backend\View\PageLayoutView\$iLimit
‪int $iLimit
Definition: PageLayoutView.php:278
‪TYPO3\CMS\Backend\View\PageLayoutView\$listOnlyInSingleTableMode
‪bool $listOnlyInSingleTableMode
Definition: PageLayoutView.php:320
‪TYPO3\CMS\Core\Routing\SiteMatcher
Definition: SiteMatcher.php:53
‪TYPO3\CMS\Backend\View\PageLayoutView\$calcPerms
‪int $calcPerms
Definition: PageLayoutView.php:260
‪TYPO3\CMS\Backend\View\PageLayoutView\$agePrefixes
‪string $agePrefixes
Definition: PageLayoutView.php:104
‪TYPO3\CMS\Backend\View\PageLayoutView\getResult
‪array getResult(Statement $result, string $table='tt_content')
Definition: PageLayoutView.php:2528
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array bool readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:635
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRecordLocked
‪static array bool isRecordLocked($table, $uid)
Definition: BackendUtility.php:3397
‪TYPO3\CMS\Backend\View\PageLayoutView\$pageinfo
‪array $pageinfo
Definition: PageLayoutView.php:499
‪TYPO3\CMS\Backend\View\PageLayoutView\tt_content_drawColHeader
‪string tt_content_drawColHeader($colName, $editParams='')
Definition: PageLayoutView.php:1781
‪TYPO3\CMS\Backend\View\PageLayoutView\$modTSconfig
‪array[] $modTSconfig
Definition: PageLayoutView.php:378
‪TYPO3\CMS\Backend\View\PageLayoutView\$modSharedTSconfig
‪array $modSharedTSconfig
Definition: PageLayoutView.php:188
‪TYPO3\CMS\Backend\View\PageLayoutView\isDisabled
‪bool isDisabled($table, $row)
Definition: PageLayoutView.php:2703
‪TYPO3\CMS\Backend\View\PageLayoutView\$clipboard
‪TYPO3 CMS Backend Clipboard Clipboard $clipboard
Definition: PageLayoutView.php:487
‪TYPO3\CMS\Backend\View\PageLayoutView\$itemsLimitSingleTable
‪int $itemsLimitSingleTable
Definition: PageLayoutView.php:350