392 $this->
id = (int)
$id;
398 $this->searchString = trim($search);
399 $this->searchLevels = (int)$levels;
400 $this->showLimit = MathUtility::forceIntegerInRange(
$showLimit, 0, 10000);
402 $this->csvOutput = (bool)GeneralUtility::_GP(
'csv');
403 $this->sortField = GeneralUtility::_GP(
'sortField');
404 $this->sortRev = GeneralUtility::_GP(
'sortRev');
405 $this->displayFields = GeneralUtility::_GP(
'displayFields');
406 $this->duplicateField = GeneralUtility::_GP(
'duplicateField');
407 if (GeneralUtility::_GP(
'justLocalized')) {
413 $this->HTMLcode =
'';
415 if (isset($this->modTSconfig[
'properties'][
'itemsLimitPerTable'])) {
416 $this->itemsLimitPerTable = MathUtility::forceIntegerInRange(
417 (
int)$this->modTSconfig[
'properties'][
'itemsLimitPerTable'],
422 if (isset($this->modTSconfig[
'properties'][
'itemsLimitSingleTable'])) {
423 $this->itemsLimitSingleTable = MathUtility::forceIntegerInRange(
424 (
int)$this->modTSconfig[
'properties'][
'itemsLimitSingleTable'],
433 $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
434 ->getQueryBuilderForTable(
'pages')
436 $permsClause = $expressionBuilder->andX($backendUser->getPagePermsClause(Permission::PAGE_SHOW));
438 $pidList = GeneralUtility::intExplode(
',', $backendUser->getTSConfig()[
'options.'][
'hideRecords.'][
'pages'] ??
'',
true);
439 if (!empty($pidList)) {
440 $permsClause->add($expressionBuilder->notIn(
'pages.uid', $pidList));
442 $this->perms_clause = (string)$permsClause;
445 $this->tablesCollapsed = is_array($backendUser->uc[
'moduleData'][
'list'])
446 ? $backendUser->uc[
'moduleData'][
'list']
448 $collapseOverride = GeneralUtility::_GP(
'collapse');
449 if (is_array($collapseOverride)) {
450 foreach ($collapseOverride as $collapseTable => $collapseValue) {
451 if (is_array(
$GLOBALS[
'TCA'][$collapseTable]) && ($collapseValue == 0 || $collapseValue == 1)) {
452 $this->tablesCollapsed[$collapseTable] = $collapseValue;
457 $backendUser->writeUC($backendUser->uc);
458 $returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP(
'returnUrl'));
475 $this->pageRecord = BackendUtility::getRecordWSOL(
'pages', $this->
id);
476 $hideTablesArray = GeneralUtility::trimExplode(
',', $this->hideTables);
481 $tableNames = array_flip(array_keys(
$GLOBALS[
'TCA']));
482 foreach ($tableNames as $tableName => &$config) {
487 if ($this->table && $tableName !== $this->table
488 || $this->tableList && !GeneralUtility::inList($this->tableList, $tableName)
489 || !$backendUser->check(
'tables_select', $tableName)
497 $hideTable = $hideTable
498 || !empty(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'hideTable'])
499 || in_array($tableName, $hideTablesArray,
true)
500 || in_array(
'*', $hideTablesArray,
true);
502 if (isset($this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'])) {
503 $hideTable = (bool)$this->tableTSconfigOverTCA[$tableName .
'.'][
'hideTable'];
507 unset($tableNames[$tableName]);
509 if (isset($this->tableDisplayOrder[$tableName])) {
511 $tableNames[$tableName] = $this->tableDisplayOrder[$tableName];
513 $tableNames[$tableName] = [];
519 $orderedTableNames = GeneralUtility::makeInstance(DependencyOrderingService::class)
520 ->orderByDependencies($tableNames);
522 foreach ($orderedTableNames as $tableName => $_) {
525 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems'])
526 ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxSingleDBListItems']
527 : $this->itemsLimitSingleTable;
530 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
531 ->getQueryBuilderForTable($tableName);
532 $queryBuilder->getRestrictions()
534 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
535 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
537 $firstRow = $queryBuilder->select(
'uid')
541 if (!is_array($firstRow)) {
544 $this->iLimit = isset(
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems'])
545 ? (int)
$GLOBALS[
'TCA'][$tableName][
'interface'][
'maxDBListItems']
546 : $this->itemsLimitPerTable;
548 if ($this->showLimit) {
552 if ($this->allFields) {
558 if (is_array($this->setFields[$tableName])) {
568 $this->HTMLcode .= $this->
getTable($tableName, $this->
id, implode(
',',
$fields));
596 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
599 $formElements = [
'',
''];
601 $formElements = [
'<form action="' . htmlspecialchars($this->
listURL(
'',
'-1',
'firstElementNumber,search_field')) .
'" method="post">',
'</form>'];
607 $config = BackendUtility::getPagesTSconfig($this->
id);
608 $searchLevelsFromTSconfig = $config[
'mod.'][
'web_list.'][
'searchLevel.'][
'items.'];
609 $searchLevelItems = [];
612 foreach ($searchLevelsFromTSconfig as $keySearchLevel => $labelConfigured) {
613 $label = $lang->sL(
'LLL:' . $labelConfigured);
615 $label = $labelConfigured;
617 $searchLevelItems[$keySearchLevel] = $label;
620 foreach ($searchLevelItems as $kv => $label) {
621 $opt[] =
'<option value="' . $kv .
'"' . ($kv === $this->searchLevels ?
' selected="selected"' :
'') .
'>' . htmlspecialchars($label) .
'</option>';
623 $lMenu =
'<select class="form-control" name="search_levels" title="' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search_levels')) .
'" id="search_levels">' . implode(
'', $opt) .
'</select>';
625 $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') .
';">
626 ' . $formElements[0] .
'
627 <div id="typo3-dblist-search">
628 <div class="panel panel-default">
629 <div class="panel-body">
631 <div class="form-group col-xs-12">
632 <label for="search_field">' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.searchString')) .
': </label>
633 <input class="form-control" type="search" placeholder="' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')) .
'" title="' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchString')) .
'" name="search_field" id="search_field" value="' . htmlspecialchars($this->searchString) .
'" />
635 <div class="form-group col-xs-12 col-sm-6">
636 <label for="search_levels">' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.search_levels')) .
': </label>
639 <div class="form-group col-xs-12 col-sm-6">
640 <label for="showLimit">' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.limit')) .
': </label>
641 <input class="form-control" type="number" min="0" max="10000" placeholder="10" title="' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.limit')) .
'" name="showLimit" id="showLimit" value="' . htmlspecialchars(($this->showLimit ? $this->showLimit :
'')) .
'" />
643 <div class="form-group col-xs-12">
644 <div class="form-control-wrap">
645 <button type="submit" class="btn btn-default" name="search" title="' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')) .
'">
646 ' .
$iconFactory->
getIcon(
'actions-search', Icon::SIZE_SMALL)->
render() .
' ' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search')) .
'
654 ' . $formElements[1] .
'</div>';
672 $dispFields = $backendUser->getModuleData(
'list/displayFields');
674 if (is_array($this->displayFields)) {
675 reset($this->displayFields);
676 $tKey = key($this->displayFields);
677 $dispFields[$tKey] = $this->displayFields[$tKey];
678 $backendUser->pushModuleData(
'list/displayFields', $dispFields);
681 $this->setFields = $dispFields;
695 return BackendUtility::thumbCode($row,
$table, $field);
712 array $additionalConstraints = [],
715 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
716 ->getQueryBuilderForTable(
$table);
717 $queryBuilder->getRestrictions()
719 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
720 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
725 if (!empty($additionalConstraints)) {
726 $queryBuilder->andWhere(...$additionalConstraints);
731 return $queryBuilder;
750 array $fieldList = [
'*'],
751 array $additionalConstraints = [],
752 QueryBuilder $queryBuilder,
753 bool $addSorting =
true
757 'fields' => $fieldList,
760 'firstResult' => $this->firstElementNumber ?:
null,
761 'maxResults' => $this->iLimit ?: null
764 if ($this->iLimit > 0) {
765 $queryBuilder->setMaxResults($this->iLimit);
769 if ($this->sortField && in_array($this->sortField, $this->
makeFieldList($table, 1))) {
770 $queryBuilder->orderBy($this->sortField, $this->sortRev ?
'DESC' :
'ASC');
773 $orderBys = QueryHelper::parseOrderBy((
string)$orderBy);
774 foreach ($orderBys as $orderBy) {
775 $queryBuilder->addOrderBy($orderBy[0], $orderBy[1]);
783 if (!empty($searchWhere)) {
784 $queryBuilder->andWhere($searchWhere);
788 if (
$table ===
'pages' && $this->perms_clause) {
789 $queryBuilder->andWhere($this->perms_clause);
794 && (GeneralUtility::inList($this->hideTranslations,
$table) || $this->hideTranslations ===
'*')
796 $queryBuilder->andWhere($queryBuilder->expr()->eq(
802 $hookName = DatabaseRecordList::class;
803 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][$hookName][
'buildQueryParameters'])) {
805 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);
806 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][$hookName][
'buildQueryParameters'] as $className) {
807 $hookObject = GeneralUtility::makeInstance($className);
808 if (method_exists($hookObject,
'buildQueryParametersPostProcess')) {
809 $hookObject->buildQueryParametersPostProcess(
813 $additionalConstraints,
826 if (!empty($parameters[
'where'])) {
827 $parameters[
'where'] = array_unique(array_filter(array_values($parameters[
'where'])));
829 if (!empty($parameters[
'where'])) {
831 $queryBuilder->where(...$parameters[
'where']);
833 if (!empty($parameters[
'orderBy'])) {
835 foreach ($parameters[
'orderBy'] as $fieldNameAndSorting) {
836 list($fieldName, $sorting) = $fieldNameAndSorting;
837 $queryBuilder->addOrderBy($fieldName, $sorting);
840 if (!empty($parameters[
'firstResult'])) {
842 $queryBuilder->setFirstResult((
int)$parameters[
'firstResult']);
844 if (!empty($parameters[
'maxResults']) && $parameters[
'maxResults'] !== $this->iLimit) {
846 $queryBuilder->setMaxResults((
int)$parameters[
'maxResults']);
848 if (!empty($parameters[
'groupBy'])) {
850 $queryBuilder->groupBy($parameters[
'groupBy']);
853 return $queryBuilder;
867 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
868 ->getQueryBuilderForTable(
$table);
870 $queryBuilder->getRestrictions()
872 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
873 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
877 if (!empty($constraints)) {
878 $queryBuilder->andWhere(...$constraints);
881 $queryBuilder = $this->
prepareQueryBuilder($table, $pageId, [
'*'], $constraints, $queryBuilder,
false);
883 $queryBuilder->setFirstResult(0);
884 $queryBuilder->setMaxResults(1);
886 $this->totalItems = (int)$queryBuilder->count(
'*')
902 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
$table);
903 $expressionBuilder = $queryBuilder->expr();
905 $currentPid = (int)$currentPid;
906 $tablePidField =
$table ===
'pages' ?
'uid' :
'pid';
908 if (empty($this->searchString)) {
913 if (MathUtility::canBeInterpretedAsInteger($this->searchString)) {
914 $constraints[] = $expressionBuilder->eq(
'uid', (
int)$this->searchString);
915 foreach ($searchableFields as $fieldName) {
920 $fieldType = $fieldConfig[
'type'];
921 $evalRules = $fieldConfig[
'eval'] ?:
'';
922 if ($fieldType ===
'input' && $evalRules && GeneralUtility::inList($evalRules,
'int')) {
923 if (is_array($fieldConfig[
'search'])
924 && in_array(
'pidonly', $fieldConfig[
'search'],
true)
927 $constraints[] = $expressionBuilder->andX(
928 $expressionBuilder->eq($fieldName, (
int)$this->searchString),
929 $expressionBuilder->eq($tablePidField, (
int)$currentPid)
932 } elseif ($fieldType ===
'text'
933 || $fieldType ===
'flex'
934 || ($fieldType ===
'input' && (!$evalRules || !preg_match(
'/date|time|int/', $evalRules)))
936 $constraints[] = $expressionBuilder->like(
938 $queryBuilder->quote(
'%' . (
int)$this->searchString .
'%')
942 } elseif (!empty($searchableFields)) {
943 $like = $queryBuilder->quote(
'%' . $queryBuilder->escapeLikeWildcards($this->searchString) .
'%');
944 foreach ($searchableFields as $fieldName) {
949 $fieldType = $fieldConfig[
'type'];
950 $evalRules = $fieldConfig[
'eval'] ?:
'';
951 $searchConstraint = $expressionBuilder->andX(
952 $expressionBuilder->comparison(
953 'LOWER(' . $queryBuilder->quoteIdentifier($fieldName) .
')',
955 'LOWER(' . $like .
')'
958 if (is_array($fieldConfig[
'search'])) {
959 $searchConfig = $fieldConfig[
'search'];
960 if (in_array(
'case', $searchConfig)) {
962 $searchConstraint = $expressionBuilder->andX($expressionBuilder->like($fieldName, $like));
964 if (in_array(
'pidonly', $searchConfig) && $currentPid > 0) {
965 $searchConstraint->add($expressionBuilder->eq($tablePidField, (
int)$currentPid));
967 if ($searchConfig[
'andWhere']) {
968 $searchConstraint->add(
969 QueryHelper::stripLogicalOperatorPrefix($fieldConfig[
'search'][
'andWhere'])
973 if ($fieldType ===
'text'
974 || $fieldType ===
'flex'
975 || $fieldType ===
'input' && (!$evalRules || !preg_match(
'/date|time|int/', $evalRules))
977 if ($searchConstraint->count() !== 0) {
978 $constraints[] = $searchConstraint;
984 if (empty($constraints)) {
988 return $expressionBuilder->orX(...$constraints);
1001 $fieldListWasSet =
false;
1003 if (isset(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'])) {
1004 $fieldArray = GeneralUtility::trimExplode(
',',
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'searchFields'],
true);
1005 $fieldListWasSet =
true;
1009 'tableHasSearchConfiguration' => $fieldListWasSet,
1010 'tableName' => $tableName,
1014 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'mod_list'][
'getSearchFieldList'] ?? [] as $hookFunction) {
1015 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
1031 if ($this->table !==
$table) {
1032 return '<a href="' . htmlspecialchars($this->
listURL(
'', $table,
'firstElementNumber')) .
'">' . $code .
'</a>';
1034 return '<a href="' . htmlspecialchars($this->
listURL(
'',
'',
'sortField,sortRev,table,firstElementNumber')) .
'">' . $code .
'</a>';
1052 if ((
string)$code ===
'') {
1053 $code =
'<i>[' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title')) .
']</i> - '
1054 . htmlspecialchars(BackendUtility::getRecordTitle(
$table, $row));
1056 $code = htmlspecialchars($code, ENT_QUOTES,
'UTF-8',
false);
1057 if ($code != htmlspecialchars($origCode)) {
1058 $code =
'<span title="' . htmlspecialchars($origCode, ENT_QUOTES,
'UTF-8',
false) .
'">' . $code .
'</span>';
1061 switch ((
string)$this->clickTitleMode) {
1066 $permsEdit = $localCalcPerms & Permission::PAGE_EDIT;
1068 $permsEdit = $this->calcPerms & Permission::CONTENT_EDIT;
1072 $params =
'&edit[' .
$table .
'][' . $row[
'uid'] .
']=edit';
1073 $code =
'<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params,
'', -1)) .
'" title="' . htmlspecialchars($lang->getLL(
'edit')) .
'">' . $code .
'</a>';
1079 $code =
'<a href="#" onclick="' . htmlspecialchars(
1080 BackendUtility::viewOnClick((
$table ===
'tt_content' ? $this->
id .
'#' . $row[
'uid'] : $row[
'uid']))
1081 ) .
'" title="' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')) .
'">' . $code .
'</a>';
1086 $code =
'<a href="#" onclick="' . htmlspecialchars(
'top.TYPO3.InfoWindow.showItem(\'' .
$table .
'\', \
'' . $row[
'uid'] .
'\');
return false;
') . '" title="' . htmlspecialchars($lang->getLL('showInfo
')) . '">' . $code . '</a>';
1089 // Output the label now:
1090 if ($table === 'pages') {
1091 $code = '<a href="' . htmlspecialchars($this->listURL($uid, '', 'firstElementNumber
')) . '" onclick="setHighlight(
' . $uid . ')
">' . $code . '</a>';
1093 $code = $this->linkUrlMail($code, $origCode);
1107 public function linkUrlMail($code, $testString)
1110 $scheme = parse_url($testString, PHP_URL_SCHEME);
1111 if ($scheme === 'http' || $scheme === 'https' || $scheme === 'ftp') {
1112 return '<a href="' . htmlspecialchars($testString) . '" target="_blank
">' . $code . '</a>';
1115 if (GeneralUtility::validEmail($testString)) {
1116 return '<a href="mailto:
' . htmlspecialchars($testString) . '" target="_blank
">' . $code . '</a>';
1118 // Return if nothing else...
1133 public function listURL($altId = '', $table = '-1', $exclList = '')
1135 $urlParameters = [];
1136 if ((string)$altId !== '') {
1137 $urlParameters['id'] = $altId;
1139 $urlParameters['id'] = $this->id;
1141 if ($table === '-1') {
1142 $urlParameters['table'] = $this->table;
1144 $urlParameters['table'] = $table;
1146 if ($this->thumbs) {
1147 $urlParameters['imagemode'] = $this->thumbs;
1149 if ($this->returnUrl) {
1150 $urlParameters['returnUrl'] = $this->returnUrl;
1152 if ((!$exclList || !GeneralUtility::inList($exclList, 'search_field')) && $this->searchString) {
1153 $urlParameters['search_field'] = $this->searchString;
1155 if ($this->searchLevels) {
1156 $urlParameters['search_levels'] = $this->searchLevels;
1158 if ($this->showLimit) {
1159 $urlParameters['showLimit'] = $this->showLimit;
1161 if ((!$exclList || !GeneralUtility::inList($exclList, 'firstElementNumber')) && $this->firstElementNumber) {
1162 $urlParameters['pointer'] = $this->firstElementNumber;
1164 if ((!$exclList || !GeneralUtility::inList($exclList, 'sortField')) && $this->sortField) {
1165 $urlParameters['sortField'] = $this->sortField;
1167 if ((!$exclList || !GeneralUtility::inList($exclList, 'sortRev')) && $this->sortRev) {
1168 $urlParameters['sortRev'] = $this->sortRev;
1171 $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters);
1173 if ($routePath = GeneralUtility::_GP('route')) {
1174 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1175 $url = (string)$uriBuilder->buildUriFromRoutePath($routePath, $urlParameters);
1177 $url = GeneralUtility::getIndpEnv('SCRIPT_NAME') . HttpUtility::buildQueryString($urlParameters, '?');
1187 public function requestUri()
1189 return $this->listURL();
1201 public function makeFieldList($table, $dontCheckUser = false, $addDateFields = false)
1203 $backendUser = $this->getBackendUserAuthentication();
1204 // Init fieldlist array:
1207 if (is_array($GLOBALS['TCA'][$table]) && isset($GLOBALS['TCA'][$table]['columns']) && is_array($GLOBALS['TCA'][$table]['columns'])) {
1208 if (isset($GLOBALS['TCA'][$table]['columns']) && is_array($GLOBALS['TCA'][$table]['columns'])) {
1209 // Traverse configured columns and add them to field array, if available for user.
1210 foreach ($GLOBALS['TCA'][$table]['columns'] as $fN => $fieldValue) {
1211 if ($dontCheckUser || (!$fieldValue['exclude'] || $backendUser->check('non_exclude_fields', $table . ':' . $fN)) && $fieldValue['config']['type'] !== 'passthrough') {
1212 $fieldListArr[] = $fN;
1216 $fieldListArr[] = 'uid';
1217 $fieldListArr[] = 'pid';
1220 if ($dontCheckUser || $backendUser->isAdmin() || $addDateFields) {
1221 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
1222 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
1224 if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
1225 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
1228 // Add more special fields:
1229 if ($dontCheckUser || $backendUser->isAdmin()) {
1230 if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
1231 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['cruser_id'];
1233 if ($GLOBALS['TCA'][$table]['ctrl']['sortby']) {
1234 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
1236 if (ExtensionManagementUtility::isLoaded('workspaces') && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1237 $fieldListArr[] = 't3ver_id';
1238 $fieldListArr[] = 't3ver_state';
1239 $fieldListArr[] = 't3ver_wsid';
1243 GeneralUtility::makeInstance(LogManager::class)
1244 ->getLogger(__CLASS__)
1245 ->error('TCA is broken for the table "' . $table . '": no required "columns
" entry in TCA.');
1248 return $fieldListArr;
1260 protected function getSearchableWebmounts($id, $depth, $perms_clause)
1262 $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
1263 $cacheIdentifier = md5('pidList_' . $id . '_' . $depth . '_' . $perms_clause);
1264 $idList = $runtimeCache->get($cacheIdentifier);
1269 $backendUser = $this->getBackendUserAuthentication();
1271 $tree = GeneralUtility::makeInstance(PageTreeView::class);
1272 $tree->init('AND ' . $perms_clause);
1273 $tree->makeHTML = 0;
1274 $tree->fieldArray = ['uid', 'php_tree_stop'];
1277 $allowedMounts = !$backendUser->isAdmin() && $id === 0
1278 ? $backendUser->returnWebmounts()
1281 foreach ($allowedMounts as $allowedMount) {
1282 $idList[] = $allowedMount;
1284 $tree->getTree($allowedMount, $depth, '');
1286 $idList = array_merge($idList, $tree->ids);
1288 $runtimeCache->set($cacheIdentifier, $idList);
1298 public function localizationRedirect($justLocalized)
1300 list($table, $orig_uid, $language) = explode(':', $justLocalized);
1301 if ($GLOBALS['TCA'][$table]
1302 && $GLOBALS['TCA'][$table]['ctrl']['languageField']
1303 && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
1305 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
1306 $queryBuilder->getRestrictions()
1308 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1309 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
1311 $localizedRecordUid = $queryBuilder->select('uid')
1314 $queryBuilder->expr()->eq(
1315 $GLOBALS['TCA'][$table]['ctrl']['languageField'],
1316 $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
1318 $queryBuilder->expr()->eq(
1319 $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
1320 $queryBuilder->createNamedParameter($orig_uid, \PDO::PARAM_INT)
1327 if ($localizedRecordUid !== false) {
1328 // Create parameters and finally run the classic page module for creating a new page translation
1329 $url = $this->listURL();
1331 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
1332 $editUserAccountUrl = (string)$uriBuilder->buildUriFromRoute(
1335 'edit[' . $table . '][' . $localizedRecordUid . ']' => 'edit',
1339 HttpUtility::redirect($editUserAccountUrl);
1350 public function setOverrideUrlParameters(array $urlParameters)
1352 $this->overrideUrlParameters = $urlParameters;
1368 public function setTableDisplayOrder(array $orderInformation)
1370 foreach ($orderInformation as $tableName => &$configuration) {
1371 if (isset($configuration['before'])) {
1372 if (is_string($configuration['before'])) {
1373 $configuration['before'] = GeneralUtility::trimExplode(',', $configuration['before'], true);
1374 } elseif (!is_array($configuration['before'])) {
1375 throw new \UnexpectedValueException('The specified "before
" order configuration for table "' . $tableName . '" is invalid.', 1436195933);
1378 if (isset($configuration['after'])) {
1379 if (is_string($configuration['after'])) {
1380 $configuration['after'] = GeneralUtility::trimExplode(',', $configuration['after'], true);
1381 } elseif (!is_array($configuration['after'])) {
1382 throw new \UnexpectedValueException('The specified "after
" order configuration for table "' . $tableName . '" is invalid.', 1436195934);
1386 $this->tableDisplayOrder = $orderInformation;
1393 public function getOverridePageIdList(): array
1395 return $this->overridePageIdList;
1402 public function setOverridePageIdList(array $overridePageIdList)
1404 $this->overridePageIdList = array_map('intval', $overridePageIdList);
1416 protected function addPageIdConstraint(string $tableName, QueryBuilder $queryBuilder): QueryBuilder
1418 // Set search levels:
1419 $searchLevels = $this->searchLevels;
1421 // Set search levels to 999 instead of -1 as the following methods
1422 // do not support -1 as valid value for infinite search.
1423 if ($searchLevels === -1) {
1424 $searchLevels = 999;
1427 if ($searchLevels === 0) {
1428 $queryBuilder->andWhere(
1429 $queryBuilder->expr()->eq(
1430 $tableName . '.pid',
1431 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
1434 } elseif ($searchLevels > 0) {
1435 $allowedPidList = $this->getSearchableWebmounts($this->id, $searchLevels, $this->perms_clause);
1436 $queryBuilder->andWhere(
1437 $queryBuilder->expr()->in(
1438 $tableName . '.pid',
1439 $queryBuilder->createNamedParameter($allowedPidList, Connection::PARAM_INT_ARRAY)
1444 if (!empty($this->getOverridePageIdList())) {
1445 $queryBuilder->andWhere(
1446 $queryBuilder->expr()->in(
1447 $tableName . '.pid',
1448 $queryBuilder->createNamedParameter($this->getOverridePageIdList(), Connection::PARAM_INT_ARRAY)
1453 return $queryBuilder;
1462 protected function logDeprecation(string $index)
1464 trigger_error('[index: ' . $index . '] $parameters in "buildQueryParameters
"-Hook will be removed in TYPO3 v10.0, use $queryBuilder instead.', E_USER_DEPRECATED);
1471 protected function getBackendUserAuthentication()
1473 return $GLOBALS['BE_USER'];