206 parent::__construct();
238 $localCalcPerms = $backendUser->calcPerms($this->pageRow);
240 if ((
string)$this->
id ===
'') {
247 if (isset($this->
id)) {
250 if (isset($module->modTSconfig[
'properties'][
'noViewWithDokTypes'])) {
254 $noViewDokTypes = array(
255 PageRepository::DOKTYPE_SYSFOLDER,
256 PageRepository::DOKTYPE_RECYCLER
259 if (!in_array($this->pageRow[
'doktype'], $noViewDokTypes)) {
261 $buttons[
'view'] =
'<a href="#" onclick="' . $onClick .
'" title="'
262 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.showPage',
true) .
'">'
263 . $this->iconFactory->getIcon(
'actions-document-view',
Icon::SIZE_SMALL)->render() .
'</a>';
266 if (!$module->modTSconfig[
'properties'][
'noCreateRecordsLink'] && $this->editLockPermissions()) {
267 $onClick = htmlspecialchars(
'return jumpExt(' .
GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl(
'db_new', [
'id' => $this->
id])) .
');');
268 $buttons[
'new_record'] =
'<a href="#" onclick="' . $onClick .
'" title="'
269 .
$lang->getLL(
'newRecordGeneral',
true) .
'">'
270 . $this->iconFactory->getIcon(
'actions-add',
Icon::SIZE_SMALL)->render() .
'</a>';
276 $params =
'&edit[pages][' . $this->pageRow[
'uid'] .
']=edit';
278 $buttons[
'edit'] =
'<a href="#" onclick="' . $onClick .
'" title="' .
$lang->getLL(
'editPage',
true) .
'">'
279 . $this->iconFactory->getIcon(
'actions-page-open',
Icon::SIZE_SMALL)->render()
284 $elFromTable = $this->clipObj->elFromTable(
'');
285 if (!empty($elFromTable)) {
286 $onClick = htmlspecialchars((
'return ' . $this->clipObj->confirmMsg(
'pages', $this->pageRow,
'into', $elFromTable)));
287 $buttons[
'paste'] =
'<a href="' . htmlspecialchars($this->clipObj->pasteUrl(
'', $this->id))
288 .
'" onclick="' . $onClick .
'" title="' .
$lang->getLL(
'clip_paste',
true) .
'">'
289 . $this->iconFactory->getIcon(
'actions-document-paste-after',
Icon::SIZE_SMALL)->render() .
'</a>';
293 $buttons[
'cache'] =
'<a href="' . htmlspecialchars(($this->
listURL() .
'&clear_cache=1')) .
'" title="'
294 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.clear_cache',
true) .
'">'
295 . $this->iconFactory->getIcon(
'actions-system-cache-clear',
Icon::SIZE_SMALL)->render() .
'</a>';
296 if ($this->table && (!isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
297 || (isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
298 && !$module->modTSconfig[
'properties'][
'noExportRecordsLinks']))
301 $buttons[
'csv'] =
'<a href="' . htmlspecialchars(($this->
listURL() .
'&csv=1')) .
'" title="'
302 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.csv',
true) .
'">'
303 . $this->iconFactory->getIcon(
'actions-document-export-csv',
Icon::SIZE_SMALL)->render() .
'</a>';
306 $url = BackendUtility::getModuleUrl(
'xMOD_tximpexp', array(
'tx_impexp[action]' =>
'export'));
307 $buttons[
'export'] =
'<a href="' . htmlspecialchars(
$url .
'&tx_impexp[list][]='
308 . rawurlencode($this->table .
':' . $this->
id)) .
'" title="'
309 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:rm.export',
true) .
'">'
310 . $this->iconFactory->getIcon(
'actions-document-export-t3d',
Icon::SIZE_SMALL)->render() .
'</a>';
314 $buttons[
'reload'] =
'<a href="' . htmlspecialchars($this->
listURL()) .
'" title="'
315 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.reload',
true) .
'">'
316 . $this->iconFactory->getIcon(
'actions-refresh',
Icon::SIZE_SMALL)->render() .
'</a>';
318 if ($backendUser->mayMakeShortcut()) {
320 'id, M, imagemode, pointer, table, search_field, search_levels, showLimit, sortField, sortRev',
321 implode(
',', array_keys($this->MOD_MENU)),
326 if ($this->returnUrl) {
328 $buttons[
'back'] =
'<a href="' . $href .
'" class="typo3-goBack" title="'
329 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.goBack',
true) .
'">'
330 . $this->iconFactory->getIcon(
'actions-view-go-back',
Icon::SIZE_SMALL)->render() .
'</a>';
349 $localCalcPerms = $backendUser->calcPerms($this->pageRow);
351 if ((
string)$this->
id ===
'') {
352 $fieldName =
'list_module_noId';
354 $fieldName =
'list_module_root';
356 $fieldName =
'list_module';
358 $cshButton = $buttonBar->makeHelpButton()
359 ->setModuleName(
'xMOD_csh_corebe')
360 ->setFieldName($fieldName);
361 $buttonBar->addButton($cshButton);
362 if (isset($this->
id)) {
365 if (isset($module->modTSconfig[
'properties'][
'noViewWithDokTypes'])) {
369 $noViewDokTypes = array(
370 PageRepository::DOKTYPE_SYSFOLDER,
371 PageRepository::DOKTYPE_RECYCLER
375 if (!$module->modTSconfig[
'properties'][
'noCreateRecordsLink'] && $this->editLockPermissions()) {
377 $newRecordButton = $buttonBar->makeLinkButton()
379 ->setOnClick($onClick)
380 ->setTitle(
$lang->getLL(
'newRecordGeneral',
true))
381 ->setIcon($this->iconFactory->getIcon(
'actions-document-new',
Icon::SIZE_SMALL));
384 if (!in_array($this->pageRow[
'doktype'], $noViewDokTypes)) {
386 $viewButton = $buttonBar->makeLinkButton()
388 ->setOnClick($onClick)
389 ->setTitle(
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.showPage',
true))
390 ->setIcon($this->iconFactory->getIcon(
'actions-document-view',
Icon::SIZE_SMALL));
397 $params =
'&edit[pages][' . $this->pageRow[
'uid'] .
']=edit';
399 $editButton = $buttonBar->makeLinkButton()
401 ->setOnClick($onClick)
402 ->setTitle(
$lang->getLL(
'editPage',
true))
403 ->setIcon($this->iconFactory->getIcon(
'actions-page-open',
Icon::SIZE_SMALL));
408 $elFromTable = $this->clipObj->elFromTable(
'');
409 if (!empty($elFromTable)) {
410 $onClick =
'return ' . $this->clipObj->confirmMsg(
'pages', $this->pageRow,
'into', $elFromTable);
411 $pasteButton = $buttonBar->makeLinkButton()
412 ->setHref($this->clipObj->pasteUrl(
'', $this->id))
413 ->setOnClick($onClick)
414 ->setTitle(
$lang->getLL(
'clip_paste',
true))
415 ->setIcon($this->iconFactory->getIcon(
'actions-document-paste-after',
Icon::SIZE_SMALL));
420 $clearCacheButton = $buttonBar->makeLinkButton()
421 ->setHref($this->
listURL() .
'&clear_cache=1')
422 ->setTitle(
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.clear_cache',
true))
423 ->setIcon($this->iconFactory->getIcon(
'actions-system-cache-clear',
Icon::SIZE_SMALL));
425 if ($this->table && (!isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
426 || (isset($module->modTSconfig[
'properties'][
'noExportRecordsLinks'])
427 && !$module->modTSconfig[
'properties'][
'noExportRecordsLinks']))
430 $csvButton = $buttonBar->makeLinkButton()
431 ->setHref($this->
listURL() .
'&csv=1')
432 ->setTitle(
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.csv',
true))
433 ->setIcon($this->iconFactory->getIcon(
'actions-document-export-csv',
Icon::SIZE_SMALL));
437 $url = BackendUtility::getModuleUrl(
'xMOD_tximpexp', array(
'tx_impexp[action]' =>
'export'));
438 $exportButton = $buttonBar->makeLinkButton()
439 ->setHref(
$url .
'&tx_impexp[list][]=' . rawurlencode($this->table .
':' . $this->
id))
440 ->setTitle(
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:rm.export',
true))
441 ->setIcon($this->iconFactory->getIcon(
'actions-document-export-t3d',
Icon::SIZE_SMALL));
446 $reloadButton = $buttonBar->makeLinkButton()
448 ->setTitle(
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.reload',
true))
449 ->setIcon($this->iconFactory->getIcon(
'actions-refresh',
Icon::SIZE_SMALL));
452 if ($backendUser->mayMakeShortcut()) {
453 $shortCutButton = $buttonBar->makeShortcutButton()
454 ->setModuleName(
'web_list')
467 ->setSetVariables(array_keys($this->MOD_MENU));
471 if ($this->returnUrl) {
473 $buttons[
'back'] =
'<a href="' . $href .
'" class="typo3-goBack" title="'
474 .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.goBack',
true) .
'">'
475 . $this->iconFactory->getIcon(
'actions-view-go-back',
Icon::SIZE_SMALL) .
'</a>';
489 public function getTable(
$table,
$id, $rowList =
'')
493 if (!empty(
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'descriptionColumn']) && empty($rowListArray)) {
494 array_push($rowListArray,
$GLOBALS[
'TCA'][$table][
'ctrl'][
'descriptionColumn']);
498 $db = $this->getDatabaseConnection();
506 $tableCollapsed = (bool)$this->tablesCollapsed[$table];
508 $this->spaceIcon =
'<span class="btn btn-default disabled">' . $this->iconFactory->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>';
510 $this->fieldArray = array();
513 $this->fieldArray[] = $titleCol;
516 $this->fieldArray[] =
'_CONTROL_';
519 if ($this->showClipboard) {
520 $this->fieldArray[] =
'_CLIPBOARD_';
523 if (!$this->dontShowClipControlPanels) {
524 $this->fieldArray[] =
'_REF_';
527 if ($this->searchLevels) {
528 $this->fieldArray[] =
'_PATH_';
531 if ($this->localizationView && $l10nEnabled) {
532 $this->fieldArray[] =
'_LOCALIZATION_';
533 $this->fieldArray[] =
'_LOCALIZATION_b';
537 ' .
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField'] .
' = 0
541 $this->fieldArray = array_unique(array_merge($this->fieldArray, $rowListArray));
542 if ($this->noControlPanels) {
543 $tempArray = array_flip($this->fieldArray);
544 unset($tempArray[
'_CONTROL_']);
545 unset($tempArray[
'_CLIPBOARD_']);
546 $this->fieldArray = array_keys($tempArray);
549 $selectFields = $this->fieldArray;
550 $selectFields[] =
'uid';
551 $selectFields[] =
'pid';
554 $selectFields[] = $thumbsCol;
556 if ($table ==
'pages') {
557 $selectFields[] =
'module';
558 $selectFields[] =
'extendToSubpages';
559 $selectFields[] =
'nav_hide';
560 $selectFields[] =
'doktype';
561 $selectFields[] =
'shortcut';
562 $selectFields[] =
'shortcut_mode';
563 $selectFields[] =
'mount_pid';
565 if (is_array(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns'])) {
566 $selectFields = array_merge($selectFields,
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns']);
568 foreach (array(
'type',
'typeicon_column',
'editlock') as $field) {
569 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][$field]) {
573 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'versioningWS']) {
574 $selectFields[] =
't3ver_id';
575 $selectFields[] =
't3ver_state';
576 $selectFields[] =
't3ver_wsid';
579 $selectFields[] =
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'languageField'];
580 $selectFields[] =
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField'];
582 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'label_alt']) {
583 $selectFields = array_merge(
589 $selectFields = array_unique($selectFields);
591 if (empty($fieldListFields) &&
$GLOBALS[
'TYPO3_CONF_VARS'][
'BE'][
'debug']) {
592 $message = sprintf(
$lang->sL(
'LLL:EXT:lang/locallang_mod_web_list.xlf:missingTcaColumnsMessage',
true),
$table,
$table);
593 $messageTitle =
$lang->sL(
'LLL:EXT:lang/locallang_mod_web_list.xlf:missingTcaColumnsMessageTitle',
true);
605 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
606 $defaultFlashMessageQueue->enqueue($flashMessage);
609 $selectFields = array_intersect($selectFields, $fieldListFields);
613 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'getTable'])) {
614 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'getTable'] as $classData) {
616 if (!$hookObject instanceof RecordListGetTableHookInterface) {
617 throw new \UnexpectedValueException(
'$hookObject must implement interface ' . RecordListGetTableHookInterface::class, 1195114460);
619 $hookObject->getDBlistQuery($table,
$id, $addWhere, $selFieldList, $this);
624 if ($this->csvOutput) {
627 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
629 $this->firstElementNumber = $this->firstElementNumber - 2;
630 $this->iLimit = $this->iLimit + 2;
633 $this->firstElementNumber = $this->firstElementNumber + 2;
634 $this->iLimit = $this->iLimit - 2;
652 if ($this->totalItems) {
654 if ($listOnlyInSingleTableMode) {
655 $dbCount = $this->totalItems;
658 if ($this->csvOutput) {
659 $this->showLimit = $this->totalItems;
660 $this->iLimit = $this->totalItems;
662 $result = $db->exec_SELECT_queryArray($queryParts);
663 $dbCount = $db->sql_num_rows($result);
668 $tableTitle =
$lang->sL(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'title'],
true);
669 if ($tableTitle ===
'') {
674 if ($this->disableSingleTableView) {
675 $theData[$titleCol] =
'<span class="c-table">' . BackendUtility::wrapInHelp($table,
'', $tableTitle)
676 .
'</span> (<span class="t3js-table-total-items">' . $this->totalItems .
'</span>)';
679 ?
'<span title="' .
$lang->getLL(
'contractView',
true) .
'">' . $this->iconFactory->getIcon(
'actions-view-table-collapse',
Icon::SIZE_SMALL)->render() .
'</span>'
680 :
'<span title="' .
$lang->getLL(
'expandView',
true) .
'">' . $this->iconFactory->getIcon(
'actions-view-table-expand',
Icon::SIZE_SMALL)->render() .
'</span>';
681 $theData[$titleCol] = $this->
linkWrapTable($table, $tableTitle .
' (<span class="t3js-table-total-items">' . $this->totalItems .
'</span>) ' . $icon);
683 if ($listOnlyInSingleTableMode) {
684 $tableHeader .= BackendUtility::wrapInHelp($table,
'', $theData[$titleCol]);
689 $href = htmlspecialchars(($this->
listURL() .
'&collapse[' . $table .
']=' . ($tableCollapsed ?
'0' :
'1')));
690 $title = $tableCollapsed
691 ?
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.expandTable',
true)
692 :
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.collapseTable',
true);
693 $icon =
'<span class="collapseIcon">' . $this->iconFactory->getIcon(($tableCollapsed ?
'actions-view-list-expand' :
'actions-view-list-collapse'),
Icon::SIZE_SMALL)->render() .
'</span>';
694 $collapseIcon =
'<a href="' . $href .
'" title="' . $title .
'" class="pull-right t3js-toggle-recordlist" data-table="' . htmlspecialchars($table) .
'" data-toggle="collapse" data-target="#recordlist-' . htmlspecialchars($table) .
'">' . $icon .
'</a>';
696 $tableHeader .= $theData[$titleCol] . $collapseIcon;
700 if (!$listOnlyInSingleTableMode || $this->table) {
702 $this->currentTable = array();
703 $currentIdList = array();
704 $doSort =
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'sortby'] && !$this->sortField;
708 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
709 $row = $db->sql_fetch_assoc($result);
710 $prevPrevUid = -((int)$row[
'uid']);
711 $row = $db->sql_fetch_assoc($result);
712 $prevUid = $row[
'uid'];
716 while ($row = $db->sql_fetch_assoc($result)) {
722 if (is_array($row)) {
724 $currentIdList[] = $row[
'uid'];
727 $this->currentTable[
'prev'][$row[
'uid']] = $prevPrevUid;
728 $this->currentTable[
'next'][$prevUid] =
'-' . $row[
'uid'];
729 $this->currentTable[
'prevUid'][$row[
'uid']] = $prevUid;
731 $prevPrevUid = isset($this->currentTable[
'prev'][$row[
'uid']]) ? -$prevUid : $row[
'pid'];
732 $prevUid = $row[
'uid'];
736 $db->sql_free_result($result);
737 $this->totalRowCount = count($accRows);
739 if ($this->csvOutput) {
743 $this->CBnames = array();
744 $this->duplicateStack = array();
745 $this->eCounter = $this->firstElementNumber;
747 foreach ($accRows as $row) {
749 if ($cc < $this->iLimit) {
751 $this->translations =
false;
752 $rowOutput .= $this->
renderListRow($table, $row, $cc, $titleCol, $thumbsCol);
756 if ($this->localizationView && $l10nEnabled) {
758 if (is_array($this->translations)) {
759 foreach ($this->translations as $lRow) {
762 if ($row[
'_MOVE_PLH_uid'] && $row[
'_MOVE_PLH_pid']) {
763 $where =
't3ver_move_id="' . (int)$lRow[
'uid'] .
'" AND pid="' . $row[
'_MOVE_PLH_pid']
766 $lRow = is_array($tmpRow) ? $tmpRow : $lRow;
770 if (is_array($lRow) && $backendUser->checkLanguageAccess($lRow[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField']])) {
771 $currentIdList[] = $lRow[
'uid'];
772 $rowOutput .= $this->
renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 18);
787 if ($this->totalItems > $this->itemsLimitPerTable) {
788 $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems;
789 $hasMore = $this->totalItems > $this->itemsLimitSingleTable;
790 $colspan = $this->showIcon ? count($this->fieldArray) + 1 : count($this->fieldArray);
791 $rowOutput .=
'<tr><td colspan="' . $colspan .
'">
792 <a href="' . htmlspecialchars(($this->
listURL() .
'&table=' . rawurlencode($table))) .
'" class="btn btn-default">'
793 .
'<span class="t3-icon fa fa-chevron-down"></span> <i>[1 - ' . $countOnFirstPage . ($hasMore ?
'+' :
'') .
']</i></a>
801 $collapseClass = $tableCollapsed && !$this->table ?
'collapse' :
'collapse in';
802 $dataState = $tableCollapsed && !$this->table ?
'collapsed' :
'expanded';
812 DB listing of elements: "' . htmlspecialchars($table) .
'"
814 <div class="panel panel-space panel-default">
815 <div class="panel-heading">
818 <div class="table-fit ' . $collapseClass .
'" id="recordlist-' . htmlspecialchars($table) .
'" data-state="' . $dataState .
'">
819 <table data-table="' . htmlspecialchars($table) .
'" class="table table-striped table-hover' . (
$listOnlyInSingleTableMode ?
' typo3-dblist-overview' :
'') .
'">
827 if ($this->csvOutput) {
862 public function renderListRow($table, $row, $cc, $titleCol, $thumbsCol, $indent = 0)
864 if (!is_array($row)) {
870 if ((
string)$this->searchString !==
'') {
872 $this->
id = $row[
'pid'];
876 if ($cc == 1 && $indent == 0) {
877 $rowSpecial .=
' firstcol';
879 if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
880 $rowSpecial .=
' lastcol';
883 $row_bgColor =
' class="' . $rowSpecial .
'"';
886 $row_bgColor = $row[
'_CSSCLASS'] ?
' class="' . $row[
'_CSSCLASS'] .
'"' : $row_bgColor;
891 $additionalStyle = $indent ?
' style="margin-left: ' . $indent .
'px;"' :
'';
892 $iconImg =
'<span ' . $toolTip .
' ' . $additionalStyle .
'>'
893 . $this->iconFactory->getIconForRecord($table, $row,
Icon::SIZE_SMALL)->render()
898 $localizationMarkerClass =
'';
899 foreach ($this->fieldArray as $fCol) {
900 if ($fCol == $titleCol) {
906 $warning =
'<a href="#" onclick="alert('
908 . htmlspecialchars($lockInfo[
'msg']) .
'">'
909 . $this->iconFactory->getIcon(
'status-warning-in-use',
Icon::SIZE_SMALL)->render() .
'</a>';
911 $theData[$fCol] = $theData[
'__label'] = $warning . $this->
linkWrapItems($table, $row[
'uid'], $recTitle, $row);
917 if (isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'type'])) {
919 $type = $row[$typeColumn];
923 if (!isset(
$GLOBALS[
'TCA'][$table][
'types'][$type])) {
924 $type = isset(
$GLOBALS[
'TCA'][$table][
'types'][0]) ? 0 : 1;
926 $visibleColumns =
$GLOBALS[
'TCA'][
$table][
'types'][$type][
'showitem'];
929 trim($row[$thumbsCol]) &&
930 preg_match(
'/(^|(.*(;|,)?))' . $thumbsCol .
'(((;|,).*)|$)/', $visibleColumns) === 1
932 $theData[$fCol] .=
'<br />' . $this->
thumbCode($row, $table, $thumbsCol);
934 if (isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField'])
935 && $row[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField']] != 0
936 && $row[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField']] != 0
939 $localizationMarkerClass =
' localization';
941 }
elseif ($fCol ==
'pid') {
942 $theData[$fCol] = $row[$fCol];
943 }
elseif ($fCol ==
'_PATH_') {
944 $theData[$fCol] = $this->
recPath($row[
'pid']);
945 }
elseif ($fCol ==
'_REF_') {
947 }
elseif ($fCol ==
'_CONTROL_') {
948 $theData[$fCol] = $this->
makeControl($table, $row);
949 }
elseif ($fCol ==
'_CLIPBOARD_') {
950 $theData[$fCol] = $this->
makeClip($table, $row);
951 }
elseif ($fCol ==
'_LOCALIZATION_') {
953 $theData[$fCol] = $lC1;
954 $theData[$fCol .
'b'] =
'<div class="btn-group">' . $lC2 .
'</div>';
955 }
elseif ($fCol ==
'_LOCALIZATION_b') {
958 $pageId = $table ===
'pages' ? $row[
'uid'] : $row[
'pid'];
960 $theData[$fCol] = $this->
linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
961 if ($this->csvOutput) {
967 if ((
string)$this->searchString !==
'') {
968 $this->
id = $id_orig;
971 if ($this->csvOutput) {
975 $this->addElement_tdCssClass[$titleCol] =
'col-title' . $localizationMarkerClass;
976 $this->addElement_tdCssClass[
'_CONTROL_'] =
'col-control';
977 if ($this->
getModule()->MOD_SETTINGS[
'clipBoard']) {
978 $this->addElement_tdCssClass[
'_CLIPBOARD_'] =
'col-clipboard';
980 $this->addElement_tdCssClass[
'_PATH_'] =
'col-path';
981 $this->addElement_tdCssClass[
'_LOCALIZATION_'] =
'col-localizationa';
982 $this->addElement_tdCssClass[
'_LOCALIZATION_b'] =
'col-localizationb';
984 $theData[
'uid'] = $row[
'uid'];
985 if (isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField'])
986 && isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField'])
987 && !isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerTable'])
989 $theData[
'parent'] = $row[
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField']];
991 $rowOutput .= $this->
addElement(1, $theIcon, $theData, $row_bgColor);
1007 if (!isset($this->referenceCount[$tableName][$uid])) {
1008 $where =
'ref_table = ' . $db->fullQuoteStr($tableName,
'sys_refindex')
1009 .
' AND ref_uid = ' . $uid .
' AND deleted = 0';
1010 $numberOfReferences = $db->exec_SELECTcountRows(
'*',
'sys_refindex', $where);
1011 $this->referenceCount[$tableName][$uid] = $numberOfReferences;
1013 return $this->referenceCount[$tableName][$uid];
1033 foreach ($this->fieldArray as $fCol) {
1036 switch ((
string)$fCol) {
1039 $theData[$fCol] =
'<i>[' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels._PATH_',
true) .
']</i>';
1043 $theData[$fCol] =
'<i>[' .
$lang->sL(
'LLL:EXT:lang/locallang_mod_file_list.xlf:c__REF_',
true) .
']</i>';
1045 case '_LOCALIZATION_':
1047 $theData[$fCol] =
'<i>[' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels._LOCALIZATION_',
true) .
']</i>';
1049 case '_LOCALIZATION_b':
1051 $theData[$fCol] =
$lang->getLL(
'Localize',
true);
1054 if (!$this->
getModule()->MOD_SETTINGS[
'clipBoard']) {
1061 $elFromTable = $this->clipObj->elFromTable($table);
1063 $href = htmlspecialchars($this->clipObj->pasteUrl($table, $this->id));
1064 $onClick = htmlspecialchars(
'return ' . $this->clipObj->confirmMsg(
'pages', $this->pageRow,
'into', $elFromTable));
1065 $cells[
'pasteAfter'] =
'<a class="btn btn-default" href="' . $href .
'" onclick="' . $onClick
1066 .
'" title="' .
$lang->getLL(
'clip_paste',
true) .
'">'
1067 . $this->iconFactory->getIcon(
'actions-document-paste-after',
Icon::SIZE_SMALL)->render() .
'</a>';
1070 if ($this->clipObj->current !=
'normal') {
1072 $spriteIcon =
'<span title="' .
$lang->getLL(
'clip_selectMarked',
true) .
'">'
1073 . $this->iconFactory->getIcon(
'actions-edit-copy',
Icon::SIZE_SMALL)->render()
1077 $editIdList = implode(
',', $currentIdList);
1078 $editIdList =
'\'+editList(\
'' . $table .
'\',\
'' . $editIdList .
'\')+\
'';
1079 $params =
'edit[' . $table .
'][' . $editIdList .
']=edit';
1081 $onClickArray = explode(
'?', $onClick, 2);
1082 $lastElement = array_pop($onClickArray);
1083 array_push($onClickArray, $params .
'&' . $lastElement);
1084 $onClick = implode(
'?', $onClickArray);
1085 $cells[
'edit'] =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) .
'" title="'
1086 .
$lang->getLL(
'clip_editMarked',
true) .
'">'
1087 . $this->iconFactory->getIcon(
'actions-document-open',
Icon::SIZE_SMALL)->render() .
'</a>';
1090 '<span title="' .
$lang->getLL(
'clip_deleteMarked',
true) .
'">' . $this->iconFactory->getIcon(
'actions-edit-delete',
Icon::SIZE_SMALL)->render() .
'</span>',
1093 sprintf(
$lang->getLL(
'clip_deleteMarkedWarning'),
$lang->sL(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'title']))
1096 $onClick = htmlspecialchars((
'checkOffCB(\'' . implode(
',', $this->CBnames) .
'\',
this);
return false;
'));
1097 $cells['markAll
'] = '<a
class=
"btn btn-default" rel=
"" href=
"#" onclick=
"' . $onClick . '" title=
"'
1098 . $lang->getLL('clip_markRecords', true) . '">
'
1099 . $this->iconFactory->getIcon('actions-document-select
', Icon::SIZE_SMALL)->render() . '</a>
';
1101 $cells['empty
'] = '';
1110 if (is_array($GLOBALS['TYPO3_CONF_VARS
']['SC_OPTIONS
']['typo3/
class.db_list_extra.inc
']['actions
'])) {
1111 foreach ($GLOBALS['TYPO3_CONF_VARS
']['SC_OPTIONS
']['typo3/
class.db_list_extra.inc
']['actions
'] as $classData) {
1112 $hookObject = GeneralUtility::getUserObj($classData);
1113 if (!$hookObject instanceof RecordListHookInterface) {
1114 throw new \UnexpectedValueException('$hookObject must implement
interface ' . RecordListHookInterface::class, 1195567850);
1116 $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this);
1119 $theData[$fCol] =
'<div class="btn-group" role="group">' . implode(
'', $cells) .
'</div>';
1125 $permsAdditional = ($table ===
'pages' ? 8 : 16);
1126 if ($this->calcPerms & $permsAdditional && $this->
showNewRecLink($table)) {
1127 $spriteIcon = $table ===
'pages'
1130 if ($table ===
'tt_content' && $this->newWizards) {
1133 $newContentElementWizard = $tmpTSc[
'properties'][
'newContentElementWizard.'][
'override'] ?:
'new_content_element';
1134 $newContentWizScriptPath = BackendUtility::getModuleUrl($newContentElementWizard, array(
'id' => $this->
id));
1137 $icon =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) .
'" title="'
1138 .
$lang->getLL(
'new',
true) .
'">' . $spriteIcon->render() .
'</a>';
1139 }
elseif ($table ==
'pages' && $this->newWizards) {
1141 $href = BackendUtility::getModuleUrl(
'db_new', $parameters);
1142 $icon =
'<a class="btn btn-default" href="' . htmlspecialchars($href) .
'" title="' .
$lang->getLL(
'new',
true) .
'">'
1143 . $spriteIcon->render() .
'</a>';
1145 $params =
'&edit[' . $table .
'][' . $this->
id .
']=new';
1146 if ($table ==
'pages_language_overlay') {
1147 $params .=
'&overrideVals[pages_language_overlay][doktype]=' . (int)$this->pageRow[
'doktype'];
1150 .
'" title="' .
$lang->getLL(
'new',
true) .
'">' . $spriteIcon->render() .
'</a>';
1154 if ($permsEdit && $this->table && is_array($currentIdList)) {
1155 $editIdList = implode(
',', $currentIdList);
1157 $editIdList =
'\'+editList(\
'' . $table .
'\',\
'' . $editIdList .
'\')+\
'';
1159 $params =
'edit[' . $table .
'][' . $editIdList .
']=edit&columnsOnly=' . implode(
',', $this->fieldArray);
1162 $onClickArray = explode(
'?', $onClick, 2);
1163 $lastElement = array_pop($onClickArray);
1164 array_push($onClickArray, $params .
'&' . $lastElement);
1165 $onClick = implode(
'?', $onClickArray);
1166 $icon .=
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick)
1167 .
'" title="' .
$lang->getLL(
'editShownColumns',
true) .
'">'
1168 . $this->iconFactory->getIcon(
'actions-document-open',
Icon::SIZE_SMALL)->render() .
'</a>';
1169 $icon =
'<div class="btn-group" role="group">' . $icon .
'</div>';
1172 $theData[$fCol] =
' ';
1177 $theData[$fCol] =
'';
1182 if ($sortLabel !== null) {
1183 $sortLabel =
$lang->sL($sortLabel,
true);
1184 $sortLabel = rtrim(trim($sortLabel),
':');
1187 $sortLabel = htmlspecialchars($fCol);
1188 $sortLabel =
'<i>[' . rtrim(trim($sortLabel),
':') .
']</i>';
1191 if ($this->table && is_array($currentIdList)) {
1194 $theData[$fCol] .=
'<a class="btn btn-default" href="' . htmlspecialchars($this->
listURL(
'', -1) .
'&duplicateField=' . $fCol)
1195 .
'" title="' .
$lang->getLL(
'clip_duplicates',
true) .
'">'
1196 . $this->iconFactory->getIcon(
'actions-document-duplicates-select',
Icon::SIZE_SMALL)->render() .
'</a>';
1200 if ($this->
isEditable($table) && $permsEdit &&
$GLOBALS[
'TCA'][$table][
'columns'][$fCol]) {
1201 $editIdList = implode(
',', $currentIdList);
1203 $editIdList =
'\'+editList(\
'' . $table .
'\',\
'' . $editIdList .
'\')+\
'';
1205 $params =
'edit[' . $table .
'][' . $editIdList .
']=edit&columnsOnly=' . $fCol;
1208 $onClickArray = explode(
'?', $onClick, 2);
1209 $lastElement = array_pop($onClickArray);
1210 array_push($onClickArray, $params .
'&' . $lastElement);
1211 $onClick = implode(
'?', $onClickArray);
1212 $iTitle = sprintf(
$lang->getLL(
'editThisColumn'), $sortLabel);
1213 $theData[$fCol] .=
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick)
1214 .
'" title="' . htmlspecialchars($iTitle) .
'">'
1215 . $this->iconFactory->getIcon(
'actions-document-open',
Icon::SIZE_SMALL)->render() .
'</a>';
1217 if (strlen($theData[$fCol]) > 0) {
1218 $theData[$fCol] =
'<div class="btn-group" role="group">' . $theData[$fCol] .
'</div> ';
1221 $theData[$fCol] .= $this->
addSortLink($sortLabel, $fCol, $table);
1230 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'])) {
1231 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] as $classData) {
1233 if (!$hookObject instanceof RecordListHookInterface) {
1234 throw new \UnexpectedValueException(
'$hookObject must implement interface ' . RecordListHookInterface::class, 1195567855);
1236 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this);
1242 return '<thead>' . $this->addElement(1, $icon, $theData,
'',
'',
'',
'th') .
'</thead>';
1251 protected function getPointerForPage($page)
1253 return ($page - 1) * $this->iLimit;
1262 protected function renderListNavigation($renderPart =
'top')
1264 $totalPages = ceil($this->totalItems / $this->iLimit);
1266 if ($totalPages <= 1) {
1270 $listURL = $this->listURL(
'', $this->table);
1273 $currentPage = floor($this->firstElementNumber / $this->iLimit) + 1;
1275 if ($currentPage > 1) {
1276 $labelFirst = $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:first',
true);
1277 $labelPrevious = $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:previous',
true);
1278 $first =
'<li><a href="' . $listURL .
'&pointer=' . $this->getPointerForPage(1) .
'" title="' . $labelFirst .
'">'
1279 . $this->iconFactory->getIcon(
'actions-view-paging-first', Icon::SIZE_SMALL)->render() .
'</a></li>';
1280 $previous =
'<li><a href="' . $listURL .
'&pointer=' . $this->getPointerForPage($currentPage - 1) .
'" title="' . $labelPrevious .
'">'
1281 . $this->iconFactory->getIcon(
'actions-view-paging-previous', Icon::SIZE_SMALL)->render() .
'</a></li>';
1283 $first =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-first', Icon::SIZE_SMALL)->render() .
'</span></li>';
1284 $previous =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-previous', Icon::SIZE_SMALL)->render() .
'</span></li>';
1286 if ($currentPage < $totalPages) {
1287 $labelNext = $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:next',
true);
1288 $labelLast = $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:last',
true);
1289 $next =
'<li><a href="' . $listURL .
'&pointer=' . $this->getPointerForPage($currentPage + 1) .
'" title="' . $labelNext .
'">'
1290 . $this->iconFactory->getIcon(
'actions-view-paging-next', Icon::SIZE_SMALL)->render() .
'</a></li>';
1291 $last =
'<li><a href="' . $listURL .
'&pointer=' . $this->getPointerForPage($totalPages) .
'" title="' . $labelLast .
'">'
1292 . $this->iconFactory->getIcon(
'actions-view-paging-last', Icon::SIZE_SMALL)->render() .
'</a></li>';
1294 $next =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-next', Icon::SIZE_SMALL)->render() .
'</span></li>';
1295 $last =
'<li class="disabled"><span>' . $this->iconFactory->getIcon(
'actions-view-paging-last', Icon::SIZE_SMALL)->render() .
'</span></li>';
1297 $reload =
'<li><a href="#" onclick="document.dblistForm.action=\'' . $listURL
1298 .
'&pointer=\'+calculatePointer(document.getElementById(\'jumpPage-' . $renderPart
1299 .
'\').value); document.dblistForm.submit();
return true;
" title="'
1300 . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:reload
', true) . '">'
1301 . $this->iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL)->render() . '</a></li>';
1302 if ($renderPart === 'top') {
1303 // Add js to traverse a page select input to a pointer value
1305 <script type="text/javascript
">
1307 function calculatePointer(page) {
1308 if (page > ' . $totalPages . ') {
1309 page = ' . $totalPages . ';
1314 return (page - 1) * ' . $this->iLimit . ';
1320 $pageNumberInput = '
1321 <input type="text
" value="' . $currentPage . '" size="3
" class="form-control input-sm paginator-input
" id="jumpPage-
' . $renderPart . '" name="jumpPage-
'
1322 . $renderPart . '" onkeyup="if (event.keyCode == 13) { document.dblistForm.action=\
'' . $listURL
1323 .
'&pointer=\'+calculatePointer(this.value); document.dblistForm.submit(); } return true;" />
1325 $pageIndicatorText = sprintf(
1326 $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_mod_web_list.xlf:pageIndicator'),
1330 $pageIndicator =
'<li><span>' . $pageIndicatorText .
'</span></li>';
1331 if ($this->totalItems > $this->firstElementNumber + $this->iLimit) {
1332 $lastElementNumber = $this->firstElementNumber + $this->iLimit;
1334 $lastElementNumber = $this->totalItems;
1336 $rangeIndicator =
'<li><span>' . sprintf($this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_mod_web_list.xlf:rangeIndicator'), ($this->firstElementNumber + 1), $lastElementNumber) .
'</span></li>';
1338 $titleColumn = $this->fieldArray[0];
1340 $titleColumn => $content .
'
1341 <nav class="pagination-wrap">
1342 <ul class="pagination pagination-block">
1345 ' . $rangeIndicator .
'
1346 ' . $pageIndicator .
'
1354 return $this->addElement(1,
'', $data);
1371 public function makeControl($table, $row)
1373 $module = $this->getModule();
1374 $rowUid = $row[
'uid'];
1375 if (ExtensionManagementUtility::isLoaded(
'version') && isset($row[
'_ORIG_uid'])) {
1376 $rowUid = $row[
'_ORIG_uid'];
1379 'primary' => array(),
1380 'secondary' => array()
1383 $localCalcPerms = 0;
1384 if ($table ==
'pages') {
1385 $localCalcPerms = $this->getBackendUserAuthentication()->calcPerms(BackendUtility::getRecord(
'pages', $row[
'uid']));
1387 $permsEdit = $table ===
'pages' && $localCalcPerms & Permission::PAGE_EDIT || $table !==
'pages' && $this->calcPerms & Permission::CONTENT_EDIT;
1388 $permsEdit = $this->overlayEditLockPermissions($table, $row, $permsEdit);
1390 if ($table ==
'pages' || $table ==
'tt_content') {
1391 $viewAction =
'<a class="btn btn-default" href="#" onclick="'
1393 BackendUtility::viewOnClick(
1394 ($table ===
'tt_content' ? $this->
id : $row[
'uid']),
1397 ($table ===
'tt_content' ?
'#' . $row[
'uid'] :
'')
1399 ) .
'" title="' . $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.showPage',
true) .
'">'
1400 . $this->iconFactory->getIcon(
'actions-view', Icon::SIZE_SMALL)->render() .
'</a>';
1401 $this->addActionToCellGroup($cells, $viewAction,
'view');
1405 $params =
'&edit[' . $table .
'][' . $row[
'uid'] .
']=edit';
1406 $iconIdentifier =
'actions-open';
1407 $overlayIdentifier = !$this->isEditable($table) ?
'overlay-readonly' : null;
1408 $editAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params,
'', -1))
1409 .
'" title="' . $this->getLanguageService()->getLL(
'edit',
true) .
'">' . $this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL, $overlayIdentifier)->render() .
'</a>';
1411 $editAction = $this->spaceIcon;
1413 $this->addActionToCellGroup($cells, $editAction,
'edit');
1415 $onClick =
'top.launchView(\'' . $table .
'\', \
'' . $row[
'uid'] .
'\');
return false;
';
1416 $viewBigAction = '<a
class=
"btn btn-default" href=
"#" onclick=
"' . htmlspecialchars($onClick) . '" title=
"' . $this->getLanguageService()->getLL('showInfo', true) . '">
'
1417 . $this->iconFactory->getIcon('actions-document-info
', Icon::SIZE_SMALL)->render() . '</a>
';
1418 $this->addActionToCellGroup($cells, $viewBigAction, 'viewBig
');
1419 // "Move" wizard link for pages/tt_content elements:
1420 if ($permsEdit && ($table === 'tt_content
' || $table === 'pages
')) {
1421 $onClick = 'return jumpExt(\
'' . BackendUtility::getModuleUrl(
'move_element') .
'&table=' . $table .
'&uid=' . $row[
'uid'] .
'\');
';
1422 $linkTitleLL = $this->getLanguageService()->getLL('move_
' . ($table === 'tt_content
' ? 'record
' : 'page
'), true);
1423 $icon = ($table == 'pages
' ? $this->iconFactory->getIcon('actions-page-move
', Icon::SIZE_SMALL) : $this->iconFactory->getIcon('actions-document-move
', Icon::SIZE_SMALL));
1424 $moveAction = '<a
class=
"btn btn-default" href=
"#" onclick=
"' . htmlspecialchars($onClick) . '" title=
"' . $linkTitleLL . '">
' . $icon->render() . '</a>
';
1425 $this->addActionToCellGroup($cells, $moveAction, 'move
');
1427 // If the table is NOT a read-only table, then show these links:
1428 if ($this->isEditable($table)) {
1429 // "Revert" link (history/undo)
1430 $moduleUrl = BackendUtility::getModuleUrl('record_history
', array('element
' => $table . ':
' . $row['uid
']));
1431 $onClick = 'return jumpExt(
' . GeneralUtility::quoteJSvalue($moduleUrl) . ',\
'#latest\');';
1432 $historyAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) .
'" title="'
1433 . $this->getLanguageService()->getLL(
'history',
true) .
'">'
1434 . $this->iconFactory->getIcon(
'actions-document-history-open', Icon::SIZE_SMALL)->render() .
'</a>';
1435 $this->addActionToCellGroup($cells, $historyAction,
'history');
1437 if (ExtensionManagementUtility::isLoaded(
'version') && !ExtensionManagementUtility::isLoaded(
'workspaces')) {
1438 $vers = BackendUtility::selectVersionsOfRecord($table, $row[
'uid'],
'uid', $this->getBackendUserAuthentication()->workspace,
false, $row);
1440 if (is_array($vers)) {
1441 $href = BackendUtility::getModuleUrl(
'web_txversionM1', array(
1442 'table' => $table,
'uid' => $row[
'uid']
1444 $versionAction =
'<a class="btn btn-default" href="' . htmlspecialchars($href) .
'" title="'
1445 . $this->getLanguageService()->getLL(
'displayVersions',
true) .
'">'
1446 . $this->iconFactory->getIcon(
'actions-version-page-open', Icon::SIZE_SMALL)->render() .
'</a>';
1447 $this->addActionToCellGroup($cells, $versionAction,
'version');
1451 if ($table ===
'pages' && $this->getBackendUserAuthentication()->check(
'modules',
'system_BeuserTxPermission') && ExtensionManagementUtility::isLoaded(
'beuser')) {
1452 $href = BackendUtility::getModuleUrl(
'system_BeuserTxPermission') .
'&id=' . $row[
'uid'] .
'&return_id=' . $row[
'uid'] .
'&edit=1';
1453 $permsAction =
'<a class="btn btn-default" href="' . htmlspecialchars($href) .
'" title="'
1454 . $this->getLanguageService()->getLL(
'permissions',
true) .
'">'
1455 . $this->iconFactory->getIcon(
'status-status-locked', Icon::SIZE_SMALL)->render() .
'</a>';
1456 $this->addActionToCellGroup($cells, $permsAction,
'perms');
1460 if ((
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby'] ||
$GLOBALS[
'TCA'][$table][
'ctrl'][
'useColumnsForDefaultValues']) && $permsEdit) {
1461 if ($table !==
'pages' && $this->calcPerms & Permission::CONTENT_EDIT || $table ===
'pages' && $this->calcPerms & Permission::PAGE_NEW) {
1462 if ($this->showNewRecLink($table)) {
1463 $params =
'&edit[' . $table .
'][' . -($row[
'_MOVE_PLH'] ? $row[
'_MOVE_PLH_uid'] : $row[
'uid']) .
']=new';
1464 $icon = ($table ==
'pages' ? $this->iconFactory->getIcon(
'actions-page-new', Icon::SIZE_SMALL) : $this->iconFactory->getIcon(
'actions-add', Icon::SIZE_SMALL));
1465 $newAction =
'<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params,
'', -1))
1466 .
'" title="' . $this->getLanguageService()->getLL(
'new' . ($table ==
'pages ' ?
'Page' :
'Record'),
true) .
'">'
1467 . $icon->render() .
'</a>';
1468 $this->addActionToCellGroup($cells, $newAction,
'new');
1473 if ($permsEdit &&
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby'] && !$this->sortField && !$this->searchLevels) {
1474 if (isset($this->currentTable[
'prev'][$row[
'uid']])) {
1476 $params =
'&cmd[' . $table .
'][' . $row[
'uid'] .
'][move]=' . $this->currentTable[
'prev'][$row[
'uid']];
1477 $moveUpAction =
'<a class="btn btn-default" href="#" onclick="'
1478 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
1479 .
'" title="' . $this->getLanguageService()->getLL(
'moveUp',
true) .
'">'
1480 . $this->iconFactory->getIcon(
'actions-move-up', Icon::SIZE_SMALL)->render() .
'</a>';
1482 $moveUpAction = $this->spaceIcon;
1484 $this->addActionToCellGroup($cells, $moveUpAction,
'moveUp');
1486 if ($this->currentTable[
'next'][$row[
'uid']]) {
1488 $params =
'&cmd[' . $table .
'][' . $row[
'uid'] .
'][move]=' . $this->currentTable[
'next'][$row[
'uid']];
1489 $moveDownAction =
'<a class="btn btn-default" href="#" onclick="'
1490 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
1491 .
'" title="' . $this->getLanguageService()->getLL(
'moveDown',
true) .
'">'
1492 . $this->iconFactory->getIcon(
'actions-move-down', Icon::SIZE_SMALL)->render() .
'</a>';
1494 $moveDownAction = $this->spaceIcon;
1496 $this->addActionToCellGroup($cells, $moveDownAction,
'moveDown');
1499 $hiddenField =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns'][
'disabled'];
1502 $permsEdit && $hiddenField &&
$GLOBALS[
'TCA'][$table][
'columns'][$hiddenField]
1503 && (!
$GLOBALS[
'TCA'][$table][
'columns'][$hiddenField][
'exclude']
1504 || $this->getBackendUserAuthentication()->check(
'non_exclude_fields', $table .
':' . $hiddenField))
1506 if ($this->isRecordCurrentBackendUser($table, $row)) {
1507 $hideAction = $this->spaceIcon;
1509 $hideTitle = $this->getLanguageService()->getLL(
'hide' . ($table ==
'pages' ?
'Page' :
''),
true);
1510 $unhideTitle = $this->getLanguageService()->getLL(
'unHide' . ($table ==
'pages' ?
'Page' :
''),
true);
1511 if ($row[$hiddenField]) {
1512 $params =
'data[' . $table .
'][' . $rowUid .
'][' . $hiddenField .
']=0';
1513 $hideAction =
'<a class="btn btn-default t3js-record-hide" data-state="hidden" href="#"'
1514 .
' data-params="' . htmlspecialchars($params) .
'"'
1515 .
' title="' . $unhideTitle .
'"'
1516 .
' data-toggle-title="' . $hideTitle .
'">'
1517 . $this->iconFactory->getIcon(
'actions-edit-unhide', Icon::SIZE_SMALL)->render() .
'</a>';
1519 $params =
'data[' . $table .
'][' . $rowUid .
'][' . $hiddenField .
']=1';
1520 $hideAction =
'<a class="btn btn-default t3js-record-hide" data-state="visible" href="#"'
1521 .
' data-params="' . htmlspecialchars($params) .
'"'
1522 .
' title="' . $hideTitle .
'"'
1523 .
' data-toggle-title="' . $unhideTitle .
'">'
1524 . $this->iconFactory->getIcon(
'actions-edit-hide', Icon::SIZE_SMALL)->render() .
'</a>';
1527 $this->addActionToCellGroup($cells, $hideAction,
'hide');
1530 if ($permsEdit && ($table ===
'pages' && $localCalcPerms & Permission::PAGE_DELETE || $table !==
'pages' && $this->calcPerms & Permission::CONTENT_EDIT)) {
1532 if ($this->getBackendUserAuthentication()->workspace > 0 && isset($row[
't3ver_state']) && (
int)$row[
't3ver_state'] === 2) {
1533 $actionName =
'restore';
1536 $actionName =
'delete';
1537 $refCountMsg = BackendUtility::referenceCount(
1540 ' ' . $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.referencesToRecord'),
1541 $this->getReferenceCount($table, $row[
'uid'])) . BackendUtility::translationCount($table, $row[
'uid'],
1542 ' ' . $this->getLanguageService()->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord')
1546 if ($this->isRecordCurrentBackendUser($table, $row)) {
1547 $deleteAction = $this->spaceIcon;
1549 $titleOrig = BackendUtility::getRecordTitle($table, $row,
false,
true);
1550 $title = GeneralUtility::slashJS(GeneralUtility::fixed_lgd_cs($titleOrig, $this->fixedL),
true);
1551 $warningText = $this->getLanguageService()->getLL($actionName .
'Warning') .
' "' . $title .
'" ' .
'[' . $table .
':' . $row[
'uid'] .
']' . $refCountMsg;
1553 $params =
'cmd[' . $table .
'][' . $row[
'uid'] .
'][delete]=1';
1554 $icon = $this->iconFactory->getIcon(
'actions-edit-' . $actionName, Icon::SIZE_SMALL)->render();
1555 $linkTitle = $this->getLanguageService()->getLL($actionName,
true);
1556 $deleteAction =
'<a class="btn btn-default t3js-record-delete" href="#" '
1557 .
' data-l10parent="' . htmlspecialchars($row[
'l10n_parent']) .
'"'
1558 .
' data-params="' . htmlspecialchars($params) .
'" data-title="' . htmlspecialchars($titleOrig) .
'"'
1559 .
' data-message="' . htmlspecialchars($warningText) .
'" title="' . $linkTitle .
'"'
1560 .
'>' . $icon .
'</a>';
1563 $deleteAction = $this->spaceIcon;
1565 $this->addActionToCellGroup($cells, $deleteAction,
'delete');
1567 if ($permsEdit && $table ==
'pages' && !$this->searchLevels) {
1569 if ($this->calcPerms & Permission::PAGE_NEW) {
1570 $params =
'&cmd[' . $table .
'][' . $row[
'uid'] .
'][move]=' . -$this->id;
1571 $moveLeftAction =
'<a class="btn btn-default" href="#" onclick="'
1572 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
1573 .
'" title="' . $this->getLanguageService()->getLL(
'prevLevel',
true) .
'">'
1574 . $this->iconFactory->getIcon(
'actions-move-left', Icon::SIZE_SMALL)->render() .
'</a>';
1575 $this->addActionToCellGroup($cells, $moveLeftAction,
'moveLeft');
1578 if ($this->currentTable[
'prevUid'][$row[
'uid']]) {
1579 $localCalcPerms = $this->getBackendUserAuthentication()->calcPerms(BackendUtility::getRecord(
'pages', $this->currentTable[
'prevUid'][$row[
'uid']]));
1580 if ($localCalcPerms & Permission::PAGE_NEW) {
1581 $params =
'&cmd[' . $table .
'][' . $row[
'uid'] .
'][move]=' . $this->currentTable[
'prevUid'][$row[
'uid']];
1582 $moveRightAction =
'<a class="btn btn-default" href="#" onclick="'
1583 . htmlspecialchars(
'return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) .
');')
1584 .
'" title="' . $this->getLanguageService()->getLL(
'nextLevel',
true) .
'">'
1585 . $this->iconFactory->getIcon(
'actions-move-right', Icon::SIZE_SMALL)->render() .
'</a>';
1587 $moveRightAction = $this->spaceIcon;
1590 $moveRightAction = $this->spaceIcon;
1592 $this->addActionToCellGroup($cells, $moveRightAction,
'moveRight');
1598 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'GLOBAL'][
'recStatInfoHooks'])) {
1600 $_params = array($table, $row[
'uid']);
1601 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'GLOBAL'][
'recStatInfoHooks'] as $_funcRef) {
1602 $stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1604 $this->addActionToCellGroup($cells, $stat,
'stat');
1613 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'])) {
1616 foreach ($cells as $section => $actions) {
1617 foreach ($actions as $actionKey => $action) {
1618 $cells[$actionKey] = $action;
1621 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list_extra.inc'][
'actions'] as $classData) {
1622 $hookObject = GeneralUtility::getUserObj($classData);
1623 if (!$hookObject instanceof RecordListHookInterface) {
1624 throw new \UnexpectedValueException(
'$hookObject must implement interface ' . RecordListHookInterface::class, 1195567840);
1626 $cells = $hookObject->makeControl($table, $row, $cells, $this);
1630 $hookCells = $cells;
1631 foreach ($hookCells as $key => $value) {
1632 if ($key ===
'primary' || $key ===
'secondary') {
1635 $this->addActionToCellGroup($cells, $value, $key);
1638 $output =
'<!-- CONTROL PANEL: ' . $table .
':' . $row[
'uid'] .
' -->';
1639 foreach ($cells as $classification => $actions) {
1640 $visibilityClass = ($classification !==
'primary' && !$module->MOD_SETTINGS[
'bigControlPanel'] ?
'collapsed' :
'expanded');
1641 if ($visibilityClass ===
'collapsed') {
1643 foreach ($actions as $action) {
1644 $cellOutput .= $action;
1646 $output .=
' <div class="btn-group">' .
1647 '<span id="actions_' . $table .
'_' . $row[
'uid'] .
'" class="btn-group collapse collapse-horizontal width">' . $cellOutput .
'</span>' .
1648 '<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>' .
1651 $output .=
' <div class="btn-group" role="group">' . implode(
'', $actions) .
'</div>';
1665 public function makeClip($table, $row)
1668 if (!$this->getModule()->MOD_SETTINGS[
'clipBoard']) {
1672 $cells[
'pasteAfter'] = ($cells[
'pasteInto'] = $this->spaceIcon);
1674 $isL10nOverlay = $this->localizationView && $table !=
'pages_language_overlay' && $row[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField']] != 0;
1678 if ($this->clipObj->current ===
'normal') {
1680 $isSel = (string)$this->clipObj->isSelected($table, $row[
'uid']);
1681 if ($isL10nOverlay || !$this->overlayEditLockPermissions($table, $row)) {
1682 $cells[
'copy'] = $this->spaceIcon;
1683 $cells[
'cut'] = $this->spaceIcon;
1685 $copyIcon = $this->iconFactory->getIcon(
'actions-edit-copy', Icon::SIZE_SMALL);
1686 $cutIcon = $this->iconFactory->getIcon(
'actions-edit-cut', Icon::SIZE_SMALL);
1688 if ($isSel ===
'copy') {
1689 $copyIcon = $this->iconFactory->getIcon(
'actions-edit-copy-release', Icon::SIZE_SMALL);
1690 }
elseif ($isSel ===
'cut') {
1691 $cutIcon = $this->iconFactory->getIcon(
'actions-edit-cut-release', Icon::SIZE_SMALL);
1694 $cells[
'copy'] =
'<a class="btn btn-default" href="#" onclick="'
1695 . htmlspecialchars(
'return jumpSelf(\'' . $this->clipObj->selUrlDB($table, $row[
'uid'], 1, ($isSel ===
'copy'), array(
'returnUrl' =>
'')) .
'\');
')
1696 . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:cm.copy
', true) . '">'
1697 . $copyIcon->render() . '</a>';
1699 $cells['cut'] = '<a class="btn btn-
default" href="#
" onclick="'
1700 . htmlspecialchars('return jumpSelf(\
'' . $this->clipObj->selUrlDB($table, $row[
'uid'], 0, ($isSel ===
'cut'), array(
'returnUrl' =>
'')) .
'\');
')
1701 . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:cm.cut
', true) . '">'
1702 . $cutIcon->render() . '</a>';
1704 $cells['cut'] = $this->spaceIcon;
1708 // For the numeric clipboard pads (showing checkboxes where one can select elements on/off)
1709 // Setting name of the element in ->CBnames array:
1710 $n = $table . '|' . $row['uid'];
1711 $this->CBnames[] = $n;
1712 // Check if the current element is selected and if so, prepare to set the checkbox as selected:
1713 $checked = $this->clipObj->isSelected($table, $row['uid']) ? 'checked="checked
" ' : '';
1714 // If the "duplicateField
" value is set then select all elements which are duplicates...
1715 if ($this->duplicateField && isset($row[$this->duplicateField])) {
1717 if (in_array($row[$this->duplicateField], $this->duplicateStack)) {
1718 $checked = 'checked="checked
" ';
1720 $this->duplicateStack[] = $row[$this->duplicateField];
1722 // Adding the checkbox to the panel:
1723 $cells['select'] = $isL10nOverlay
1725 : '<input type="hidden
" name="CBH[
' . $n . ']
" value="0
" /><label class="btn btn-
default btn-checkbox
"><input type="checkbox
"'
1726 . ' name="CBC[
' . $n . ']
" value="1
" ' . $checked . '/><span class="t3-icon fa
"></span></label>';
1728 // Now, looking for selected elements from the current table:
1729 $elFromTable = $this->clipObj->elFromTable($table);
1730 if (!empty($elFromTable) && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
1731 // IF elements are found, they can be individually ordered and are not locked by editlock, then add a "paste after
" icon:
1732 $cells['pasteAfter'] = $isL10nOverlay || !$this->overlayEditLockPermissions($table, $row)
1734 : '<a class="btn btn-
default" href="' . htmlspecialchars($this->clipObj->pasteUrl($table, -$row['uid
'])) . '" onclick="'
1735 . htmlspecialchars(('return ' . $this->clipObj->confirmMsg($table, $row, 'after
', $elFromTable)))
1736 . '" title="' . $this->getLanguageService()->getLL('clip_pasteAfter
', true) . '">'
1737 . $this->iconFactory->getIcon('actions-document-paste-after', Icon::SIZE_SMALL)->render() . '</a>';
1739 // Now, looking for elements in general:
1740 $elFromTable = $this->clipObj->elFromTable('');
1741 if ($table == 'pages' && !empty($elFromTable)) {
1742 $cells['pasteInto'] = '<a class="btn btn-
default" href="' . htmlspecialchars($this->clipObj->pasteUrl('', $row['uid
']))
1743 . '" onclick="' . htmlspecialchars('return ' . $this->clipObj->confirmMsg($table, $row, 'into
', $elFromTable))
1744 . '" title="' . $this->getLanguageService()->getLL('clip_pasteInto
', true) . '">'
1745 . $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render() . '</a>';
1754 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1755 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1756 $hookObject = GeneralUtility::getUserObj($classData);
1757 if (!$hookObject instanceof RecordListHookInterface) {
1758 throw new \UnexpectedValueException('$hookObject must implement interface ' . RecordListHookInterface::class, 1195567845);
1760 $cells = $hookObject->makeClip($table, $row, $cells, $this);
1763 // Compile items into a DIV-element:
1764 return '<!-- CLIPBOARD PANEL: ' . $table . ':' . $row['uid'] . ' -->
1765 <div class="btn-group
" role="group
">' . implode('', $cells) . '</div>';
1776 protected function createReferenceHtml($tableName, $uid)
1778 $db = $this->getDatabaseConnection();
1779 $referenceCount = $db->exec_SELECTcountRows(
1782 'ref_table = ' . $db->fullQuoteStr($tableName, 'sys_refindex') .
1783 ' AND ref_uid = ' . $uid . ' AND deleted = 0'
1785 return $this->generateReferenceToolTip($referenceCount, '\'' . $tableName . '\', \'' . $uid . '\'');
1795 public function makeLocalizationPanel($table, $row)
1801 // Reset translations
1802 $this->translations = array();
1804 // Language title and icon:
1805 $out[0] = $this->languageFlag($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]);
1806 // Guard clause so we can quickly return if a record is localized to "all languages
"
1807 // It should only be possible to localize a record off default (uid 0)
1808 // Reasoning: The Parent is for ALL languages... why overlay with a localization?
1809 if ((int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === -1) {
1813 $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList);
1814 if (is_array($translations)) {
1815 $this->translations = $translations['translations'];
1816 // Traverse page translations and add icon for each language that does NOT yet exist:
1818 foreach ($this->pageOverlays as $lUid_OnPage => $lsysRec) {
1819 if ($this->isEditable($table) && !isset($translations['translations'][$lUid_OnPage]) && $this->getBackendUserAuthentication()->checkLanguageAccess($lUid_OnPage)) {
1820 $url = $this->listURL();
1821 $href = BackendUtility::getLinkToDataHandlerAction(
1822 '&cmd[' . $table . '][' . $row['uid'] . '][localize]=' . $lUid_OnPage,
1823 $url . '&justLocalized=' . rawurlencode($table . ':' . $row['uid'] . ':' . $lUid_OnPage)
1825 $language = BackendUtility::getRecord('sys_language', $lUid_OnPage, 'title');
1826 if ($this->languageIconTitles[$lUid_OnPage]['flagIcon']) {
1827 $lC = $this->iconFactory->getIcon($this->languageIconTitles[$lUid_OnPage]['flagIcon'], Icon::SIZE_SMALL)->render();
1829 $lC = $this->languageIconTitles[$lUid_OnPage]['title'];
1831 $lC = '<a href="' . htmlspecialchars($href) . '" title="'
1832 . htmlspecialchars($language['title
']) . '" class="btn btn-
default">' . $lC . '</a> ';
1839 } elseif ($row['l18n_parent']) {
1840 $out[0] = ' ' . $out[0];
1852 public function fieldSelectBox($table, $formFields = true)
1854 $lang = $this->getLanguageService();
1856 $formElements = array('', '');
1858 $formElements = array('<form action="' . htmlspecialchars($this->listURL()) . '" method="post
" name="fieldSelectBox
">', '</form>');
1860 // Load already selected fields, if any:
1861 $setFields = is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
1862 // Request fields from table:
1863 $fields = $this->makeFieldList($table, false, true);
1864 // Add pseudo "control
" fields
1865 $fields[] = '_PATH_';
1866 $fields[] = '_REF_';
1867 $fields[] = '_LOCALIZATION_';
1868 $fields[] = '_CONTROL_';
1869 $fields[] = '_CLIPBOARD_';
1870 // Create a checkbox for each field:
1871 $checkboxes = array();
1872 $checkAllChecked = true;
1873 foreach ($fields as $fieldName) {
1874 // Determine, if checkbox should be checked
1875 if (in_array($fieldName, $setFields, true) || $fieldName === $this->fieldArray[0]) {
1876 $checked = ' checked="checked
"';
1878 $checkAllChecked = false;
1882 $fieldLabel = is_array($GLOBALS['TCA'][$table]['columns'][$fieldName])
1883 ? rtrim($lang->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label']), ':')
1885 $checkboxes[] = '<tr><td class="col-checkbox
"><input type="checkbox
" id="check-
' . $fieldName . '" name="displayFields[
'
1886 . $table . '][]
" value="' . $fieldName . '" ' . $checked
1887 . ($fieldName === $this->fieldArray[0] ? ' disabled="disabled
"' : '') . '></td><td class="col-title
">'
1888 . '<label class="label-block
" for="check-
' . $fieldName . '">' . htmlspecialchars($fieldLabel) . ' <span class="text-muted text-monospace
">[' . htmlspecialchars($fieldName) . ']</span></label></td></tr>';
1890 // Table with the field selector::
1891 $content = $formElements[0] . '
1892 <input type="hidden
" name="displayFields[
' . $table . '][]
" value="">
1893 <div class="table-fit table-scrollable
">
1894 <table border="0
" cellpadding="0
" cellspacing="0
" class="table table-transparent table-hover
">
1897 <th class="col-checkbox
" colspan="2
">
1898 <input type="checkbox
" class="checkbox checkAll
" ' . ($checkAllChecked ? ' checked="checked
"' : '') . '>
1903 ' . implode('', $checkboxes) . '
1907 <input type="submit
" name="search
" class="btn btn-
default" value="'
1908 . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.setFields
', true) . '"/>
1909 ' . $formElements[1];
1910 return '<div class="fieldSelectBox
">' . $content . '</div>';
1913 /*********************************
1917 *********************************/
1929 public function linkClipboardHeaderIcon($string, $table, $cmd, $warning = '')
1931 $onClickEvent = 'document.dblistForm.cmd.value=\'' . $cmd . '\';document.dblistForm.cmd_table.value=\''
1932 . $table . '\';document.dblistForm.submit();';
1934 $onClickEvent = 'if (confirm(' . GeneralUtility::quoteJSvalue($warning) . ')){' . $onClickEvent . '}';
1936 return '<a class="btn btn-
default" href="#
" onclick="' . htmlspecialchars(($onClickEvent . 'return false;
')) . '">' . $string . '</a>';
1944 public function clipNumPane()
1946 return in_array('_CLIPBOARD_', $this->fieldArray) && $this->clipObj->current != 'normal';
1959 public function addSortLink($code, $field, $table)
1961 // Certain circumstances just return string right away (no links):
1962 if ($field == '_CONTROL_' || $field == '_LOCALIZATION_' || $field == '_CLIPBOARD_' || $field == '_REF_' || $this->disableSingleTableView) {
1965 // If "_PATH_
" (showing record path) is selected, force sorting by pid field (will at least group the records!)
1966 if ($field == '_PATH_') {
1969 // Create the sort link:
1970 $sortUrl = $this->listURL('', -1, 'sortField,sortRev,table,firstElementNumber') . '&table=' . $table
1971 . '&sortField=' . $field . '&sortRev=' . ($this->sortRev || $this->sortField != $field ? 0 : 1);
1972 $sortArrow = $this->sortField === $field
1973 ? $this->iconFactory->getIcon('status-status-sorting-' . ($this->sortRev ? 'desc' : 'asc'), Icon::SIZE_SMALL)->render()
1975 // Return linked field:
1976 return '<a href="' . htmlspecialchars($sortUrl) . '">' . $code . $sortArrow . '</a>';
1987 public function recPath($pid)
1989 if (!isset($this->recPath_cache[$pid])) {
1990 $this->recPath_cache[$pid] = BackendUtility::getRecordPath($pid, $this->perms_clause, 20);
1992 return $this->recPath_cache[$pid];
2002 public function showNewRecLink($table)
2004 // No deny/allow tables are set:
2005 if (empty($this->allowedNewTables) && empty($this->deniedNewTables)) {
2008 return !in_array($table, $this->deniedNewTables)
2009 && (empty($this->allowedNewTables) || in_array($table, $this->allowedNewTables));
2019 public function makeReturnUrl()
2021 return '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'));
2024 /************************************
2026 * CSV related functions
2028 ************************************/
2034 protected function initCSV()
2036 $this->addHeaderRowToCSV();
2044 protected function addHeaderRowToCSV()
2046 // Add header row, control fields will be reduced inside addToCSV()
2047 $this->addToCSV(array_combine($this->fieldArray, $this->fieldArray));
2056 protected function addToCSV(array $row = array())
2058 $rowReducedByControlFields = self::removeControlFieldsFromFieldRow($row);
2059 $rowReducedToSelectedColumns = array_intersect_key($rowReducedByControlFields, array_flip($this->fieldArray));
2060 $this->setCsvRow($rowReducedToSelectedColumns);
2069 protected static function removeControlFieldsFromFieldRow(array $row = array())
2071 // Possible control fields in a list row
2072 $controlFields = array(
2080 return array_diff_key($row, array_flip($controlFields));
2089 public function setCsvRow($csvRow)
2091 $this->csvLines[] = GeneralUtility::csvValues($csvRow);
2101 public function outputCSV($prefix)
2103 // Setting filename:
2104 $filename = $prefix . '_' . date('dmy-Hi') . '.csv';
2105 // Creating output header:
2106 header('Content-Type: application/octet-stream');
2107 header('Content-Disposition: attachment; filename=' . $filename);
2108 // Cache-Control header is needed here to solve an issue with browser IE and
2109 // versions lower than 9. See for more information: http://support.microsoft.com/kb/323308
2110 header("Cache-Control:
''");
2111 // Printing the content of the CSV lines:
2112 echo implode(CRLF, $this->csvLines);
2124 public function addActionToCellGroup(&$cells, $action, $actionKey)
2128 'view', 'edit', 'hide', 'delete', 'stat'
2130 'secondary' => array(
2131 'viewBig', 'history', 'perms', 'new', 'move', 'moveUp', 'moveDown', 'moveLeft', 'moveRight', 'version'
2134 $classification = in_array($actionKey, $cellsMap['primary']) ? 'primary' : 'secondary';
2135 $cells[$classification][$actionKey] = $action;
2136 unset($cells[$actionKey]);
2146 protected function isRecordCurrentBackendUser($table, $row)
2148 return $table === 'be_users' && (int)$row['uid'] === $this->getBackendUserAuthentication()->user['uid'];
2154 public function setIsEditable($isEditable)
2156 $this->editable = $isEditable;
2164 public function isEditable($table)
2166 return $GLOBALS['TCA'][$table]['ctrl']['readOnly'] || $this->editable;
2179 protected function overlayEditLockPermissions($table, $row = array(), $editPermission = true)
2181 if ($editPermission && !$this->getBackendUserAuthentication()->isAdmin()) {
2182 // If no $row is submitted we only check for general edit lock of current page (except for table "pages
")
2184 return $table === 'pages' ? true : !$this->pageRow['editlock'];
2186 if (($table === 'pages' && $row['editlock']) || ($table !== 'pages' && $this->pageRow['editlock'])) {
2187 $editPermission = false;
2188 } elseif (isset($GLOBALS['TCA'][$table]['ctrl']['editlock']) && $row[$GLOBALS['TCA'][$table]['ctrl']['editlock']]) {
2189 $editPermission = false;
2192 return $editPermission;
2201 protected function editLockPermissions()
2203 return $this->getBackendUserAuthentication()->isAdmin() || !$this->pageRow['editlock'];
2209 protected function getDatabaseConnection()
2211 return $GLOBALS['TYPO3_DB'];
2217 protected function getModule()
2219 return $GLOBALS['SOBE'];
2225 protected function getDocumentTemplate()
2227 return $GLOBALS['TBE_TEMPLATE'];