18 use Doctrine\DBAL\Driver\Statement;
19 use Psr\Log\LoggerAwareInterface;
20 use Psr\Log\LoggerAwareTrait;
111 public $agePrefixes =
' min| hrs| days| yrs| min| hour| day| year';
147 'languageColsPointer' => 0,
150 'sys_language_uid' => 0,
153 'activeCols' =>
'1,0,2,3'
641 if (isset(
$GLOBALS[
'BE_USER']->uc[
'titleLen']) &&
$GLOBALS[
'BE_USER']->uc[
'titleLen'] > 0) {
642 $this->fixedL =
$GLOBALS[
'BE_USER']->uc[
'titleLen'];
644 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
646 $this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
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');
670 if (isset($this->externalTables[
$table])) {
699 $fList = $this->externalTables[
$table][$type][
'fList'];
702 $icon = $this->externalTables[
$table][$type][
'icon'];
703 $addWhere = $this->externalTables[
$table][$type][
'addWhere'];
726 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
727 ->getQueryBuilderForTable(
'pages');
728 $queryBuilder->getRestrictions()
730 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
735 $queryBuilder->expr()->eq(
'uid', $queryBuilder->createNamedParameter(
$id, \PDO::PARAM_INT)),
743 if (is_array($row)) {
747 $this->no_noWrap = 0;
757 if ($this->
getBackendUser()->doesUserHaveAccess($row, 2) && $row[
'uid'] > 0) {
758 $editUids[] = $row[
'uid'];
762 foreach ($theRows as $sRow) {
764 $editUids[] = $sRow[
'uid'];
772 $editIdList = implode(
',', $editUids);
774 foreach ($this->fieldArray as $field) {
776 && isset(
$GLOBALS[
'TCA'][
'pages'][
'columns'][$field])
778 && !$this->pages_noEditColumns
781 $lang->getLL(
'editThisColumn'),
787 $editIdList =>
'edit'
790 'columnsOnly' => $field,
791 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
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>';
803 $theData[$field] = $eI .
' <strong>'
804 . $lang->sL(
$GLOBALS[
'TCA'][
'pages'][
'columns'][$field][
'label'])
808 $theData[$field] =
'';
811 if (strpos($field,
'table_') === 0) {
812 $f2 = substr($field, 6);
814 $theData[$field] =
' ' .
816 htmlspecialchars($lang->sL(
$GLOBALS[
'TCA'][$f2][
'ctrl'][
'title'])) .
822 $theData[$field] = $eI .
' <strong>'
823 . htmlspecialchars($lang->sL(
$GLOBALS[
'TCA'][
'pages'][
'columns'][$field][
'label']))
828 $out =
'<div class="table-fit">'
829 .
'<table class="table table-striped table-hover typo3-page-pages">'
850 $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
851 ->getConnectionForTable(
'tt_content')
852 ->getExpressionBuilder();
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;
864 $languageOverlayId = 0;
866 if (is_array($pageLocalizationRecord)) {
867 $pageLocalizationRecord = reset($pageLocalizationRecord);
869 if (!empty($pageLocalizationRecord[
'uid'])) {
870 $languageOverlayId = $pageLocalizationRecord[
'uid'];
872 $pageActionsCallback =
'function(PageActions) {
873 PageActions.setPageId(' . (int)$this->
id .
');
874 PageActions.setLanguageOverlayId(' . $languageOverlayId .
');
877 $pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/PageActions', $pageActionsCallback);
879 $this->CType_labels = [];
880 foreach (
$GLOBALS[
'TCA'][
'tt_content'][
'columns'][
'CType'][
'config'][
'items'] as $val) {
884 $this->itemLabels = [];
885 foreach (
$GLOBALS[
'TCA'][
'tt_content'][
'columns'] as $name => $val) {
888 $languageColumn = [];
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'];
897 $langList = implode(
',', array_keys($this->tt_contentConfig[
'languageCols']));
899 $languageColumn = [];
901 $langListArr = GeneralUtility::intExplode(
',', $langList);
902 $defaultLanguageElementsByColumn = [];
906 foreach ($langListArr as $lP) {
909 if (!isset($this->contentElementCache[$lP])) {
910 $this->contentElementCache[$lP] = [];
913 if (count($langListArr) === 1 || $lP === 0) {
914 $showLanguage = $expressionBuilder->in(
'sys_language_uid', [$lP, -1]);
916 $showLanguage = $expressionBuilder->eq(
'sys_language_uid', $lP);
922 $columns = $backendLayout[
'__colPosList'];
925 $cList = array_keys($contentRecordsPerColumn);
927 foreach ($cList as $columnId) {
928 if (!isset($this->contentElementCache[$lP])) {
929 $this->contentElementCache[$lP] = [];
933 $defaultLanguageElementsByColumn[$columnId] = [];
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';
941 $content[$columnId] .=
'">';
947 if ($this->option_newWizard) {
950 'sys_language_uid' => $lP,
951 'colPos' => $columnId,
953 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
956 ??
'new_content_element_wizard';
957 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
958 $url = (string)$uriBuilder->buildUriFromRoute($routeName, $urlParameters);
968 'colPos' => $columnId,
969 'sys_language_uid' => $lP
972 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
974 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
975 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
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' :
'') .
'">'
986 if ($this->
getBackendUser()->checkLanguageAccess($lP) && $columnId !==
'unused') {
987 $content[$columnId] .=
'
992 <div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div>
997 if (!isset($contentRecordsPerColumn[$columnId]) || !is_array($contentRecordsPerColumn[$columnId])) {
998 $message = GeneralUtility::makeInstance(
1000 $this->
getLanguageService()->sL(
'LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:error.invalidBackendLayout'),
1004 $service = GeneralUtility::makeInstance(FlashMessageService::class);
1005 $queue = $service->getMessageQueueByIdentifier();
1006 $queue->addMessage($message);
1008 $rowArr = $contentRecordsPerColumn[$columnId];
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];
1018 if (!$lP && ($this->defLangBinding || $row[
'sys_language_uid'] != -1)) {
1019 $defaultLanguageElementsByColumn[$columnId][] = ($row[
'_ORIG_uid'] ?? $row[
'uid']);
1021 $editUidList .= $row[
'uid'] .
',';
1025 $this->tt_contentConfig[
'showInfo'] ? 15 : 5,
1026 $disableMoveAndNewButtons,
1030 $innerContent =
'<div ' . ($row[
'_ORIG_uid'] ?
' class="ver-element"' :
'') .
'>'
1032 $singleElementHTML .=
'<div class="t3-page-ce-body-inner">' . $innerContent .
'</div></div>'
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 =
'';
1039 $highlightHeader =
' t3-page-ce-danger';
1040 } elseif ($columnId ===
'unused') {
1041 $highlightHeader =
' t3-page-ce-warning';
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>';
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 .
1050 if (!$disableMoveAndNewButtons
1053 && $columnId !==
'unused'
1056 if ($this->option_newWizard) {
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')
1065 ??
'new_content_element_wizard';
1066 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1067 $url = (string)$uriBuilder->buildUriFromRoute($routeName, $urlParameters);
1072 -$row[
'uid'] =>
'new'
1075 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
1077 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1078 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
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' :
'') .
'">'
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;
1093 $content[$columnId] .= $singleElementHTML;
1096 unset($rowArr[$rKey]);
1099 $content[$columnId] .=
'</div>';
1101 $tcaItems = GeneralUtility::callUserFunction(\
TYPO3\CMS\Backend\View\BackendLayoutView::class .
'->getColPosListItemsParsed',
$id, $this);
1102 foreach ($tcaItems as $item) {
1103 if ($item[1] == $columnId) {
1107 if ($columnId ===
'unused') {
1108 if (empty($unusedElementsMessage)) {
1109 $unusedElementsMessage = GeneralUtility::makeInstance(
1110 FlashMessage::class,
1115 $service = GeneralUtility::makeInstance(FlashMessageService::class);
1116 $queue = $service->getMessageQueueByIdentifier();
1117 $queue->addMessage($unusedElementsMessage);
1119 $colTitle = $this->
getLanguageService()->
sL(
'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.unused');
1122 $editParam = $this->doEdit && !empty($rowArr)
1123 ?
'&edit[tt_content][' . $editUidList .
']=edit' . $pageTitleParamForAltDoc
1131 if ($this->tt_contentConfig[
'languageMode']) {
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];
1139 $sortedLanguageColumn[$columnId] = $languageColumn[$columnId];
1142 if (!empty($languageColumn[
'unused'])) {
1143 $sortedLanguageColumn[
'unused'] = $languageColumn[
'unused'];
1145 $languageColumn = $sortedLanguageColumn;
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">';
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++) {
1156 $grid .=
'</colgroup>';
1162 for ($row = 1; $row <= $rowCount; $row++) {
1163 $rowConfig = $backendLayout[
'__config'][
'backend_layout.'][
'rows.'][$row .
'.'];
1164 if (!isset($rowConfig)) {
1168 for ($col = 1; $col <= $colCount; $col++) {
1169 $columnConfig = $rowConfig[
'columns.'][$col .
'.'];
1170 if (!isset($columnConfig)) {
1174 $columnKey = (int)$columnConfig[
'colPos'];
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 :
'') .
'">';
1189 if (isset($columnConfig[
'colPos']) && $columnConfig[
'colPos'] !==
'' && $head[$columnKey]
1190 && GeneralUtility::inList($this->tt_contentConfig[
'activeCols'], $columnConfig[
'colPos'])
1192 $grid .= $head[$columnKey] . $content[$columnKey];
1193 } elseif (isset($columnConfig[
'colPos']) && $columnConfig[
'colPos'] !==
''
1194 && GeneralUtility::inList($this->tt_contentConfig[
'activeCols'], $columnConfig[
'colPos'])
1196 if (!$hideRestrictedCols) {
1199 } elseif (isset($columnConfig[
'colPos']) && $columnConfig[
'colPos'] !==
''
1200 && !GeneralUtility::inList($this->tt_contentConfig[
'activeCols'], $columnConfig[
'colPos'])
1202 if (!$hideRestrictedCols) {
1206 } elseif (isset($columnConfig[
'name']) && $columnConfig[
'name'] !==
'') {
1217 if (!empty($content[
'unused'])) {
1220 $columnKey =
'unused';
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 :
'') .
'">';
1231 $grid .= $head[$columnKey] . $content[$columnKey];
1232 $grid .=
'</td></tr>';
1234 $out .= $grid .
'</table></div>';
1237 $elFromTable = $this->clipboard->elFromTable(
'tt_content');
1239 $pasteItem = substr(key($elFromTable), 11);
1241 $pasteTitle = $pasteRecord[
'header'] ? $pasteRecord[
'header'] : $pasteItem;
1242 $copyMode = $this->clipboard->clipData[
'normal'][
'mode'] ?
'-' . $this->clipboard->clipData[
'normal'][
'mode'] :
'';
1243 $addExtOnReadyCode =
'
1244 top.pasteIntoLinkTemplate = '
1247 top.pasteAfterLinkTemplate = '
1251 $addExtOnReadyCode =
'
1252 top.pasteIntoLinkTemplate = \'\';
1253 top.pasteAfterLinkTemplate = \'\';';
1255 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
1256 $pageRenderer->addJsInlineCode(
'pasteLinkTemplates', $addExtOnReadyCode);
1260 if ($this->tt_contentConfig[
'languageMode']) {
1268 foreach ($langListArr as $lP) {
1270 $labelClass =
'info';
1274 if ($lP > 0 && isset($this->languageHasTranslationsCache[$lP][
'mode'])) {
1275 switch ($this->languageHasTranslationsCache[$lP][
'mode']) {
1278 $labelClass =
'danger';
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>' :
'') .
'
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>';
1312 if (is_array($pageLocalizationRecord)) {
1313 $pageLocalizationRecord = reset($pageLocalizationRecord);
1317 $this->iconFactory->getIconForRecord(
'pages', $pageLocalizationRecord,
Icon::SIZE_SMALL)->render(),
1319 $pageLocalizationRecord[
'uid']
1324 $pageLocalizationRecord[
'uid'] =>
'edit'
1330 'sys_language_uid' => $lP
1333 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
1335 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1336 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
1339 ?
'<a href="' . htmlspecialchars($url) .
'" class="btn btn-default btn-sm"'
1341 . $this->iconFactory->getIcon(
'actions-open',
Icon::SIZE_SMALL)->render() .
'</a>'
1345 $defaultLanguageElements = [];
1346 array_walk($defaultLanguageElementsByColumn,
function (array $columnContent) use (&$defaultLanguageElements) {
1347 $defaultLanguageElements = array_merge($defaultLanguageElements, $columnContent);
1350 $localizationButtons = [];
1357 '<div class="btn-group">'
1360 . (!empty($localizationButtons) ? implode(LF, $localizationButtons) :
'')
1362 .
' ' . $recordIcon .
' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageLocalizationRecord[
'title'], 20))
1369 $this->iconFactory->getIconForRecord(
'pages', $this->pageRecord,
Icon::SIZE_SMALL)->render(),
1379 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
1381 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1382 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
1385 ?
'<a href="' . htmlspecialchars($url) .
'" class="btn btn-default btn-sm"'
1393 '<div class="btn-group">'
1397 .
' ' . $recordIcon .
' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->pageRecord[
'title'], 20));
1400 <td class="t3-page-column t3-page-lang-label nowrap">' . $lPLabel .
'</td>';
1403 $out .=
'<tr>' . implode(
'', $cCont) .
'</tr>';
1404 $out .=
'<tr>' . implode(
'', $sCont) .
'</tr>';
1405 unset($cCont, $sCont);
1408 foreach ($languageColumn as $cKey => $cCont) {
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>';
1416 for ($i = 0; $i < $maxItemsCount; $i++) {
1417 $defUid = $defaultLanguageElementsByColumn[$cKey][$i] ?? 0;
1419 foreach ($langListArr as $lP) {
1426 $element = $slice[0] ??
'';
1430 $cCont[] = $element;
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>
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">
1476 if ($this->totalItems) {
1477 $result = $queryBuilder->execute();
1479 $dbCount = $queryBuilder->count(
'uid')->execute()->fetchColumn(0);
1487 $this->fieldArray = GeneralUtility::trimExplode(
',',
'__cmds__,' . $fList .
',__editIconLink__',
true);
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>'
1497 if ($this->doEdit) {
1504 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
1506 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1507 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
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>';
1514 $out .= $this->
addElement(1,
'', $theData,
' class="c-headLine"', 15,
'',
'th');
1517 while ($row = $result->fetch()) {
1519 if (is_array($row)) {
1526 $Nrow[
'__cmds__'] = $this->
getIcon($table, $row);
1531 if ($this->doEdit) {
1535 $row[
'uid'] =>
'edit'
1538 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
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)
1544 . $this->iconFactory->getIcon(
'actions-open',
Icon::SIZE_SMALL)->render() .
'</a>';
1556 Standard list of table "' .
$table .
'"
1558 <div class="table-fit"><table class="table table-hover table-striped">
1587 foreach ($fieldArr as $fieldName) {
1591 if ($fieldName == $thumbsCol) {
1595 $out[$fieldName] = nl2br(htmlspecialchars(trim(GeneralUtility::fixed_lgd_cs(
1603 $theFields = explode(
';', $fieldName);
1605 foreach ($theFields as $fName2) {
1609 )) .
'</strong>' .
' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs(
1617 if (!$out[$fieldName]) {
1618 $out[$fieldName] =
' ';
1622 $out[$fieldName] =
'<span class="text-muted">' . $out[$fieldName] .
'</span>';
1639 foreach ($fieldArr as $fieldName) {
1641 $out[$fieldName] = $ll ? $ll :
' ';
1658 $contentRecordsPerColumn = array_fill_keys($columns, []);
1659 $columns = array_flip($columns);
1664 $additionalWhereClause
1669 $results = $this->
getResult($queryBuilder->execute());
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);
1679 $columnValue = (string)$record[
'colPos'];
1680 $contentRecordsPerColumn[$columnValue][] = $record;
1682 $unused[] = $record;
1685 if (!empty($unused)) {
1686 $contentRecordsPerColumn[
'unused'] = $unused;
1688 return $contentRecordsPerColumn;
1706 protected function getPageRecordsRecursive(
int $pid,
int $depth,
string $iconPrefix =
'', array $rows = []): array
1709 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages');
1710 $queryBuilder->getRestrictions()
1712 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1713 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
1719 $queryBuilder->expr()->eq(
'pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)),
1720 $queryBuilder->expr()->eq(
'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
1724 if (!empty(
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'sortby'])) {
1725 $queryBuilder->orderBy(
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'sortby']);
1729 $result = $queryBuilder->execute();
1730 $rowCount = $queryBuilder->count(
'uid')->execute()->fetchColumn(0);
1732 while ($row = $result->fetch()) {
1734 if (is_array($row)) {
1736 $row[
'treeIcons'] = $iconPrefix
1737 .
'<span class="treeline-icon treeline-icon-join'
1738 . ($rowCount === $count ?
'bottom' :
'')
1742 $spaceOutIcons =
'<span class="treeline-icon treeline-icon-'
1743 . ($rowCount === $count ?
'clear' :
'line')
1747 $row[
'php_tree_stop'] ? 0 : $depth,
1748 $iconPrefix . $spaceOutIcons,
1770 $theIcon = $this->
getIcon(
'pages', $row);
1773 foreach ($fieldArr as $field) {
1776 $showPageId = !empty($userTsConfig[
'options.'][
'pageTree.'][
'showPageIdWithTitle']);
1778 $theData[$field] = $row[
'treeIcons'] . $theIcon . ($showPageId ?
'[' . $row[
'uid'] .
'] ' :
'') . $pTitle;
1780 case 'php_tree_stop':
1783 $theData[$field] = $row[$field] ?
'<strong>x</strong>' :
' ';
1790 $row[
'uid'] =>
'edit'
1793 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
1795 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1796 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
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') .
'">' .
1805 '<a class="btn btn-default" href="' . htmlspecialchars($url) .
'" title="' .
1812 $theData[$field] =
'<div class="btn-group" role="group">' . $eI .
'</div>';
1815 case 'shortcut_mode':
1816 if ((
int)$row[
'doktype'] === \
TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_SHORTCUT) {
1821 if (strpos($field,
'table_') === 0) {
1822 $f2 = substr($field, 6);
1825 $theData[$field] = ($c ? $c :
'');
1832 $this->addElement_tdParams[
'title'] = $row[
'_CSSCLASS'] ?
' class="' . $row[
'_CSSCLASS'] .
'"' :
'';
1865 if ($this->tt_contentConfig[
'showCommands']) {
1868 $iconsArr[
'edit'] =
'<a href="#" onclick="'
1871 . $this->iconFactory->getIcon(
'actions-document-open',
Icon::SIZE_SMALL)->render() .
'</a>';
1875 if (!empty($iconsArr)) {
1876 $icons =
'<div class="t3-page-column-header-icons">' . implode(
'', $iconsArr) .
'</div>';
1879 $out =
'<div class="t3-page-column-header">
1881 <div class="t3-page-column-header-label">' . htmlspecialchars($colName) .
'</div>
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"'
1905 . $this->iconFactory->getIcon(
'actions-document-paste-into',
Icon::SIZE_SMALL)->render()
1923 $this->
getProcessedValue(
'tt_content',
'starttime,endtime,fe_group,space_before_class,space_after_class', $row, $info);
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']]);
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);
1936 $hookObject->preProcess($this, $info, $row);
1940 if (!empty($info)) {
1941 $content =
'<div class="t3-page-ce-info">
1942 ' . implode(
'<br>', $info) .
'
1946 if (!empty($content)) {
1947 $content =
'<div class="t3-page-ce-footer">' . $content .
'</div>';
1962 public function tt_content_drawHeader($row, $space = 0, $disableMoveAndNewButtons =
false, $langMode =
false, $dragDropEnabled =
false)
1967 if ($this->tt_contentConfig[
'showInfo'] && $backendUser->recordEditAccessInternals(
'tt_content', $row)) {
1969 if ($this->tt_contentConfig[
'showCommands'] && $this->
isContentEditable($row[
'sys_language_uid'])) {
1974 $this->tt_contentData[
'nextThree'][$row[
'uid']] =>
'edit'
1977 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI') .
'#element-tt_content-' . $row[
'uid'],
1979 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1980 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters) .
'#element-tt_content-' . $row[
'uid'];
1982 $out .=
'<a class="btn btn-default" href="' . htmlspecialchars($url)
1983 .
'" title="' . htmlspecialchars($this->nextThree > 1
1986 .
'">' . $this->iconFactory->getIcon(
'actions-open',
Icon::SIZE_SMALL)->render() .
'</a>';
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))
1993 if ($row[$hiddenField]) {
2000 $params =
'&data[tt_content][' . ($row[
'_ORIG_uid'] ? $row[
'_ORIG_uid'] : $row[
'uid'])
2001 .
'][' . $hiddenField .
']=' . $value;
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>';
2007 $disableDelete = (bool)\trim(
2008 $backendUser->getTSConfig()[
'options.'][
'disableDelete.'][
'tt_content']
2009 ?? $backendUser->getTSConfig()[
'options.'][
'disableDelete']
2012 if (!$disableDelete) {
2013 $params =
'&cmd[tt_content][' . $row[
'uid'] .
'][delete]=1';
2017 ' ' . $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord'),
2022 ' ' . $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord')
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')) .
'"'
2032 . $this->iconFactory->getIcon(
'actions-edit-delete',
Icon::SIZE_SMALL)->render() .
'</a>';
2034 $out =
'<div class="btn-group btn-group-sm" role="group">' . $out .
'</div>';
2039 if (!$disableMoveAndNewButtons) {
2040 $moveButtonContent =
'';
2041 $displayMoveButtons =
false;
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="'
2048 . $this->iconFactory->getIcon(
'actions-move-up',
Icon::SIZE_SMALL)->render() .
'</a>';
2049 if (!$dragDropEnabled) {
2050 $displayMoveButtons =
true;
2053 $moveButtonContent .=
'<span class="btn btn-default disabled">' . $this->iconFactory->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>';
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="'
2061 . $this->iconFactory->getIcon(
'actions-move-down',
Icon::SIZE_SMALL)->render() .
'</a>';
2062 if (!$dragDropEnabled) {
2063 $displayMoveButtons =
true;
2066 $moveButtonContent .=
'<span class="btn btn-default disabled">' . $this->iconFactory->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>';
2068 if ($displayMoveButtons) {
2069 $out .=
'<div class="btn-group btn-group-sm" role="group">' . $moveButtonContent .
'</div>';
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']]);
2082 $additionalIcons[] =
'<a href="#" data-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo[
'msg']) .
'">'
2083 . $this->iconFactory->getIcon(
'warning-in-use',
Icon::SIZE_SMALL)->render() .
'</a>';
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);
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>
2097 <div class="t3-page-ce-body">';
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;
2115 return $this->referenceCount[$tableName][$uid];
2126 if ((
int)$row[
'l18n_parent'] === 0 &&
2129 || ((
int)$row[
'editlock'] === 0 && (
int)$this->pageinfo[
'editlock'] === 0)
2131 && $this->
getBackendUser()->checkAuthMode(
'tt_content',
'CType', $row[
'CType'],
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'explicitADmode'])
2152 if ($row[
'header']) {
2153 $hiddenHeaderNote =
'';
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>';
2158 $outHeader = $row[
'date']
2159 ? htmlspecialchars($this->itemLabels[
'date'] .
' ' .
BackendUtility::date($row[
'date'])) .
'<br />'
2162 . $hiddenHeaderNote .
'</strong><br />';
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);
2172 $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row);
2181 $fluidTemplateFile =
'';
2183 if ($row[
'CType'] ===
'list' && !empty($row[
'list_type'])
2184 && !empty($tsConfig[
'list.'][$row[
'list_type']])
2186 $fluidTemplateFile = $tsConfig[
'list.'][$row[
'list_type']];
2187 } elseif (!empty($tsConfig[$row[
'CType']])) {
2188 $fluidTemplateFile = $tsConfig[$row[
'CType']];
2191 if ($fluidTemplateFile) {
2192 $fluidTemplateFile = GeneralUtility::getFileAbsFileName($fluidTemplateFile);
2193 if ($fluidTemplateFile) {
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']));
2202 $out = $view->render();
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',
2218 switch ($row[
'CType']) {
2220 if ($row[
'subheader']) {
2226 if ($row[
'bodytext']) {
2231 if ($row[
'media']) {
2236 $contentType = $this->CType_labels[$row[
'CType']];
2237 $out .= $this->
linkEditContent(
'<strong>' . htmlspecialchars($contentType) .
'</strong>', $row) .
'<br />';
2242 $menuTypeLabel = $menuTypeLabel ?:
'invalid menu type';
2244 if ($row[
'menu_type'] !==
'2' && ($row[
'pages'] || $row[
'selected_categories'])) {
2250 if (!empty($row[
'records'])) {
2251 $shortcutContent = [];
2252 $recordList = explode(
',', $row[
'records']);
2253 foreach ($recordList as $recordIdentifier) {
2255 $tableName = empty($split[0]) ?
'tt_content' : $split[0];
2257 if (is_array($shortcutRecord)) {
2258 $icon = $this->iconFactory->getIconForRecord($tableName, $shortcutRecord,
Icon::SIZE_SMALL)->render();
2262 $shortcutRecord[
'uid']
2264 $shortcutContent[] = $icon
2268 $out .= implode(
'<br />', $shortcutContent) .
'<br />';
2273 $_params = [
'pObj' => &$this,
'row' => $row,
'infoArr' => []];
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'] ??
2279 $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2281 if ((
string)$hookOut !==
'') {
2283 } elseif (!empty($row[
'list_type'])) {
2285 if (!empty($label)) {
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>';
2299 $contentType = $this->CType_labels[$row[
'CType']];
2300 if (!isset($contentType)) {
2305 $out .= $this->
linkEditContent(
'<strong>' . htmlspecialchars($contentType) .
'</strong>', $row) .
'<br />';
2306 if ($row[
'bodytext']) {
2309 if ($row[
'image']) {
2314 $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'),
2317 $out .=
'<span class="label label-warning">' . htmlspecialchars($message) .
'</span>';
2323 <span class="exampleContent">' . $out .
'</span>';
2325 $out = $outHeader . $out;
2328 return '<span class="text-muted">' . $out .
'</span>';
2344 if (strpos($row[
'menu_type'],
'categorized_') !==
false) {
2346 $field =
'selected_categories';
2348 if (trim($row[$field]) ===
'') {
2352 $uidList = explode(
',', $row[$field]);
2353 foreach ($uidList as $uid) {
2356 $content .=
'<br>' . htmlspecialchars($record[
'title']) .
' (' . $uid .
')';
2373 if ($lP && !empty($defaultLanguageUids)) {
2375 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2376 ->getQueryBuilderForTable(
'tt_content');
2377 $queryBuilder->getRestrictions()
2379 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2380 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class,
null,
false));
2383 ->from(
'tt_content')
2385 $queryBuilder->expr()->eq(
2387 $queryBuilder->createNamedParameter($lP, \PDO::PARAM_INT)
2389 $queryBuilder->expr()->in(
2391 $queryBuilder->createNamedParameter($defaultLanguageUids, Connection::PARAM_INT_ARRAY)
2395 $result = $queryBuilder->execute();
2398 $defaultLanguageUids = array_flip($defaultLanguageUids);
2400 while ($row = $result->fetch()) {
2402 unset($defaultLanguageUids[$row[
'l18n_parent']]);
2405 $defaultLanguageUids = array_keys($defaultLanguageUids);
2407 return $defaultLanguageUids;
2420 if (!$this->doEdit || !$lP) {
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;
2432 if (isset($this->languageHasTranslationsCache[$lP][
'hasTranslations'])) {
2433 $allowCopy = $allowCopy && !$this->languageHasTranslationsCache[$lP][
'hasTranslations'];
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]);
2448 if (!empty($defaultLanguageUids)) {
2452 .
' class="btn btn-default btn-sm t3js-localize disabled"'
2453 .
' title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'newPageContent_translate')) .
'"'
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]) .
'"'
2468 return $theNewButton;
2482 if ($this->option_newWizard) {
2484 ??
'new_content_element_wizard';
2485 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2486 $url = $uriBuilder->buildUriFromRoute($routeName, [
2488 'colPos' => $colPos,
2489 'sys_language_uid' => $sys_language,
2491 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
2493 $onClick =
'window.location.href=' . GeneralUtility::quoteJSvalue((
string)$url) .
';';
2496 . $colPos .
'&defVals[tt_content][sys_language_uid]=' . $sys_language);
2512 if ($this->doEdit && $this->
getBackendUser()->recordEditAccessInternals(
'tt_content', $row)) {
2516 $row[
'uid'] =>
'edit'
2519 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI') .
'#element-tt_content-' . $row[
'uid']
2521 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2522 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
2524 return '<a href="' . htmlspecialchars($url) .
'" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'edit')) .
'">' . $str .
'</a>';
2546 $availableTranslations = [];
2547 foreach ($this->siteLanguages as $language) {
2548 if ($language->getLanguageId() <= 0) {
2551 $availableTranslations[$language->getLanguageId()] = $language->getTitle();
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'])
2562 $queryBuilder->expr()->eq(
2563 $GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'transOrigPointerField'],
2564 $queryBuilder->createNamedParameter(
$id, \PDO::PARAM_INT)
2567 $statement = $queryBuilder->execute();
2568 while ($row = $statement->fetch()) {
2569 unset($availableTranslations[(
int)$row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField']]]);
2572 if (!empty($availableTranslations)) {
2574 foreach ($availableTranslations as $languageUid => $languageTitle) {
2579 'justLocalized' =>
'pages:' .
$id .
':' . $languageUid,
2580 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')
2582 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2583 $redirectUrl = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $parameters);
2585 '&cmd[pages][' .
$id .
'][localize]=' . $languageUid,
2589 $output .=
'<option value="' . htmlspecialchars($targetUrl) .
'">' . htmlspecialchars($languageTitle) .
'</option>';
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">'
2596 .
'</select></div></div>';
2608 public function getResult(Statement $result,
string $table =
'tt_content'): array
2612 while ($row = $result->fetch()) {
2640 $this->clipboard = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Clipboard\Clipboard::class);
2643 $this->clipboard->initializeClipboard();
2646 $this->clipboard->lockToNormal();
2649 $this->clipboard->cleanCurrent();
2652 $this->clipboard->endClipboard();
2662 if (empty($this->tt_contentData)) {
2663 $this->tt_contentData = [
2669 foreach ($rowArray as $key => $value) {
2672 if (isset($rowArray[$key - $i])
2673 && !GeneralUtility::inList($this->tt_contentData[
'nextThree'][$rowArray[$key - $i][
'uid']], $value[
'uid'])
2675 $this->tt_contentData[
'nextThree'][$rowArray[$key - $i][
'uid']] .= $value[
'uid'] .
',';
2680 if (isset($rowArray[$key - 1])) {
2681 if (isset($rowArray[$key - 2])) {
2682 $this->tt_contentData[
'prev'][$value[
'uid']] = -$rowArray[$key - 2][
'uid'];
2684 $this->tt_contentData[
'prev'][$value[
'uid']] = $value[
'pid'];
2686 $this->tt_contentData[
'next'][$rowArray[$key - 1][
'uid']] = -$value[
'uid'];
2702 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2704 $queryBuilder->getRestrictions()
2706 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2707 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2708 $count = (int)$queryBuilder->count(
'uid')
2711 $queryBuilder->expr()->eq(
'pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))
2728 $input = strip_tags($input);
2729 $input = GeneralUtility::fixed_lgd_cs($input, 1500);
2730 return nl2br(htmlspecialchars(trim($input), ENT_QUOTES,
'UTF-8',
false));
2745 $icon =
'<span ' . $toolTip .
'>' . $this->iconFactory->getIconForRecord(
$table, $row,
Icon::SIZE_SMALL)->render() .
'</span>';
2766 $fieldArr = explode(
',', $fieldList);
2768 foreach ($fieldArr as $field) {
2770 $info[] =
'<strong>' . htmlspecialchars($this->itemLabels[$field]) .
'</strong> '
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'];
2799 public function noEditIcon($label =
'noEditItems')
2802 return '<span title="' . $title .
'">' . $this->iconFactory->getIcon(
'status-edit-read-only',
Icon::SIZE_SMALL)->render() .
'</span>';
2822 $this->activeTables = [];
2823 $theTables = [
'tt_content'];
2825 if (is_array($this->externalTables)) {
2826 $theTables = array_unique(array_merge($theTables, array_keys($this->externalTables)));
2830 foreach ($theTables as $tName) {
2834 isset($this->externalTables[$tName])
2835 || $tName ===
'fe_users' || $tName ===
'tt_content'
2840 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2841 ->getQueryBuilderForTable($tName);
2842 $queryBuilder->getRestrictions()
2844 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2845 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2846 $count = $queryBuilder->count(
'uid')
2848 ->where($queryBuilder->expr()->eq(
'pid', $queryBuilder->createNamedParameter(
$id, \PDO::PARAM_INT)))
2852 if ($count || $tName ===
'tt_content') {
2855 <td><a href="#' . $tName .
'" title="' . htmlspecialchars($this->
getLanguageService()->sL(
$GLOBALS[
'TCA'][$tName][
'ctrl'][
'title'])) .
'"></a>'
2861 $this->activeTables[$tName] =
'<span title="' . $title .
'">'
2871 Menu of tables on the page (table menu)
2873 <table border="0" cellpadding="0" cellspacing="0" id="typo3-page-tblMenu">
2909 if ($language === 0 || $allowInconsistentLanguageHandling) {
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';
2922 if ((
int)$contentElement[
'l18n_parent'] > 0) {
2923 $this->languageHasTranslationsCache[$language][
'hasTranslations'] =
true;
2924 $this->languageHasTranslationsCache[$language][
'mode'] =
'connected';
2928 if (!isset($this->languageHasTranslationsCache[$language])) {
2929 $this->languageHasTranslationsCache[$language][
'hasTranslations'] =
false;
2932 if (isset($this->languageHasTranslationsCache[$language][
'hasStandAloneContent'])
2933 && $this->languageHasTranslationsCache[$language][
'hasTranslations']
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()),
2943 $service = GeneralUtility::makeInstance(FlashMessageService::class);
2944 $queue = $service->getMessageQueueByIdentifier();
2945 $queue->addMessage($message);
2949 return $this->languageHasTranslationsCache[$language][
'hasTranslations'];
2957 return GeneralUtility::makeInstance(BackendLayoutView::class);
2993 $this->
id = (int)
$id;
2998 $this->firstElementNumber = $pointer;
2999 $this->searchString = trim($search);
3000 $this->searchLevels = (int)$levels;
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')) {
3014 $this->HTMLcode =
'';
3016 if (isset($this->modTSconfig[
'properties'][
'itemsLimitPerTable'])) {
3018 (
int)$this->modTSconfig[
'properties'][
'itemsLimitPerTable'],
3023 if (isset($this->modTSconfig[
'properties'][
'itemsLimitSingleTable'])) {
3025 (
int)$this->modTSconfig[
'properties'][
'itemsLimitSingleTable'],
3034 $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3035 ->getQueryBuilderForTable(
'pages')
3039 $pidList = GeneralUtility::intExplode(
',', $backendUser->getTSConfig()[
'options.'][
'hideRecords.'][
'pages'] ??
'',
true);
3040 if (!empty($pidList)) {
3041 $permsClause->add($expressionBuilder->notIn(
'pages.uid', $pidList));
3043 $this->perms_clause = (string)$permsClause;
3046 $this->tablesCollapsed = is_array($backendUser->uc[
'moduleData'][
'list'])
3047 ? $backendUser->uc[
'moduleData'][
'list']
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;
3058 $backendUser->writeUC($backendUser->uc);
3059 $returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP(
'returnUrl'));
3076 $hideTablesArray = GeneralUtility::trimExplode(
',', $this->hideTables);
3081 $tableNames = array_flip(array_keys(
$GLOBALS[
'TCA']));
3082 foreach ($tableNames as $tableName => &$config) {
3087 if ($this->table && $tableName !== $this->table
3088 || $this->tableList && !GeneralUtility::inList($this->tableList, $tableName)
3089 || !$backendUser->check(
'tables_select', $tableName)
3097 $hideTable = $hideTable
3098 || !empty(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'hideTable'])
3099 || in_array($tableName, $hideTablesArray,
true)
3100 || in_array(
'*', $hideTablesArray,
true);
3102 if (isset($this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'])) {
3103 $hideTable = (bool)$this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'];
3107 unset($tableNames[$tableName]);
3109 if (isset($this->tableDisplayOrder[$tableName])) {
3111 $tableNames[$tableName] = $this->tableDisplayOrder[$tableName];
3113 $tableNames[$tableName] = [];
3119 $orderedTableNames = GeneralUtility::makeInstance(DependencyOrderingService::class)
3120 ->orderByDependencies($tableNames);
3122 foreach ($orderedTableNames as $tableName => $_) {
3125 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems'])
3126 ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems']
3127 : $this->itemsLimitSingleTable;
3130 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3131 ->getQueryBuilderForTable($tableName);
3132 $queryBuilder->getRestrictions()
3134 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3135 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3137 $firstRow = $queryBuilder->select(
'uid')
3141 if (!is_array($firstRow)) {
3144 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems'])
3145 ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems']
3146 : $this->itemsLimitPerTable;
3148 if ($this->showLimit) {
3152 if ($this->allFields) {
3158 if (is_array($this->setFields[$tableName])) {
3168 $this->HTMLcode .= $this->
getTable($tableName, $this->
id, implode(
',',
$fields));
3182 $formElements = [
'',
''];
3185 '<form action="' . htmlspecialchars(
3186 $this->
listURL(
'',
'-1',
'firstElementNumber,search_field')
3187 ) .
'" method="post">',
3196 $searchLevelsFromTSconfig = $config[
'mod.'][
'web_list.'][
'searchLevel.'][
'items.'];
3197 $searchLevelItems = [];
3200 foreach ($searchLevelsFromTSconfig as $keySearchLevel => $labelConfigured) {
3201 $label = $lang->sL(
'LLL:' . $labelConfigured);
3202 if ($label ===
'') {
3203 $label = $labelConfigured;
3205 $searchLevelItems[$keySearchLevel] = $label;
3208 foreach ($searchLevelItems as $kv => $label) {
3209 $opt[] =
'<option value="' . $kv .
'"' . ($kv === $this->searchLevels ?
' selected="selected"' :
'') .
'>' . htmlspecialchars(
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>';
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">
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')
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) .
'" />
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')
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')
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 :
'')
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')
3255 ) .
' ' . htmlspecialchars(
3256 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search')
3265 ' . $formElements[1] .
'</div>';
3277 $dispFields = $backendUser->getModuleData(
'list/displayFields');
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);
3286 $this->setFields = $dispFields;
3315 array $additionalConstraints = [],
3318 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3319 ->getQueryBuilderForTable(
$table);
3320 $queryBuilder->getRestrictions()
3322 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3323 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3328 if (!empty($additionalConstraints)) {
3329 $queryBuilder->andWhere(...$additionalConstraints);
3334 return $queryBuilder;
3352 array $fieldList = [
'*'],
3353 array $additionalConstraints = [],
3354 QueryBuilder $queryBuilder,
3355 bool $addSorting =
true
3359 'fields' => $fieldList,
3362 'firstResult' => $this->firstElementNumber ?:
null,
3363 'maxResults' => $this->iLimit ?: null
3366 if ($this->iLimit > 0) {
3367 $queryBuilder->setMaxResults($this->iLimit);
3371 if ($this->sortField && in_array($this->sortField, $this->
makeFieldList($table, 1))) {
3372 $queryBuilder->orderBy($this->sortField, $this->sortRev ?
'DESC' :
'ASC');
3376 foreach ($orderBys as $orderBy) {
3377 $queryBuilder->addOrderBy($orderBy[0], $orderBy[1]);
3385 if (!empty($searchWhere)) {
3386 $queryBuilder->andWhere($searchWhere);
3390 if (
$table ===
'pages' && $this->perms_clause) {
3391 $queryBuilder->andWhere($this->perms_clause);
3396 && (GeneralUtility::inList($this->hideTranslations,
$table) || $this->hideTranslations ===
'*')
3398 $queryBuilder->andWhere(
3399 $queryBuilder->expr()->eq(
3406 $hookName = DatabaseRecordList::class;
3407 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][$hookName][
'buildQueryParameters'] ?? [] as $className) {
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(
3416 $additionalConstraints,
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(
3430 $additionalConstraints,
3441 if (!empty($parameters[
'where'])) {
3442 $parameters[
'where'] = array_unique(array_filter(array_values($parameters[
'where'])));
3444 if (!empty($parameters[
'where'])) {
3446 $queryBuilder->where(...$parameters[
'where']);
3448 if (!empty($parameters[
'orderBy'])) {
3450 foreach ($parameters[
'orderBy'] as $fieldNameAndSorting) {
3451 list($fieldName, $sorting) = $fieldNameAndSorting;
3452 $queryBuilder->addOrderBy($fieldName, $sorting);
3455 if (!empty($parameters[
'firstResult'])) {
3457 $queryBuilder->setFirstResult((
int)$parameters[
'firstResult']);
3459 if (!empty($parameters[
'maxResults']) && $parameters[
'maxResults'] !== $this->iLimit) {
3461 $queryBuilder->setMaxResults((
int)$parameters[
'maxResults']);
3463 if (!empty($parameters[
'groupBy'])) {
3465 $queryBuilder->groupBy($parameters[
'groupBy']);
3468 return $queryBuilder;
3481 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3482 ->getQueryBuilderForTable(
$table);
3484 $queryBuilder->getRestrictions()
3486 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3487 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3491 if (!empty($constraints)) {
3492 $queryBuilder->andWhere(...$constraints);
3495 $queryBuilder = $this->
prepareQueryBuilder($table, $pageId, [
'*'], $constraints, $queryBuilder,
false);
3497 $queryBuilder->setFirstResult(0);
3498 $queryBuilder->setMaxResults(1);
3500 $this->totalItems = (int)$queryBuilder->count(
'*')
3515 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
$table);
3516 $expressionBuilder = $queryBuilder->expr();
3518 $currentPid = (int)$currentPid;
3519 $tablePidField =
$table ===
'pages' ?
'uid' :
'pid';
3521 if (empty($this->searchString)) {
3527 $constraints[] = $expressionBuilder->eq(
'uid', (
int)$this->searchString);
3528 foreach ($searchableFields as $fieldName) {
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)
3539 $constraints[] = $expressionBuilder->andX(
3540 $expressionBuilder->eq($fieldName, (
int)$this->searchString),
3541 $expressionBuilder->eq($tablePidField, (
int)$currentPid)
3544 } elseif ($fieldType ===
'text'
3545 || $fieldType ===
'flex'
3546 || ($fieldType ===
'input' && (!$evalRules || !preg_match(
'/\b(?:date|time|int)\b/', $evalRules)))
3548 $constraints[] = $expressionBuilder->like(
3550 $queryBuilder->quote(
'%' . (
int)$this->searchString .
'%')
3554 } elseif (!empty($searchableFields)) {
3555 $like = $queryBuilder->quote(
'%' . $queryBuilder->escapeLikeWildcards($this->searchString) .
'%');
3556 foreach ($searchableFields as $fieldName) {
3561 $fieldType = $fieldConfig[
'type'];
3562 $evalRules = $fieldConfig[
'eval'] ?:
'';
3563 $searchConstraint = $expressionBuilder->andX(
3564 $expressionBuilder->comparison(
3565 'LOWER(' . $queryBuilder->quoteIdentifier($fieldName) .
')',
3567 'LOWER(' . $like .
')'
3570 if (is_array($fieldConfig[
'search'])) {
3571 $searchConfig = $fieldConfig[
'search'];
3572 if (in_array(
'case', $searchConfig)) {
3574 $searchConstraint = $expressionBuilder->andX($expressionBuilder->like($fieldName, $like));
3576 if (in_array(
'pidonly', $searchConfig) && $currentPid > 0) {
3577 $searchConstraint->add($expressionBuilder->eq($tablePidField, (
int)$currentPid));
3579 if ($searchConfig[
'andWhere']) {
3580 $searchConstraint->add(
3585 if ($fieldType ===
'text'
3586 || $fieldType ===
'flex'
3587 || $fieldType ===
'input' && (!$evalRules || !preg_match(
'/\b(?:date|time|int)\b/', $evalRules))
3589 if ($searchConstraint->count() !== 0) {
3590 $constraints[] = $searchConstraint;
3596 if (empty($constraints)) {
3600 return $expressionBuilder->orX(...$constraints);
3612 $fieldListWasSet =
false;
3614 if (isset(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'])) {
3615 $fieldArray = GeneralUtility::trimExplode(
',',
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'],
true);
3616 $fieldListWasSet =
true;
3619 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'mod_list'][
'getSearchFieldList'] ?? [] as $hookFunction) {
3621 'tableHasSearchConfiguration' => $fieldListWasSet,
3622 'tableName' => $tableName,
3626 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
3641 if ($this->table !==
$table) {
3642 return '<a href="' . htmlspecialchars(
3643 $this->
listURL(
'', $table,
'firstElementNumber')
3644 ) .
'">' . $code .
'</a>';
3646 return '<a href="' . htmlspecialchars(
3647 $this->
listURL(
'',
'',
'sortField,sortRev,table,firstElementNumber')
3648 ) .
'">' . $code .
'</a>';
3665 if ((
string)$code ===
'') {
3666 $code =
'<i>[' . htmlspecialchars(
3667 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title')
3671 $code = htmlspecialchars($code, ENT_QUOTES,
'UTF-8',
false);
3672 if ($code != htmlspecialchars($origCode)) {
3673 $code =
'<span title="' . htmlspecialchars(
3678 ) .
'">' . $code .
'</span>';
3681 switch ((
string)$this->clickTitleMode) {
3694 $params =
'&edit[' .
$table .
'][' . $row[
'uid'] .
']=edit';
3695 $code =
'<a href="#" onclick="' . htmlspecialchars(
3697 ) .
'" title="' . htmlspecialchars($lang->getLL(
'edit')) .
'">' . $code .
'</a>';
3703 $code =
'<a href="#" onclick="' . htmlspecialchars(
3705 (
$table ===
'tt_content' ? $this->
id .
'#' . $row[
'uid'] : $row[
'uid'])
3707 ) .
'" title="' . htmlspecialchars(
3708 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')
3709 ) .
'">' . $code .
'</a>';
3714 $code =
'<a href="#" onclick="' . htmlspecialchars(
3715 'top.TYPO3.InfoWindow.showItem(\'' .
$table .
'\', \
'' . $row[
'uid'] .
'\');
return false;
'
3716 ) . '" title="' . htmlspecialchars($lang->getLL('showInfo
')) . '">' . $code . '</a>';
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>';
3725 $code = $this->linkUrlMail($code, $origCode);
3738 public function linkUrlMail($code, $testString)
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>';
3746 if (GeneralUtility::validEmail($testString)) {
3747 return '<a href="mailto:
' . htmlspecialchars($testString) . '" target="_blank
">' . $code . '</a>';
3749 // Return if nothing else...
3763 public function listURL($altId = '', $table = '-1', $exclList = '')
3765 $urlParameters = [];
3766 if ((string)$altId !== '') {
3767 $urlParameters['id'] = $altId;
3769 $urlParameters['id'] = $this->id;
3771 if ($table === '-1') {
3772 $urlParameters['table'] = $this->table;
3774 $urlParameters['table'] = $table;
3776 if ($this->thumbs) {
3777 $urlParameters['imagemode'] = $this->thumbs;
3779 if ($this->returnUrl) {
3780 $urlParameters['returnUrl'] = $this->returnUrl;
3782 if ((!$exclList || !GeneralUtility::inList($exclList, 'search_field')) && $this->searchString) {
3783 $urlParameters['search_field'] = $this->searchString;
3785 if ($this->searchLevels) {
3786 $urlParameters['search_levels'] = $this->searchLevels;
3788 if ($this->showLimit) {
3789 $urlParameters['showLimit'] = $this->showLimit;
3791 if ((!$exclList || !GeneralUtility::inList($exclList, 'firstElementNumber')) && $this->firstElementNumber) {
3792 $urlParameters['pointer'] = $this->firstElementNumber;
3794 if ((!$exclList || !GeneralUtility::inList($exclList, 'sortField')) && $this->sortField) {
3795 $urlParameters['sortField'] = $this->sortField;
3797 if ((!$exclList || !GeneralUtility::inList($exclList, 'sortRev')) && $this->sortRev) {
3798 $urlParameters['sortRev'] = $this->sortRev;
3801 $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters);
3803 if ($routePath = GeneralUtility::_GP('route')) {
3804 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
3805 $url = (string)$uriBuilder->buildUriFromRoutePath($routePath, $urlParameters);
3807 $url = GeneralUtility::getIndpEnv('SCRIPT_NAME') . HttpUtility::buildQueryString($urlParameters, '?');
3816 public function requestUri()
3818 return $this->listURL();
3829 public function makeFieldList($table, $dontCheckUser = false, $addDateFields = false)
3831 $backendUser = $this->getBackendUser();
3832 // Init fieldlist array:
3835 if (is_array($GLOBALS['TCA'][$table]) && isset($GLOBALS['TCA'][$table]['columns']) && is_array(
3836 $GLOBALS['TCA'][$table]['columns']
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',
3844 )) && $fieldValue['config']['type'] !== 'passthrough') {
3845 $fieldListArr[] = $fN;
3849 $fieldListArr[] = 'uid';
3850 $fieldListArr[] = 'pid';
3853 if ($dontCheckUser || $backendUser->isAdmin() || $addDateFields) {
3854 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
3855 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
3857 if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
3858 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
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'];
3866 if ($GLOBALS['TCA'][$table]['ctrl']['sortby']) {
3867 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
3869 if (ExtensionManagementUtility::isLoaded('workspaces')
3870 && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
3871 $fieldListArr[] = 't3ver_id';
3872 $fieldListArr[] = 't3ver_state';
3873 $fieldListArr[] = 't3ver_wsid';
3877 $this->logger->error('TCA is broken for the table "' . $table . '": no required "columns
" entry in TCA.');
3880 return $fieldListArr;
3888 public function localizationRedirect($justLocalized)
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']
3895 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
3896 $queryBuilder->getRestrictions()
3898 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3899 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3901 $localizedRecordUid = $queryBuilder->select('uid')
3904 $queryBuilder->expr()->eq(
3905 $GLOBALS['TCA'][$table]['ctrl']['languageField'],
3906 $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
3908 $queryBuilder->expr()->eq(
3909 $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
3910 $queryBuilder->createNamedParameter($orig_uid, \PDO::PARAM_INT)
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(
3924 'edit[' . $table . '][' . $localizedRecordUid . ']' => 'edit',
3928 HttpUtility::redirect($editUserAccountUrl);
3938 public function setOverrideUrlParameters(array $urlParameters)
3940 $this->overrideUrlParameters = $urlParameters;
3955 public function setTableDisplayOrder(array $orderInformation)
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.',
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.',
3979 $this->tableDisplayOrder = $orderInformation;
3985 public function getOverridePageIdList(): array
3987 return $this->overridePageIdList;
3993 public function setOverridePageIdList(array $overridePageIdList)
3995 $this->overridePageIdList = array_map('intval', $overridePageIdList);
4006 protected function getSearchableWebmounts($id, $depth, $perms_clause)
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'];
4016 $allowedMounts = !$backendUser->isAdmin() && $id === 0
4017 ? $backendUser->returnWebmounts()
4020 foreach ($allowedMounts as $allowedMount) {
4021 $idList[] = $allowedMount;
4023 $tree->getTree($allowedMount, $depth, '');
4025 $idList = array_merge($idList, $tree->ids);
4039 protected function addPageIdConstraint(string $tableName, QueryBuilder $queryBuilder): QueryBuilder
4041 // Set search levels:
4042 $searchLevels = $this->searchLevels;
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;
4050 if ($searchLevels === 0) {
4051 $queryBuilder->andWhere(
4052 $queryBuilder->expr()->eq(
4053 $tableName . '.pid',
4054 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
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)
4067 if (!empty($this->getOverridePageIdList())) {
4068 $queryBuilder->andWhere(
4069 $queryBuilder->expr()->in(
4070 $tableName . '.pid',
4071 $queryBuilder->createNamedParameter($this->getOverridePageIdList(), Connection::PARAM_INT_ARRAY)
4076 return $queryBuilder;
4085 protected function logDeprecation(string $index)
4088 '[index: ' . $index . '] $parameters in "buildQueryParameters
"-Hook will be removed in TYPO3 v10.0, use $queryBuilder instead',
4096 protected function determineScriptUrl()
4098 if ($routePath = GeneralUtility::_GP('route')) {
4099 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
4100 $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath);
4102 $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME');
4120 public function addElement($h, $icon, $data, $rowParams = '', $_ = '', $_2 = '', $colType = 'td')
4122 $colType = ($colType === 'th') ? 'th' : 'td';
4123 $noWrap = $this->no_noWrap ? '' : ' nowrap';
4125 $l10nParent = isset($data['_l10nparent_']) ? (int)$data['_l10nparent_'] : 0;
4127 <!-- Element, begin: -->
4128 <tr ' . $rowParams . ' data-uid="' . (int)$data['uid
'] . '" data-l10nparent="' . $l10nParent . '">';
4129 // Show icon and lines
4130 if ($this->showIcon) {
4132 <' . $colType . ' class="col-icon nowrap
">';
4136 for ($a = 0; $a < $h; $a++) {
4144 $out .= '</' . $colType . '>
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';
4158 // Traverse field array which contains the data to present:
4159 foreach ($fields as $vKey) {
4160 if (isset($data[$vKey])) {
4162 $cssClass = $this->addElement_tdCssClass[$lastKey];
4163 if ($this->oddColumnsCssClass && $ccount % 2 == 0) {
4164 $cssClass = implode(' ', [$this->addElement_tdCssClass[$lastKey], $this->oddColumnsCssClass]);
4167 <' . $colType . ' class="' . $cssClass . $noWrap . '"' . $colsp . $this->addElement_tdParams[$lastKey] . '>' . $data[$lastKey] . '</' . $colType . '>';
4179 $colsp = ' colspan="' . $c . '"';
4185 $cssClass = $this->addElement_tdCssClass[$lastKey];
4186 if ($this->oddColumnsCssClass) {
4187 $cssClass = implode(' ', [$this->addElement_tdCssClass[$lastKey], $this->oddColumnsCssClass]);
4190 <' . $colType . ' class="' . $cssClass . $noWrap . '"' . $colsp . $this->addElement_tdParams[$lastKey] . '>' . $data[$lastKey] . '</' . $colType . '>';
4202 public function writeTop()
4212 public function fwd_rwd_nav($table = '')
4215 if ($this->eCounter >= $this->firstElementNumber && $this->eCounter < $this->firstElementNumber + $this->iLimit) {
4216 if ($this->firstElementNumber && $this->eCounter == $this->firstElementNumber) {
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"');
4225 if ($this->eCounter == $this->firstElementNumber + $this->iLimit) {
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"');
4244 public function fwd_rwd_HTML($type, $pointer, $table = '')
4247 $tParam = $table ? '&table=' . rawurlencode($table) : '';
4250 $href = $this->listURL() . '&pointer=' . ($pointer - $this->iLimit) . $tParam;
4251 $content = '<a href="' . htmlspecialchars($href) . '">' . $this->iconFactory->getIcon(
4254 )->render() . '</a> <i>[' . (max(0, $pointer - $this->iLimit) + 1) . ' - ' . $pointer . ']</i>';
4257 $href = $this->listURL() . '&pointer=' . $pointer . $tParam;
4258 $content = '<a href="' . htmlspecialchars($href) . '">' . $this->iconFactory->getIcon(
4259 'actions-move-down',
4261 )->render() . '</a> <i>[' . ($pointer + 1) . ' - ' . $this->totalItems . ']</i>';
4270 protected function getThisScript()
4272 return strpos($this->thisScript, '?') === false ? $this->thisScript . '?' : $this->thisScript . '&';
4280 public function CBfunctions()
4284 function checkOffCB(listOfCBnames, link) { //
4285 var checkBoxes, flag, i;
4286 var checkBoxes = listOfCBnames.split(",
");
4287 if (link.rel === "") {
4288 link.rel = "allChecked
";
4294 for (i = 0; i < checkBoxes.length; i++) {
4295 setcbValue(checkBoxes[i], flag);
4299 function cbValue(CBname) { //
4300 var CBfullName = "CBC[
"+CBname+"]
";
4301 return (document.dblistForm[CBfullName] && document.dblistForm[CBfullName].checked ? 1 : 0);
4304 function setcbValue(CBname,flag) { //
4305 CBfullName = "CBC[
"+CBname+"]
";
4306 if(document.dblistForm[CBfullName]) {
4307 document.dblistForm[CBfullName].checked = flag ? "on
" : 0;
4317 public function initializeLanguages()
4319 // Look up page overlays:
4320 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4321 ->getQueryBuilderForTable('pages');
4322 $queryBuilder->getRestrictions()
4324 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
4325 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
4326 $result = $queryBuilder
4330 $queryBuilder->expr()->andX(
4331 $queryBuilder->expr()->eq(
4332 $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
4333 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
4335 $queryBuilder->expr()->gt(
4336 $GLOBALS['TCA']['pages']['ctrl']['languageField'],
4337 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
4343 $this->pageOverlays = [];
4344 while ($row = $result->fetch()) {
4345 $this->pageOverlays[$row[$GLOBALS['TCA']['pages']['ctrl']['languageField']]] = $row;
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()
4364 public function languageFlag($sys_language_uid, $addAsAdditionalText = true)
4366 trigger_error('This method will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
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'],
4373 )->render() . '</span>';
4374 if (!$addAsAdditionalText) {
4389 protected function renderLanguageFlag(SiteLanguage $language)
4391 $title = htmlspecialchars($language->getTitle());
4392 if ($language->getFlagIdentifier()) {
4393 $icon = $this->iconFactory->getIcon(
4394 $language->getFlagIdentifier(),
4397 return '<span title="' . $title . '">' . $icon . '</span> ' . $title;
4408 protected function resolveSiteLanguages(int $pageId)
4410 $site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId);
4411 $this->siteLanguages = $site->getAvailableLanguages($this->getBackendUser(), true, $pageId);
4422 protected function generateReferenceToolTip($references, $launchViewParameter = '')
4427 $htmlCode = '<a href="#
"';
4428 if ($launchViewParameter !== '') {
4429 $htmlCode .= ' onclick="' . htmlspecialchars(
4430 'top.TYPO3.InfoWindow.showItem(
' . $launchViewParameter . ');
return false;
'
4433 $htmlCode .= ' title="' . htmlspecialchars(
4434 $this->getLanguageService()->sL(
4435 'LLL:EXT:backend/Resources/Private/Language/locallang.xlf:show_references
'
4436 ) . ' (
' . $references . ')
'
4438 $htmlCode .= $references;
4439 $htmlCode .= '</a>';
4447 protected function getLocalizedPageTitle(): string
4449 if (($this->tt_contentConfig['sys_language_uid'] ?? 0) > 0) {
4450 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4451 ->getQueryBuilderForTable('pages');
4452 $queryBuilder->getRestrictions()
4454 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
4455 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
4456 $localizedPage = $queryBuilder
4460 $queryBuilder->expr()->eq(
4461 $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
4462 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
4464 $queryBuilder->expr()->eq(
4465 $GLOBALS['TCA']['pages']['ctrl']['languageField'],
4466 $queryBuilder->createNamedParameter($this->tt_contentConfig['sys_language_uid'], \PDO::PARAM_INT)
4472 BackendUtility::workspaceOL('pages', $localizedPage);
4473 return $localizedPage['title'];
4475 return $this->pageinfo['title'];
4483 protected function isPageEditable()
4485 if ($this->getBackendUser()->isAdmin()) {
4488 return !$this->pageinfo['editlock'] && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::PAGE_EDIT);
4497 protected function isContentEditable(?int $languageId = null)
4499 if ($this->getBackendUser()->isAdmin()) {
4502 return !$this->pageinfo['editlock']
4503 && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)
4504 && ($languageId === null || $this->getBackendUser()->checkLanguageAccess($languageId));
4511 protected function getLanguageService()
4513 return $GLOBALS['LANG'];