352 $this->
id = (int)
$id;
357 $this->firstElementNumber =
$pointer;
358 $this->searchString = trim($search);
359 $this->searchLevels = (int)$levels;
373 $this->HTMLcode =
'';
375 if (isset($this->modTSconfig[
'properties'][
'itemsLimitPerTable'])) {
378 if (isset($this->modTSconfig[
'properties'][
'itemsLimitSingleTable'])) {
383 $this->perms_clause = $backendUser->getPagePermsClause(1);
385 if ($pidList = $backendUser->getTSConfigVal(
'options.hideRecords.pages')) {
386 if ($pidList = $db->cleanIntList($pidList)) {
387 $this->perms_clause .=
' AND pages.uid NOT IN (' . $pidList .
')';
391 $this->tablesCollapsed = is_array($backendUser->uc[
'moduleData'][
'list']) ? $backendUser->uc[
'moduleData'][
'list'] : array();
393 if (is_array($collapseOverride)) {
394 foreach ($collapseOverride as $collapseTable => $collapseValue) {
395 if (is_array(
$GLOBALS[
'TCA'][$collapseTable]) && ($collapseValue == 0 || $collapseValue == 1)) {
396 $this->tablesCollapsed[$collapseTable] = $collapseValue;
400 $backendUser->uc[
'moduleData'][
'list'] = $this->tablesCollapsed;
401 $backendUser->writeUC($backendUser->uc);
408 $allowedMounts = $this->getSearchableWebmounts($this->
id,
$searchLevels, $this->perms_clause);
409 $pidList = implode(
',', $db->cleanIntArray($allowedMounts));
410 $this->pidSelect =
'pid IN (' . $pidList .
')';
413 $this->pidSelect =
'1=1';
415 $this->pidSelect =
'pid=' . (int)
$id;
418 if ($this->localizationView) {
439 $tableNames = array_flip(array_keys(
$GLOBALS[
'TCA']));
440 foreach ($tableNames as $tableName => &$config) {
445 if ($this->table && $tableName !== $this->table
447 || !$backendUser->check(
'tables_select', $tableName)
455 $hideTable = $hideTable || !empty(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'hideTable']) || in_array($tableName, $hideTablesArray,
true);
457 if (isset($this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'])) {
458 $hideTable = (bool)$this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'];
462 unset($tableNames[$tableName]);
464 if (isset($this->tableDisplayOrder[$tableName])) {
466 $tableNames[$tableName] = $this->tableDisplayOrder[$tableName];
468 $tableNames[$tableName] = [];
477 foreach ($orderedTableNames as $tableName => $_) {
480 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems']) ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems'] : $this->itemsLimitSingleTable;
483 $firstRow = $db->exec_SELECTgetSingleRow(
488 if ($firstRow ===
false) {
491 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems']) ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems'] : $this->itemsLimitPerTable;
493 if ($this->showLimit) {
497 if ($this->allFields) {
499 $fields[] =
'tstamp';
500 $fields[] =
'crdate';
501 $fields[] =
'_PATH_';
502 $fields[] =
'_CONTROL_';
503 if (is_array($this->setFields[$tableName])) {
504 $fields = array_intersect($fields, $this->setFields[$tableName]);
512 if ($this->searchLevels === 0) {
513 $this->pidSelect =
'pid=' . (int)$this->
id;
516 $this->HTMLcode .= $this->
getTable($tableName, $this->
id, implode(
',', $fields));
539 public function getSearchBox($formFields =
true)
545 $formElements = array(
'',
'');
547 $formElements = array(
'<form action="' . htmlspecialchars($this->listURL(
'', -1,
'firstElementNumber,search_field')) .
'" method="post">',
'</form>');
551 $parts = explode(
'|',
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.enterSearchLevels'));
552 foreach ($parts as $kv => $label) {
553 $opt[] =
'<option value="' . $kv .
'"' . ($kv === $this->searchLevels ?
' selected="selected"' :
'') .
'>' . htmlspecialchars($label) .
'</option>';
555 $lMenu =
'<select class="form-control" name="search_levels" title="' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.title.search_levels',
true) .
'" id="search_levels">' . implode(
'', $opt) .
'</select>';
557 $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') .
';">
558 ' . $formElements[0] .
'
559 <div id="typo3-dblist-search">
560 <div class="panel panel-default">
561 <div class="panel-body">
562 <div class="form-inline form-inline-spaced">
563 <div class="form-group">
564 <input class="form-control" type="search" placeholder="' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.enterSearchString',
true) .
'" title="' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.title.searchString',
true) .
'" name="search_field" id="search_field" value="' . htmlspecialchars($this->searchString) .
'" />
566 <div class="form-group">
567 <label for="search_levels">' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.label.search_levels',
true) .
': </label>
570 <div class="form-group">
571 <label for="showLimit">' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.label.limit',
true) .
': </label>
572 <input class="form-control" type="number" min="0" max="10000" placeholder="10" title="' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.title.limit',
true) .
'" name="showLimit" id="showLimit" value="' . htmlspecialchars(($this->showLimit ? $this->showLimit :
'')) .
'" />
574 <div class="form-group">
575 <button type="submit" class="btn btn-default" name="search" title="' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.title.search',
true) .
'">
583 ' . $formElements[1] .
'</div>';
602 $dispFields = $backendUser->getModuleData(
'list/displayFields');
604 if (is_array($this->displayFields)) {
605 reset($this->displayFields);
606 $tKey = key($this->displayFields);
607 $dispFields[$tKey] = $this->displayFields[$tKey];
608 $backendUser->pushModuleData(
'list/displayFields', $dispFields);
611 $this->setFields = $dispFields;
624 return BackendUtility::thumbCode($row,
$table, $field);
638 $hookObjectsArr = array();
639 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list.inc'][
'makeQueryArray'])) {
640 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'typo3/class.db_list.inc'][
'makeQueryArray'] as $classRef) {
646 if ($this->sortField) {
648 $orderBy =
'ORDER BY ' . $this->sortField;
649 if ($this->sortRev) {
655 $limit = $this->iLimit ? ($this->firstElementNumber ? $this->firstElementNumber .
',' :
'') . ($this->iLimit + 1) :
'';
657 $pC =
$table ==
'pages' && $this->perms_clause ?
' AND ' . $this->perms_clause :
'';
662 'SELECT' => $fieldList,
671 $queryParts[
'WHERE'] .=
' AND ' .
$GLOBALS[
'TCA'][
$table][
'ctrl'][
'transOrigPointerField'] .
'=0 ';
674 foreach ($hookObjectsArr as $hookObj) {
675 if (method_exists($hookObj,
'makeQueryArray_post')) {
677 'orderBy' => $orderBy,
682 $hookObj->makeQueryArray_post($queryParts, $this, $table,
$id, $addWhere, $fieldList, $_params);
698 $this->totalItems = $this->
getDatabaseConnection()->exec_SELECTcountRows(
'*', $queryParts[
'FROM'], $queryParts[
'WHERE']);
712 $currentPid = (int)$currentPid;
713 $tablePidField =
$table ===
'pages' ?
'uid' :
'pid';
715 if ($this->searchString) {
716 $result =
' AND 0=1';
718 if (!empty($searchableFields)) {
721 'uid=' . $this->searchString
723 foreach ($searchableFields as $fieldName) {
725 $fieldConfig = &
$GLOBALS[
'TCA'][
$table][
'columns'][$fieldName][
'config'];
726 $condition = $fieldName .
'=' . $this->searchString;
727 if ($fieldConfig[
'type'] ==
'input' && $fieldConfig[
'eval'] &&
GeneralUtility::inList($fieldConfig[
'eval'],
'int')) {
728 if (is_array($fieldConfig[
'search']) && in_array(
'pidonly', $fieldConfig[
'search']) && $currentPid > 0) {
729 $condition =
'(' . $condition .
' AND ' . $tablePidField .
'=' . $currentPid .
')';
731 $whereParts[] = $condition;
732 }
elseif ($fieldConfig[
'type'] ==
'text' ||
733 $fieldConfig[
'type'] ==
'flex' ||
734 ($fieldConfig[
'type'] ==
'input' && (!$fieldConfig[
'eval'] || !preg_match(
'/date|time|int/', $fieldConfig[
'eval'])))) {
735 $condition = $fieldName .
' LIKE \'%' . $this->searchString .
'%\'';
736 $whereParts[] = $condition;
741 $whereParts = array();
743 $like =
'\'%
' . $db->quoteStr($db->escapeStrForLike($this->searchString, $table), $table) . '%\
'';
744 foreach ($searchableFields as $fieldName) {
746 $fieldConfig = &
$GLOBALS[
'TCA'][
$table][
'columns'][$fieldName][
'config'];
747 $format =
'LOWER(%s) LIKE LOWER(%s)';
748 if (is_array($fieldConfig[
'search'])) {
749 if (in_array(
'case', $fieldConfig[
'search'])) {
750 $format =
'%s LIKE %s';
752 if (in_array(
'pidonly', $fieldConfig[
'search']) && $currentPid > 0) {
753 $format =
'(' . $format .
' AND ' . $tablePidField .
'=' . $currentPid .
')';
755 if ($fieldConfig[
'search'][
'andWhere']) {
756 $format =
'((' . $fieldConfig[
'search'][
'andWhere'] .
') AND (' . $format .
'))';
759 if ($fieldConfig[
'type'] ==
'text' || $fieldConfig[
'type'] ==
'flex' || $fieldConfig[
'type'] ==
'input' && (!$fieldConfig[
'eval'] || !preg_match(
'/date|time|int/', $fieldConfig[
'eval']))) {
760 $whereParts[] = sprintf($format, $fieldName, $like);
766 if (!empty($whereParts)) {
767 $result =
' AND (' . implode(
' OR ', $whereParts) .
')';
783 $fieldListWasSet =
false;
785 if (isset(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'])) {
787 $fieldListWasSet =
true;
790 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'mod_list'][
'getSearchFieldList'])) {
791 $hookParameters = array(
792 'tableHasSearchConfiguration' => $fieldListWasSet,
793 'tableName' => $tableName,
795 'searchString' => $this->searchString
797 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'mod_list'][
'getSearchFieldList'] as $hookFunction) {
814 if ($this->table !==
$table) {
815 return '<a href="' . htmlspecialchars($this->
listURL(
'',
$table,
'firstElementNumber')) .
'">' . $code .
'</a>';
817 return '<a href="' . htmlspecialchars($this->
listURL(
'',
'',
'sortField,sortRev,table,firstElementNumber')) .
'">' . $code .
'</a>';
834 if ((
string)$code ===
'') {
841 if ($code != htmlspecialchars($origCode)) {
842 $code =
'<span title="' . htmlspecialchars($origCode, ENT_QUOTES,
'UTF-8',
false) .
'">' . $code .
'</span>';
845 switch ((
string)$this->clickTitleMode) {
856 $params =
'&edit[' .
$table .
'][' . $row[
'uid'] .
']=edit';
857 $code =
'<a href="#" onclick="' . htmlspecialchars(
BackendUtility::editOnClick($params,
'', -1)) .
'" title="' .
$lang->getLL(
'edit',
true) .
'">' . $code .
'</a>';
863 $code =
'<a href="#" onclick="' . htmlspecialchars(
865 ) .
'" title="' .
$lang->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.showPage',
true) .
'">' . $code .
'</a>';
870 $code =
'<a href="#" onclick="' . htmlspecialchars((
'top.launchView(\'' .
$table .
'\', \
'' . $row[
'uid'] .
'\');
return false;
')) . '" title="' . $lang->getLL('showInfo
', true) . '">' . $code . '</a>';
873 // Output the label now:
874 if ($table == 'pages') {
875 $code = '<a href="' . htmlspecialchars($this->listURL($uid, '', 'firstElementNumber
')) . '" onclick="setHighlight(
' . $uid . ')
">' . $code . '</a>';
877 $code = $this->linkUrlMail($code, $origCode);
890 public function linkUrlMail($code, $testString)
893 $schema = parse_url($testString);
894 if ($schema['scheme'] && GeneralUtility::inList('http,https,ftp', $schema['scheme'])) {
895 return '<a href="' . htmlspecialchars($testString) . '" target="_blank
">' . $code . '</a>';
898 if (GeneralUtility::validEmail($testString)) {
899 return '<a href="mailto:
' . htmlspecialchars($testString) . '" target="_blank
">' . $code . '</a>';
901 // Return if nothing else...
915 public function listURL($altId = '', $table = '-1', $exclList = '')
917 $urlParameters = array();
918 if ((string)$altId !== '') {
919 $urlParameters['id'] = $altId;
921 $urlParameters['id'] = $this->id;
923 if ($table === '-1') {
924 $urlParameters['table'] = $this->table;
926 $urlParameters['table'] = $table;
929 $urlParameters['imagemode'] = $this->thumbs;
931 if ($this->returnUrl) {
932 $urlParameters['returnUrl'] = $this->returnUrl;
934 if ((!$exclList || !GeneralUtility::inList($exclList, 'search_field')) && $this->searchString) {
935 $urlParameters['search_field'] = $this->searchString;
937 if ($this->searchLevels) {
938 $urlParameters['search_levels'] = $this->searchLevels;
940 if ($this->showLimit) {
941 $urlParameters['showLimit'] = $this->showLimit;
943 if ((!$exclList || !GeneralUtility::inList($exclList, 'firstElementNumber')) && $this->firstElementNumber) {
944 $urlParameters['pointer'] = $this->firstElementNumber;
946 if ((!$exclList || !GeneralUtility::inList($exclList, 'sortField')) && $this->sortField) {
947 $urlParameters['sortField'] = $this->sortField;
949 if ((!$exclList || !GeneralUtility::inList($exclList, 'sortRev')) && $this->sortRev) {
950 $urlParameters['sortRev'] = $this->sortRev;
953 $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters);
955 return BackendUtility::getModuleUrl(GeneralUtility::_GP('M'), $urlParameters);
963 public function requestUri()
965 return $this->listURL();
976 public function makeFieldList($table, $dontCheckUser = false, $addDateFields = false)
978 $backendUser = $this->getBackendUserAuthentication();
979 // Init fieldlist array:
980 $fieldListArr = array();
982 if (is_array($GLOBALS['TCA'][$table]) && isset($GLOBALS['TCA'][$table]['columns']) && is_array($GLOBALS['TCA'][$table]['columns'])) {
983 if (isset($GLOBALS['TCA'][$table]['columns']) && is_array($GLOBALS['TCA'][$table]['columns'])) {
984 // Traverse configured columns and add them to field array, if available for user.
985 foreach ($GLOBALS['TCA'][$table]['columns'] as $fN => $fieldValue) {
986 if ($dontCheckUser || (!$fieldValue['exclude'] || $backendUser->check('non_exclude_fields', $table . ':' . $fN)) && $fieldValue['config']['type'] != 'passthrough') {
987 $fieldListArr[] = $fN;
991 $fieldListArr[] = 'uid';
992 $fieldListArr[] = 'pid';
995 if ($dontCheckUser || $backendUser->isAdmin() || $addDateFields) {
996 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
997 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
999 if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
1000 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
1003 // Add more special fields:
1004 if ($dontCheckUser || $backendUser->isAdmin()) {
1005 if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
1006 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['cruser_id'];
1008 if ($GLOBALS['TCA'][$table]['ctrl']['sortby']) {
1009 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
1011 if (ExtensionManagementUtility::isLoaded('version') && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1012 $fieldListArr[] = 't3ver_id';
1013 $fieldListArr[] = 't3ver_state';
1014 $fieldListArr[] = 't3ver_wsid';
1018 GeneralUtility::sysLog(sprintf('$TCA is broken for the table "%s
": no required "columns
" entry in $TCA.', $table), 'core', GeneralUtility::SYSLOG_SEVERITY_ERROR);
1021 return $fieldListArr;
1032 protected function getSearchableWebmounts($id, $depth, $perms_clause)
1034 $backendUser = $this->getBackendUserAuthentication();
1036 $tree = GeneralUtility::makeInstance(PageTreeView::class);
1037 $tree->init('AND ' . $perms_clause);
1038 $tree->makeHTML = 0;
1039 $tree->fieldArray = array('uid', 'php_tree_stop');
1042 $allowedMounts = !$backendUser->isAdmin() && $id === 0
1043 ? $backendUser->returnWebmounts()
1046 foreach ($allowedMounts as $allowedMount) {
1047 $idList[] = $allowedMount;
1049 $tree->getTree($allowedMount, $depth, '');
1051 $idList = array_merge($idList, $tree->ids);
1063 public function localizationRedirect($justLocalized)
1065 list($table, $orig_uid, $language) = explode(':', $justLocalized);
1066 if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) {
1067 $localizedRecord = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid', $table, $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '=' . (int)$language . ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=' . (int)$orig_uid . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table));
1068 if (is_array($localizedRecord)) {
1069 // Create parameters and finally run the classic page module for creating a new page translation
1070 $url = $this->listURL();
1071 $editUserAccountUrl = BackendUtility::getModuleUrl(
1074 'edit[' . $table . '][' . $localizedRecord['uid'] . ']' => 'edit',
1078 HttpUtility::redirect($editUserAccountUrl);
1089 public function setOverrideUrlParameters(array $urlParameters)
1091 $this->overrideUrlParameters = $urlParameters;
1106 public function setTableDisplayOrder(array $orderInformation)
1108 foreach ($orderInformation as $tableName => &$configuration) {
1109 if (isset($configuration['before'])) {
1110 if (is_string($configuration['before'])) {
1111 $configuration['before'] = GeneralUtility::trimExplode(',', $configuration['before'], true);
1112 } elseif (!is_array($configuration['before'])) {
1113 throw new \UnexpectedValueException('The specified "before
" order configuration for table "' . $tableName . '" is invalid.', 1436195933);
1116 if (isset($configuration['after'])) {
1117 if (is_string($configuration['after'])) {
1118 $configuration['after'] = GeneralUtility::trimExplode(',', $configuration['after'], true);
1119 } elseif (!is_array($configuration['after'])) {
1120 throw new \UnexpectedValueException('The specified "after
" order configuration for table "' . $tableName . '" is invalid.', 1436195934);
1124 $this->tableDisplayOrder = $orderInformation;
1130 protected function getBackendUserAuthentication()
1132 return $GLOBALS['BE_USER'];
1138 protected function getDatabaseConnection()
1140 return $GLOBALS['TYPO3_DB'];