66 'newWizards' =>
'Using $newWizards of class DatabaseRecordList from outside is discouraged, property will be removed in TYPO3 v10.0.',
643 if (isset(
$GLOBALS[
'BE_USER']->uc[
'titleLen']) &&
$GLOBALS[
'BE_USER']->uc[
'titleLen'] > 0) {
644 $this->fixedL =
$GLOBALS[
'BE_USER']->uc[
'titleLen'];
646 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
650 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
681 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
683 $localCalcPerms = $backendUser->calcPerms($this->pageRow);
685 if ((
string)$this->
id ===
'') {
686 $buttons[
'csh'] = BackendUtility::cshItem(
'xMOD_csh_corebe',
'list_module_noId');
687 } elseif (!$this->
id) {
688 $buttons[
'csh'] = BackendUtility::cshItem(
'xMOD_csh_corebe',
'list_module_root');
690 $buttons[
'csh'] = BackendUtility::cshItem(
'xMOD_csh_corebe',
'list_module');
692 if (isset($this->
id)) {
695 if (isset($module->modTSconfig[
'properties'][
'noViewWithDokTypes'])) {
696 $noViewDokTypes = GeneralUtility::trimExplode(
',', $module->modTSconfig[
'properties'][
'noViewWithDokTypes'],
true);
700 PageRepository::DOKTYPE_SYSFOLDER,
701 PageRepository::DOKTYPE_RECYCLER
704 if (!in_array($this->pageRow[
'doktype'], $noViewDokTypes)) {
705 $onClick = htmlspecialchars(BackendUtility::viewOnClick($this->
id,
'', BackendUtility::BEgetRootLine($this->
id)));
706 $buttons[
'view'] =
'<a href="#" onclick="' . $onClick .
'" title="'
707 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')) .
'">'
708 . $this->iconFactory->getIcon(
'actions-document-view', Icon::SIZE_SMALL)->render() .
'</a>';
711 if (!$module->modTSconfig[
'properties'][
'noCreateRecordsLink'] && $this->editLockPermissions()) {
712 $onClick = htmlspecialchars(
'return jumpExt(' . GeneralUtility::quoteJSvalue((
string)$uriBuilder->buildUriFromRoute(
'db_new', [
'id' => $this->id])) .
');');
713 $buttons[
'new_record'] =
'<a href="#" onclick="' . $onClick .
'" title="'
714 . htmlspecialchars($lang->getLL(
'newRecordGeneral')) .
'">'
715 . $this->iconFactory->getIcon(
'actions-add', Icon::SIZE_SMALL)->render() .
'</a>';
721 $params =
'&edit[pages][' . $this->pageRow[
'uid'] .
']=edit';
722 $onClick = htmlspecialchars(BackendUtility::editOnClick($params,
'', -1));
723 $buttons[
'edit'] =
'<a href="#" onclick="' . $onClick .
'" title="' . htmlspecialchars($lang->getLL(
'editPage')) .
'">'
724 . $this->iconFactory->getIcon(
'actions-page-open', Icon::SIZE_SMALL)->render()
728 if (($localCalcPerms & Permission::PAGE_NEW || $localCalcPerms & Permission::CONTENT_EDIT) && $this->
editLockPermissions()) {
729 $elFromTable = $this->clipObj->elFromTable(
'');
730 if (!empty($elFromTable)) {
731 $confirmText = $this->clipObj->confirmMsgText(
'pages', $this->pageRow,
'into', $elFromTable);
732 $buttons[
'paste'] =
'<a'
733 .
' href="' . htmlspecialchars($this->clipObj->pasteUrl(
'', $this->id)) .
'"'
734 .
' title="' . htmlspecialchars($lang->getLL(
'clip_paste')) .
'"'
735 .
' class="t3js-modal-trigger"'
736 .
' data-severity="warning"'
737 .
' data-title="' . htmlspecialchars($lang->getLL(
'clip_paste')) .
'"'
738 .
' data-content="' . htmlspecialchars($confirmText) .
'"'
740 . $this->iconFactory->getIcon(
'actions-document-paste-into', Icon::SIZE_SMALL)->render()
745 $buttons[
'cache'] =
'<a href="' . htmlspecialchars($this->
listURL() .
'&clear_cache=1') .
'" title="'
746 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.clear_cache')) .
'">'
747 . $this->iconFactory->getIcon(
'actions-system-cache-clear', Icon::SIZE_SMALL)->render() .
'</a>';
748 if ($this->table && (!isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
749 || (isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
750 && !$module->modTSconfig[
'properties'][
'noExportRecordsLinks']))
753 $buttons[
'csv'] =
'<a href="' . htmlspecialchars($this->
listURL() .
'&csv=1') .
'" title="'
754 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.csv')) .
'">'
755 . $this->iconFactory->getIcon(
'actions-document-export-csv', Icon::SIZE_SMALL)->render() .
'</a>';
757 if (ExtensionManagementUtility::isLoaded(
'impexp')) {
758 $url = (string)$uriBuilder->buildUriFromRoute(
'xMOD_tximpexp', [
'tx_impexp[action]' =>
'export']);
759 $buttons[
'export'] =
'<a href="' . htmlspecialchars($url .
'&tx_impexp[list][]='
760 . rawurlencode($this->table .
':' . $this->
id)) .
'" title="'
761 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.export')) .
'">'
762 . $this->iconFactory->getIcon(
'actions-document-export-t3d', Icon::SIZE_SMALL)->render() .
'</a>';
766 $buttons[
'reload'] =
'<a href="' . htmlspecialchars($this->
listURL()) .
'" title="'
767 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload')) .
'">'
768 . $this->iconFactory->getIcon(
'actions-refresh', Icon::SIZE_SMALL)->render() .
'</a>';
770 if ($backendUser->mayMakeShortcut()) {
772 'id, M, imagemode, pointer, table, search_field, search_levels, showLimit, sortField, sortRev',
773 implode(
',', array_keys($this->MOD_MENU)),
778 if ($this->returnUrl) {
779 $href = htmlspecialchars(GeneralUtility::linkThisUrl($this->returnUrl, [
'id' => $this->
id]));
780 $buttons[
'back'] =
'<a href="' . $href .
'" class="typo3-goBack" title="'
781 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack')) .
'">'
782 . $this->iconFactory->getIcon(
'actions-view-go-back', Icon::SIZE_SMALL)->render() .
'</a>';
801 $localCalcPerms = $backendUser->calcPerms($this->pageRow);
803 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
805 if ((
string)$this->
id ===
'') {
806 $fieldName =
'list_module_noId';
807 } elseif (!$this->
id) {
808 $fieldName =
'list_module_root';
810 $fieldName =
'list_module';
812 $cshButton = $buttonBar->makeHelpButton()
813 ->setModuleName(
'xMOD_csh_corebe')
814 ->setFieldName($fieldName);
815 $buttonBar->addButton($cshButton);
816 if (isset($this->
id)) {
819 if (isset($module->modTSconfig[
'properties'][
'noViewWithDokTypes'])) {
820 $noViewDokTypes = GeneralUtility::trimExplode(
',', $module->modTSconfig[
'properties'][
'noViewWithDokTypes'],
true);
824 PageRepository::DOKTYPE_SYSFOLDER,
825 PageRepository::DOKTYPE_RECYCLER
829 if (!$module->modTSconfig[
'properties'][
'noCreateRecordsLink'] && $this->editLockPermissions()) {
830 $onClick =
'return jumpExt(' . GeneralUtility::quoteJSvalue((
string)$uriBuilder->buildUriFromRoute(
'db_new', [
'id' => $this->id])) .
');';
831 $newRecordButton = $buttonBar->makeLinkButton()
833 ->setOnClick($onClick)
834 ->setTitle($lang->getLL(
'newRecordGeneral'))
835 ->setIcon($this->iconFactory->getIcon(
'actions-add', Icon::SIZE_SMALL));
836 $buttonBar->addButton($newRecordButton, ButtonBar::BUTTON_POSITION_LEFT, 10);
838 if (!in_array($this->pageRow[
'doktype'], $noViewDokTypes)) {
839 $onClick = BackendUtility::viewOnClick($this->
id,
'', BackendUtility::BEgetRootLine($this->
id));
840 $viewButton = $buttonBar->makeLinkButton()
842 ->setOnClick($onClick)
843 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
844 ->setIcon($this->iconFactory->getIcon(
'actions-view-page', Icon::SIZE_SMALL));
845 $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, 20);
849 if ($localCalcPerms & Permission::PAGE_EDIT && !empty($this->
id) && $this->
editLockPermissions() && $backendUser->checkLanguageAccess(0)) {
851 $params =
'&edit[pages][' . $this->pageRow[
'uid'] .
']=edit';
852 $onClick = BackendUtility::editOnClick($params,
'', -1);
853 $editButton = $buttonBar->makeLinkButton()
855 ->setOnClick($onClick)
856 ->setTitle($lang->getLL(
'editPage'))
857 ->setIcon($this->iconFactory->getIcon(
'actions-page-open', Icon::SIZE_SMALL));
858 $buttonBar->addButton($editButton, ButtonBar::BUTTON_POSITION_LEFT, 20);
861 if ($this->showClipboard && ($localCalcPerms & Permission::PAGE_NEW || $localCalcPerms & Permission::CONTENT_EDIT) && $this->
editLockPermissions()) {
862 $elFromTable = $this->clipObj->elFromTable(
'');
863 if (!empty($elFromTable)) {
864 $confirmMessage = $this->clipObj->confirmMsgText(
'pages', $this->pageRow,
'into', $elFromTable);
865 $pasteButton = $buttonBar->makeLinkButton()
866 ->setHref($this->clipObj->pasteUrl(
'', $this->id))
867 ->setTitle($lang->getLL(
'clip_paste'))
868 ->setClasses(
't3js-modal-trigger')
869 ->setDataAttributes([
870 'severity' =>
'warning',
871 'content' => $confirmMessage,
872 'title' => $lang->getLL(
'clip_paste')
874 ->setIcon($this->iconFactory->getIcon(
'actions-document-paste-into', Icon::SIZE_SMALL));
875 $buttonBar->addButton($pasteButton, ButtonBar::BUTTON_POSITION_LEFT, 40);
879 $clearCacheButton = $buttonBar->makeLinkButton()
880 ->setHref($this->
listURL() .
'&clear_cache=1')
881 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.clear_cache'))
882 ->setIcon($this->iconFactory->getIcon(
'actions-system-cache-clear', Icon::SIZE_SMALL));
883 $buttonBar->addButton($clearCacheButton, ButtonBar::BUTTON_POSITION_RIGHT);
884 if ($this->table && (!isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
885 || (isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
886 && !$module->modTSconfig[
'properties'][
'noExportRecordsLinks']))
889 $csvButton = $buttonBar->makeLinkButton()
890 ->setHref($this->
listURL() .
'&csv=1')
891 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.csv'))
892 ->setIcon($this->iconFactory->getIcon(
'actions-document-export-csv', Icon::SIZE_SMALL))
893 ->setShowLabelText(
true);
894 $buttonBar->addButton($csvButton, ButtonBar::BUTTON_POSITION_LEFT, 40);
896 if (ExtensionManagementUtility::isLoaded(
'impexp')) {
897 $url = (string)$uriBuilder->buildUriFromRoute(
'xMOD_tximpexp', [
'tx_impexp[action]' =>
'export']);
898 $exportButton = $buttonBar->makeLinkButton()
899 ->setHref($url .
'&tx_impexp[list][]=' . rawurlencode($this->table .
':' . $this->
id))
900 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.export'))
901 ->setIcon($this->iconFactory->getIcon(
'actions-document-export-t3d', Icon::SIZE_SMALL))
902 ->setShowLabelText(
true);
903 $buttonBar->addButton($exportButton, ButtonBar::BUTTON_POSITION_LEFT, 40);
907 $reloadButton = $buttonBar->makeLinkButton()
909 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
910 ->setIcon($this->iconFactory->getIcon(
'actions-refresh', Icon::SIZE_SMALL));
911 $buttonBar->addButton($reloadButton, ButtonBar::BUTTON_POSITION_RIGHT);
913 if ($backendUser->mayMakeShortcut()) {
914 $shortCutButton = $buttonBar->makeShortcutButton()
915 ->setModuleName(
'web_list')
928 ->setSetVariables(array_keys($this->MOD_MENU));
929 $buttonBar->addButton($shortCutButton, ButtonBar::BUTTON_POSITION_RIGHT);
932 if ($this->returnUrl) {
933 $backButton = $buttonBar->makeLinkButton()
934 ->setHref($this->returnUrl)
935 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
936 ->setIcon($this->iconFactory->getIcon(
'actions-view-go-back', Icon::SIZE_SMALL));
937 $buttonBar->addButton($backButton, ButtonBar::BUTTON_POSITION_LEFT);
953 $rowListArray = GeneralUtility::trimExplode(
',', $rowList,
true);
955 if (!empty(
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'descriptionColumn']) && empty($rowListArray)) {
962 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
$table);
967 $tableCollapsed = (bool)$this->tablesCollapsed[
$table];
969 $this->spaceIcon =
'<span class="btn btn-default disabled">' . $this->iconFactory->getIcon(
'empty-empty', Icon::SIZE_SMALL)->render() .
'</span>';
971 $this->fieldArray = [];
974 $this->fieldArray[] = $titleCol;
976 if (!GeneralUtility::inList($rowList,
'_CONTROL_')) {
977 $this->fieldArray[] =
'_CONTROL_';
980 if ($this->showClipboard) {
981 $this->fieldArray[] =
'_CLIPBOARD_';
984 if (!$this->dontShowClipControlPanels) {
985 $this->fieldArray[] =
'_REF_';
988 if ($this->searchLevels) {
989 $this->fieldArray[] =
'_PATH_';
993 $this->fieldArray[] =
'_LOCALIZATION_';
996 $this->fieldArray[] =
'_LOCALIZATION_b';
1001 $addWhere = (string)$queryBuilder->expr()->orX(
1002 $queryBuilder->expr()->lte(
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'languageField'], 0),
1003 $queryBuilder->expr()->eq(
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField'], 0)
1008 $this->fieldArray = array_unique(array_merge($this->fieldArray, $rowListArray));
1009 if ($this->noControlPanels) {
1010 $tempArray = array_flip($this->fieldArray);
1011 unset($tempArray[
'_CONTROL_']);
1012 unset($tempArray[
'_CLIPBOARD_']);
1013 $this->fieldArray = array_keys($tempArray);
1017 $selectFields[] =
'uid';
1018 $selectFields[] =
'pid';
1021 $selectFields[] = $thumbsCol;
1024 $selectFields[] =
'module';
1025 $selectFields[] =
'extendToSubpages';
1026 $selectFields[] =
'nav_hide';
1027 $selectFields[] =
'doktype';
1028 $selectFields[] =
'shortcut';
1029 $selectFields[] =
'shortcut_mode';
1030 $selectFields[] =
'mount_pid';
1033 $selectFields = array_merge($selectFields,
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'enablecolumns']);
1035 foreach ([
'type',
'typeicon_column',
'editlock'] as $field) {
1041 $selectFields[] =
't3ver_id';
1042 $selectFields[] =
't3ver_state';
1043 $selectFields[] =
't3ver_wsid';
1047 $selectFields[] =
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField'];
1050 $selectFields = array_merge(
1052 GeneralUtility::trimExplode(
',',
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'label_alt'],
true)
1056 $selectFields = array_unique($selectFields);
1058 if (empty($fieldListFields) &&
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'debug']) {
1059 $message = sprintf($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:missingTcaColumnsMessage'),
$table,
$table);
1060 $messageTitle = $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:missingTcaColumnsMessageTitle');
1062 $flashMessage = GeneralUtility::makeInstance(
1063 FlashMessage::class,
1066 FlashMessage::WARNING,
1070 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1072 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1073 $defaultFlashMessageQueue->enqueue($flashMessage);
1076 $selectFields = array_intersect($selectFields, $fieldListFields);
1080 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'getTable'] ?? [] as $className) {
1081 $hookObject = GeneralUtility::makeInstance($className);
1082 if (!$hookObject instanceof RecordListGetTableHookInterface) {
1083 throw new \UnexpectedValueException($className .
' must implement interface ' . RecordListGetTableHookInterface::class, 1195114460);
1089 $addWhere .=
' AND ' .
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField'] .
' IN(' . implode(
',', array_keys($this->languagesAllowedForUser)) .
')';
1092 $additionalConstraints = empty($addWhere) ? [] : [QueryHelper::stripLogicalOperatorPrefix($addWhere)];
1097 if ($this->csvOutput) {
1100 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
1102 $this->firstElementNumber -= 2;
1106 $this->firstElementNumber += 2;
1118 $queryResult = $queryBuilder->execute();
1125 if ($this->totalItems) {
1131 if ($this->csvOutput) {
1136 if ($this->firstElementNumber + $this->showLimit <= $this->totalItems) {
1137 $dbCount = $this->showLimit + 2;
1139 $dbCount = $this->totalItems - $this->firstElementNumber + 2;
1153 $tableTitle = htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:pageTranslation'));
1154 $tableIdentifier =
'pages_translated';
1156 $tableTitle = htmlspecialchars($lang->sL(
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'title']));
1157 if ($tableTitle ===
'') {
1163 if ($this->disableSingleTableView) {
1164 $theData[$titleCol] =
'<span class="c-table">' . BackendUtility::wrapInHelp(
$table,
'', $tableTitle)
1165 .
'</span> (<span class="t3js-table-total-items">' . $this->totalItems .
'</span>)';
1167 $icon = $this->table
1168 ?
'<span title="' . htmlspecialchars($lang->getLL(
'contractView')) .
'">' . $this->iconFactory->getIcon(
'actions-view-table-collapse', Icon::SIZE_SMALL)->render() .
'</span>'
1169 :
'<span title="' . htmlspecialchars($lang->getLL(
'expandView')) .
'">' . $this->iconFactory->getIcon(
'actions-view-table-expand', Icon::SIZE_SMALL)->render() .
'</span>';
1170 $theData[$titleCol] = $this->
linkWrapTable($table, $tableTitle .
' (<span class="t3js-table-total-items">' . $this->totalItems .
'</span>) ' . $icon);
1173 $tableHeader .= BackendUtility::wrapInHelp(
$table,
'', $theData[$titleCol]);
1177 if (!$this->table) {
1178 $href = htmlspecialchars($this->
listURL() .
'&collapse[' . $table .
']=' . ($tableCollapsed ?
'0' :
'1'));
1179 $title = $tableCollapsed
1180 ? htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.expandTable'))
1181 : htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.collapseTable'));
1182 $icon =
'<span class="collapseIcon">' . $this->iconFactory->getIcon(($tableCollapsed ?
'actions-view-list-expand' :
'actions-view-list-collapse'), Icon::SIZE_SMALL)->render() .
'</span>';
1183 $collapseIcon =
'<a href="' . $href .
'" title="' . $title .
'" class="pull-right t3js-toggle-recordlist" data-table="' . htmlspecialchars($tableIdentifier) .
'" data-toggle="collapse" data-target="#recordlist-' . htmlspecialchars($tableIdentifier) .
'">' . $icon .
'</a>';
1185 $tableHeader .= $theData[$titleCol] . $collapseIcon;
1191 $this->currentTable = [];
1192 $currentIdList = [];
1197 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
1198 $row = $queryResult->fetch();
1199 $prevPrevUid = -((int)$row[
'uid']);
1200 $row = $queryResult->fetch();
1201 $prevUid = $row[
'uid'];
1205 while ($row = $queryResult->fetch()) {
1210 BackendUtility::workspaceOL(
$table, $row, $backendUser->workspace,
true);
1211 if (is_array($row)) {
1213 $currentIdList[] = $row[
'uid'];
1216 $this->currentTable[
'prev'][$row[
'uid']] = $prevPrevUid;
1217 $this->currentTable[
'next'][$prevUid] =
'-' . $row[
'uid'];
1218 $this->currentTable[
'prevUid'][$row[
'uid']] = $prevUid;
1220 $prevPrevUid = isset($this->currentTable[
'prev'][$row[
'uid']]) ? -$prevUid : $row[
'pid'];
1221 $prevUid = $row[
'uid'];
1225 $this->totalRowCount = count($accRows);
1227 if ($this->csvOutput) {
1231 $this->CBnames = [];
1232 $this->duplicateStack = [];
1235 foreach ($accRows as $row) {
1237 if ($cc < $this->iLimit) {
1239 $this->translations =
false;
1240 $rowOutput .= $this->
renderListRow($table, $row, $cc, $titleCol, $thumbsCol);
1244 if ($l10nEnabled && $this->searchString ===
'' && !($this->hideTranslations ===
'*' || GeneralUtility::inList($this->hideTranslations,
$table))) {
1246 if (is_array($this->translations)) {
1247 foreach ($this->translations as $lRow) {
1250 if ($row[
'_MOVE_PLH_uid'] && $row[
'_MOVE_PLH_pid']) {
1251 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1252 ->getQueryBuilderForTable(
$table);
1253 $queryBuilder->getRestrictions()
1255 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1257 $queryBuilder->expr()->eq(
1259 $queryBuilder->createNamedParameter((
int)$lRow[
'uid'], \PDO::PARAM_INT)
1261 $queryBuilder->expr()->eq(
1263 $queryBuilder->createNamedParameter((
int)$row[
'_MOVE_PLH_pid'], \PDO::PARAM_INT)
1265 $queryBuilder->expr()->eq(
1267 $queryBuilder->createNamedParameter((
int)$row[
't3ver_wsid'], \PDO::PARAM_INT)
1271 $tmpRow = $queryBuilder
1274 ->andWhere(...$predicates)
1278 $lRow = is_array($tmpRow) ? $tmpRow : $lRow;
1284 BackendUtility::workspaceOL(
$table, $lRow, $backendUser->workspace,
true);
1285 if (is_array($lRow) && $backendUser->checkLanguageAccess($lRow[
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'languageField']])) {
1286 $currentIdList[] = $lRow[
'uid'];
1287 $rowOutput .= $this->
renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 18);
1302 if ($this->totalItems > $this->itemsLimitPerTable) {
1303 $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable :
$this->totalItems;
1305 $colspan = $this->showIcon ? count($this->fieldArray) + 1 : count($this->fieldArray);
1306 $rowOutput .=
'<tr><td colspan="' . $colspan .
'">
1307 <a href="' . htmlspecialchars($this->
listURL() .
'&table=' . rawurlencode($tableIdentifier)) .
'" class="btn btn-default">'
1308 .
'<span class="t3-icon fa fa-chevron-down"></span> <i>[1 - ' . $countOnFirstPage . ($hasMore ?
'+' :
'') .
']</i></a>
1316 $collapseClass = $tableCollapsed && !$this->table ?
'collapse' :
'collapse in';
1317 $dataState = $tableCollapsed && !$this->table ?
'collapsed' :
'expanded';
1327 DB listing of elements: "' . htmlspecialchars($tableIdentifier) .
'"
1329 <div class="panel panel-space panel-default recordlist">
1330 <div class="panel-heading">
1331 ' . $tableHeader .
'
1333 <div class="' . $collapseClass .
'" data-state="' . $dataState .
'" id="recordlist-' . htmlspecialchars($tableIdentifier) .
'">
1334 <div class="table-fit">
1335 <table data-table="' . htmlspecialchars($tableIdentifier) .
'" class="table table-striped table-hover' . (
$listOnlyInSingleTableMode ?
' typo3-dblist-overview' :
'') .
'">
1344 if ($this->csvOutput) {
1362 if (
$table ===
'tt_content') {
1364 $additionalParams =
'';
1365 $language = (int)$row[
$GLOBALS[
'TCA'][
'tt_content'][
'ctrl'][
'languageField']];
1366 if ($language > 0) {
1367 $additionalParams =
'&L=' . $language;
1369 $onClick = BackendUtility::viewOnClick(
1377 } elseif (
$table ===
'pages' && $row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'transOrigPointerField']] > 0) {
1379 $onClick = BackendUtility::viewOnClick(
1380 $row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'transOrigPointerField']],
1385 '&L=' . (
int)$row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField']]
1389 $onClick = BackendUtility::viewOnClick($row[
'uid']);
1423 if (!is_array($row)) {
1429 if ((
string)$this->searchString !==
'') {
1431 $this->
id = $row[
'pid'];
1437 'title' =>
'id=' . $row[
'uid'],
1442 isset($this->currentLink[
'tableNames'])
1443 && (
int)$this->currentLink[
'uid'] === (
int)$row[
'uid']
1444 && GeneralUtility::inList($this->currentLink[
'tableNames'],
$table)
1446 $tagAttributes[
'class'][] =
'active';
1449 if ($cc == 1 && $indent == 0) {
1450 $tagAttributes[
'class'][] =
'firstcol';
1452 if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
1453 $tagAttributes[
'class'][] =
'lastcol';
1456 if (!empty($row[
'_CSSCLASS'])) {
1457 $tagAttributes[
'class'] = [$row[
'_CSSCLASS']];
1460 $tagAttributes[
'class'][] =
't3js-entity';
1465 $toolTip = BackendUtility::getRecordToolTip($row,
$table);
1466 $additionalStyle = $indent ?
' style="margin-left: ' . $indent .
'px;"' :
'';
1467 $iconImg =
'<span ' . $toolTip .
' ' . $additionalStyle .
'>'
1468 . $this->iconFactory->getIconForRecord(
$table, $row, Icon::SIZE_SMALL)->render()
1470 $theIcon = $this->clickMenuEnabled ? BackendUtility::wrapClickMenuOnIcon($iconImg,
$table, $row[
'uid']) : $iconImg;
1473 $localizationMarkerClass =
'';
1474 foreach ($this->fieldArray as $fCol) {
1475 if ($fCol == $titleCol) {
1476 $recTitle = BackendUtility::getRecordTitle(
$table, $row,
false,
true);
1479 $lockInfo = BackendUtility::isRecordLocked(
$table, $row[
'uid']);
1481 $warning =
'<span data-toggle="tooltip" data-placement="right" data-title="' . htmlspecialchars($lockInfo[
'msg']) .
'">'
1482 . $this->iconFactory->getIcon(
'warning-in-use', Icon::SIZE_SMALL)->render() .
'</span>';
1484 $theData[$fCol] = $theData[
'__label'] = $warning . $this->
linkWrapItems($table, $row[
'uid'], $recTitle, $row);
1492 $type = $row[$typeColumn];
1502 if ($this->thumbs &&
1503 trim($row[$thumbsCol]) &&
1504 preg_match(
'/(^|(.*(;|,)?))' . $thumbsCol .
'(((;|,).*)|$)/', $visibleColumns) === 1
1507 $theData[$fCol] .= $thumbCode;
1508 $theData[
'__label'] .= $thumbCode;
1515 $localizationMarkerClass =
' localization';
1517 } elseif ($fCol ===
'pid') {
1518 $theData[$fCol] = $row[$fCol];
1519 } elseif ($fCol ===
'_PATH_') {
1521 } elseif ($fCol ===
'_REF_') {
1523 } elseif ($fCol ===
'_CONTROL_') {
1525 } elseif ($fCol ===
'_CLIPBOARD_') {
1526 $theData[$fCol] = $this->
makeClip($table, $row);
1527 } elseif ($fCol ===
'_LOCALIZATION_') {
1529 $theData[$fCol] = $lC1;
1530 $theData[$fCol .
'b'] =
'<div class="btn-group">' . $lC2 .
'</div>';
1531 } elseif ($fCol ===
'_LOCALIZATION_b') {
1534 $pageId =
$table ===
'pages' ? $row[
'uid'] : $row[
'pid'];
1535 $tmpProc = BackendUtility::getProcessedValueExtra(
$table, $fCol, $row[$fCol], 100, $row[
'uid'],
true, $pageId);
1536 $theData[$fCol] = $this->
linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
1537 if ($this->csvOutput) {
1538 $row[$fCol] = BackendUtility::getProcessedValueExtra(
$table, $fCol, $row[$fCol], 0, $row[
'uid']);
1543 if ((
string)$this->searchString !==
'') {
1544 $this->
id = $id_orig;
1547 if ($this->csvOutput) {
1548 $hooks =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][__CLASS__][
'customizeCsvRow'] ?? [];
1549 if (!empty($hooks)) {
1551 'databaseRow' => &$row,
1555 foreach ($hooks as $hookFunction) {
1556 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
1562 $this->addElement_tdCssClass[$titleCol] =
'col-title col-responsive' . $localizationMarkerClass;
1563 $this->addElement_tdCssClass[
'__label'] = $this->addElement_tdCssClass[$titleCol];
1564 $this->addElement_tdCssClass[
'_CONTROL_'] =
'col-control';
1565 if ($this->
getModule()->MOD_SETTINGS[
'clipBoard']) {
1566 $this->addElement_tdCssClass[
'_CLIPBOARD_'] =
'col-clipboard';
1568 $this->addElement_tdCssClass[
'_PATH_'] =
'col-path';
1569 $this->addElement_tdCssClass[
'_LOCALIZATION_'] =
'col-localizationa';
1570 $this->addElement_tdCssClass[
'_LOCALIZATION_b'] =
'col-localizationb';
1572 $theData[
'uid'] = $row[
'uid'];
1576 $theData[
'_l10nparent_'] = $row[
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField']];
1579 $tagAttributes = array_map(
1580 function ($attributeValue) {
1581 if (is_array($attributeValue)) {
1582 return implode(
' ', $attributeValue);
1584 return $attributeValue;
1589 $rowOutput .= $this->
addElement(1, $theIcon, $theData, GeneralUtility::implodeAttributes($tagAttributes,
true));
1604 if (!isset($this->referenceCount[$tableName][$uid])) {
1605 $referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
1606 $numberOfReferences = $referenceIndex->getNumberOfReferencedRecords($tableName, $uid);
1607 $this->referenceCount[$tableName][$uid] = $numberOfReferences;
1609 return $this->referenceCount[$tableName][$uid];
1624 $tsConfig = BackendUtility::getPagesTSconfig($this->
id);
1625 $tsConfigOfTable = is_array($tsConfig[
'TCEFORM.'][
$table .
'.']) ? $tsConfig[
'TCEFORM.'][
$table .
'.'] :
null;
1632 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
1634 foreach ($this->fieldArray as $fCol) {
1637 switch ((
string)$fCol) {
1640 $theData[$fCol] =
'<i>[' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels._PATH_')) .
']</i>';
1644 $theData[$fCol] =
'<i>[' . htmlspecialchars($lang->sL(
'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c__REF_')) .
']</i>';
1646 case '_LOCALIZATION_':
1648 $theData[$fCol] =
'<i>[' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels._LOCALIZATION_')) .
']</i>';
1650 case '_LOCALIZATION_b':
1652 $theData[$fCol] = htmlspecialchars($lang->getLL(
'Localize'));
1655 if (!$this->
getModule()->MOD_SETTINGS[
'clipBoard']) {
1662 $elFromTable = $this->clipObj->elFromTable(
$table);
1664 $href = htmlspecialchars($this->clipObj->pasteUrl(
$table, $this->id));
1665 $confirmMessage = $this->clipObj->confirmMsgText(
'pages', $this->pageRow,
'into', $elFromTable);
1666 $cells[
'pasteAfter'] =
'<a class="btn btn-default t3js-modal-trigger"'
1667 .
' href="' . $href .
'"'
1668 .
' title="' . htmlspecialchars($lang->getLL(
'clip_paste')) .
'"'
1669 .
' data-title="' . htmlspecialchars($lang->getLL(
'clip_paste')) .
'"'
1670 .
' data-content="' . htmlspecialchars($confirmMessage) .
'"'
1671 .
' data-severity="warning">'
1672 . $this->iconFactory->getIcon(
'actions-document-paste-into', Icon::SIZE_SMALL)->render()
1676 if ($this->clipObj->current !==
'normal') {
1678 $spriteIcon = $this->iconFactory->getIcon(
'actions-edit-copy', Icon::SIZE_SMALL)->render();
1681 $editUri = (string)$uriBuilder->buildUriFromRoute(
'record_edit')
1682 .
'&edit[' .
$table .
'][{entityIdentifiers:editList}]=edit'
1683 .
'&returnUrl={T3_THIS_LOCATION}';
1684 $cells[
'edit'] =
'<a class="btn btn-default t3js-record-edit-multiple" href="#"'
1685 .
' data-uri="' . htmlspecialchars($editUri) .
'"'
1686 .
' title="' . htmlspecialchars($lang->getLL(
'clip_editMarked')) .
'">'
1687 . $this->iconFactory->getIcon(
'actions-document-open', Icon::SIZE_SMALL)->render() .
'</a>';
1690 $this->iconFactory->getIcon(
'actions-edit-delete', Icon::SIZE_SMALL)->render(),
1693 sprintf($lang->getLL(
'clip_deleteMarkedWarning'), $lang->sL(
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'title'])),
1694 $lang->getLL(
'clip_deleteMarked')
1697 $onClick = htmlspecialchars(
'checkOffCB(' . GeneralUtility::quoteJSvalue(implode(
',', $this->CBnames)) .
', this); return false;');
1698 $cells[
'markAll'] =
'<a class="btn btn-default" rel="" href="#" onclick="' . $onClick .
'" title="'
1699 . htmlspecialchars($lang->getLL(
'clip_markRecords')) .
'">'
1700 . $this->iconFactory->getIcon(
'actions-document-select', Icon::SIZE_SMALL)->render() .
'</a>';
1702 $cells[
'empty'] =
'';
1711 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] ?? [] as $className) {
1712 $hookObject = GeneralUtility::makeInstance($className);
1713 if (!$hookObject instanceof RecordListHookInterface) {
1714 throw new \UnexpectedValueException($className .
' must implement interface ' . RecordListHookInterface::class, 1195567850);
1716 $cells = $hookObject->renderListHeaderActions(
$table, $currentIdList, $cells, $this);
1718 $theData[$fCol] =
'';
1719 if (isset($cells[
'edit']) && isset($cells[
'delete'])) {
1720 $theData[$fCol] .=
'<div class="btn-group" role="group">' . $cells[
'edit'] . $cells[
'delete'] .
'</div>';
1721 unset($cells[
'edit'], $cells[
'delete']);
1723 $theData[$fCol] .=
'<div class="btn-group" role="group">' . implode(
'', $cells) .
'</div>';
1729 $permsAdditional = (
$table ===
'pages' ? 8 : 16);
1730 if ($this->calcPerms & $permsAdditional && $this->
showNewRecLink($table)) {
1731 $spriteIcon =
$table ===
'pages'
1732 ? $this->iconFactory->getIcon(
'actions-page-new', Icon::SIZE_SMALL)
1733 : $this->iconFactory->getIcon(
'actions-add', Icon::SIZE_SMALL);
1734 if (
$table ===
'tt_content') {
1736 $newContentElementWizard = BackendUtility::getPagesTSconfig($this->pageinfo[
'uid'])[
'mod.'][
'newContentElementWizard.'][
'override']
1737 ??
'new_content_element_wizard';
1738 $url = (string)$uriBuilder->buildUriFromRoute(
1739 $newContentElementWizard,
1742 'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI'),
1745 $icon =
'<a href="' . htmlspecialchars($url) .
'" '
1746 .
'data-title="' . htmlspecialchars($lang->getLL(
'new')) .
'"'
1747 .
'class="btn btn-default t3js-toggle-new-content-element-wizard disabled"">'
1748 . $spriteIcon->render()
1750 } elseif (
$table ===
'pages') {
1751 $parameters = [
'id' =>
$this->id,
'pagesOnly' => 1,
'returnUrl' => GeneralUtility::getIndpEnv(
'REQUEST_URI')];
1752 $href = (string)$uriBuilder->buildUriFromRoute(
'db_new', $parameters);
1753 $icon =
'<a class="btn btn-default" href="' . htmlspecialchars($href) .
'" title="' . htmlspecialchars($lang->getLL(
'new')) .
'">'
1754 . $spriteIcon->render() .
'</a>';
1756 $params =
'&edit[' .
$table .
'][' . $this->
id .
']=new';
1757 if ($table ===
'pages') {
1758 $params .=
'&overrideVals[pages][doktype]=' . (int)$this->pageRow[
'doktype'];
1760 $icon =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params,
'', -1))
1761 .
'" title="' . htmlspecialchars($lang->getLL(
'new')) .
'">' . $spriteIcon->render() .
'</a>';
1765 if ($permsEdit && $this->table && is_array($currentIdList)) {
1766 $entityIdentifiers =
'entityIdentifiers';
1768 $entityIdentifiers .=
':editList';
1770 $editUri = (string)$uriBuilder->buildUriFromRoute(
'record_edit')
1771 .
'&edit[' .
$table .
'][{' . $entityIdentifiers .
'}]=edit'
1772 .
'&columnsOnly=' . implode(
',', $this->fieldArray)
1773 .
'&returnUrl={T3_THIS_LOCATION}';
1774 $icon .=
'<a class="btn btn-default t3js-record-edit-multiple" href="#"'
1775 .
' data-uri="' . htmlspecialchars($editUri) .
'"'
1776 .
' title="' . htmlspecialchars($lang->getLL(
'editShownColumns')) .
'">'
1777 . $this->iconFactory->getIcon(
'actions-document-open', Icon::SIZE_SMALL)->render() .
'</a>';
1778 $icon =
'<div class="btn-group" role="group">' . $icon .
'</div>';
1781 $theData[$fCol] =
' ';
1788 $theData[$fCol] =
'';
1792 $sortLabel = BackendUtility::getItemLabel(
$table, $fCol);
1793 if ($sortLabel !==
null) {
1794 $sortLabel = rtrim(trim($lang->sL($sortLabel)),
':');
1797 $fieldTSConfig = [];
1798 if (isset($tsConfigOfTable[$fCol .
'.'])
1799 && is_array($tsConfigOfTable[$fCol .
'.'])
1801 $fieldTSConfig = $tsConfigOfTable[$fCol .
'.'];
1803 if (!empty($fieldTSConfig[
'label'])) {
1804 $sortLabel = $lang->sL($fieldTSConfig[
'label']);
1806 if (!empty($fieldTSConfig[
'label.'][$lang->lang])) {
1807 $sortLabel = $lang->sL($fieldTSConfig[
'label.'][$lang->lang]);
1809 $sortLabel = htmlspecialchars($sortLabel);
1812 $sortLabel = htmlspecialchars($fCol);
1813 $sortLabel =
'<i>[' . rtrim(trim($sortLabel),
':') .
']</i>';
1816 if ($this->table && is_array($currentIdList)) {
1819 $theData[$fCol] .=
'<a class="btn btn-default" href="' . htmlspecialchars($this->
listURL(
'',
'-1') .
'&duplicateField=' . $fCol)
1820 .
'" title="' . htmlspecialchars($lang->getLL(
'clip_duplicates')) .
'">'
1821 . $this->iconFactory->getIcon(
'actions-document-duplicates-select', Icon::SIZE_SMALL)->render() .
'</a>';
1826 $entityIdentifiers =
'entityIdentifiers';
1828 $entityIdentifiers .=
':editList';
1830 $editUri = (string)$uriBuilder->buildUriFromRoute(
'record_edit')
1831 .
'&edit[' .
$table .
'][{' . $entityIdentifiers .
'}]=edit'
1832 .
'&columnsOnly=' . $fCol
1833 .
'&returnUrl={T3_THIS_LOCATION}';
1834 $iTitle = sprintf($lang->getLL(
'editThisColumn'), $sortLabel);
1835 $theData[$fCol] .=
'<a class="btn btn-default t3js-record-edit-multiple" href="#"'
1836 .
' data-uri="' . htmlspecialchars($editUri) .
'"'
1837 .
' title="' . htmlspecialchars($iTitle) .
'">'
1838 . $this->iconFactory->getIcon(
'actions-document-open', Icon::SIZE_SMALL)->render() .
'</a>';
1840 if (strlen($theData[$fCol]) > 0) {
1841 $theData[$fCol] =
'<div class="btn-group" role="group">' . $theData[$fCol] .
'</div> ';
1853 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] ?? [] as $className) {
1854 $hookObject = GeneralUtility::makeInstance($className);
1855 if (!$hookObject instanceof RecordListHookInterface) {
1856 throw new \UnexpectedValueException($className .
' must implement interface ' . RecordListHookInterface::class, 1195567855);
1858 $theData = $hookObject->renderListHeader(
$table, $currentIdList, $theData, $this);
1862 return '<thead>' . $this->
addElement(1, $icon, $theData,
'',
'',
'',
'th') .
'</thead>';
1884 $totalPages = ceil($this->totalItems / $this->iLimit);
1886 if ($totalPages <= 1) {
1890 $listURL = $this->
listURL(
'', $this->table,
'firstElementNumber');
1893 $currentPage = floor($this->firstElementNumber / $this->iLimit) + 1;
1895 if ($currentPage > 1) {
1896 $labelFirst = htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:first'));
1897 $labelPrevious = htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:previous'));
1898 $first =
'<li><a href="' . $listURL .
'&pointer=' . $this->
getPointerForPage(1) .
'" title="' . $labelFirst .
'">'
1899 . $this->iconFactory->getIcon(
'actions-view-paging-first', Icon::SIZE_SMALL)->render() .
'</a></li>';
1900 $previous =
'<li><a href="' . $listURL .
'&pointer=' . $this->
getPointerForPage($currentPage - 1) .
'" title="' . $labelPrevious .
'">'
1901 . $this->iconFactory->getIcon(
'actions-view-paging-previous', Icon::SIZE_SMALL)->render() .
'</a></li>';
1903 $first =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-first', Icon::SIZE_SMALL)->render() .
'</span></li>';
1904 $previous =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-previous', Icon::SIZE_SMALL)->render() .
'</span></li>';
1906 if ($currentPage < $totalPages) {
1907 $labelNext = htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:next'));
1908 $labelLast = htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:last'));
1909 $next =
'<li><a href="' . $listURL .
'&pointer=' . $this->
getPointerForPage($currentPage + 1) .
'" title="' . $labelNext .
'">'
1910 . $this->iconFactory->getIcon(
'actions-view-paging-next', Icon::SIZE_SMALL)->render() .
'</a></li>';
1911 $last =
'<li><a href="' . $listURL .
'&pointer=' . $this->
getPointerForPage($totalPages) .
'" title="' . $labelLast .
'">'
1912 . $this->iconFactory->getIcon(
'actions-view-paging-last', Icon::SIZE_SMALL)->render() .
'</a></li>';
1914 $next =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-next', Icon::SIZE_SMALL)->render() .
'</span></li>';
1915 $last =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-last', Icon::SIZE_SMALL)->render() .
'</span></li>';
1917 $reload =
'<li><a href="#" onclick="document.dblistForm.action=' . GeneralUtility::quoteJSvalue($listURL
1918 .
'&pointer=') .
'+calculatePointer(document.getElementById(' . GeneralUtility::quoteJSvalue(
'jumpPage-' . $renderPart)
1919 .
').value); document.dblistForm.submit(); return true;" title="'
1920 . htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:reload')) .
'">'
1921 . $this->iconFactory->getIcon(
'actions-refresh', Icon::SIZE_SMALL)->render() .
'</a></li>';
1922 if ($renderPart ===
'top') {
1925 <script type="text/javascript">
1927 function calculatePointer(page) {
1928 if (page > ' . $totalPages .
') {
1929 page = ' . $totalPages .
';
1934 return (page - 1) * ' . $this->iLimit .
';
1940 $pageNumberInput =
'
1941 <input type="number" min="1" max="' . $totalPages .
'" value="' . $currentPage .
'" size="3" class="form-control input-sm paginator-input" id="jumpPage-' . $renderPart .
'" name="jumpPage-'
1942 . $renderPart .
'" onkeyup="if (event.keyCode == 13) { document.dblistForm.action=' . htmlspecialchars(GeneralUtility::quoteJSvalue($listURL .
'&pointer='))
1943 .
'+calculatePointer(this.value); document.dblistForm.submit(); } return true;" />
1945 $pageIndicatorText = sprintf(
1946 $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:pageIndicator'),
1950 $pageIndicator =
'<li><span>' . $pageIndicatorText .
'</span></li>';
1951 if ($this->totalItems > $this->firstElementNumber + $this->iLimit) {
1956 $rangeIndicator =
'<li><span>' . sprintf(
1957 $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:rangeIndicator'),
1958 $this->firstElementNumber + 1,
1962 $titleColumn = $this->fieldArray[0];
1965 <nav class="pagination-wrap">
1966 <ul class="pagination pagination-block">
1969 ' . $rangeIndicator .
'
1970 ' . $pageIndicator .
'
1998 $userTsConfig = $backendUser->getTSConfig();
2000 $rowUid = $row[
'uid'];
2001 if (ExtensionManagementUtility::isLoaded(
'workspaces') && isset($row[
'_ORIG_uid'])) {
2002 $rowUid = $row[
'_ORIG_uid'];
2010 $isL10nOverlay =
$table ===
'pages' && $row[
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField']] != 0;
2013 $localCalcPerms = $backendUser->calcPerms(BackendUtility::getRecord(
'pages', $row[
'uid']));
2016 $localCalcPerms = $backendUser->calcPerms(BackendUtility::getRecord(
'pages', $row[
'pid']));
2018 $permsEdit =
$table ===
'pages'
2019 && $backendUser->checkLanguageAccess((
int)$row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField']])
2020 && $localCalcPerms & Permission::PAGE_EDIT
2022 && $localCalcPerms & Permission::CONTENT_EDIT
2023 && $backendUser->recordEditAccessInternals(
$table, $row);
2027 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
2031 $viewAction =
'<a class="btn btn-default" href="#" onclick="'
2034 ) .
'" title="' . htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')) .
'">';
2036 $viewAction .= $this->iconFactory->getIcon(
'actions-view-page', Icon::SIZE_SMALL)->render();
2038 $viewAction .= $this->iconFactory->getIcon(
'actions-view', Icon::SIZE_SMALL)->render();
2040 $viewAction .=
'</a>';
2045 $params =
'&edit[' .
$table .
'][' . $row[
'uid'] .
']=edit';
2046 $iconIdentifier =
'actions-open';
2049 $params .=
'&overrideVals[pages][sys_language_uid]=' . (int)$row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField']];
2050 $iconIdentifier =
'actions-page-open';
2052 $editAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params,
'', -1))
2053 .
'" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'edit')) .
'">' . $this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL)->render() .
'</a>';
2059 $onClick =
'top.TYPO3.InfoWindow.showItem(' . GeneralUtility::quoteJSvalue(
$table) .
', ' . (int)$row[
'uid'] .
'); return false;';
2060 $viewBigAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) .
'" title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'showInfo')) .
'">'
2061 . $this->iconFactory->getIcon(
'actions-document-info', Icon::SIZE_SMALL)->render() .
'</a>';
2065 if ($isL10nOverlay) {
2068 $onClick =
'return jumpExt(' . GeneralUtility::quoteJSvalue((
string)$uriBuilder->buildUriFromRoute(
'move_element') .
'&table=' .
$table .
'&uid=' . $row[
'uid']) .
');';
2069 $linkTitleLL = htmlspecialchars($this->
getLanguageService()->getLL(
'move_' . (
$table ===
'tt_content' ?
'record' :
'page')));
2070 $icon = (
$table ===
'pages' ? $this->iconFactory->getIcon(
'actions-page-move', Icon::SIZE_SMALL) : $this->iconFactory->getIcon(
'actions-document-move', Icon::SIZE_SMALL));
2071 $moveAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) .
'" title="' . $linkTitleLL .
'">' . $icon->render() .
'</a>';
2078 if ((
bool)\trim($userTsConfig[
'options.'][
'showHistory.'][
$table] ?? $userTsConfig[
'options.'][
'showHistory'] ??
'1')) {
2079 $moduleUrl = (string)$uriBuilder->buildUriFromRoute(
'record_history', [
'element' =>
$table .
':' . $row[
'uid']]);
2080 $onClick =
'return jumpExt(' . GeneralUtility::quoteJSvalue($moduleUrl) .
',\'#latest\');';
2081 $historyAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) .
'" title="'
2083 . $this->iconFactory->getIcon(
'actions-document-history-open', Icon::SIZE_SMALL)->render() .
'</a>';
2087 if (
$table ===
'pages' && $backendUser->check(
'modules',
'system_BeuserTxPermission') && ExtensionManagementUtility::isLoaded(
'beuser')) {
2088 if ($isL10nOverlay) {
2091 $href = (string)$uriBuilder->buildUriFromRoute(
'system_BeuserTxPermission') .
'&id=' . $row[
'uid'] .
'&tx_beuser_system_beusertxpermission[action]=edit' . $this->
makeReturnUrl();
2092 $permsAction =
'<a class="btn btn-default" href="' . htmlspecialchars($href) .
'" title="'
2094 . $this->iconFactory->getIcon(
'actions-lock', Icon::SIZE_SMALL)->render() .
'</a>';
2101 if (
$table !==
'pages' && $this->calcPerms & Permission::CONTENT_EDIT ||
$table ===
'pages' && $this->calcPerms & Permission::PAGE_NEW) {
2102 if (
$table ===
'pages' && $isL10nOverlay) {
2105 $params =
'&edit[' .
$table .
'][' . -($row[
'_MOVE_PLH'] ? $row[
'_MOVE_PLH_uid'] : $row[
'uid']) .
']=new';
2106 $icon = (
$table ===
'pages' ? $this->iconFactory->getIcon(
'actions-page-new', Icon::SIZE_SMALL) : $this->iconFactory->getIcon(
'actions-add', Icon::SIZE_SMALL));
2107 $titleLabel =
'new';
2109 $titleLabel .= (
$table ===
'pages' ?
'Page' :
'Record');
2111 $newAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params,
'', -1))
2113 . $icon->render() .
'</a>';
2119 if ($permsEdit &&
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'sortby'] && !$this->sortField && !$this->searchLevels) {
2120 if (!$isL10nOverlay && isset($this->currentTable[
'prev'][$row[
'uid']])) {
2122 $params =
'&cmd[' .
$table .
'][' . $row[
'uid'] .
'][move]=' . $this->currentTable[
'prev'][$row[
'uid']];
2123 $moveUpAction =
'<a class="btn btn-default" href="#" onclick="'
2124 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
2126 . $this->iconFactory->getIcon(
'actions-move-up', Icon::SIZE_SMALL)->render() .
'</a>';
2132 if (!$isL10nOverlay && $this->currentTable[
'next'][$row[
'uid']]) {
2134 $params =
'&cmd[' .
$table .
'][' . $row[
'uid'] .
'][move]=' . $this->currentTable[
'next'][$row[
'uid']];
2135 $moveDownAction =
'<a class="btn btn-default" href="#" onclick="'
2136 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
2138 . $this->iconFactory->getIcon(
'actions-move-down', Icon::SIZE_SMALL)->render() .
'</a>';
2145 $hiddenField =
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'enablecolumns'][
'disabled'];
2150 || $backendUser->check(
'non_exclude_fields',
$table .
':' . $hiddenField))
2157 if ($row[$hiddenField]) {
2158 $params =
'data[' .
$table .
'][' . $rowUid .
'][' . $hiddenField .
']=0';
2159 $hideAction =
'<a class="btn btn-default t3js-record-hide" data-state="hidden" href="#"'
2160 .
' data-params="' . htmlspecialchars($params) .
'"'
2161 .
' title="' . $unhideTitle .
'"'
2162 .
' data-toggle-title="' . $hideTitle .
'">'
2163 . $this->iconFactory->getIcon(
'actions-edit-unhide', Icon::SIZE_SMALL)->render() .
'</a>';
2165 $params =
'data[' .
$table .
'][' . $rowUid .
'][' . $hiddenField .
']=1';
2166 $hideAction =
'<a class="btn btn-default t3js-record-hide" data-state="visible" href="#"'
2167 .
' data-params="' . htmlspecialchars($params) .
'"'
2168 .
' title="' . $hideTitle .
'"'
2169 .
' data-toggle-title="' . $unhideTitle .
'">'
2170 . $this->iconFactory->getIcon(
'actions-edit-hide', Icon::SIZE_SMALL)->render() .
'</a>';
2176 $disableDelete = (bool)\trim($userTsConfig[
'options.'][
'disableDelete.'][
$table] ?? $userTsConfig[
'options.'][
'disableDelete'] ??
'0');
2177 if ($permsEdit && !$disableDelete && (
$table ===
'pages' && $localCalcPerms & Permission::PAGE_DELETE ||
$table !==
'pages' && $this->calcPerms & Permission::CONTENT_EDIT)) {
2179 if ($backendUser->workspace > 0 && isset($row[
't3ver_state']) && VersionState::cast($row[
't3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
2180 $actionName =
'restore';
2183 $actionName =
'delete';
2184 $refCountMsg = BackendUtility::referenceCount(
2187 ' ' . $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord'),
2189 ) . BackendUtility::translationCount(
2192 ' ' . $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord')
2199 $title = BackendUtility::getRecordTitle(
$table, $row);
2200 $warningText = $this->
getLanguageService()->
getLL($actionName .
'Warning') .
' "' . $title .
'" ' .
'[' .
$table .
':' . $row[
'uid'] .
']' . $refCountMsg;
2202 $params =
'cmd[' .
$table .
'][' . $row[
'uid'] .
'][delete]=1';
2203 $icon = $this->iconFactory->getIcon(
'actions-edit-' . $actionName, Icon::SIZE_SMALL)->render();
2205 $l10nParentField =
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField'] ??
'';
2206 $deleteAction =
'<a class="btn btn-default t3js-record-delete" href="#" '
2207 .
' data-button-ok-text="' . htmlspecialchars($linkTitle) .
'"'
2208 .
' data-l10parent="' . ($l10nParentField ? htmlspecialchars($row[$l10nParentField]) :
'') .
'"'
2209 .
' data-params="' . htmlspecialchars($params) .
'" data-title="' . htmlspecialchars($title) .
'"'
2210 .
' data-message="' . htmlspecialchars($warningText) .
'" title="' . $linkTitle .
'"'
2211 .
'>' . $icon .
'</a>';
2218 if ($permsEdit &&
$table ===
'pages' && !$this->searchLevels) {
2220 if ($this->calcPerms & Permission::PAGE_NEW) {
2222 $moveLeftAction =
'<a class="btn btn-default" href="#" onclick="'
2223 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
2225 . $this->iconFactory->getIcon(
'actions-move-left', Icon::SIZE_SMALL)->render() .
'</a>';
2226 $this->
addActionToCellGroup($cells, $isL10nOverlay ? $this->spaceIcon : $moveLeftAction,
'moveLeft');
2229 if (!$isL10nOverlay && $this->currentTable[
'prevUid'][$row[
'uid']]) {
2230 $localCalcPerms = $backendUser->calcPerms(BackendUtility::getRecord(
'pages', $this->currentTable[
'prevUid'][$row[
'uid']]));
2231 if ($localCalcPerms & Permission::PAGE_NEW) {
2232 $params =
'&cmd[' .
$table .
'][' . $row[
'uid'] .
'][move]=' . $this->currentTable[
'prevUid'][$row[
'uid']];
2233 $moveRightAction =
'<a class="btn btn-default" href="#" onclick="'
2234 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
2236 . $this->iconFactory->getIcon(
'actions-move-right', Icon::SIZE_SMALL)->render() .
'</a>';
2249 $hooks =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'GLOBAL'][
'recStatInfoHooks'] ?? [];
2250 if (!empty($hooks)) {
2252 $_params = [
$table, $row[
'uid']];
2253 foreach ($hooks as $_funcRef) {
2254 $stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2265 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] ??
false)) {
2268 foreach ($cells as $section => $actions) {
2269 foreach ($actions as $actionKey => $action) {
2270 $cells[$actionKey] = $action;
2273 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] as $className) {
2274 $hookObject = GeneralUtility::makeInstance($className);
2275 if (!$hookObject instanceof RecordListHookInterface) {
2276 throw new \UnexpectedValueException($className .
' must implement interface ' . RecordListHookInterface::class, 1195567840);
2278 $cells = $hookObject->makeControl(
$table, $row, $cells, $this);
2282 $hookCells = $cells;
2283 foreach ($hookCells as $key => $value) {
2284 if ($key ===
'primary' || $key ===
'secondary') {
2290 $output =
'<!-- CONTROL PANEL: ' .
$table .
':' . $row[
'uid'] .
' -->';
2291 foreach ($cells as $classification => $actions) {
2292 $visibilityClass = ($classification !==
'primary' && !$module->MOD_SETTINGS[
'bigControlPanel'] ?
'collapsed' :
'expanded');
2293 if ($visibilityClass ===
'collapsed') {
2295 foreach ($actions as $action) {
2296 $cellOutput .= $action;
2298 $output .=
' <div class="btn-group">' .
2299 '<span id="actions_' .
$table .
'_' . $row[
'uid'] .
'" class="btn-group collapse collapse-horizontal width">' . $cellOutput .
'</span>' .
2300 '<a href="#actions_' .
$table .
'_' . $row[
'uid'] .
'" class="btn btn-default collapsed" data-toggle="collapse" aria-expanded="false"><span class="t3-icon fa fa-ellipsis-h"></span></a>' .
2303 $output .=
' <div class="btn-group" role="group">' . implode(
'', $actions) .
'</div>';
2320 if (!$this->
getModule()->MOD_SETTINGS[
'clipBoard']) {
2330 $isL10nOverlay =
$table ===
'pages' && $row[
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField']] != 0;
2334 if ($this->clipObj->current ===
'normal') {
2336 $isSel = (string)$this->clipObj->isSelected(
$table, $row[
'uid']);
2341 $copyIcon = $this->iconFactory->getIcon(
'actions-edit-copy', Icon::SIZE_SMALL);
2342 $cutIcon = $this->iconFactory->getIcon(
'actions-edit-cut', Icon::SIZE_SMALL);
2344 if ($isSel ===
'copy') {
2345 $copyIcon = $this->iconFactory->getIcon(
'actions-edit-copy-release', Icon::SIZE_SMALL);
2346 } elseif ($isSel ===
'cut') {
2347 $cutIcon = $this->iconFactory->getIcon(
'actions-edit-cut-release', Icon::SIZE_SMALL);
2350 $cells[
'copy'] =
'<a class="btn btn-default" href="#" onclick="'
2351 . htmlspecialchars(
'return jumpSelf(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB(
2358 .
'" title="' . htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.copy')) .
'">'
2359 . $copyIcon->render() .
'</a>';
2364 $permsEdit = $localCalcPerms & Permission::PAGE_EDIT;
2366 $permsEdit = $this->calcPerms & Permission::CONTENT_EDIT;
2373 $cells[
'cut'] =
'<a class="btn btn-default" href="#" onclick="'
2374 . htmlspecialchars(
'return jumpSelf(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB(
2381 .
'" title="' . htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.cut')) .
'">'
2382 . $cutIcon->render() .
'</a>';
2387 if ($this->calcPerms & Permission::CONTENT_EDIT) {
2388 $cells[
'cut'] =
'<a class="btn btn-default" href="#" onclick="'
2389 . htmlspecialchars(
'return jumpSelf(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB(
2396 .
'" title="' . htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.cut')) .
'">'
2397 . $cutIcon->render() .
'</a>';
2406 $n =
$table .
'|' . $row[
'uid'];
2407 $this->CBnames[] = $n;
2409 $checked = $this->clipObj->isSelected(
$table, $row[
'uid']) ?
'checked="checked" ' :
'';
2411 if ($this->duplicateField && isset($row[$this->duplicateField])) {
2413 if (in_array($row[$this->duplicateField], $this->duplicateStack)) {
2414 $checked =
'checked="checked" ';
2419 $cells[
'select'] = $isL10nOverlay
2421 :
'<input type="hidden" name="CBH[' . $n .
']" value="0" /><label class="btn btn-default btn-checkbox"><input type="checkbox"'
2422 .
' name="CBC[' . $n .
']" value="1" ' . $checked .
'/><span class="t3-icon fa"></span></label>';
2425 $elFromTable = $this->clipObj->elFromTable(
$table);
2430 :
'<a class="btn btn-default t3js-modal-trigger"'
2431 .
' href="' . htmlspecialchars($this->clipObj->pasteUrl(
$table, -$row[
'uid'])) .
'"'
2432 .
' title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'clip_pasteAfter')) .
'"'
2433 .
' data-title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'clip_pasteAfter')) .
'"'
2434 .
' data-content="' . htmlspecialchars($this->clipObj->confirmMsgText(
$table, $row,
'after', $elFromTable)) .
'"'
2435 .
' data-severity="warning">'
2436 . $this->iconFactory->getIcon(
'actions-document-paste-after', Icon::SIZE_SMALL)->render() .
'</a>';
2439 $elFromTable = $this->clipObj->elFromTable(
'');
2440 if (
$table ===
'pages' && !$isL10nOverlay && !empty($elFromTable)) {
2441 $cells[
'pasteInto'] =
'<a class="btn btn-default t3js-modal-trigger"'
2442 .
' href="' . htmlspecialchars($this->clipObj->pasteUrl(
'', $row[
'uid'])) .
'"'
2443 .
' title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'clip_pasteInto')) .
'"'
2444 .
' data-title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'clip_pasteInto')) .
'"'
2445 .
' data-content="' . htmlspecialchars($this->clipObj->confirmMsgText(
$table, $row,
'into', $elFromTable)) .
'"'
2446 .
' data-severity="warning">'
2447 . $this->iconFactory->getIcon(
'actions-document-paste-into', Icon::SIZE_SMALL)->render() .
'</a>';
2456 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] ?? [] as $className) {
2457 $hookObject = GeneralUtility::makeInstance($className);
2458 if (!$hookObject instanceof RecordListHookInterface) {
2459 throw new \UnexpectedValueException($className .
' must implement interface ' . RecordListHookInterface::class, 1195567845);
2461 $cells = $hookObject->makeClip(
$table, $row, $cells, $this);
2463 return '<div class="btn-group" role="group">' . implode(
'', $cells) .
'</div>';
2477 ->getConnectionForTable(
'sys_refindex')
2482 'ref_table' => $tableName,
2483 'ref_uid' => (
int)$uid,
2490 GeneralUtility::quoteJSvalue($tableName) .
', ' . GeneralUtility::quoteJSvalue($uid)
2508 $this->translations = [];
2515 if ((
int)$row[
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'languageField']] === -1) {
2519 $translations = $this->translateTools->translationInfo(
$table, $row[
'uid'], 0, $row, $this->selFieldList);
2524 foreach ($this->pageOverlays as $lUid_OnPage => $lsysRec) {
2527 $href = BackendUtility::getLinkToDataHandlerAction(
2528 '&cmd[' .
$table .
'][' . $row[
'uid'] .
'][localize]=' . $lUid_OnPage,
2529 $url .
'&justLocalized=' . rawurlencode(
$table .
':' . $row[
'uid'] .
':' . $lUid_OnPage)
2531 $language = BackendUtility::getRecord(
'sys_language', $lUid_OnPage,
'title');
2532 if ($this->languageIconTitles[$lUid_OnPage][
'flagIcon']) {
2533 $lC = $this->iconFactory->getIcon($this->languageIconTitles[$lUid_OnPage][
'flagIcon'], Icon::SIZE_SMALL)->render();
2535 $lC = $this->languageIconTitles[$lUid_OnPage][
'title'];
2537 $lC =
'<a href="' . htmlspecialchars($href) .
'" title="'
2538 . htmlspecialchars($language[
'title']) .
'" class="btn btn-default t3js-action-localize">'
2546 } elseif ($row[
'l18n_parent']) {
2547 $out[0] =
' ' . $out[0];
2563 $formElements = [
'',
''];
2565 $formElements = [
'<form action="' . htmlspecialchars($this->
listURL()) .
'" method="post" name="fieldSelectBox">',
'</form>'];
2579 $checkAllChecked =
true;
2580 $tsConfig = BackendUtility::getPagesTSconfig($this->
id);
2581 $tsConfigOfTable = is_array($tsConfig[
'TCEFORM.'][
$table .
'.']) ? $tsConfig[
'TCEFORM.'][
$table .
'.'] :
null;
2584 if ($tsConfigOfTable && is_array($tsConfigOfTable[$fieldName .
'.']) && isset($tsConfigOfTable[$fieldName .
'.'][
'disabled']) && (
int)$tsConfigOfTable[$fieldName .
'.'][
'disabled'] === 1) {
2588 if (in_array($fieldName,
$setFields,
true) || $fieldName === $this->fieldArray[0]) {
2589 $checked =
' checked="checked"';
2591 $checkAllChecked =
false;
2596 $fieldTSConfig = [];
2598 if (isset($tsConfigOfTable[$fieldName .
'.'])
2599 && is_array($tsConfigOfTable[$fieldName .
'.'])
2601 $fieldTSConfig = $tsConfigOfTable[$fieldName .
'.'];
2603 if (!empty($fieldTSConfig[
'label'])) {
2604 $fieldLabel = $fieldTSConfig[
'label'];
2606 if (!empty($fieldTSConfig[
'label.'][$lang->lang])) {
2607 $fieldLabel = $fieldTSConfig[
'label.'][$lang->lang];
2610 $fieldLabel = $fieldLabel ?: BackendUtility::getItemLabel(
$table, $fieldName);
2612 $checkboxes[] =
'<tr><td class="col-checkbox"><input type="checkbox" id="check-' . $fieldName .
'" name="displayFields['
2613 .
$table .
'][]" value="' . $fieldName .
'" ' . $checked
2614 . ($fieldName === $this->fieldArray[0] ?
' disabled="disabled"' :
'') .
'></td><td class="col-title">'
2615 .
'<label class="label-block" for="check-' . $fieldName .
'">' . htmlspecialchars($lang->sL($fieldLabel)) .
' <span class="text-muted text-monospace">[' . htmlspecialchars($fieldName) .
']</span></label></td></tr>';
2619 <input type="hidden" name="displayFields[' .
$table .
'][]" value="">
2620 <div class="table-fit table-scrollable">
2621 <table border="0" cellpadding="0" cellspacing="0" class="table table-transparent table-hover">
2624 <th class="col-checkbox checkbox" colspan="2">
2625 <label><input type="checkbox" class="checkbox checkAll" ' . ($checkAllChecked ?
' checked="checked"' :
'') .
'>
2626 ' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleall')) .
'</label>
2631 ' . implode(
'', $checkboxes) .
'
2635 <input type="submit" name="search" class="btn btn-default" value="'
2636 . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.setFields')) .
'"/>
2637 ' . $formElements[1];
2638 return '<div class="fieldSelectBox">' .
$content .
'</div>';
2660 $jsCode =
'document.dblistForm.cmd.value=' . GeneralUtility::quoteJSvalue(
$cmd)
2661 .
';document.dblistForm.cmd_table.value='
2662 . GeneralUtility::quoteJSvalue(
$table)
2663 .
';document.dblistForm.submit();';
2666 if ($title !==
'') {
2667 $attributes[
'title'] = $title;
2670 $attributes[
'class'] =
'btn btn-default t3js-modal-trigger';
2671 $attributes[
'data-href'] =
'javascript:' . $jsCode;
2672 $attributes[
'data-severity'] =
'warning';
2673 $attributes[
'data-title'] = $title;
2674 $attributes[
'data-content'] = $warning;
2676 $attributes[
'class'] =
'btn btn-default';
2677 $attributes[
'onclick'] = $jsCode .
'return false;';
2680 $attributesString =
'';
2681 foreach ($attributes as $key => $value) {
2682 $attributesString .=
' ' . $key .
'="' . htmlspecialchars($value) .
'"';
2684 return '<a href="#" ' . $attributesString .
'>' . $string .
'</a>';
2694 return in_array(
'_CLIPBOARD_', $this->fieldArray) && $this->clipObj->current !==
'normal';
2710 if ($field ===
'_CONTROL_' || $field ===
'_LOCALIZATION_' || $field ===
'_CLIPBOARD_' || $field ===
'_REF_' || $this->disableSingleTableView) {
2714 if ($field ===
'_PATH_') {
2718 $sortUrl = $this->
listURL(
'',
'-1',
'sortField,sortRev,table,firstElementNumber') .
'&table=' . $table
2719 .
'&sortField=' . $field .
'&sortRev=' . ($this->sortRev || $this->sortField != $field ? 0 : 1);
2720 $sortArrow = $this->sortField === $field
2721 ? $this->iconFactory->getIcon(
'status-status-sorting-' . ($this->sortRev ?
'desc' :
'asc'), Icon::SIZE_SMALL)->render()
2724 return '<a href="' . htmlspecialchars($sortUrl) .
'">' . $code . $sortArrow .
'</a>';
2737 if (!isset($this->recPath_cache[$pid])) {
2738 $this->recPath_cache[$pid] = BackendUtility::getRecordPath($pid, $this->perms_clause, 20);
2740 return $this->recPath_cache[$pid];
2753 if (empty($this->allowedNewTables) && empty($this->deniedNewTables)) {
2756 return !in_array(
$table, $this->deniedNewTables)
2757 && (empty($this->allowedNewTables) || in_array(
$table, $this->allowedNewTables));
2769 return '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv(
'REQUEST_URI'));
2790 $fieldArray = array_combine($this->fieldArray, $this->fieldArray);
2791 $hooks =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][__CLASS__][
'customizeCsvHeader'] ?? [];
2792 if (!empty($hooks)) {
2796 foreach ($hooks as $hookFunction) {
2797 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
2809 protected function addToCSV(array $row = [])
2813 $fieldArray = array_intersect_key(array_flip($this->fieldArray), $rowReducedByControlFields);
2815 $rowReducedToSelectedColumns = array_replace(
$fieldArray, array_intersect_key($rowReducedByControlFields,
$fieldArray));
2816 $this->
setCsvRow($rowReducedToSelectedColumns);
2836 return array_diff_key($row, array_flip($controlFields));
2846 $csvDelimiter = $this->modTSconfig[
'properties'][
'csvDelimiter'] ??
',';
2847 $csvQuote = $this->modTSconfig[
'properties'][
'csvQuote'] ??
'"';
2849 $this->csvLines[] = CsvUtility::csvValues($csvRow, $csvDelimiter, $csvQuote);
2861 $filename = $prefix .
'_' . date(
'dmy-Hi') .
'.csv';
2863 header(
'Content-Type: application/octet-stream');
2864 header(
'Content-Disposition: attachment; filename=' . $filename);
2867 header(
"Cache-Control: ''");
2869 echo implode(CRLF, $this->csvLines);
2885 'view',
'edit',
'hide',
'delete',
'stat'
2888 'viewBig',
'history',
'perms',
'new',
'move',
'moveUp',
'moveDown',
'moveLeft',
'moveRight',
'version'
2891 $classification = in_array($actionKey, $cellsMap[
'primary']) ?
'primary' :
'secondary';
2892 $cells[$classification][$actionKey] = $action;
2893 unset($cells[$actionKey]);
2913 $this->editable = $isEditable;
2924 return !$GLOBALS[
'TCA'][
$table][
'ctrl'][
'readOnly']
2926 && ($backendUser->isAdmin() || $backendUser->check(
'tables_modify',
$table));
2944 return $table ===
'pages' ? true : !$this->pageRow[
'editlock'];
2946 if ((
$table ===
'pages' && $row[
'editlock']) || (
$table !==
'pages' && $this->pageRow[
'editlock'])) {
2947 $editPermission =
false;
2949 $editPermission =
false;
2952 return $editPermission;
2997 $this->
id = (int)
$id;
2999 $this->systemLanguagesOnPage = $this->translateTools->getSystemLanguages($this->
id);
3000 if ($GLOBALS[
'TCA'][
$table]) {
3005 $this->searchString = trim($search);
3006 $this->searchLevels = (int)$levels;
3007 $this->showLimit = MathUtility::forceIntegerInRange(
$showLimit, 0, 10000);
3009 $this->csvOutput = (bool)GeneralUtility::_GP(
'csv');
3010 $this->sortField = GeneralUtility::_GP(
'sortField');
3011 $this->sortRev = GeneralUtility::_GP(
'sortRev');
3012 $this->displayFields = GeneralUtility::_GP(
'displayFields');
3013 $this->duplicateField = GeneralUtility::_GP(
'duplicateField');
3014 if (GeneralUtility::_GP(
'justLocalized')) {
3020 $this->HTMLcode =
'';
3022 if (isset($this->modTSconfig[
'properties'][
'itemsLimitPerTable'])) {
3023 $this->itemsLimitPerTable = MathUtility::forceIntegerInRange(
3024 (
int)$this->modTSconfig[
'properties'][
'itemsLimitPerTable'],
3029 if (isset($this->modTSconfig[
'properties'][
'itemsLimitSingleTable'])) {
3030 $this->itemsLimitSingleTable = MathUtility::forceIntegerInRange(
3031 (
int)$this->modTSconfig[
'properties'][
'itemsLimitSingleTable'],
3038 $currentLinkValue = isset($this->overrideUrlParameters[
'P'][
'currentValue']) ? trim($this->overrideUrlParameters[
'P'][
'currentValue']) :
'';
3039 if ($currentLinkValue) {
3040 $linkService = GeneralUtility::makeInstance(LinkService::class);
3042 $currentLinkParts = $linkService->resolve($currentLinkValue);
3043 if ($currentLinkParts[
'type'] ===
'record' && isset($currentLinkParts[
'identifier'])) {
3045 $this->currentLink[
'uid'] = (int)$currentLinkParts[
'uid'];
3047 }
catch (UnknownLinkHandlerException $e) {
3054 $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3055 ->getQueryBuilderForTable(
'pages')
3057 $permsClause = $expressionBuilder->andX($backendUser->getPagePermsClause(Permission::PAGE_SHOW));
3059 $pidList = GeneralUtility::intExplode(
',', $backendUser->getTSConfig()[
'options.'][
'hideRecords.'][
'pages'] ??
'',
true);
3060 if (!empty($pidList)) {
3061 $permsClause->add($expressionBuilder->notIn(
'pages.uid', $pidList));
3063 $this->perms_clause = (string)$permsClause;
3066 $this->tablesCollapsed = is_array($backendUser->uc[
'moduleData'][
'list'])
3067 ? $backendUser->uc[
'moduleData'][
'list']
3069 $collapseOverride = GeneralUtility::_GP(
'collapse');
3070 if (is_array($collapseOverride)) {
3071 foreach ($collapseOverride as $collapseTable => $collapseValue) {
3072 if (is_array(
$GLOBALS[
'TCA'][$collapseTable]) && ($collapseValue == 0 || $collapseValue == 1)) {
3073 $this->tablesCollapsed[$collapseTable] = $collapseValue;
3078 $backendUser->writeUC($backendUser->uc);
3079 $returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP(
'returnUrl'));
3095 $this->pageRecord = BackendUtility::getRecordWSOL(
'pages', $this->
id);
3096 $hideTablesArray = GeneralUtility::trimExplode(
',', $this->hideTables);
3101 $tableNames = array_flip(array_keys(
$GLOBALS[
'TCA']));
3102 foreach ($tableNames as $tableName => &$config) {
3107 if ($this->table && $tableName !== $this->table
3108 || $this->tableList && !GeneralUtility::inList($this->tableList, $tableName)
3109 || !$backendUser->check(
'tables_select', $tableName)
3117 $hideTable = $hideTable
3118 || !empty(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'hideTable'])
3119 || in_array($tableName, $hideTablesArray,
true)
3120 || in_array(
'*', $hideTablesArray,
true);
3122 if (isset($this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'])) {
3123 $hideTable = (bool)$this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'];
3127 unset($tableNames[$tableName]);
3129 if (isset($this->tableDisplayOrder[$tableName])) {
3131 $tableNames[$tableName] = $this->tableDisplayOrder[$tableName];
3133 $tableNames[$tableName] = [];
3139 $orderedTableNames = GeneralUtility::makeInstance(DependencyOrderingService::class)
3140 ->orderByDependencies($tableNames);
3142 foreach ($orderedTableNames as $tableName => $_) {
3145 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems'])
3146 ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems']
3147 : $this->itemsLimitSingleTable;
3150 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3151 ->getQueryBuilderForTable($tableName);
3152 $queryBuilder->getRestrictions()
3154 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3155 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3157 $firstRow = $queryBuilder->select(
'uid')
3162 if (!is_array($firstRow)) {
3165 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems'])
3166 ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems']
3167 : $this->itemsLimitPerTable;
3169 if ($this->showLimit) {
3173 if ($this->allFields) {
3179 if (is_array($this->setFields[$tableName])) {
3189 $this->HTMLcode .= $this->
getTable($tableName, $this->
id, implode(
',',
$fields));
3202 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
3205 $formElements = [
'',
''];
3208 '<form action="' . htmlspecialchars(
3209 $this->
listURL(
'',
'-1',
'firstElementNumber,search_field')
3210 ) .
'" method="post">',
3218 $config = BackendUtility::getPagesTSconfig($this->
id);
3219 $searchLevelsFromTSconfig = $config[
'mod.'][
'web_list.'][
'searchLevel.'][
'items.'];
3220 $searchLevelItems = [];
3223 foreach ($searchLevelsFromTSconfig as $keySearchLevel => $labelConfigured) {
3224 $label = $lang->sL(
'LLL:' . $labelConfigured);
3225 if ($label ===
'') {
3226 $label = $labelConfigured;
3228 $searchLevelItems[$keySearchLevel] = $label;
3231 foreach ($searchLevelItems as $kv => $label) {
3232 $opt[] =
'<option value="' . $kv .
'"' . ($kv === $this->searchLevels ?
' selected="selected"' :
'') .
'>' . htmlspecialchars(
3236 $lMenu =
'<select class="form-control" name="search_levels" title="' . htmlspecialchars(
3237 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search_levels')
3238 ) .
'" id="search_levels">' . implode(
'', $opt) .
'</select>';
3240 $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') .
';">
3241 ' . $formElements[0] .
'
3242 <div id="typo3-dblist-search">
3243 <div class="panel panel-default">
3244 <div class="panel-body">
3246 <div class="col-sm-6 col-xs-12">
3247 <label for="search_field">' . htmlspecialchars(
3248 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.searchString')
3250 <input class="form-control" type="search" placeholder="' . htmlspecialchars(
3251 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')
3252 ) .
'" title="' . htmlspecialchars(
3253 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchString')
3254 ) .
'" name="search_field" id="search_field" value="' . htmlspecialchars($this->searchString) .
'" />
3256 <div class="col-xs-12 col-sm-3">
3257 <label for="search_levels">' . htmlspecialchars(
3258 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.search_levels')
3262 <div class="col-xs-12 col-sm-3">
3263 <label for="showLimit">' . htmlspecialchars(
3264 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.limit')
3266 <input class="form-control" type="number" min="0" max="10000" placeholder="10" title="' . htmlspecialchars(
3267 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.limit')
3268 ) .
'" name="showLimit" id="showLimit" value="' . htmlspecialchars(
3269 ($this->showLimit ? $this->showLimit :
'')
3272 <div class="col-xs-12">
3273 <div class="form-control-wrap">
3274 <button type="submit" class="btn btn-default" name="search" title="' . htmlspecialchars(
3275 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')
3278 ) .
' ' . htmlspecialchars(
3279 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search')
3288 ' . $formElements[1] .
'</div>';
3300 $dispFields = $backendUser->getModuleData(
'list/displayFields');
3302 if (is_array($this->displayFields)) {
3303 reset($this->displayFields);
3304 $tKey = key($this->displayFields);
3305 $dispFields[$tKey] = $this->displayFields[$tKey];
3306 $backendUser->pushModuleData(
'list/displayFields', $dispFields);
3309 $this->setFields = $dispFields;
3322 return BackendUtility::thumbCode($row,
$table, $field);
3338 array $additionalConstraints = [],
3341 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3342 ->getQueryBuilderForTable(
$table);
3343 $queryBuilder->getRestrictions()
3345 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3346 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3351 if (!empty($additionalConstraints)) {
3352 $queryBuilder->andWhere(...$additionalConstraints);
3357 return $queryBuilder;
3375 array $fieldList = [
'*'],
3376 array $additionalConstraints = [],
3377 QueryBuilder $queryBuilder,
3378 bool $addSorting =
true
3382 'fields' => $fieldList,
3385 'firstResult' => $this->firstElementNumber ?:
null,
3386 'maxResults' => $this->iLimit ?: null
3389 if ($this->iLimit > 0) {
3390 $queryBuilder->setMaxResults($this->iLimit);
3393 if ($this->firstElementNumber > 0) {
3394 $queryBuilder->setFirstResult($this->firstElementNumber);
3398 if ($this->sortField && in_array($this->sortField, $this->
makeFieldList($table, 1))) {
3399 $queryBuilder->orderBy($this->sortField, $this->sortRev ?
'DESC' :
'ASC');
3402 $orderBys = QueryHelper::parseOrderBy((
string)$orderBy);
3403 foreach ($orderBys as $orderBy) {
3404 $queryBuilder->addOrderBy($orderBy[0], $orderBy[1]);
3412 if (!empty($searchWhere)) {
3413 $queryBuilder->andWhere($searchWhere);
3417 if (
$table ===
'pages' && $this->perms_clause) {
3418 $queryBuilder->andWhere($this->perms_clause);
3423 && (GeneralUtility::inList($this->hideTranslations,
$table) || $this->hideTranslations ===
'*')
3425 $queryBuilder->andWhere(
3426 $queryBuilder->expr()->eq(
3434 $queryBuilder->andWhere(
3435 $queryBuilder->expr()->eq(
3437 $queryBuilder->createNamedParameter(
3445 $hookName = DatabaseRecordList::class;
3446 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][$hookName][
'buildQueryParameters'])) {
3448 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);
3449 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][$hookName][
'buildQueryParameters'] as $className) {
3450 $hookObject = GeneralUtility::makeInstance($className);
3451 if (method_exists($hookObject,
'buildQueryParametersPostProcess')) {
3452 $hookObject->buildQueryParametersPostProcess(
3456 $additionalConstraints,
3464 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][$hookName][
'modifyQuery'] ?? [] as $className) {
3465 $hookObject = GeneralUtility::makeInstance($className);
3466 if (method_exists($hookObject,
'modifyQuery')) {
3467 $hookObject->modifyQuery(
3471 $additionalConstraints,
3482 if (!empty($parameters[
'where'])) {
3483 $parameters[
'where'] = array_unique(array_filter(array_values($parameters[
'where'])));
3485 if (!empty($parameters[
'where'])) {
3487 $queryBuilder->where(...$parameters[
'where']);
3489 if (!empty($parameters[
'orderBy'])) {
3491 foreach ($parameters[
'orderBy'] as $fieldNameAndSorting) {
3492 [$fieldName, $sorting] = $fieldNameAndSorting;
3493 $queryBuilder->addOrderBy($fieldName, $sorting);
3496 if (!empty($parameters[
'firstResult']) && $parameters[
'firstResult'] !== $this->firstElementNumber) {
3498 $queryBuilder->setFirstResult((
int)$parameters[
'firstResult']);
3500 if (!empty($parameters[
'maxResults']) && $parameters[
'maxResults'] !== $this->iLimit) {
3502 $queryBuilder->setMaxResults((
int)$parameters[
'maxResults']);
3504 if (!empty($parameters[
'groupBy'])) {
3506 $queryBuilder->groupBy($parameters[
'groupBy']);
3509 return $queryBuilder;
3522 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3523 ->getQueryBuilderForTable(
$table);
3525 $queryBuilder->getRestrictions()
3527 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3528 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3532 if (!empty($constraints)) {
3533 $queryBuilder->andWhere(...$constraints);
3536 $queryBuilder = $this->
prepareQueryBuilder($table, $pageId, [
'*'], $constraints, $queryBuilder,
false);
3538 $queryBuilder->setFirstResult(0);
3539 $queryBuilder->setMaxResults(1);
3541 $this->totalItems = (int)$queryBuilder->count(
'*')
3556 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
$table);
3557 $expressionBuilder = $queryBuilder->expr();
3559 $currentPid = (int)$currentPid;
3560 $tablePidField =
$table ===
'pages' ?
'uid' :
'pid';
3562 if (empty($this->searchString)) {
3567 if (MathUtility::canBeInterpretedAsInteger($this->searchString)) {
3568 $constraints[] = $expressionBuilder->eq(
'uid', (
int)$this->searchString);
3569 foreach ($searchableFields as $fieldName) {
3574 $fieldType = $fieldConfig[
'type'];
3575 $evalRules = $fieldConfig[
'eval'] ?:
'';
3576 if ($fieldType ===
'input' && $evalRules && GeneralUtility::inList($evalRules,
'int')) {
3577 if (!isset($fieldConfig[
'search'][
'pidonly'])
3578 || ($fieldConfig[
'search'][
'pidonly'] && $currentPid > 0)
3580 $constraints[] = $expressionBuilder->andX(
3581 $expressionBuilder->eq($fieldName, (
int)$this->searchString),
3582 $expressionBuilder->eq($tablePidField, (
int)$currentPid)
3585 } elseif ($fieldType ===
'text'
3586 || $fieldType ===
'flex'
3587 || ($fieldType ===
'input' && (!$evalRules || !preg_match(
'/\b(?:date|time|int)\b/', $evalRules)))
3589 $constraints[] = $expressionBuilder->like(
3591 $queryBuilder->quote(
'%' . (
int)$this->searchString .
'%')
3595 } elseif (!empty($searchableFields)) {
3596 $like = $queryBuilder->quote(
'%' . $queryBuilder->escapeLikeWildcards($this->searchString) .
'%');
3597 foreach ($searchableFields as $fieldName) {
3602 $fieldType = $fieldConfig[
'type'];
3603 $evalRules = $fieldConfig[
'eval'] ?:
'';
3604 $searchConstraint = $expressionBuilder->andX(
3605 $expressionBuilder->comparison(
3606 'LOWER(' . $queryBuilder->castFieldToTextType($fieldName) .
')',
3608 'LOWER(' . $like .
')'
3611 if (is_array($fieldConfig[
'search'])) {
3612 $searchConfig = $fieldConfig[
'search'];
3613 if (in_array(
'case', $searchConfig)) {
3615 $searchConstraint = $expressionBuilder->andX($expressionBuilder->like($fieldName, $like));
3617 if (in_array(
'pidonly', $searchConfig) && $currentPid > 0) {
3618 $searchConstraint->add($expressionBuilder->eq($tablePidField, (
int)$currentPid));
3620 if ($searchConfig[
'andWhere']) {
3621 $searchConstraint->add(
3622 QueryHelper::stripLogicalOperatorPrefix($fieldConfig[
'search'][
'andWhere'])
3626 if ($fieldType ===
'text'
3627 || $fieldType ===
'flex'
3628 || $fieldType ===
'input' && (!$evalRules || !preg_match(
'/\b(?:date|time|int)\b/', $evalRules))
3630 if ($searchConstraint->count() !== 0) {
3631 $constraints[] = $searchConstraint;
3637 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][DatabaseRecordList::class][
'makeSearchStringConstraints'] ?? [] as $className) {
3638 $hookObject = GeneralUtility::makeInstance($className);
3639 if (method_exists($hookObject,
'makeSearchStringConstraints')) {
3640 $constraints = $hookObject->makeSearchStringConstraints(
3643 $this->searchString,
3650 if (empty($constraints)) {
3654 return $expressionBuilder->orX(...$constraints);
3666 $fieldListWasSet =
false;
3668 if (isset(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'])) {
3669 $fieldArray = GeneralUtility::trimExplode(
',',
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'],
true);
3670 $fieldListWasSet =
true;
3673 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'mod_list'][
'getSearchFieldList'])) {
3675 'tableHasSearchConfiguration' => $fieldListWasSet,
3676 'tableName' => $tableName,
3680 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'mod_list'][
'getSearchFieldList'] as $hookFunction) {
3681 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
3697 if ($this->table !==
$table) {
3698 return '<a href="' . htmlspecialchars(
3699 $this->
listURL(
'', $table,
'firstElementNumber')
3700 ) .
'">' . $code .
'</a>';
3702 return '<a href="' . htmlspecialchars(
3703 $this->
listURL(
'',
'',
'sortField,sortRev,table,firstElementNumber')
3704 ) .
'">' . $code .
'</a>';
3721 if ((
string)$code ===
'') {
3722 $code =
'<i>[' . htmlspecialchars(
3723 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title')
3725 . htmlspecialchars(BackendUtility::getRecordTitle(
$table, $row));
3727 $code = htmlspecialchars($code, ENT_QUOTES,
'UTF-8',
false);
3728 if ($code != htmlspecialchars($origCode)) {
3729 $code =
'<span title="' . htmlspecialchars(
3734 ) .
'">' . $code .
'</span>';
3736 $code =
'<span title="' . $code .
'">' . $code .
'</span>';
3739 switch ((
string)$this->clickTitleMode) {
3744 BackendUtility::getRecord(
'pages', $row[
'uid'])
3746 $permsEdit = $localCalcPerms & Permission::PAGE_EDIT;
3749 $permsEdit = $this->calcPerms & Permission::CONTENT_EDIT && $backendUser->recordEditAccessInternals(
$table, $row);
3753 $params =
'&edit[' .
$table .
'][' . $row[
'uid'] .
']=edit';
3754 $code =
'<a href="#" onclick="' . htmlspecialchars(
3755 BackendUtility::editOnClick($params,
'', -1)
3756 ) .
'" title="' . htmlspecialchars($lang->getLL(
'edit')) .
'">' . $code .
'</a>';
3763 $code =
'<a href="#" onclick="' . htmlspecialchars($onClick) .
'" title="' . htmlspecialchars(
3764 $lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')
3765 ) .
'">' . $code .
'</a>';
3770 $code =
'<a href="#" onclick="' . htmlspecialchars(
3771 'top.TYPO3.InfoWindow.showItem(' . GeneralUtility::quoteJSvalue(
$table) .
', ' . (
int)$row[
'uid'] .
'); return false;'
3772 ) .
'" title="' . htmlspecialchars($lang->getLL(
'showInfo')) .
'">' . $code .
'</a>';
3777 $code =
'<a href="' . htmlspecialchars(
3778 $this->
listURL($uid,
'',
'firstElementNumber')
3779 ) .
'" onclick="setHighlight(' . (int)$uid .
')">' . $code .
'</a>';
3797 $scheme = parse_url($testString, PHP_URL_SCHEME);
3798 if ($scheme ===
'http' || $scheme ===
'https' || $scheme ===
'ftp') {
3799 return '<a href="' . htmlspecialchars($testString) .
'" target="_blank">' . $code .
'</a>';
3802 if (GeneralUtility::validEmail($testString)) {
3803 return '<a href="mailto:' . htmlspecialchars($testString) .
'" target="_blank">' . $code .
'</a>';
3821 $urlParameters = [];
3822 if ((
string)$altId !==
'') {
3823 $urlParameters[
'id'] = $altId;
3830 $urlParameters[
'table'] =
$table;
3832 if ($this->thumbs) {
3835 if ($this->returnUrl) {
3838 if ((!$exclList || !GeneralUtility::inList($exclList,
'search_field')) && $this->searchString) {
3841 if ($this->searchLevels) {
3844 if ($this->showLimit) {
3847 if ((!$exclList || !GeneralUtility::inList($exclList,
'firstElementNumber')) && $this->firstElementNumber) {
3850 if ((!$exclList || !GeneralUtility::inList($exclList,
'sortField')) && $this->sortField) {
3853 if ((!$exclList || !GeneralUtility::inList($exclList,
'sortRev')) && $this->sortRev) {
3857 $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters);
3859 if ($routePath = GeneralUtility::_GP(
'route')) {
3860 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
3861 $url = (string)$uriBuilder->buildUriFromRoutePath($routePath, $urlParameters);
3863 $url = GeneralUtility::getIndpEnv(
'SCRIPT_NAME') . HttpUtility::buildQueryString($urlParameters,
'?');
3885 public function makeFieldList($table, $dontCheckUser =
false, $addDateFields =
false)
3897 if ($fieldValue[
'config'][
'type'] ===
'none') {
3902 || (!$fieldValue[
'exclude'] || $backendUser->check(
'non_exclude_fields',
$table .
':' . $fN)) && $fieldValue[
'config'][
'type'] !==
'passthrough'
3904 $fieldListArr[] = $fN;
3908 $fieldListArr[] =
'uid';
3909 $fieldListArr[] =
'pid';
3912 if ($dontCheckUser || $backendUser->isAdmin() || $addDateFields) {
3921 if ($dontCheckUser || $backendUser->isAdmin()) {
3928 if (ExtensionManagementUtility::isLoaded(
3931 $fieldListArr[] =
't3ver_id';
3932 $fieldListArr[] =
't3ver_state';
3933 $fieldListArr[] =
't3ver_wsid';
3937 GeneralUtility::makeInstance(LogManager::class)
3938 ->getLogger(__CLASS__)
3939 ->error(
'TCA is broken for the table "' .
$table .
'": no required "columns" entry in TCA.');
3942 return $fieldListArr;
3952 [
$table, $orig_uid, $language] = explode(
':', $justLocalized);
3957 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
$table);
3958 $queryBuilder->getRestrictions()
3960 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3961 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
3963 $localizedRecordUid = $queryBuilder->select(
'uid')
3966 $queryBuilder->expr()->eq(
3968 $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
3970 $queryBuilder->expr()->eq(
3972 $queryBuilder->createNamedParameter($orig_uid, \PDO::PARAM_INT)
3979 if ($localizedRecordUid !==
false) {
3983 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
3985 $editUserAccountUrl = (string)$uriBuilder->buildUriFromRoute(
3988 'edit[' .
$table .
'][' . $localizedRecordUid .
']' =>
'edit',
3992 HttpUtility::redirect($editUserAccountUrl);
4004 $currentUrlParameter = GeneralUtility::_GP(
'curUrl');
4005 if (isset($currentUrlParameter[
'url'])) {
4006 $urlParameters[
'P'][
'currentValue'] = $currentUrlParameter[
'url'];
4008 $this->overrideUrlParameters = $urlParameters;
4025 foreach ($orderInformation as $tableName => &$configuration) {
4026 if (isset($configuration[
'before'])) {
4027 if (is_string($configuration[
'before'])) {
4028 $configuration[
'before'] = GeneralUtility::trimExplode(
',', $configuration[
'before'],
true);
4029 } elseif (!is_array($configuration[
'before'])) {
4030 throw new \UnexpectedValueException(
4031 'The specified "before" order configuration for table "' . $tableName .
'" is invalid.',
4036 if (isset($configuration[
'after'])) {
4037 if (is_string($configuration[
'after'])) {
4038 $configuration[
'after'] = GeneralUtility::trimExplode(
',', $configuration[
'after'],
true);
4039 } elseif (!is_array($configuration[
'after'])) {
4040 throw new \UnexpectedValueException(
4041 'The specified "after" order configuration for table "' . $tableName .
'" is invalid.',
4047 $this->tableDisplayOrder = $orderInformation;
4076 $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache(
'cache_runtime');
4078 if ($runtimeCache->has($hash)) {
4079 $idList = $runtimeCache->get($hash);
4083 $tree = GeneralUtility::makeInstance(PageTreeView::class);
4085 $tree->makeHTML = 0;
4086 $tree->fieldArray = [
'uid',
'php_tree_stop'];
4089 $allowedMounts = !$backendUser->isAdmin() &&
$id === 0
4090 ? $backendUser->returnWebmounts()
4093 foreach ($allowedMounts as $allowedMount) {
4094 $idList[] = $allowedMount;
4096 $tree->getTree($allowedMount, $depth,
'');
4098 $idList = array_merge($idList, $tree->ids);
4100 $runtimeCache->set($hash, $idList);
4130 $tableName .
'.pid',
4137 $tableName .
'.pid',
4145 $tableName .
'.pid',
4154 $tableName .
'.pid',
4160 return $queryBuilder;
4171 trigger_error(
'[index: ' . $index .
'] $parameters in "buildQueryParameters"-Hook will be removed in TYPO3 v10.0, use $queryBuilder instead.', E_USER_DEPRECATED);
4196 public function addElement($h, $icon, $data, $rowParams =
'', $_ =
'', $_2 =
'', $colType =
'td')
4198 $colType = ($colType ===
'th') ?
'th' :
'td';
4199 $noWrap = $this->no_noWrap ?
'' :
' nowrap';
4201 $l10nParent = isset($data[
'_l10nparent_']) ? (int)$data[
'_l10nparent_'] : 0;
4203 <!-- Element, begin: -->
4204 <tr ' . $rowParams .
' data-uid="' . (int)$data[
'uid'] .
'" data-l10nparent="' . $l10nParent .
'">';
4206 if ($this->showIcon) {
4208 <' . $colType .
' class="col-icon nowrap">';
4212 for ($a = 0; $a < $h; $a++) {
4220 $out .=
'</' . $colType .
'>
4231 if ($colType ===
'td' && array_key_exists(
'__label', $data)) {
4236 if (isset($data[$vKey])) {
4238 $cssClass = $this->addElement_tdCssClass[$lastKey];
4239 if ($this->oddColumnsCssClass && $ccount % 2 == 0) {
4240 $cssClass = implode(
' ', [$this->addElement_tdCssClass[$lastKey], $this->oddColumnsCssClass]);
4243 <' . $colType .
' class="' . $cssClass . $noWrap .
'"' . $colsp . $this->addElement_tdParams[$lastKey] .
'>' . $data[$lastKey] .
'</' . $colType .
'>';
4255 $colsp =
' colspan="' . $c .
'"';
4261 $cssClass = $this->addElement_tdCssClass[$lastKey];
4262 if ($this->oddColumnsCssClass) {
4263 $cssClass = implode(
' ', [$this->addElement_tdCssClass[$lastKey], $this->oddColumnsCssClass]);
4266 <' . $colType .
' class="' . $cssClass . $noWrap .
'"' . $colsp . $this->addElement_tdParams[$lastKey] .
'>' . $data[$lastKey] .
'</' . $colType .
'>';
4291 if ($this->eCounter >= $this->firstElementNumber && $this->eCounter < $this->firstElementNumber + $this->iLimit) {
4292 if ($this->firstElementNumber && $this->eCounter == $this->firstElementNumber) {
4295 $titleCol = $this->fieldArray[0];
4297 $code = $this->
addElement(1,
'', $theData,
'class="fwd_rwd_nav"');
4301 if ($this->eCounter == $this->firstElementNumber + $this->iLimit) {
4304 $titleCol = $this->fieldArray[0];
4306 $code = $this->
addElement(1,
'', $theData,
'class="fwd_rwd_nav"');
4327 $content =
'<a href="' . htmlspecialchars($href) .
'">' . $this->iconFactory->getIcon(
4330 )->render() .
'</a> <i>[' . (max(0,
$pointer - $this->iLimit) + 1) .
' - ' .
$pointer .
']</i>';
4334 $content =
'<a href="' . htmlspecialchars($href) .
'">' . $this->iconFactory->getIcon(
4335 'actions-move-down',
4337 )->render() .
'</a> <i>[' . (
$pointer + 1) .
' - ' . $this->totalItems .
']</i>';
4352 function checkOffCB(listOfCBnames, link) { //
4353 var checkBoxes, flag, i;
4354 var checkBoxes = listOfCBnames.split(",");
4355 if (link.rel === "") {
4356 link.rel = "allChecked";
4362 for (i = 0; i < checkBoxes.length; i++) {
4363 setcbValue(checkBoxes[i], flag);
4367 function cbValue(CBname) { //
4368 var CBfullName = "CBC["+CBname+"]";
4369 return (document.dblistForm[CBfullName] && document.dblistForm[CBfullName].checked ? 1 : 0);
4372 function setcbValue(CBname,flag) { //
4373 CBfullName = "CBC["+CBname+"]";
4374 if(document.dblistForm[CBfullName]) {
4375 document.dblistForm[CBfullName].checked = flag ? "on" : 0;
4388 $localizationParentField =
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'transOrigPointerField'];
4389 $languageField =
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField'];
4390 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4391 ->getQueryBuilderForTable(
'pages');
4392 $queryBuilder->getRestrictions()
4394 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
4395 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
4396 $result = $queryBuilder
4400 $queryBuilder->expr()->andX(
4401 $queryBuilder->expr()->eq($localizationParentField, $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)),
4402 $queryBuilder->expr()->gt(
4404 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
4410 $this->pageOverlays = [];
4411 while ($row = $result->fetch()) {
4412 $this->pageOverlays[$row[$languageField]] = $row;
4425 public function languageFlag($sys_language_uid, $addAsAdditionalText =
true)
4428 $title = htmlspecialchars($this->languageIconTitles[$sys_language_uid][
'title']);
4429 if ($this->languageIconTitles[$sys_language_uid][
'flagIcon']) {
4430 $out .=
'<span title="' . $title .
'">' . $this->iconFactory->getIcon(
4431 $this->languageIconTitles[$sys_language_uid][
'flagIcon'],
4433 )->render() .
'</span>';
4434 if (!$addAsAdditionalText) {
4448 if ($routePath = GeneralUtility::_GP(
'route')) {
4449 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
4450 $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath);
4452 $this->thisScript = GeneralUtility::getIndpEnv(
'SCRIPT_NAME');
4461 return strpos($this->thisScript,
'?') ===
false ? $this->thisScript .
'?' : $this->thisScript .
'&';
4471 if (!isset($this->translateTools)) {
4472 $this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
4490 $htmlCode =
'<a href="#"';
4491 if ($launchViewParameter !==
'') {
4492 $htmlCode .=
' onclick="' . htmlspecialchars(
4493 'top.TYPO3.InfoWindow.showItem(' . $launchViewParameter .
'); return false;'
4496 $htmlCode .=
' title="' . htmlspecialchars(
4498 'LLL:EXT:backend/Resources/Private/Language/locallang.xlf:show_references'
4499 ) .
' (' . $references .
')'
4501 $htmlCode .= $references;
4502 $htmlCode .=
'</a>';
4530 $visibleColumns = $tableTCA[
'types'][$type][
'showitem'] ??
'';
4532 if (strpos($visibleColumns,
'--palette--') !==
false) {
4534 preg_match_all(
'/--palette--\s*;[^;]*;\s*(\w+)/', $visibleColumns, $matches, PREG_SET_ORDER);
4535 if (!empty($matches)) {
4536 foreach ($matches as $palette) {
4537 $paletteColumns = $tableTCA[
'palettes'][$palette[1]][
'showitem'] ??
'';
4538 $paletteColumns = rtrim($paletteColumns,
", \t\r\n");
4539 $visibleColumns = str_replace($palette[0], $paletteColumns, $visibleColumns);
4544 return $visibleColumns;